]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/test-mplexer.cc
2 #define BOOST_TEST_DYN_LINK
3 #define BOOST_TEST_NO_MAIN
6 #include <boost/test/unit_test.hpp>
11 BOOST_AUTO_TEST_SUITE(mplexer
)
13 BOOST_AUTO_TEST_CASE(test_MPlexer
) {
14 auto mplexer
= std::unique_ptr
<FDMultiplexer
>(FDMultiplexer::getMultiplexerSilent());
15 BOOST_REQUIRE(mplexer
!= nullptr);
18 int ready
= mplexer
->run(&now
, 100);
19 BOOST_CHECK_EQUAL(ready
, 0);
21 std::vector
<int> readyFDs
;
22 mplexer
->getAvailableFDs(readyFDs
, 0);
23 BOOST_CHECK_EQUAL(readyFDs
.size(), 0);
25 auto timeouts
= mplexer
->getTimeouts(now
);
26 BOOST_CHECK_EQUAL(timeouts
.size(), 0);
29 int res
= pipe(pipes
);
30 BOOST_REQUIRE_EQUAL(res
, 0);
31 BOOST_REQUIRE_EQUAL(setNonBlocking(pipes
[0]), true);
32 BOOST_REQUIRE_EQUAL(setNonBlocking(pipes
[1]), true);
34 /* let's declare a TTD that expired 5s ago */
35 struct timeval ttd
= now
;
38 bool writeCBCalled
= false;
39 auto writeCB
= [](int fd
, FDMultiplexer::funcparam_t param
) {
40 auto calledPtr
= boost::any_cast
<bool*>(param
);
41 BOOST_REQUIRE(calledPtr
!= nullptr);
44 mplexer
->addWriteFD(pipes
[1],
48 /* we can't add it twice */
49 BOOST_CHECK_THROW(mplexer
->addWriteFD(pipes
[1],
53 FDMultiplexerException
);
56 mplexer
->getAvailableFDs(readyFDs
, 0);
57 BOOST_REQUIRE_EQUAL(readyFDs
.size(), 1);
58 BOOST_CHECK_EQUAL(readyFDs
.at(0), pipes
[1]);
60 ready
= mplexer
->run(&now
, 100);
61 BOOST_CHECK_EQUAL(ready
, 1);
62 BOOST_CHECK_EQUAL(writeCBCalled
, true);
64 /* no read timeouts */
65 timeouts
= mplexer
->getTimeouts(now
, false);
66 BOOST_CHECK_EQUAL(timeouts
.size(), 0);
67 /* but we should have a write one */
68 timeouts
= mplexer
->getTimeouts(now
, true);
69 BOOST_REQUIRE_EQUAL(timeouts
.size(), 1);
70 BOOST_CHECK_EQUAL(timeouts
.at(0).first
, pipes
[1]);
72 /* can't remove from the wrong type of FD */
73 BOOST_CHECK_THROW(mplexer
->removeReadFD(pipes
[1]), FDMultiplexerException
);
74 mplexer
->removeWriteFD(pipes
[1]);
75 /* can't remove a non-existing FD */
76 BOOST_CHECK_THROW(mplexer
->removeWriteFD(pipes
[0]), FDMultiplexerException
);
77 BOOST_CHECK_THROW(mplexer
->removeWriteFD(pipes
[1]), FDMultiplexerException
);
80 mplexer
->getAvailableFDs(readyFDs
, 0);
81 BOOST_REQUIRE_EQUAL(readyFDs
.size(), 0);
83 ready
= mplexer
->run(&now
, 100);
84 BOOST_CHECK_EQUAL(ready
, 0);
86 bool readCBCalled
= false;
87 auto readCB
= [](int fd
, FDMultiplexer::funcparam_t param
) {
88 auto calledPtr
= boost::any_cast
<bool*>(param
);
89 BOOST_REQUIRE(calledPtr
!= nullptr);
92 mplexer
->addReadFD(pipes
[0],
97 /* not ready for reading yet */
99 mplexer
->getAvailableFDs(readyFDs
, 0);
100 BOOST_REQUIRE_EQUAL(readyFDs
.size(), 0);
102 ready
= mplexer
->run(&now
, 100);
103 BOOST_CHECK_EQUAL(ready
, 0);
104 BOOST_CHECK_EQUAL(readCBCalled
, false);
106 /* let's make the pipe readable */
107 BOOST_REQUIRE_EQUAL(write(pipes
[1], "0", 1), 1);
110 mplexer
->getAvailableFDs(readyFDs
, 0);
111 BOOST_REQUIRE_EQUAL(readyFDs
.size(), 1);
112 BOOST_CHECK_EQUAL(readyFDs
.at(0), pipes
[0]);
114 ready
= mplexer
->run(&now
, 100);
115 BOOST_CHECK_EQUAL(ready
, 1);
116 BOOST_CHECK_EQUAL(readCBCalled
, true);
118 /* add back the write FD */
119 mplexer
->addWriteFD(pipes
[1],
124 /* both should be available */
126 mplexer
->getAvailableFDs(readyFDs
, 0);
127 if (readyFDs
.size() == 1) {
128 /* something is wrong, we need some debug infos */
129 cerr
<<"FDMultiPlexer implementation is "<<mplexer
->getName()<<endl
;
130 cerr
<<"Watching "<<mplexer
->getWatchedFDCount(false)<<" FDs for read and "<<mplexer
->getWatchedFDCount(true)<<" for write"<<endl
;
131 cerr
<<"pipes[0] is "<<pipes
[0]<<endl
;
132 cerr
<<"pipes[1] is "<<pipes
[1]<<endl
;
133 cerr
<<"The file descripttor returned as ready is "<<readyFDs
.at(0)<<endl
;
135 ssize_t res
= read(pipes
[0], &buffer
[0], sizeof(buffer
));
137 cerr
<<"Reading from pipes[0] returns "<<res
<<endl
;
139 cerr
<<"errno is "<<saved
<<endl
;
141 res
= write(pipes
[1], "0", 1);
143 cerr
<<"Writing to pipes[1] returns "<<res
<<endl
;
145 cerr
<<"errno is "<<saved
<<endl
;
148 BOOST_REQUIRE_EQUAL(readyFDs
.size(), 2);
150 readCBCalled
= false;
151 writeCBCalled
= false;
152 ready
= mplexer
->run(&now
, 100);
153 BOOST_CHECK_EQUAL(ready
, 2);
154 BOOST_CHECK_EQUAL(readCBCalled
, true);
155 BOOST_CHECK_EQUAL(writeCBCalled
, true);
157 /* both the read and write FD should be reported */
158 timeouts
= mplexer
->getTimeouts(now
, false);
159 BOOST_REQUIRE_EQUAL(timeouts
.size(), 1);
160 BOOST_CHECK_EQUAL(timeouts
.at(0).first
, pipes
[0]);
161 timeouts
= mplexer
->getTimeouts(now
, true);
162 BOOST_REQUIRE_EQUAL(timeouts
.size(), 1);
163 BOOST_CHECK_EQUAL(timeouts
.at(0).first
, pipes
[1]);
165 struct timeval past
= ttd
;
166 /* so five seconds before the actual TTD */
169 /* no read timeouts */
170 timeouts
= mplexer
->getTimeouts(past
, false);
171 BOOST_CHECK_EQUAL(timeouts
.size(), 0);
172 /* and we should not have a write one either */
173 timeouts
= mplexer
->getTimeouts(past
, true);
174 BOOST_CHECK_EQUAL(timeouts
.size(), 0);
176 /* update the timeouts to now, they should not be reported anymore */
177 mplexer
->setReadTTD(pipes
[0], now
, 0);
178 mplexer
->setWriteTTD(pipes
[1], now
, 0);
179 timeouts
= mplexer
->getTimeouts(now
, false);
180 BOOST_REQUIRE_EQUAL(timeouts
.size(), 0);
181 timeouts
= mplexer
->getTimeouts(now
, true);
182 BOOST_REQUIRE_EQUAL(timeouts
.size(), 0);
184 /* put it back into the past */
185 mplexer
->setReadTTD(pipes
[0], now
, -5);
186 mplexer
->setWriteTTD(pipes
[1], now
, -5);
187 timeouts
= mplexer
->getTimeouts(now
, false);
188 BOOST_REQUIRE_EQUAL(timeouts
.size(), 1);
189 BOOST_CHECK_EQUAL(timeouts
.at(0).first
, pipes
[0]);
190 timeouts
= mplexer
->getTimeouts(now
, true);
191 BOOST_REQUIRE_EQUAL(timeouts
.size(), 1);
192 BOOST_CHECK_EQUAL(timeouts
.at(0).first
, pipes
[1]);
194 mplexer
->removeReadFD(pipes
[0]);
195 mplexer
->removeWriteFD(pipes
[1]);
203 BOOST_AUTO_TEST_SUITE_END()