]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
mplexer: Add some unit tests for our multiplexers
authorRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 22 Mar 2019 17:25:44 +0000 (18:25 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 4 Apr 2019 09:54:04 +0000 (11:54 +0200)
pdns/Makefile.am
pdns/dnsdistdist/Makefile.am
pdns/dnsdistdist/test-mplexer.cc [new symlink]
pdns/recursordist/Makefile.am
pdns/recursordist/test-mplexer.cc [new symlink]
pdns/test-mplexer.cc [new file with mode: 0644]

index 080f0e552f63c59b600ac42fd51c052ed2894429..6749e4cf6e15e6d3aa4608ff818209b56a531ea4 100644 (file)
@@ -1291,6 +1291,7 @@ testrunner_SOURCES = \
        nameserver.cc \
        nsecrecords.cc \
        opensslsigners.cc opensslsigners.hh \
+       pollmplexer.cc \
        qtype.cc \
        rcpgenerator.cc \
        responsestats.cc \
@@ -1316,6 +1317,7 @@ testrunner_SOURCES = \
        test-lock_hh.cc \
        test-lua_auth4_cc.cc \
        test-misc_hh.cc \
+       test-mplexer.cc \
        test-nameserver_cc.cc \
        test-packetcache_cc.cc \
        test-packetcache_hh.cc \
@@ -1360,6 +1362,25 @@ testrunner_SOURCES += decafsigners.cc
 testrunner_LDADD += $(LIBDECAF_LIBS)
 endif
 
+if HAVE_FREEBSD
+ixfrdist_SOURCES += kqueuemplexer.cc
+testrunner_SOURCES += kqueuemplexer.cc
+endif
+
+if HAVE_LINUX
+ixfrdist_SOURCES += epollmplexer.cc
+testrunner_SOURCES += epollmplexer.cc
+endif
+
+if HAVE_SOLARIS
+ixfrdist_SOURCES += \
+       devpollmplexer.cc \
+       portsmplexer.cc
+testrunner_SOURCES += \
+       devpollmplexer.cc \
+       portsmplexer.cc
+endif
+
 pdns_control_SOURCES = \
        arguments.cc \
        dynloader.cc \
index 8c9e90b5cd55a5cfc1031664bd0f324b3f205584..b827fe03c0cb05fc626d95e2d4355eb84bced9ac 100644 (file)
@@ -213,20 +213,6 @@ dnsdist.$(OBJEXT): dnsmessage.pb.cc dnstap.pb.cc
 endif
 endif
 
-if HAVE_FREEBSD
-dnsdist_SOURCES += kqueuemplexer.cc
-endif
-
-if HAVE_LINUX
-dnsdist_SOURCES += epollmplexer.cc
-endif
-
-if HAVE_SOLARIS
-dnsdist_SOURCES += \
-        devpollmplexer.cc \
-        portsmplexer.cc
-endif
-
 testrunner_SOURCES = \
        base64.hh \
        dns.hh \
@@ -240,6 +226,7 @@ testrunner_SOURCES = \
        test-dnsdistrules_cc.cc \
        test-dnsparser_cc.cc \
        test-iputils_hh.cc \
+       test-mplexer.cc \
        cachecleaner.hh \
        dnsdist.hh \
        dnsdist-cache.cc dnsdist-cache.hh \
@@ -259,6 +246,7 @@ testrunner_SOURCES = \
        misc.cc misc.hh \
        namespaces.hh \
        pdnsexception.hh \
+       pollmplexer.cc \
        qtype.cc qtype.hh \
        sholder.hh \
        sodcrypto.cc \
@@ -268,6 +256,25 @@ testrunner_SOURCES = \
        testrunner.cc \
        xpf.cc xpf.hh
 
+if HAVE_FREEBSD
+dnsdist_SOURCES += kqueuemplexer.cc
+testrunner_SOURCES += kqueuemplexer.cc
+endif
+
+if HAVE_LINUX
+dnsdist_SOURCES += epollmplexer.cc
+testrunner_SOURCES += epollmplexer.cc
+endif
+
+if HAVE_SOLARIS
+dnsdist_SOURCES += \
+        devpollmplexer.cc \
+        portsmplexer.cc
+testrunner_SOURCES += \
+        devpollmplexer.cc \
+        portsmplexer.cc
+endif
+
 testrunner_LDFLAGS = \
        $(AM_LDFLAGS) \
        $(PROGRAM_LDFLAGS) \
diff --git a/pdns/dnsdistdist/test-mplexer.cc b/pdns/dnsdistdist/test-mplexer.cc
new file mode 120000 (symlink)
index 0000000..f406267
--- /dev/null
@@ -0,0 +1 @@
+../test-mplexer.cc
\ No newline at end of file
index 92c8ae5a27ed0b0eb3ae11fd64c662c64771f1e7..64adc379ad0a42ddbdde6e9d10fb09af8288bffa 100644 (file)
@@ -235,6 +235,7 @@ testrunner_SOURCES = \
        nsecrecords.cc \
        pdnsexception.hh \
        opensslsigners.cc opensslsigners.hh \
+       pollmplexer.cc \
        protobuf.cc protobuf.hh \
        qtype.cc qtype.hh \
        rcpgenerator.cc \
@@ -263,6 +264,7 @@ testrunner_SOURCES = \
        test-ixfr_cc.cc \
        test-misc_hh.cc \
        test-mtasker.cc \
+       test-mplexer.cc \
        test-negcache_cc.cc \
        test-packetcache_hh.cc \
        test-rcpgenerator_cc.cc \
@@ -335,16 +337,21 @@ endif
 
 if HAVE_FREEBSD
 pdns_recursor_SOURCES += kqueuemplexer.cc
+testrunner_SOURCES += kqueuemplexer.cc
 endif
 
 if HAVE_LINUX
 pdns_recursor_SOURCES += epollmplexer.cc
+testrunner_SOURCES += epollmplexer.cc
 endif
 
 if HAVE_SOLARIS
 pdns_recursor_SOURCES += \
        devpollmplexer.cc \
        portsmplexer.cc
+testrunner_SOURCES += \
+       devpollmplexer.cc \
+       portsmplexer.cc
 endif
 
 if HAVE_PROTOBUF
diff --git a/pdns/recursordist/test-mplexer.cc b/pdns/recursordist/test-mplexer.cc
new file mode 120000 (symlink)
index 0000000..f406267
--- /dev/null
@@ -0,0 +1 @@
+../test-mplexer.cc
\ No newline at end of file
diff --git a/pdns/test-mplexer.cc b/pdns/test-mplexer.cc
new file mode 100644 (file)
index 0000000..8a7412f
--- /dev/null
@@ -0,0 +1,182 @@
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_NO_MAIN
+
+#include <thread>
+#include <boost/test/unit_test.hpp>
+
+#include "mplexer.hh"
+#include "misc.hh"
+
+BOOST_AUTO_TEST_SUITE(mplexer)
+
+BOOST_AUTO_TEST_CASE(test_MPlexer) {
+  auto mplexer = std::unique_ptr<FDMultiplexer>(FDMultiplexer::getMultiplexerSilent());
+  BOOST_REQUIRE(mplexer != nullptr);
+
+  struct timeval now;
+  int ready = mplexer->run(&now, 100);
+  BOOST_CHECK_EQUAL(ready, 0);
+
+  std::vector<int> readyFDs;
+  mplexer->getAvailableFDs(readyFDs, 0);
+  BOOST_CHECK_EQUAL(readyFDs.size(), 0);
+
+  auto timeouts = mplexer->getTimeouts(now);
+  BOOST_CHECK_EQUAL(timeouts.size(), 0);
+
+  int pipes[2];
+  int res = pipe(pipes);
+  BOOST_REQUIRE_EQUAL(res, 0);
+  BOOST_REQUIRE_EQUAL(setNonBlocking(pipes[0]), true);
+  BOOST_REQUIRE_EQUAL(setNonBlocking(pipes[1]), true);
+
+  /* let's declare a TTD that expired 5s ago */
+  struct timeval ttd = now;
+  ttd.tv_sec -= 5;
+
+  bool writeCBCalled = false;
+  auto writeCB = [](int fd, FDMultiplexer::funcparam_t param) {
+                        auto calledPtr = boost::any_cast<bool*>(param);
+                        BOOST_REQUIRE(calledPtr != nullptr);
+                        *calledPtr = true;
+                 };
+  mplexer->addWriteFD(pipes[1],
+                      writeCB,
+                      &writeCBCalled,
+                      &ttd);
+  /* we can't add it twice */
+  BOOST_CHECK_THROW(mplexer->addWriteFD(pipes[1],
+                                        writeCB,
+                                        &writeCBCalled,
+                                        &ttd),
+                    FDMultiplexerException);
+
+  readyFDs.clear();
+  mplexer->getAvailableFDs(readyFDs, 0);
+  BOOST_REQUIRE_EQUAL(readyFDs.size(), 1);
+  BOOST_CHECK_EQUAL(readyFDs.at(0), pipes[1]);
+
+  ready = mplexer->run(&now, 100);
+  BOOST_CHECK_EQUAL(ready, 1);
+  BOOST_CHECK_EQUAL(writeCBCalled, true);
+
+  /* no read timeouts */
+  timeouts = mplexer->getTimeouts(now, false);
+  BOOST_CHECK_EQUAL(timeouts.size(), 0);
+  /* but we should have a write one */
+  timeouts = mplexer->getTimeouts(now, true);
+  BOOST_REQUIRE_EQUAL(timeouts.size(), 1);
+  BOOST_CHECK_EQUAL(timeouts.at(0).first, pipes[1]);
+
+  /* can't remove from the wrong type of FD */
+  BOOST_CHECK_THROW(mplexer->removeReadFD(pipes[1]), FDMultiplexerException);
+  mplexer->removeWriteFD(pipes[1]);
+  /* can't remove a non-existing FD */
+  BOOST_CHECK_THROW(mplexer->removeWriteFD(pipes[0]), FDMultiplexerException);
+  BOOST_CHECK_THROW(mplexer->removeWriteFD(pipes[1]), FDMultiplexerException);
+
+  readyFDs.clear();
+  mplexer->getAvailableFDs(readyFDs, 0);
+  BOOST_REQUIRE_EQUAL(readyFDs.size(), 0);
+
+  ready = mplexer->run(&now, 100);
+  BOOST_CHECK_EQUAL(ready, 0);
+
+  bool readCBCalled = false;
+  auto readCB = [](int fd, FDMultiplexer::funcparam_t param) {
+                        auto calledPtr = boost::any_cast<bool*>(param);
+                        BOOST_REQUIRE(calledPtr != nullptr);
+                        *calledPtr = true;
+                };
+  mplexer->addReadFD(pipes[0],
+                      readCB,
+                      &readCBCalled,
+                      &ttd);
+
+  /* not ready for reading yet */
+  readyFDs.clear();
+  mplexer->getAvailableFDs(readyFDs, 0);
+  BOOST_REQUIRE_EQUAL(readyFDs.size(), 0);
+
+  ready = mplexer->run(&now, 100);
+  BOOST_CHECK_EQUAL(ready, 0);
+  BOOST_CHECK_EQUAL(readCBCalled, false);
+
+  /* let's make the pipe readable */
+  BOOST_REQUIRE_EQUAL(write(pipes[1], "0", 1), 1);
+
+  readyFDs.clear();
+  mplexer->getAvailableFDs(readyFDs, 0);
+  BOOST_REQUIRE_EQUAL(readyFDs.size(), 1);
+  BOOST_CHECK_EQUAL(readyFDs.at(0), pipes[0]);
+
+  ready = mplexer->run(&now, 100);
+  BOOST_CHECK_EQUAL(ready, 1);
+  BOOST_CHECK_EQUAL(readCBCalled, true);
+
+  /* add back the write FD */
+  mplexer->addWriteFD(pipes[1],
+                      writeCB,
+                      &writeCBCalled,
+                      &ttd);
+
+  /* both should be available */
+  readyFDs.clear();
+  mplexer->getAvailableFDs(readyFDs, 0);
+  BOOST_REQUIRE_EQUAL(readyFDs.size(), 2);
+
+  readCBCalled = false;
+  writeCBCalled = false;
+  ready = mplexer->run(&now, 100);
+  BOOST_CHECK_EQUAL(ready, 2);
+  BOOST_CHECK_EQUAL(readCBCalled, true);
+  BOOST_CHECK_EQUAL(writeCBCalled, true);
+
+  /* both the read and write FD should be reported */
+  timeouts = mplexer->getTimeouts(now, false);
+  BOOST_REQUIRE_EQUAL(timeouts.size(), 1);
+  BOOST_CHECK_EQUAL(timeouts.at(0).first, pipes[0]);
+  timeouts = mplexer->getTimeouts(now, true);
+  BOOST_REQUIRE_EQUAL(timeouts.size(), 1);
+  BOOST_CHECK_EQUAL(timeouts.at(0).first, pipes[1]);
+
+  struct timeval past = ttd;
+  /* so five seconds before the actual TTD */
+  past.tv_sec -= 5;
+
+  /* no read timeouts */
+  timeouts = mplexer->getTimeouts(past, false);
+  BOOST_CHECK_EQUAL(timeouts.size(), 0);
+  /* and we should not have a write one either */
+  timeouts = mplexer->getTimeouts(past, true);
+  BOOST_CHECK_EQUAL(timeouts.size(), 0);
+
+  /* update the timeouts to now, they should not be reported anymore */
+  mplexer->setReadTTD(pipes[0], now, 0);
+  mplexer->setWriteTTD(pipes[1], now, 0);
+  timeouts = mplexer->getTimeouts(now, false);
+  BOOST_REQUIRE_EQUAL(timeouts.size(), 0);
+  timeouts = mplexer->getTimeouts(now, true);
+  BOOST_REQUIRE_EQUAL(timeouts.size(), 0);
+
+  /* put it back into the past */
+  mplexer->setReadTTD(pipes[0], now, -5);
+  mplexer->setWriteTTD(pipes[1], now, -5);
+  timeouts = mplexer->getTimeouts(now, false);
+  BOOST_REQUIRE_EQUAL(timeouts.size(), 1);
+  BOOST_CHECK_EQUAL(timeouts.at(0).first, pipes[0]);
+  timeouts = mplexer->getTimeouts(now, true);
+  BOOST_REQUIRE_EQUAL(timeouts.size(), 1);
+  BOOST_CHECK_EQUAL(timeouts.at(0).first, pipes[1]);
+
+  mplexer->removeReadFD(pipes[0]);
+  mplexer->removeWriteFD(pipes[1]);
+
+  /* clean up */
+  close(pipes[0]);
+  close(pipes[1]);
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()