changeset 588:6d1579861b4a

Net: rename Listener::set to Listener::reset, improve Listener tests
author David Demelier <markand@malikania.fr>
date Mon, 29 Aug 2016 21:16:40 +0200
parents 865610e072a0
children 5717cb946cd3
files modules/net/net.hpp modules/net/test/main.cpp
diffstat 2 files changed, 200 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- a/modules/net/net.hpp	Tue Jul 26 09:56:59 2016 +0200
+++ b/modules/net/net.hpp	Mon Aug 29 21:16:40 2016 +0200
@@ -162,6 +162,8 @@
  *
  * Set one or more condition for the given handle.
  *
+ * This erase previous flags if any.
+ *
  * ## Synopsis
  *
  * ````
@@ -965,8 +967,9 @@
  */
 enum class Condition {
     None,                       //!< No condition is required
-    Readable = (1 << 0),        //!< The socket must be readable
-    Writable = (1 << 1)         //!< The socket must be writable
+    Readable    = (1 << 0),     //!< The socket must be readable
+    Writable    = (1 << 1),     //!< The socket must be writable
+    All         = 0x3           //! Both are requested
 };
 
 /**
@@ -2495,7 +2498,7 @@
     length = sizeof (sun);
 #endif
 
-    return Address(reinterpret_cast<const sockaddr *>(&sun), length); 
+    return Address(reinterpret_cast<const sockaddr *>(&sun), length);
 }
 
 /**
@@ -3437,6 +3440,16 @@
     }
 
     /**
+     * Overloaded function.
+     *
+     * \return the backend
+     */
+    inline Backend &backend() noexcept
+    {
+        return m_backend;
+    }
+
+    /**
      * Get the non-modifiable table.
      *
      * \return the table
@@ -3494,11 +3507,13 @@
      *
      * If incorrect flags are passed, the function does nothing.
      *
+     * Previous flags are discarded.
+     *
      * \param sc the socket
      * \param condition the condition (may be OR'ed)
      * \throw Error if the backend failed to set
      */
-    void set(Handle sc, Condition condition)
+    void reset(Handle sc, Condition condition)
     {
         // Invalid or useless flags.
         if (condition == Condition::None || static_cast<int>(condition) > 0x3)
@@ -3511,18 +3526,27 @@
             m_backend.set(m_table, sc, condition, true);
             m_table.emplace(sc, condition);
         } else {
-            // Remove flag if already present.
-            if ((condition & Condition::Readable) == Condition::Readable &&
-                (it->second & Condition::Readable) == Condition::Readable)
-                condition &= ~(Condition::Readable);
-            if ((condition & Condition::Writable) == Condition::Writable &&
-                (it->second & Condition::Writable) == Condition::Writable)
-                condition &= ~(Condition::Writable);
-
-            // Still need a call?
-            if (condition != Condition::None) {
-                m_backend.set(m_table, sc, condition, false);
-                it->second |= condition;
+            /*
+             * In this scenario, the socket exist in the registry with at least
+             * one flag, the user may call set with read, write or both flags.
+             *
+             * If one of Readable or Writable is requested, we remove the
+             * opposite one if present.
+             *
+             * If both are requested, we add the missing one.
+             */
+            auto remove = it->second & ~(condition);
+
+            if (remove != Condition::None) {
+                m_backend.unset(m_table, sc, remove, false);
+                it->second &= ~(remove);
+            }
+
+            auto apply = it->second ^ condition;
+
+            if (apply != Condition::None) {
+                m_backend.set(m_table, sc, it->second ^ condition, false);
+                it->second |= (it->second ^ condition);
             }
         }
     }
--- a/modules/net/test/main.cpp	Tue Jul 26 09:56:59 2016 +0200
+++ b/modules/net/test/main.cpp	Mon Aug 29 21:16:40 2016 +0200
@@ -248,19 +248,17 @@
 
 class TestBackendSet {
 public:
-    int m_callcount{0};
-    bool m_added{false};
-    Condition m_flags{Condition::None};
+    std::function<void (Condition, bool)> onSet;
+    std::function<void (Condition, bool)> onUnset;
 
-    inline void set(const ListenerTable &, Handle, Condition flags, bool add) noexcept
+    inline void set(const ListenerTable &, Handle, Condition flags, bool addition) noexcept
     {
-        m_callcount ++;
-        m_added = add;
-        m_flags |= flags;
+        onSet(flags, addition);
     }
 
-    inline void unset(const ListenerTable &, Handle, Condition, bool) noexcept
+    inline void unset(const ListenerTable &, Handle, Condition flags, bool removal) noexcept
     {
+        onUnset(flags, removal);
     }
 
     std::vector<ListenerStatus> wait(const ListenerTable &, int)
@@ -286,17 +284,53 @@
     }
 };
 
+TEST(ListenerSet, none)
+{
+    Listener<TestBackendSet> listener;
+    Handle s = 0;
+
+    listener.backend().onSet = [&] (auto, auto) {
+        FAIL() << "unexpected set call";
+    };
+    listener.backend().onUnset = [&] (auto, auto) {
+        FAIL() << "unexpected unset call";
+    };
+    listener.reset(s, static_cast<Condition>(0U));
+
+    ASSERT_EQ(0U, listener.size());
+}
+
+TEST(ListenerSet, invalid)
+{
+    Listener<TestBackendSet> listener;
+    Handle s = 0;
+
+    listener.backend().onSet = [&] (auto, auto) {
+        FAIL() << "unexpected set call";
+    };
+    listener.backend().onUnset = [&] (auto, auto) {
+        FAIL() << "unexpected unset call";
+    };
+    listener.reset(s, static_cast<Condition>(123U));
+
+    ASSERT_EQ(0U, listener.size());
+}
+
 TEST(ListenerSet, initialAdd)
 {
     Listener<TestBackendSet> listener;
     Handle s = 0;
 
-    listener.set(s, Condition::Readable);
+    listener.backend().onSet = [&] (auto flags, auto addition) {
+        ASSERT_TRUE(addition);
+        ASSERT_EQ(Condition::Readable, flags);
+    };
+    listener.backend().onUnset = [&] (auto, auto) {
+        FAIL() << "unexpected unset call";
+    };
+    listener.reset(s, Condition::Readable);
 
     ASSERT_EQ(1U, listener.size());
-    ASSERT_EQ(1, listener.backend().m_callcount);
-    ASSERT_TRUE(listener.backend().m_added);
-    ASSERT_TRUE(listener.backend().m_flags == Condition::Readable);
 }
 
 TEST(ListenerSet, readThenWrite)
@@ -304,13 +338,28 @@
     Listener<TestBackendSet> listener;
     Handle s = 0;
 
-    listener.set(s, Condition::Readable);
-    listener.set(s, Condition::Writable);
+    // Add Readable.
+    listener.backend().onSet = [&] (auto flags, auto addition) {
+        ASSERT_TRUE(addition);
+        ASSERT_EQ(Condition::Readable, flags);
+    };
+    listener.backend().onUnset = [&] (auto, auto) {
+        FAIL() << "unexpected unset call";
+    };
+    listener.reset(s, Condition::Readable);
+
+    // Replace Readable with Writable.
+    listener.backend().onSet = [&] (auto flags, auto addition) {
+        ASSERT_FALSE(addition);
+        ASSERT_EQ(Condition::Writable, flags);
+    };
+    listener.backend().onUnset = [&] (auto flags, auto removal) {
+        ASSERT_FALSE(removal);
+        ASSERT_EQ(Condition::Readable, flags);
+    };
+    listener.reset(s, Condition::Writable);
 
     ASSERT_EQ(1U, listener.size());
-    ASSERT_EQ(2, listener.backend().m_callcount);
-    ASSERT_FALSE(listener.backend().m_added);
-    ASSERT_TRUE(static_cast<int>(listener.backend().m_flags) == 0x3);
 }
 
 TEST(ListenerSet, allOneShot)
@@ -318,12 +367,16 @@
     Listener<TestBackendSet> listener;
     Handle s = 0;
 
-    listener.set(s, Condition::Readable | Condition::Writable);
+    listener.backend().onSet = [&] (auto flags, auto addition) {
+        ASSERT_TRUE(addition);
+        ASSERT_EQ(Condition::All, flags);
+    };
+    listener.backend().onUnset = [&] (auto, auto) {
+        FAIL() << "unexpected unset call";
+    };
+    listener.reset(s, Condition::Readable | Condition::Writable);
 
     ASSERT_EQ(1U, listener.size());
-    ASSERT_EQ(1, listener.backend().m_callcount);
-    ASSERT_TRUE(listener.backend().m_added);
-    ASSERT_TRUE(static_cast<int>(listener.backend().m_flags) == 0x3);
 }
 
 TEST(ListenerSet, readTwice)
@@ -331,13 +384,86 @@
     Listener<TestBackendSet> listener;
     Handle s = 0;
 
-    listener.set(s, Condition::Readable);
-    listener.set(s, Condition::Readable);
+    listener.backend().onSet = [&] (auto flags, auto addition) {
+        ASSERT_TRUE(addition);
+        ASSERT_EQ(Condition::Readable, flags);
+    };
+    listener.backend().onUnset = [&] (auto, auto) {
+        FAIL() << "unexpected unset call";
+    };
+    listener.reset(s, Condition::Readable);
+    listener.backend().onSet = [&] (auto, auto) {
+        FAIL() << "double set call unexpected";
+    };
+    listener.reset(s, Condition::Readable);
+
+    ASSERT_EQ(1U, listener.size());
+}
+
+TEST(ListenerSet, writeTwice)
+{
+    Listener<TestBackendSet> listener;
+    Handle s = 0;
+
+    listener.backend().onSet = [&] (auto flags, auto addition) {
+        ASSERT_TRUE(addition);
+        ASSERT_EQ(Condition::Writable, flags);
+    };
+    listener.backend().onUnset = [&] (auto, auto) {
+        FAIL() << "unexpected unset call";
+    };
+    listener.reset(s, Condition::Writable);
+    listener.backend().onSet = [&] (auto, auto) {
+        FAIL() << "double set call unexpected";
+    };
+    listener.reset(s, Condition::Writable);
 
     ASSERT_EQ(1U, listener.size());
-    ASSERT_EQ(1, listener.backend().m_callcount);
-    ASSERT_TRUE(listener.backend().m_added);
-    ASSERT_TRUE(listener.backend().m_flags == Condition::Readable);
+}
+
+TEST(ListenerSet, allTwice)
+{
+    Listener<TestBackendSet> listener;
+    Handle s = 0;
+
+    listener.backend().onSet = [&] (auto flags, auto addition) {
+        ASSERT_TRUE(addition);
+        ASSERT_EQ(Condition::All, flags);
+    };
+    listener.backend().onUnset = [&] (auto, auto) {
+        FAIL() << "unexpected unset call";
+    };
+    listener.reset(s, Condition::All);
+    listener.backend().onSet = [&] (auto, auto) {
+        FAIL() << "double set call unexpected";
+    };
+    listener.reset(s, Condition::All);
+
+    ASSERT_EQ(1U, listener.size());
+}
+
+TEST(ListenerSet, bothThenReadable)
+{
+    Listener<TestBackendSet> listener;
+    Handle s = 0;
+
+    listener.backend().onSet = [&] (auto flags, auto addition) {
+        ASSERT_TRUE(addition);
+        ASSERT_EQ(Condition::All, flags);
+    };
+    listener.backend().onUnset = [&] (auto, auto) {
+        FAIL() << "unexpected unset call";
+    };
+    listener.reset(s, Condition::All);
+    listener.backend().onSet = [&] (auto flags, auto addition) {
+        ASSERT_TRUE(addition);
+        ASSERT_EQ(Condition::Readable, flags);
+    };
+    listener.backend().onUnset = [&] (auto flags, auto removal) {
+        ASSERT_FALSE(removal);
+        ASSERT_EQ(Condition::Writable, flags);
+    };
+    listener.reset(s, Condition::Readable);
 }
 
 TEST(ListenerSet, failure)
@@ -345,7 +471,7 @@
     Listener<TestBackendSetFail> listener;
     Handle s = 0;
 
-    ASSERT_ANY_THROW(listener.set(s, Condition::Readable));
+    ASSERT_ANY_THROW(listener.reset(s, Condition::Readable));
     ASSERT_EQ(0U, listener.size());
 }
 
@@ -402,7 +528,7 @@
     Listener<TestBackendUnset> listener;
     Handle s = 0;
 
-    listener.set(s, Condition::Readable);
+    listener.reset(s, Condition::Readable);
     listener.unset(s, Condition::Readable);
 
     ASSERT_EQ(0U, listener.size());
@@ -417,7 +543,7 @@
     Listener<TestBackendUnset> listener;
     Handle s = 0;
 
-    listener.set(s, Condition::Readable | Condition::Writable);
+    listener.reset(s, Condition::Readable | Condition::Writable);
     listener.unset(s, Condition::Readable);
 
     ASSERT_EQ(1U, listener.size());
@@ -432,7 +558,7 @@
     Listener<TestBackendUnset> listener;
     Handle s = 0;
 
-    listener.set(s, Condition::Readable | Condition::Writable);
+    listener.reset(s, Condition::Readable | Condition::Writable);
     listener.unset(s, Condition::Readable);
     listener.unset(s, Condition::Writable);
 
@@ -448,7 +574,7 @@
     Listener<TestBackendUnset> listener;
     Handle s = 0;
 
-    listener.set(s, Condition::Readable | Condition::Writable);
+    listener.reset(s, Condition::Readable | Condition::Writable);
     listener.remove(s);
 
     ASSERT_EQ(0U, listener.size());
@@ -463,7 +589,7 @@
     Listener<TestBackendUnsetFail> listener;
     Handle s = 0;
 
-    listener.set(s, Condition::Readable | Condition::Writable);
+    listener.reset(s, Condition::Readable | Condition::Writable);
 
     ASSERT_ANY_THROW(listener.remove(s));
 
@@ -508,7 +634,7 @@
 {
     m_tserver = std::thread([this] () {
         try {
-            m_listener.set(m_masterTcp.handle(), Condition::Readable);
+            m_listener.reset(m_masterTcp.handle(), Condition::Readable);
             m_listener.wait();
             m_masterTcp.accept();
             m_masterTcp.close();
@@ -528,7 +654,7 @@
 {
     m_tserver = std::thread([this] () {
         try {
-            m_listener.set(m_masterTcp.handle(), Condition::Readable);
+            m_listener.reset(m_masterTcp.handle(), Condition::Readable);
             m_listener.wait();
 
             TcpSocket sc = m_masterTcp.accept();