]> git.ipfire.org Git - thirdparty/pdns.git/blob - regression-tests.dnsdist/test_Routing.py
dnsdist: Use only one TCP worker for the per-thread Lua regression test
[thirdparty/pdns.git] / regression-tests.dnsdist / test_Routing.py
1 #!/usr/bin/env python
2 import base64
3 import threading
4 import time
5 import dns
6 from dnsdisttests import DNSDistTest
7
8 class TestRoutingPoolRouting(DNSDistTest):
9
10 _config_template = """
11 newServer{address="127.0.0.1:%s", pool="real"}
12 addAction(makeRule("poolaction.routing.tests.powerdns.com"), PoolAction("real"))
13 """
14
15 def testPolicyPoolAction(self):
16 """
17 Routing: Set pool by qname via PoolAction
18
19 Send an A query to "poolaction.routing.tests.powerdns.com.",
20 check that dnsdist routes the query to the "real" pool.
21 """
22 name = 'poolaction.routing.tests.powerdns.com.'
23 query = dns.message.make_query(name, 'A', 'IN')
24 response = dns.message.make_response(query)
25 rrset = dns.rrset.from_text(name,
26 60,
27 dns.rdataclass.IN,
28 dns.rdatatype.A,
29 '192.0.2.1')
30 response.answer.append(rrset)
31
32 for method in ("sendUDPQuery", "sendTCPQuery"):
33 sender = getattr(self, method)
34 (receivedQuery, receivedResponse) = sender(query, response)
35 receivedQuery.id = query.id
36 self.assertEquals(query, receivedQuery)
37 self.assertEquals(response, receivedResponse)
38
39 def testDefaultPool(self):
40 """
41 Routing: Set pool by qname canary
42
43 Send an A query to "notpool.routing.tests.powerdns.com.",
44 check that dnsdist sends no response (no servers
45 in the default pool).
46 """
47 name = 'notpool.routing.tests.powerdns.com.'
48 query = dns.message.make_query(name, 'A', 'IN')
49
50 for method in ("sendUDPQuery", "sendTCPQuery"):
51 sender = getattr(self, method)
52 (_, receivedResponse) = sender(query, response=None, useQueue=False)
53 self.assertEquals(receivedResponse, None)
54
55 class TestRoutingQPSPoolRouting(DNSDistTest):
56 _config_template = """
57 newServer{address="127.0.0.1:%s", pool="regular"}
58 addAction(makeRule("qpspoolaction.routing.tests.powerdns.com"), QPSPoolAction(10, "regular"))
59 """
60
61 def testQPSPoolAction(self):
62 """
63 Routing: Set pool by QPS via action
64
65 Send queries to "qpspoolaction.routing.tests.powerdns.com."
66 check that dnsdist does not route the query to the "regular" pool
67 when the max QPS has been reached.
68 """
69 maxQPS = 10
70 name = 'qpspoolaction.routing.tests.powerdns.com.'
71 query = dns.message.make_query(name, 'A', 'IN')
72 response = dns.message.make_response(query)
73 rrset = dns.rrset.from_text(name,
74 60,
75 dns.rdataclass.IN,
76 dns.rdatatype.A,
77 '192.0.2.1')
78 response.answer.append(rrset)
79
80 for _ in range(maxQPS):
81 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
82 receivedQuery.id = query.id
83 self.assertEquals(query, receivedQuery)
84 self.assertEquals(response, receivedResponse)
85
86 # we should now be sent to the "abuse" pool which is empty,
87 # so the queries should be dropped
88 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
89 self.assertEquals(receivedResponse, None)
90
91 time.sleep(1)
92
93 # again, over TCP this time
94 for _ in range(maxQPS):
95 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
96 receivedQuery.id = query.id
97 self.assertEquals(query, receivedQuery)
98 self.assertEquals(response, receivedResponse)
99
100
101 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
102 self.assertEquals(receivedResponse, None)
103
104
105 class TestRoutingRoundRobinLB(DNSDistTest):
106
107 _testServer2Port = 5351
108 _config_params = ['_testServerPort', '_testServer2Port']
109 _config_template = """
110 setServerPolicy(roundrobin)
111 s1 = newServer{address="127.0.0.1:%s"}
112 s1:setUp()
113 s2 = newServer{address="127.0.0.1:%s"}
114 s2:setUp()
115 """
116
117 @classmethod
118 def startResponders(cls):
119 print("Launching responders..")
120 cls._UDPResponder = threading.Thread(name='UDP Responder', target=cls.UDPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
121 cls._UDPResponder.setDaemon(True)
122 cls._UDPResponder.start()
123 cls._UDPResponder2 = threading.Thread(name='UDP Responder 2', target=cls.UDPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
124 cls._UDPResponder2.setDaemon(True)
125 cls._UDPResponder2.start()
126
127 cls._TCPResponder = threading.Thread(name='TCP Responder', target=cls.TCPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
128 cls._TCPResponder.setDaemon(True)
129 cls._TCPResponder.start()
130
131 cls._TCPResponder2 = threading.Thread(name='TCP Responder 2', target=cls.TCPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
132 cls._TCPResponder2.setDaemon(True)
133 cls._TCPResponder2.start()
134
135 def testRR(self):
136 """
137 Routing: Round Robin
138
139 Send 10 A queries to "rr.routing.tests.powerdns.com.",
140 check that dnsdist routes half of it to each backend.
141 """
142 numberOfQueries = 10
143 name = 'rr.routing.tests.powerdns.com.'
144 query = dns.message.make_query(name, 'A', 'IN')
145 response = dns.message.make_response(query)
146 rrset = dns.rrset.from_text(name,
147 60,
148 dns.rdataclass.IN,
149 dns.rdatatype.A,
150 '192.0.2.1')
151 response.answer.append(rrset)
152
153 # the round robin counter is shared for UDP and TCP,
154 # so we need to do UDP then TCP to have a clean count
155 for _ in range(numberOfQueries):
156 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
157 receivedQuery.id = query.id
158 self.assertEquals(query, receivedQuery)
159 self.assertEquals(response, receivedResponse)
160
161 for _ in range(numberOfQueries):
162 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
163 receivedQuery.id = query.id
164 self.assertEquals(query, receivedQuery)
165 self.assertEquals(response, receivedResponse)
166
167 for key in self._responsesCounter:
168 value = self._responsesCounter[key]
169 self.assertEquals(value, numberOfQueries / 2)
170
171 class TestRoutingRoundRobinLBOneDown(DNSDistTest):
172
173 _testServer2Port = 5351
174 _config_params = ['_testServerPort', '_testServer2Port']
175 _config_template = """
176 setServerPolicy(roundrobin)
177 s1 = newServer{address="127.0.0.1:%s"}
178 s1:setUp()
179 s2 = newServer{address="127.0.0.1:%s"}
180 s2:setDown()
181 """
182
183 def testRRWithOneDown(self):
184 """
185 Routing: Round Robin with one server down
186
187 Send 100 A queries to "rr.routing.tests.powerdns.com.",
188 check that dnsdist routes all of it to the only backend up.
189 """
190 numberOfQueries = 10
191 name = 'rr.routing.tests.powerdns.com.'
192 query = dns.message.make_query(name, 'A', 'IN')
193 response = dns.message.make_response(query)
194 rrset = dns.rrset.from_text(name,
195 60,
196 dns.rdataclass.IN,
197 dns.rdatatype.A,
198 '192.0.2.1')
199 response.answer.append(rrset)
200
201 # the round robin counter is shared for UDP and TCP,
202 # so we need to do UDP then TCP to have a clean count
203 for _ in range(numberOfQueries):
204 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
205 receivedQuery.id = query.id
206 self.assertEquals(query, receivedQuery)
207 self.assertEquals(response, receivedResponse)
208
209 for _ in range(numberOfQueries):
210 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
211 receivedQuery.id = query.id
212 self.assertEquals(query, receivedQuery)
213 self.assertEquals(response, receivedResponse)
214
215 total = 0
216 for key in self._responsesCounter:
217 value = self._responsesCounter[key]
218 self.assertTrue(value == numberOfQueries or value == 0)
219 total += value
220
221 self.assertEquals(total, numberOfQueries * 2)
222
223 class TestRoutingRoundRobinLBAllDown(DNSDistTest):
224
225 _testServer2Port = 5351
226 _config_params = ['_testServerPort', '_testServer2Port']
227 _config_template = """
228 setServerPolicy(roundrobin)
229 setRoundRobinFailOnNoServer(true)
230 s1 = newServer{address="127.0.0.1:%s"}
231 s1:setDown()
232 s2 = newServer{address="127.0.0.1:%s"}
233 s2:setDown()
234 """
235
236 def testRRWithAllDown(self):
237 """
238 Routing: Round Robin with all servers down
239 """
240 numberOfQueries = 10
241 name = 'alldown.rr.routing.tests.powerdns.com.'
242 query = dns.message.make_query(name, 'A', 'IN')
243 response = dns.message.make_response(query)
244 rrset = dns.rrset.from_text(name,
245 60,
246 dns.rdataclass.IN,
247 dns.rdatatype.A,
248 '192.0.2.1')
249 response.answer.append(rrset)
250
251 for method in ("sendUDPQuery", "sendTCPQuery"):
252 sender = getattr(self, method)
253 (_, receivedResponse) = sender(query, response=None, useQueue=False)
254 self.assertEquals(receivedResponse, None)
255
256 class TestRoutingLuaFFIPerThreadRoundRobinLB(DNSDistTest):
257
258 _testServer2Port = 5351
259 _config_params = ['_testServerPort', '_testServer2Port']
260 _config_template = """
261 -- otherwise we start too many TCP workers, and as each thread
262 -- uses it own counter this makes the TCP queries distribution hard to predict
263 setMaxTCPClientThreads(1)
264 setServerPolicyLuaFFIPerThread("luaffiroundrobin", [[
265 local ffi = require("ffi")
266 local C = ffi.C
267
268 local counter = 0
269 return function(servers_list, dq)
270 counter = counter + 1
271 return (counter %% tonumber(C.dnsdist_ffi_servers_list_get_count(servers_list)))
272 end
273 ]])
274
275 s1 = newServer{address="127.0.0.1:%s"}
276 s1:setUp()
277 s2 = newServer{address="127.0.0.1:%s"}
278 s2:setUp()
279 """
280
281 @classmethod
282 def startResponders(cls):
283 print("Launching responders..")
284 cls._UDPResponder = threading.Thread(name='UDP Responder', target=cls.UDPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
285 cls._UDPResponder.setDaemon(True)
286 cls._UDPResponder.start()
287 cls._UDPResponder2 = threading.Thread(name='UDP Responder 2', target=cls.UDPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
288 cls._UDPResponder2.setDaemon(True)
289 cls._UDPResponder2.start()
290
291 cls._TCPResponder = threading.Thread(name='TCP Responder', target=cls.TCPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
292 cls._TCPResponder.setDaemon(True)
293 cls._TCPResponder.start()
294
295 cls._TCPResponder2 = threading.Thread(name='TCP Responder 2', target=cls.TCPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
296 cls._TCPResponder2.setDaemon(True)
297 cls._TCPResponder2.start()
298
299 def testRR(self):
300 """
301 Routing: Round Robin
302
303 Send 10 A queries to "rr.routing.tests.powerdns.com.",
304 check that dnsdist routes half of it to each backend.
305 """
306 numberOfQueries = 10
307 name = 'rr.routing.tests.powerdns.com.'
308 query = dns.message.make_query(name, 'A', 'IN')
309 response = dns.message.make_response(query)
310 rrset = dns.rrset.from_text(name,
311 60,
312 dns.rdataclass.IN,
313 dns.rdatatype.A,
314 '192.0.2.1')
315 response.answer.append(rrset)
316
317 # the round robin counter is shared for UDP and TCP,
318 # so we need to do UDP then TCP to have a clean count
319 for _ in range(numberOfQueries):
320 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
321 receivedQuery.id = query.id
322 self.assertEquals(query, receivedQuery)
323 self.assertEquals(response, receivedResponse)
324
325 for _ in range(numberOfQueries):
326 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
327 receivedQuery.id = query.id
328 self.assertEquals(query, receivedQuery)
329 self.assertEquals(response, receivedResponse)
330
331 for key in self._responsesCounter:
332 value = self._responsesCounter[key]
333 self.assertEquals(value, numberOfQueries / 2)
334
335 class TestRoutingOrder(DNSDistTest):
336
337 _testServer2Port = 5351
338 _config_params = ['_testServerPort', '_testServer2Port']
339 _config_template = """
340 setServerPolicy(firstAvailable)
341 s1 = newServer{address="127.0.0.1:%s", order=2}
342 s1:setUp()
343 s2 = newServer{address="127.0.0.1:%s", order=1}
344 s2:setUp()
345 """
346
347 @classmethod
348 def startResponders(cls):
349 print("Launching responders..")
350 cls._UDPResponder = threading.Thread(name='UDP Responder', target=cls.UDPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
351 cls._UDPResponder.setDaemon(True)
352 cls._UDPResponder.start()
353 cls._UDPResponder2 = threading.Thread(name='UDP Responder 2', target=cls.UDPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
354 cls._UDPResponder2.setDaemon(True)
355 cls._UDPResponder2.start()
356
357 cls._TCPResponder = threading.Thread(name='TCP Responder', target=cls.TCPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
358 cls._TCPResponder.setDaemon(True)
359 cls._TCPResponder.start()
360
361 cls._TCPResponder2 = threading.Thread(name='TCP Responder 2', target=cls.TCPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
362 cls._TCPResponder2.setDaemon(True)
363 cls._TCPResponder2.start()
364
365 def testOrder(self):
366 """
367 Routing: firstAvailable policy based on 'order'
368
369 Send 50 A queries to "order.routing.tests.powerdns.com.",
370 check that dnsdist routes all of it to the second backend
371 because it has the lower order value.
372 """
373 numberOfQueries = 50
374 name = 'order.routing.tests.powerdns.com.'
375 query = dns.message.make_query(name, 'A', 'IN')
376 response = dns.message.make_response(query)
377 rrset = dns.rrset.from_text(name,
378 60,
379 dns.rdataclass.IN,
380 dns.rdatatype.A,
381 '192.0.2.1')
382 response.answer.append(rrset)
383
384 for _ in range(numberOfQueries):
385 for method in ("sendUDPQuery", "sendTCPQuery"):
386 sender = getattr(self, method)
387 (receivedQuery, receivedResponse) = sender(query, response)
388 receivedQuery.id = query.id
389 self.assertEquals(query, receivedQuery)
390 self.assertEquals(response, receivedResponse)
391
392 total = 0
393 if 'UDP Responder' in self._responsesCounter:
394 self.assertEquals(self._responsesCounter['UDP Responder'], 0)
395 self.assertEquals(self._responsesCounter['UDP Responder 2'], numberOfQueries)
396 if 'TCP Responder' in self._responsesCounter:
397 self.assertEquals(self._responsesCounter['TCP Responder'], 0)
398 self.assertEquals(self._responsesCounter['TCP Responder 2'], numberOfQueries)
399
400 class TestRoutingNoServer(DNSDistTest):
401
402 _config_template = """
403 newServer{address="127.0.0.1:%s", pool="real"}
404 setServFailWhenNoServer(true)
405 """
406
407 def testPolicyPoolNoServer(self):
408 """
409 Routing: No server should return ServFail
410 """
411 name = 'noserver.routing.tests.powerdns.com.'
412 query = dns.message.make_query(name, 'A', 'IN')
413 expectedResponse = dns.message.make_response(query)
414 expectedResponse.set_rcode(dns.rcode.SERVFAIL)
415
416 for method in ("sendUDPQuery", "sendTCPQuery"):
417 sender = getattr(self, method)
418 (_, receivedResponse) = sender(query, response=None, useQueue=False)
419 self.assertEquals(receivedResponse, expectedResponse)
420
421 class TestRoutingWRandom(DNSDistTest):
422
423 _testServer2Port = 5351
424 _config_params = ['_testServerPort', '_testServer2Port']
425 _config_template = """
426 setServerPolicy(wrandom)
427 s1 = newServer{address="127.0.0.1:%s", weight=1}
428 s1:setUp()
429 s2 = newServer{address="127.0.0.1:%s", weight=2}
430 s2:setUp()
431 """
432
433 @classmethod
434 def startResponders(cls):
435 print("Launching responders..")
436 cls._UDPResponder = threading.Thread(name='UDP Responder', target=cls.UDPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
437 cls._UDPResponder.setDaemon(True)
438 cls._UDPResponder.start()
439 cls._UDPResponder2 = threading.Thread(name='UDP Responder 2', target=cls.UDPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
440 cls._UDPResponder2.setDaemon(True)
441 cls._UDPResponder2.start()
442
443 cls._TCPResponder = threading.Thread(name='TCP Responder', target=cls.TCPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
444 cls._TCPResponder.setDaemon(True)
445 cls._TCPResponder.start()
446
447 cls._TCPResponder2 = threading.Thread(name='TCP Responder 2', target=cls.TCPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
448 cls._TCPResponder2.setDaemon(True)
449 cls._TCPResponder2.start()
450
451 def testWRandom(self):
452 """
453 Routing: WRandom
454
455 Send 100 A queries to "wrandom.routing.tests.powerdns.com.",
456 check that dnsdist routes less than half to one, more to the other.
457 """
458 numberOfQueries = 100
459 name = 'wrandom.routing.tests.powerdns.com.'
460 query = dns.message.make_query(name, 'A', 'IN')
461 response = dns.message.make_response(query)
462 rrset = dns.rrset.from_text(name,
463 60,
464 dns.rdataclass.IN,
465 dns.rdatatype.A,
466 '192.0.2.1')
467 response.answer.append(rrset)
468
469 # the counter is shared for UDP and TCP,
470 # so we need to do UDP then TCP to have a clean count
471 for _ in range(numberOfQueries):
472 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
473 receivedQuery.id = query.id
474 self.assertEquals(query, receivedQuery)
475 self.assertEquals(response, receivedResponse)
476
477 for _ in range(numberOfQueries):
478 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
479 receivedQuery.id = query.id
480 self.assertEquals(query, receivedQuery)
481 self.assertEquals(response, receivedResponse)
482
483 # The lower weight downstream should receive less than half the queries
484 self.assertLess(self._responsesCounter['UDP Responder'], numberOfQueries * 0.50)
485 self.assertLess(self._responsesCounter['TCP Responder'], numberOfQueries * 0.50)
486
487 # The higher weight downstream should receive more than half the queries
488 self.assertGreater(self._responsesCounter['UDP Responder 2'], numberOfQueries * 0.50)
489 self.assertGreater(self._responsesCounter['TCP Responder 2'], numberOfQueries * 0.50)
490
491
492 class TestRoutingHighValueWRandom(DNSDistTest):
493
494 _testServer2Port = 5351
495 _consoleKey = DNSDistTest.generateConsoleKey()
496 _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii')
497 _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort', '_testServer2Port']
498 _config_template = """
499 setKey("%s")
500 controlSocket("127.0.0.1:%s")
501 setServerPolicy(wrandom)
502 s1 = newServer{address="127.0.0.1:%s", weight=2000000000}
503 s1:setUp()
504 s2 = newServer{address="127.0.0.1:%s", weight=2000000000}
505 s2:setUp()
506 """
507
508 @classmethod
509 def startResponders(cls):
510 print("Launching responders..")
511 cls._UDPResponder = threading.Thread(name='UDP Responder', target=cls.UDPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
512 cls._UDPResponder.setDaemon(True)
513 cls._UDPResponder.start()
514 cls._UDPResponder2 = threading.Thread(name='UDP Responder 2', target=cls.UDPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
515 cls._UDPResponder2.setDaemon(True)
516 cls._UDPResponder2.start()
517
518 cls._TCPResponder = threading.Thread(name='TCP Responder', target=cls.TCPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
519 cls._TCPResponder.setDaemon(True)
520 cls._TCPResponder.start()
521
522 cls._TCPResponder2 = threading.Thread(name='TCP Responder 2', target=cls.TCPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
523 cls._TCPResponder2.setDaemon(True)
524 cls._TCPResponder2.start()
525
526 def testHighValueWRandom(self):
527 """
528 Routing: WRandom (overflow)
529
530 Send 100 A queries to "wrandom-overflow.routing.tests.powerdns.com.",
531 check that dnsdist routes to each downstream, rather than failing with
532 no-policy.
533 """
534 numberOfQueries = 100
535 name = 'wrandom-overflow.routing.tests.powerdns.com.'
536 query = dns.message.make_query(name, 'A', 'IN')
537 response = dns.message.make_response(query)
538 rrset = dns.rrset.from_text(name,
539 60,
540 dns.rdataclass.IN,
541 dns.rdatatype.A,
542 '192.0.2.1')
543 response.answer.append(rrset)
544
545 # the counter is shared for UDP and TCP,
546 # so we need to do UDP then TCP to have a clean count
547 for _ in range(numberOfQueries):
548 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
549 receivedQuery.id = query.id
550 self.assertEquals(query, receivedQuery)
551 self.assertEquals(response, receivedResponse)
552
553 for _ in range(numberOfQueries):
554 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
555 receivedQuery.id = query.id
556 self.assertEquals(query, receivedQuery)
557 self.assertEquals(response, receivedResponse)
558
559 stats = self.sendConsoleCommand("dumpStats()").split()
560 stats_dict = {}
561
562 # Map to a dict with every other element being the value to the previous one
563 for i, x in enumerate(stats):
564 if not i % 2:
565 stats_dict[x] = stats[i+1]
566
567 # There should be no queries getting "no-policy" responses
568 self.assertEquals(stats_dict['no-policy'], '0')
569
570 # Each downstream should receive some queries, but it will be unbalanced
571 # because the sum of the weights is higher than INT_MAX.
572 # The first downstream will receive more than half the queries
573 self.assertGreater(self._responsesCounter['UDP Responder'], numberOfQueries / 2)
574 self.assertGreater(self._responsesCounter['TCP Responder'], numberOfQueries / 2)
575
576 # The second downstream will receive the remainder of the queries, but it might very well be 0
577 if 'UDP Responder 2' in self._responsesCounter:
578 self.assertEquals(self._responsesCounter['UDP Responder 2'], numberOfQueries - self._responsesCounter['UDP Responder'])
579 if 'TCP Responder 2' in self._responsesCounter:
580 self.assertEquals(self._responsesCounter['TCP Responder 2'], numberOfQueries - self._responsesCounter['TCP Responder'])
581
582 class TestRoutingBadWeightWRandom(DNSDistTest):
583
584 _testServer2Port = 5351
585 _consoleKey = DNSDistTest.generateConsoleKey()
586 _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii')
587 _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort', '_testServer2Port']
588 _config_template = """
589 setKey("%s")
590 controlSocket("127.0.0.1:%s")
591 setServerPolicy(wrandom)
592 s1 = newServer{address="127.0.0.1:%s", weight=-1}
593 s2 = newServer{address="127.0.0.1:%s", weight=2147483648}
594 """
595 _checkConfigExpectedOutput = b"""Error creating new server: downstream weight value must be greater than 0.
596 Error creating new server: downstream weight value must be between 1 and 2147483647
597 Configuration 'configs/dnsdist_TestRoutingBadWeightWRandom.conf' OK!
598 """
599
600 def testBadWeightWRandom(self):
601 """
602 Routing: WRandom
603
604 Test that downstreams cannot be added with invalid weights.
605 """
606 # There should be no downstreams
607 self.assertTrue(self.sendConsoleCommand("getServer(0)").startswith("Error"))