]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
channel: Add unit tests
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 19 Dec 2022 10:57:31 +0000 (11:57 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 13 Jun 2023 07:59:44 +0000 (09:59 +0200)
pdns/Makefile.am
pdns/channel.cc
pdns/channel.hh
pdns/dnsdistdist/Makefile.am
pdns/dnsdistdist/test-channel.cc [new symlink]
pdns/test-channel.cc [new file with mode: 0644]

index f9e8c632cd24c14fff31d522578da1219447eba4..a8fccbe782fa65d06719b83c5fc6a98cb5e8fdac 100644 (file)
@@ -1337,6 +1337,7 @@ testrunner_SOURCES = \
        base64.cc \
        bindlexer.l \
        bindparser.yy \
+       channel.cc channel.hh \
        credentials.cc credentials.hh \
        dbdnsseckeeper.cc \
        dns.cc \
@@ -1384,6 +1385,7 @@ testrunner_SOURCES = \
        test-base32_cc.cc \
        test-base64_cc.cc \
        test-bindparser_cc.cc \
+       test-channel.cc \
        test-common.hh \
        test-communicator_hh.cc \
        test-credentials_cc.cc \
index ce2f0ef60cca53e54b69e0096efa89533e3265f2..ae62d23693b1b6ea0887054dfc79b1a496013421 100644 (file)
@@ -60,13 +60,14 @@ namespace channel
   {
   }
 
-  void Waiter::clear() const
+  void Waiter::clear()
   {
     ssize_t got;
     do {
       char data;
       got = read(d_fd.getHandle(), &data, sizeof(data));
       if (got == 0) {
+        d_closed = true;
         if (!d_throwOnEOF) {
           return;
         }
index e221e6b2672bf333f96da1c48560d4ae20730fa7..d220040341680169dfa885f3f8dbc0bb78ca40c7 100644 (file)
@@ -187,7 +187,7 @@ namespace channel
     /**
      * \brief Clear all notifications queued on that channel, if any.
      */
-    void clear() const;
+    void clear();
     /**
      * \brief Get a descriptor that can be used with an I/O multiplexer to wait for a notification to arrive.
      *
index 44487953ffe07e254a26f4e1305baab6f052ab2f..3931c01ca8f5356f80df6a837a6f442612821c79 100644 (file)
@@ -306,6 +306,7 @@ testrunner_SOURCES = \
        statnode.cc statnode.hh \
        svc-records.cc svc-records.hh \
        test-base64_cc.cc \
+       test-channel.cc \
        test-connectionmanagement_hh.cc \
        test-credentials_cc.cc \
        test-delaypipe_hh.cc \
diff --git a/pdns/dnsdistdist/test-channel.cc b/pdns/dnsdistdist/test-channel.cc
new file mode 120000 (symlink)
index 0000000..90f6b11
--- /dev/null
@@ -0,0 +1 @@
+../test-channel.cc
\ No newline at end of file
diff --git a/pdns/test-channel.cc b/pdns/test-channel.cc
new file mode 100644 (file)
index 0000000..e97ddbe
--- /dev/null
@@ -0,0 +1,144 @@
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_NO_MAIN
+
+#include <boost/test/unit_test.hpp>
+
+#include "channel.hh"
+
+struct MyObject
+{
+  uint64_t a{0};
+};
+
+BOOST_AUTO_TEST_SUITE(test_channel)
+
+BOOST_AUTO_TEST_CASE(test_object_queue) {
+  auto [sender, receiver] = pdns::channel::createObjectQueue<MyObject>();
+
+  BOOST_CHECK(receiver.getDescriptor() != -1);
+  BOOST_CHECK_EQUAL(receiver.isClosed(), false);
+
+  auto got = receiver.receive();
+  BOOST_CHECK(!got);
+
+  auto obj = std::make_unique<MyObject>();
+  obj->a = 42U;
+  BOOST_CHECK_EQUAL(sender.send(std::move(obj)), true);
+  BOOST_CHECK(!obj);
+  got = receiver.receive();
+  BOOST_CHECK(got != std::nullopt && *got);
+  BOOST_CHECK_EQUAL((*got)->a, 42U);
+}
+
+BOOST_AUTO_TEST_CASE(test_object_queue_full) {
+  auto [sender, receiver] = pdns::channel::createObjectQueue<MyObject>();
+
+  {
+    auto got = receiver.receive();
+    BOOST_CHECK(!got);
+  }
+
+  /* add objects to the queue until it becomes full */
+  bool blocked = false;
+  size_t queued = 0;
+  while (!blocked) {
+    auto obj = std::make_unique<MyObject>();
+    obj->a = 42U;
+    blocked = sender.send(std::move(obj)) == false;
+    if (blocked) {
+      BOOST_CHECK(obj);
+    }
+    else {
+      BOOST_CHECK(!obj);
+      ++queued;
+    }
+  }
+
+  BOOST_CHECK_GT(queued, 1U);
+
+  /* clear the queue */
+  blocked = false;
+  size_t received = 0;
+  while (!blocked) {
+    auto got = receiver.receive();
+    if (got) {
+      ++received;
+    }
+    else {
+      blocked = true;
+    }
+  }
+
+  BOOST_CHECK_EQUAL(queued, received);
+
+  /* we should be able to write again */
+  auto obj = std::make_unique<MyObject>();
+  obj->a = 42U;
+  BOOST_CHECK(sender.send(std::move(obj)));
+}
+
+BOOST_AUTO_TEST_CASE(test_object_queue_throw_on_eof) {
+  auto [sender, receiver] = pdns::channel::createObjectQueue<MyObject>();
+  sender.close();
+  BOOST_CHECK_THROW(receiver.receive(), std::runtime_error);
+  BOOST_CHECK_EQUAL(receiver.isClosed(), true);
+}
+
+BOOST_AUTO_TEST_CASE(test_object_queue_do_not_throw_on_eof) {
+  auto [sender, receiver] = pdns::channel::createObjectQueue<MyObject>(true, true, 0U, false);
+  sender.close();
+  auto got = receiver.receive();
+  BOOST_CHECK(got == std::nullopt);
+  BOOST_CHECK_EQUAL(receiver.isClosed(), true);
+}
+
+BOOST_AUTO_TEST_CASE(test_notification_queue_full) {
+  auto [notifier, waiter] = pdns::channel::createNotificationQueue();
+
+  BOOST_CHECK(waiter.getDescriptor() != -1);
+  BOOST_CHECK_EQUAL(waiter.isClosed(), false);
+  waiter.clear();
+
+  /* add notifications until the queue becomes full */
+  bool blocked = false;
+  while (!blocked)
+  {
+    blocked = notifier.notify();
+  }
+
+  /* clear the queue */
+  waiter.clear();
+
+  /* we should be able to write again */
+  BOOST_CHECK(notifier.notify());
+}
+
+BOOST_AUTO_TEST_CASE(test_notification_queue_throw_on_eof) {
+  auto [notifier, waiter] = pdns::channel::createNotificationQueue();
+
+  BOOST_CHECK(waiter.getDescriptor() != -1);
+  BOOST_CHECK_EQUAL(waiter.isClosed(), false);
+
+  BOOST_CHECK_EQUAL(notifier.notify(), true);
+  waiter.clear();
+
+  notifier = pdns::channel::Notifier();
+  BOOST_CHECK_THROW(waiter.clear(), std::runtime_error);
+}
+
+BOOST_AUTO_TEST_CASE(test_notification_queue_do_not_throw_on_eof) {
+  auto [notifier, waiter] = pdns::channel::createNotificationQueue(true, 0, false);
+
+  BOOST_CHECK(waiter.getDescriptor() != -1);
+  BOOST_CHECK_EQUAL(waiter.isClosed(), false);
+
+  BOOST_CHECK_EQUAL(notifier.notify(), true);
+  waiter.clear();
+
+  notifier = pdns::channel::Notifier();
+  waiter.clear();
+  BOOST_CHECK_EQUAL(waiter.isClosed(), true);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+