]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnsdistdist/test-dnsdistasync.cc
Merge pull request #11431 from jroessler-ox/docs-kskzskroll-update
[thirdparty/pdns.git] / pdns / dnsdistdist / test-dnsdistasync.cc
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22 #ifndef BOOST_TEST_DYN_LINK
23 #define BOOST_TEST_DYN_LINK
24 #endif
25
26 #define BOOST_TEST_NO_MAIN
27
28 #include <boost/test/unit_test.hpp>
29
30 #include "dnsdist-async.hh"
31
32 BOOST_AUTO_TEST_SUITE(test_dnsdistasync)
33
34 class DummyQuerySender : public TCPQuerySender
35 {
36 public:
37 bool active() const override
38 {
39 return true;
40 }
41
42 void handleResponse([[maybe_unused]] const struct timeval& now, [[maybe_unused]] TCPResponse&& response) override
43 {
44 }
45
46 void handleXFRResponse([[maybe_unused]] const struct timeval& now, [[maybe_unused]] TCPResponse&& response) override
47 {
48 }
49
50 void notifyIOError([[maybe_unused]] const struct timeval& now, [[maybe_unused]] TCPResponse&& response) override
51 {
52 errorRaised = true;
53 }
54
55 std::atomic<bool> errorRaised{false};
56 };
57
58 struct DummyCrossProtocolQuery : public CrossProtocolQuery
59 {
60 DummyCrossProtocolQuery() :
61 CrossProtocolQuery()
62 {
63 d_sender = std::make_shared<DummyQuerySender>();
64 }
65
66 std::shared_ptr<TCPQuerySender> getTCPQuerySender() override
67 {
68 return d_sender;
69 }
70
71 std::shared_ptr<DummyQuerySender> d_sender;
72 };
73
74 BOOST_AUTO_TEST_CASE(test_Basic)
75 {
76 auto holder = std::make_unique<dnsdist::AsynchronousHolder>();
77 BOOST_CHECK(holder->empty());
78
79 {
80 auto query = holder->get(0, 0);
81 BOOST_CHECK(query == nullptr);
82 }
83
84 {
85 uint16_t asyncID = 1;
86 uint16_t queryID = 42;
87 struct timeval ttd;
88 gettimeofday(&ttd, nullptr);
89 // timeout in 100 ms
90 const timeval add{0, 100000};
91 ttd = ttd + add;
92
93 holder->push(asyncID, queryID, ttd, std::make_unique<DummyCrossProtocolQuery>());
94 BOOST_CHECK(!holder->empty());
95
96 auto query = holder->get(0, 0);
97 BOOST_CHECK(query == nullptr);
98
99 query = holder->get(asyncID, queryID);
100 BOOST_CHECK(holder->empty());
101
102 query = holder->get(asyncID, queryID);
103 BOOST_CHECK(query == nullptr);
104
105 // sleep for 200 ms, to be sure the main thread has
106 // been awakened
107 usleep(200000);
108 }
109
110 holder->stop();
111 }
112
113 BOOST_AUTO_TEST_CASE(test_TimeoutFailClose)
114 {
115 auto holder = std::make_unique<dnsdist::AsynchronousHolder>(false);
116 uint16_t asyncID = 1;
117 uint16_t queryID = 42;
118 struct timeval ttd
119 {
120 };
121
122 std::shared_ptr<DummyQuerySender> sender{nullptr};
123 {
124 // timeout in 10 ms
125 const timeval add{0, 10000};
126 auto query = std::make_unique<DummyCrossProtocolQuery>();
127 sender = query->d_sender;
128 BOOST_REQUIRE(sender != nullptr);
129 gettimeofday(&ttd, nullptr);
130 ttd = ttd + add;
131 holder->push(asyncID, queryID, ttd, std::move(query));
132 BOOST_CHECK(!holder->empty());
133 }
134
135 // the event should be triggered after 10 ms, but we have seen
136 // many spurious failures on our CI, likely because the box is
137 // overloaded, so sleep for up to 100 ms to be sure
138 for (size_t counter = 0; !holder->empty() && counter < 10; counter++) {
139 usleep(10000);
140 }
141
142 BOOST_CHECK(holder->empty());
143 BOOST_CHECK(sender->errorRaised.load());
144
145 holder->stop();
146 }
147
148 BOOST_AUTO_TEST_CASE(test_AddingExpiredEvent)
149 {
150 auto holder = std::make_unique<dnsdist::AsynchronousHolder>(false);
151 uint16_t asyncID = 1;
152 uint16_t queryID = 42;
153 struct timeval ttd;
154 gettimeofday(&ttd, nullptr);
155 // timeout was 10 ms ago, for some reason (long processing time, CPU starvation...)
156 const timeval sub{0, 10000};
157 ttd = ttd - sub;
158
159 std::shared_ptr<DummyQuerySender> sender{nullptr};
160 {
161 auto query = std::make_unique<DummyCrossProtocolQuery>();
162 sender = query->d_sender;
163 BOOST_REQUIRE(sender != nullptr);
164 holder->push(asyncID, queryID, ttd, std::move(query));
165 }
166
167 // the expired event should be triggered almost immediately,
168 // but we have seen many spurious failures on our CI,
169 // likely because the box is overloaded, so sleep for up to
170 // 100 ms to be sure
171 for (size_t counter = 0; !holder->empty() && counter < 10; counter++) {
172 usleep(10000);
173 }
174
175 BOOST_CHECK(holder->empty());
176 BOOST_CHECK(sender->errorRaised.load());
177
178 holder->stop();
179 }
180
181 BOOST_AUTO_TEST_SUITE_END();