From: Remi Gacogne Date: Mon, 19 Dec 2022 10:57:31 +0000 (+0100) Subject: channel: Add unit tests X-Git-Tag: rec-5.0.0-alpha1~161^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cd93bea912fe3a5a7eaa99f314ab23a8ef667d79;p=thirdparty%2Fpdns.git channel: Add unit tests --- diff --git a/pdns/Makefile.am b/pdns/Makefile.am index f9e8c632cd..a8fccbe782 100644 --- a/pdns/Makefile.am +++ b/pdns/Makefile.am @@ -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 \ diff --git a/pdns/channel.cc b/pdns/channel.cc index ce2f0ef60c..ae62d23693 100644 --- a/pdns/channel.cc +++ b/pdns/channel.cc @@ -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; } diff --git a/pdns/channel.hh b/pdns/channel.hh index e221e6b267..d220040341 100644 --- a/pdns/channel.hh +++ b/pdns/channel.hh @@ -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. * diff --git a/pdns/dnsdistdist/Makefile.am b/pdns/dnsdistdist/Makefile.am index 44487953ff..3931c01ca8 100644 --- a/pdns/dnsdistdist/Makefile.am +++ b/pdns/dnsdistdist/Makefile.am @@ -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 index 0000000000..90f6b118d7 --- /dev/null +++ b/pdns/dnsdistdist/test-channel.cc @@ -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 index 0000000000..e97ddbe5ff --- /dev/null +++ b/pdns/test-channel.cc @@ -0,0 +1,144 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN + +#include + +#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(); + + BOOST_CHECK(receiver.getDescriptor() != -1); + BOOST_CHECK_EQUAL(receiver.isClosed(), false); + + auto got = receiver.receive(); + BOOST_CHECK(!got); + + auto obj = std::make_unique(); + 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(); + + { + 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(); + 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(); + 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(); + 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(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() +