]>
git.ipfire.org Git - thirdparty/pdns.git/blob - regression-tests.dnsdist/test_Caching.py
5 import clientsubnetoption
6 from dnsdisttests
import DNSDistTest
8 class TestCaching ( DNSDistTest
):
10 _config_template
= """
11 pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
12 getPool(""):setCache(pc)
13 addAction(makeRule("nocache.cache.tests.powerdns.com."), SkipCacheAction())
14 function skipViaLua(dq)
16 return DNSAction.None, ""
18 addAction("nocachevialua.cache.tests.powerdns.com.", LuaAction(skipViaLua))
19 newServer{address="127.0.0.1: %d "}
24 Cache: Served from cache
26 dnsdist is configured to cache entries, we are sending several
27 identical requests and checking that the backend only receive
31 name
= 'cached.cache.tests.powerdns.com.'
32 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
33 response
= dns
. message
. make_response ( query
)
34 rrset
= dns
. rrset
. from_text ( name
,
39 response
. answer
. append ( rrset
)
41 # first query to fill the cache
42 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
43 self
. assertTrue ( receivedQuery
)
44 self
. assertTrue ( receivedResponse
)
45 receivedQuery
. id = query
. id
46 self
. assertEquals ( query
, receivedQuery
)
47 self
. assertEquals ( receivedResponse
, response
)
49 for _
in range ( numberOfQueries
):
50 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
51 self
. assertEquals ( receivedResponse
, response
)
54 for key
in self
._ responsesCounter
:
55 total
+= self
._ responsesCounter
[ key
]
56 TestCaching
._ responsesCounter
[ key
] = 0
58 self
. assertEquals ( total
, 1 )
60 # TCP should not be cached
61 # first query to fill the cache
62 ( receivedQuery
, receivedResponse
) = self
. sendTCPQuery ( query
, response
)
63 self
. assertTrue ( receivedQuery
)
64 self
. assertTrue ( receivedResponse
)
65 receivedQuery
. id = query
. id
66 self
. assertEquals ( query
, receivedQuery
)
67 self
. assertEquals ( receivedResponse
, response
)
69 for _
in range ( numberOfQueries
):
70 ( _
, receivedResponse
) = self
. sendTCPQuery ( query
, response
= None , useQueue
= False )
71 self
. assertEquals ( receivedResponse
, response
)
74 for key
in self
._ responsesCounter
:
75 total
+= self
._ responsesCounter
[ key
]
76 TestCaching
._ responsesCounter
[ key
] = 0
78 self
. assertEquals ( total
, 1 )
80 def testDOCached ( self
):
82 Cache: Served from cache, query has DO bit set
84 dnsdist is configured to cache entries, we are sending several
85 identical requests and checking that the backend only receive
89 name
= 'cached-do.cache.tests.powerdns.com.'
90 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , payload
= 4096 , want_dnssec
= True )
91 response
= dns
. message
. make_response ( query
)
92 rrset
= dns
. rrset
. from_text ( name
,
97 response
. answer
. append ( rrset
)
99 # first query to fill the cache
100 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
101 self
. assertTrue ( receivedQuery
)
102 self
. assertTrue ( receivedResponse
)
103 receivedQuery
. id = query
. id
104 self
. assertEquals ( query
, receivedQuery
)
105 self
. assertEquals ( receivedResponse
, response
)
107 for _
in range ( numberOfQueries
):
108 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
109 self
. assertEquals ( receivedResponse
, response
)
112 for key
in self
._ responsesCounter
:
113 total
+= self
._ responsesCounter
[ key
]
114 TestCaching
._ responsesCounter
[ key
] = 0
116 self
. assertEquals ( total
, 1 )
118 # TCP should not be cached
119 # first query to fill the cache
120 ( receivedQuery
, receivedResponse
) = self
. sendTCPQuery ( query
, response
)
121 self
. assertTrue ( receivedQuery
)
122 self
. assertTrue ( receivedResponse
)
123 receivedQuery
. id = query
. id
124 self
. assertEquals ( query
, receivedQuery
)
125 self
. assertEquals ( receivedResponse
, response
)
127 for _
in range ( numberOfQueries
):
128 ( _
, receivedResponse
) = self
. sendTCPQuery ( query
, response
= None , useQueue
= False )
129 self
. assertEquals ( receivedResponse
, response
)
132 for key
in self
._ responsesCounter
:
133 total
+= self
._ responsesCounter
[ key
]
134 TestCaching
._ responsesCounter
[ key
] = 0
136 self
. assertEquals ( total
, 1 )
138 def testSkipCache ( self
):
140 Cache: SkipCacheAction
142 dnsdist is configured to not cache entries for nocache.cache.tests.powerdns.com.
143 we are sending several requests and checking that the backend get them all.
145 name
= 'nocache.cache.tests.powerdns.com.'
147 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
148 response
= dns
. message
. make_response ( query
)
149 rrset
= dns
. rrset
. from_text ( name
,
154 response
. answer
. append ( rrset
)
156 for _
in range ( numberOfQueries
):
157 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
158 sender
= getattr ( self
, method
)
159 ( receivedQuery
, receivedResponse
) = sender ( query
, response
)
160 self
. assertTrue ( receivedQuery
)
161 self
. assertTrue ( receivedResponse
)
162 receivedQuery
. id = query
. id
163 self
. assertEquals ( query
, receivedQuery
)
164 self
. assertEquals ( receivedResponse
, response
)
166 for key
in self
._ responsesCounter
:
167 value
= self
._ responsesCounter
[ key
]
168 self
. assertEquals ( value
, numberOfQueries
)
170 def testSkipCacheViaLua ( self
):
172 Cache: SkipCache via Lua
174 dnsdist is configured to not cache entries for nocachevialua.cache.tests.powerdns.com.
175 we are sending several requests and checking that the backend get them all.
177 name
= 'nocachevialua.cache.tests.powerdns.com.'
179 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
180 response
= dns
. message
. make_response ( query
)
181 rrset
= dns
. rrset
. from_text ( name
,
186 response
. answer
. append ( rrset
)
188 for _
in range ( numberOfQueries
):
189 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
190 sender
= getattr ( self
, method
)
191 ( receivedQuery
, receivedResponse
) = sender ( query
, response
)
192 self
. assertTrue ( receivedQuery
)
193 self
. assertTrue ( receivedResponse
)
194 receivedQuery
. id = query
. id
195 self
. assertEquals ( query
, receivedQuery
)
196 self
. assertEquals ( receivedResponse
, response
)
198 for key
in self
._ responsesCounter
:
199 value
= self
._ responsesCounter
[ key
]
200 self
. assertEquals ( value
, numberOfQueries
)
202 def testCacheExpiration ( self
):
204 Cache: Cache expiration
206 dnsdist is configured to cache entries, we are sending one request
207 (cache miss) with a very short TTL, checking that the next requests
208 are cached. Then we wait for the TTL to expire, check that the
209 next request is a miss but the following one a hit.
213 name
= 'cacheexpiration.cache.tests.powerdns.com.'
214 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
215 response
= dns
. message
. make_response ( query
)
216 rrset
= dns
. rrset
. from_text ( name
,
221 response
. answer
. append ( rrset
)
223 # first query to fill the cache
224 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
225 self
. assertTrue ( receivedQuery
)
226 self
. assertTrue ( receivedResponse
)
227 receivedQuery
. id = query
. id
228 self
. assertEquals ( query
, receivedQuery
)
229 self
. assertEquals ( receivedResponse
, response
)
232 # next queries should hit the cache
233 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
234 self
. assertEquals ( receivedResponse
, response
)
236 # now we wait a bit for the cache entry to expire
239 # next query should be a miss, fill the cache again
240 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
241 self
. assertTrue ( receivedQuery
)
242 self
. assertTrue ( receivedResponse
)
243 receivedQuery
. id = query
. id
244 self
. assertEquals ( query
, receivedQuery
)
245 self
. assertEquals ( receivedResponse
, response
)
248 # following queries should hit the cache again
249 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
250 self
. assertEquals ( receivedResponse
, response
)
253 for key
in self
._ responsesCounter
:
254 total
+= self
._ responsesCounter
[ key
]
256 self
. assertEquals ( total
, misses
)
258 def testCacheExpirationDifferentSets ( self
):
260 Cache: Cache expiration with different sets
262 dnsdist is configured to cache entries, we are sending one request
263 (cache miss) whose response has a long and a very short TTL,
264 checking that the next requests are cached. Then we wait for the
265 short TTL to expire, check that the
266 next request is a miss but the following one a hit.
270 name
= 'cacheexpirationdifferentsets.cache.tests.powerdns.com.'
271 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
272 response
= dns
. message
. make_response ( query
)
273 rrset
= dns
. rrset
. from_text ( name
,
277 'cname.cacheexpirationdifferentsets.cache.tests.powerdns.com.' )
278 response
. answer
. append ( rrset
)
279 rrset
= dns
. rrset
. from_text ( 'cname.cacheexpirationdifferentsets.cache.tests.powerdns.com.' ,
284 response
. additional
. append ( rrset
)
286 # first query to fill the cache
287 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
288 self
. assertTrue ( receivedQuery
)
289 self
. assertTrue ( receivedResponse
)
290 receivedQuery
. id = query
. id
291 self
. assertEquals ( query
, receivedQuery
)
292 self
. assertEquals ( receivedResponse
, response
)
295 # next queries should hit the cache
296 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
297 self
. assertEquals ( receivedResponse
, response
)
299 # now we wait a bit for the cache entry to expire
302 # next query should be a miss, fill the cache again
303 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
304 self
. assertTrue ( receivedQuery
)
305 self
. assertTrue ( receivedResponse
)
306 receivedQuery
. id = query
. id
307 self
. assertEquals ( query
, receivedQuery
)
308 self
. assertEquals ( receivedResponse
, response
)
311 # following queries should hit the cache again
312 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
313 self
. assertEquals ( receivedResponse
, response
)
316 for key
in self
._ responsesCounter
:
317 total
+= self
._ responsesCounter
[ key
]
319 self
. assertEquals ( total
, misses
)
321 def testCacheDecreaseTTL ( self
):
323 Cache: Cache decreases TTL
325 dnsdist is configured to cache entries, we are sending one request
326 (cache miss) and verify that the cache hits have a decreasing TTL.
330 name
= 'cachedecreasettl.cache.tests.powerdns.com.'
331 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
332 response
= dns
. message
. make_response ( query
)
333 rrset
= dns
. rrset
. from_text ( name
,
338 response
. answer
. append ( rrset
)
340 # first query to fill the cache
341 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
342 self
. assertTrue ( receivedQuery
)
343 self
. assertTrue ( receivedResponse
)
344 receivedQuery
. id = query
. id
345 self
. assertEquals ( query
, receivedQuery
)
346 self
. assertEquals ( receivedResponse
, response
)
349 # next queries should hit the cache
350 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
351 self
. assertEquals ( receivedResponse
, response
)
352 for an
in receivedResponse
. answer
:
353 self
. assertTrue ( an
. ttl
<= ttl
)
355 # now we wait a bit for the TTL to decrease
358 # next queries should hit the cache
359 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
360 self
. assertEquals ( receivedResponse
, response
)
361 for an
in receivedResponse
. answer
:
362 self
. assertTrue ( an
. ttl
< ttl
)
365 for key
in self
._ responsesCounter
:
366 total
+= self
._ responsesCounter
[ key
]
368 self
. assertEquals ( total
, misses
)
370 def testCacheDifferentCase ( self
):
372 Cache: Cache matches different case
374 dnsdist is configured to cache entries, we are sending one request
375 (cache miss) and verify that the same one with a different case
379 name
= 'cachedifferentcase.cache.tests.powerdns.com.'
380 differentCaseName
= 'CacheDifferentCASE.cache.tests.powerdns.com.'
381 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
382 differentCaseQuery
= dns
. message
. make_query ( differentCaseName
, 'AAAA' , 'IN' )
383 response
= dns
. message
. make_response ( query
)
384 differentCaseResponse
= dns
. message
. make_response ( differentCaseQuery
)
385 rrset
= dns
. rrset
. from_text ( name
,
390 response
. answer
. append ( rrset
)
391 differentCaseResponse
. answer
. append ( rrset
)
393 # first query to fill the cache
394 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
395 self
. assertTrue ( receivedQuery
)
396 self
. assertTrue ( receivedResponse
)
397 receivedQuery
. id = query
. id
398 self
. assertEquals ( query
, receivedQuery
)
399 self
. assertEquals ( receivedResponse
, response
)
401 # different case query should still hit the cache
402 ( _
, receivedResponse
) = self
. sendUDPQuery ( differentCaseQuery
, response
= None , useQueue
= False )
403 self
. assertEquals ( receivedResponse
, differentCaseResponse
)
405 def testLargeAnswer ( self
):
407 Cache: Check that we can cache (and retrieve) large answers
409 We should be able to get answers as large as 4096 bytes
412 name
= 'large-answer.cache.tests.powerdns.com.'
413 query
= dns
. message
. make_query ( name
, 'TXT' , 'IN' )
414 response
= dns
. message
. make_response ( query
)
415 # we prepare a large answer
419 content
= content
+ ', '
420 content
= content
+ ( str ( i
)* 50 )
422 content
= content
+ 'A' * 42
424 rrset
= dns
. rrset
. from_text ( name
,
429 response
. answer
. append ( rrset
)
430 self
. assertEquals ( len ( response
. to_wire ()), 4096 )
432 # first query to fill the cache
433 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
434 self
. assertTrue ( receivedQuery
)
435 self
. assertTrue ( receivedResponse
)
436 receivedQuery
. id = query
. id
437 self
. assertEquals ( query
, receivedQuery
)
438 self
. assertEquals ( receivedResponse
, response
)
440 for _
in range ( numberOfQueries
):
441 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
442 self
. assertEquals ( receivedResponse
, response
)
445 for key
in self
._ responsesCounter
:
446 total
+= self
._ responsesCounter
[ key
]
447 TestCaching
._ responsesCounter
[ key
] = 0
449 self
. assertEquals ( total
, 1 )
451 # TCP should not be cached
452 # first query to fill the cache
453 ( receivedQuery
, receivedResponse
) = self
. sendTCPQuery ( query
, response
)
454 self
. assertTrue ( receivedQuery
)
455 self
. assertTrue ( receivedResponse
)
456 receivedQuery
. id = query
. id
457 self
. assertEquals ( query
, receivedQuery
)
458 self
. assertEquals ( receivedResponse
, response
)
460 for _
in range ( numberOfQueries
):
461 ( _
, receivedResponse
) = self
. sendTCPQuery ( query
, response
= None , useQueue
= False )
462 self
. assertEquals ( receivedResponse
, response
)
465 for key
in self
._ responsesCounter
:
466 total
+= self
._ responsesCounter
[ key
]
467 TestCaching
._ responsesCounter
[ key
] = 0
469 self
. assertEquals ( total
, 1 )
471 class TestTempFailureCacheTTLAction ( DNSDistTest
):
473 _config_template
= """
474 pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
475 getPool(""):setCache(pc)
476 addAction("servfail.cache.tests.powerdns.com.", TempFailureCacheTTLAction(1))
477 newServer{address="127.0.0.1: %d "}
480 def testTempFailureCacheTTLAction ( self
):
482 Cache: When a TempFailure TTL is set, it should be honored
484 dnsdist is configured to cache packets, plus a specific qname is
485 set up with a lower TempFailure Cache TTL. we are sending one request
486 (cache miss) and verify that the cache is hit for the following query,
487 but the TTL then expires before the larger "good" packetcache TTL.
489 name
= 'servfail.cache.tests.powerdns.com.'
490 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
491 response
= dns
. message
. make_response ( query
)
492 response
. set_rcode ( dns
. rcode
. SERVFAIL
)
494 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
495 self
. assertTrue ( receivedQuery
)
496 self
. assertTrue ( receivedResponse
)
497 receivedQuery
. id = query
. id
498 self
. assertEquals ( query
, receivedQuery
)
499 self
. assertEquals ( receivedResponse
, response
)
501 # next query should hit the cache
502 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
503 self
. assertFalse ( receivedQuery
)
504 self
. assertTrue ( receivedResponse
)
505 self
. assertEquals ( receivedResponse
, response
)
507 # now we wait a bit for the Failure-Cache TTL to expire
510 # next query should NOT hit the cache
511 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
512 self
. assertTrue ( receivedQuery
)
513 self
. assertTrue ( receivedResponse
)
514 self
. assertEquals ( receivedResponse
, response
)
517 class TestCachingWithExistingEDNS ( DNSDistTest
):
519 _config_template
= """
520 pc = newPacketCache(5, {maxTTL=86400, minTTL=1})
521 getPool(""):setCache(pc)
522 newServer{address="127.0.0.1: %d "}
524 def testCacheWithEDNS ( self
):
526 Cache: Cache should not match different EDNS value
528 dnsdist is configured to cache entries, we are sending one request
529 (cache miss) and verify that the same one with a different EDNS UDP
530 Payload size is not served from the cache.
533 name
= 'cachedifferentedns.cache.tests.powerdns.com.'
534 query
= dns
. message
. make_query ( name
, 'A' , 'IN' , use_edns
= True , payload
= 512 )
535 response
= dns
. message
. make_response ( query
)
536 rrset
= dns
. rrset
. from_text ( name
,
541 response
. answer
. append ( rrset
)
543 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
544 self
. assertTrue ( receivedQuery
)
545 self
. assertTrue ( receivedResponse
)
546 receivedQuery
. id = query
. id
547 self
. assertEquals ( query
, receivedQuery
)
548 self
. assertEquals ( response
, receivedResponse
)
551 query
= dns
. message
. make_query ( name
, 'A' , 'IN' , use_edns
= True , payload
= 4096 )
552 response
= dns
. message
. make_response ( query
)
553 rrset
= dns
. rrset
. from_text ( name
,
558 response
. answer
. append ( rrset
)
560 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
561 self
. assertTrue ( receivedQuery
)
562 self
. assertTrue ( receivedResponse
)
563 receivedQuery
. id = query
. id
564 self
. assertEquals ( query
, receivedQuery
)
565 self
. assertEquals ( response
, receivedResponse
)
569 for key
in self
._ responsesCounter
:
570 total
+= self
._ responsesCounter
[ key
]
572 self
. assertEquals ( total
, misses
)
574 class TestCachingCacheFull ( DNSDistTest
):
576 _config_template
= """
577 pc = newPacketCache(1, {maxTTL=86400, minTTL=1})
578 getPool(""):setCache(pc)
579 newServer{address="127.0.0.1: %d "}
581 def testCacheFull ( self
):
583 Cache: No new entries are cached when the cache is full
587 name
= 'cachenotfullyet.cache.tests.powerdns.com.'
588 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
589 response
= dns
. message
. make_response ( query
)
590 rrset
= dns
. rrset
. from_text ( name
,
595 response
. answer
. append ( rrset
)
598 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
599 self
. assertTrue ( receivedQuery
)
600 self
. assertTrue ( receivedResponse
)
601 receivedQuery
. id = query
. id
602 self
. assertEquals ( query
, receivedQuery
)
603 self
. assertEquals ( response
, receivedResponse
)
606 # next queries should hit the cache
607 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
608 self
. assertEquals ( receivedResponse
, response
)
610 # ok, now the cache is full, send another query
611 name
= 'cachefull.cache.tests.powerdns.com.'
612 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
613 response
= dns
. message
. make_response ( query
)
614 rrset
= dns
. rrset
. from_text ( name
,
619 response
. answer
. append ( rrset
)
622 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
623 self
. assertTrue ( receivedQuery
)
624 self
. assertTrue ( receivedResponse
)
625 receivedQuery
. id = query
. id
626 self
. assertEquals ( query
, receivedQuery
)
627 self
. assertEquals ( response
, receivedResponse
)
630 # next queries should NOT hit the cache
631 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
632 self
. assertTrue ( receivedQuery
)
633 self
. assertTrue ( receivedResponse
)
634 receivedQuery
. id = query
. id
635 self
. assertEquals ( query
, receivedQuery
)
636 self
. assertEquals ( response
, receivedResponse
)
640 for key
in self
._ responsesCounter
:
641 total
+= self
._ responsesCounter
[ key
]
643 self
. assertEquals ( total
, misses
)
645 class TestCachingNoStale ( DNSDistTest
):
647 _consoleKey
= DNSDistTest
. generateConsoleKey ()
648 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
649 _config_params
= [ '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
650 _config_template
= """
651 pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
652 getPool(""):setCache(pc)
654 controlSocket("127.0.0.1: %d ")
655 newServer{address="127.0.0.1: %d "}
657 def testCacheNoStale ( self
):
659 Cache: Cache entry, set backend down, we should not get a stale entry
663 name
= 'nostale.cache.tests.powerdns.com.'
664 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
665 response
= dns
. message
. make_response ( query
)
666 rrset
= dns
. rrset
. from_text ( name
,
671 response
. answer
. append ( rrset
)
674 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
675 self
. assertTrue ( receivedQuery
)
676 self
. assertTrue ( receivedResponse
)
677 receivedQuery
. id = query
. id
678 self
. assertEquals ( query
, receivedQuery
)
679 self
. assertEquals ( response
, receivedResponse
)
681 # next queries should hit the cache
682 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
683 self
. assertEquals ( receivedResponse
, response
)
685 # ok, we mark the backend as down
686 self
. sendConsoleCommand ( "getServer(0):setDown()" )
687 # and we wait for the entry to expire
690 # we should NOT get a cached, stale, entry
691 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
692 self
. assertEquals ( receivedResponse
, None )
695 class TestCachingStale ( DNSDistTest
):
697 _consoleKey
= DNSDistTest
. generateConsoleKey ()
698 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
700 _config_params
= [ '_staleCacheTTL' , '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
701 _config_template
= """
702 pc = newPacketCache(100, {maxTTL=86400, minTTL=1, temporaryFailureTTL=0, staleTTL= %d })
703 getPool(""):setCache(pc)
704 setStaleCacheEntriesTTL(600)
706 controlSocket("127.0.0.1: %d ")
707 newServer{address="127.0.0.1: %d "}
709 def testCacheStale ( self
):
711 Cache: Cache entry, set backend down, get stale entry
716 name
= 'stale.cache.tests.powerdns.com.'
717 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
718 response
= dns
. message
. make_response ( query
)
719 rrset
= dns
. rrset
. from_text ( name
,
724 response
. answer
. append ( rrset
)
727 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
728 self
. assertTrue ( receivedQuery
)
729 self
. assertTrue ( receivedResponse
)
730 receivedQuery
. id = query
. id
731 self
. assertEquals ( query
, receivedQuery
)
732 self
. assertEquals ( response
, receivedResponse
)
735 # next queries should hit the cache
736 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
737 self
. assertEquals ( receivedResponse
, response
)
739 # ok, we mark the backend as down
740 self
. sendConsoleCommand ( "getServer(0):setDown()" )
741 # and we wait for the entry to expire
744 # we should get a cached, stale, entry
745 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
746 self
. assertEquals ( receivedResponse
, response
)
747 for an
in receivedResponse
. answer
:
748 self
. assertEquals ( an
. ttl
, self
._ staleCacheTTL
)
751 for key
in self
._ responsesCounter
:
752 total
+= self
._ responsesCounter
[ key
]
754 self
. assertEquals ( total
, misses
)
756 class TestCachingStaleExpunged ( DNSDistTest
):
758 _consoleKey
= DNSDistTest
. generateConsoleKey ()
759 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
761 _config_params
= [ '_staleCacheTTL' , '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
762 _config_template
= """
763 pc = newPacketCache(100, {maxTTL=86400, minTTL=1, temporaryFailureTTL=0, staleTTL= %d })
764 getPool(""):setCache(pc)
765 setStaleCacheEntriesTTL(600)
766 -- try to remove all expired entries
767 setCacheCleaningPercentage(100)
768 -- clean the cache every second
769 setCacheCleaningDelay(1)
771 controlSocket("127.0.0.1: %d ")
772 newServer{address="127.0.0.1: %d "}
774 def testCacheStale ( self
):
776 Cache: Cache entry, set backend down, wait for the cache cleaning to run and remove the entry, get no entry
781 name
= 'stale-but-expunged.cache.tests.powerdns.com.'
782 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
783 response
= dns
. message
. make_response ( query
)
784 rrset
= dns
. rrset
. from_text ( name
,
789 response
. answer
. append ( rrset
)
792 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
793 self
. assertTrue ( receivedQuery
)
794 self
. assertTrue ( receivedResponse
)
795 receivedQuery
. id = query
. id
796 self
. assertEquals ( query
, receivedQuery
)
797 self
. assertEquals ( response
, receivedResponse
)
799 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" misses \" ]" ). strip ( " \n " )), misses
+ drops
)
801 # next queries should hit the cache
802 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
803 self
. assertEquals ( receivedResponse
, response
)
804 # the cache should have one entry
805 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" entries \" ]" ). strip ( " \n " )), 1 )
806 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" hits \" ]" ). strip ( " \n " )), 1 )
808 # ok, we mark the backend as down
809 self
. sendConsoleCommand ( "getServer(0):setDown()" )
810 # and we wait for the entry to expire
812 # wait a bit more to be sure that the cache cleaning algo has been run
814 # the cache should be empty now
815 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" entries \" ]" ). strip ( " \n " )), 0 )
817 # we should get a DROP (backend is down, nothing in the cache anymore)
818 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
819 self
. assertEquals ( receivedResponse
, None )
822 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" misses \" ]" ). strip ( " \n " )), misses
+ drops
)
823 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" hits \" ]" ). strip ( " \n " )), 1 )
826 for key
in self
._ responsesCounter
:
827 total
+= self
._ responsesCounter
[ key
]
829 self
. assertEquals ( total
, misses
)
831 class TestCachingStaleExpungePrevented ( DNSDistTest
):
833 _consoleKey
= DNSDistTest
. generateConsoleKey ()
834 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
835 _config_params
= [ '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
836 _config_template
= """
837 pc = newPacketCache(100, {maxTTL=86400, minTTL=1, temporaryFailureTTL=0, staleTTL=60, dontAge=false, numberOfShards=1, deferrableInsertLock=true, maxNegativeTTL=3600, ecsParsing=false, keepStaleData=true})
838 getPool(""):setCache(pc)
839 setStaleCacheEntriesTTL(600)
840 -- try to remove all expired entries
841 setCacheCleaningPercentage(100)
842 -- clean the cache every second
843 setCacheCleaningDelay(1)
845 controlSocket("127.0.0.1: %d ")
846 newServer{address="127.0.0.1: %d "}
848 def testCacheStale ( self
):
850 Cache: Cache entry, set backend down, wait for the cache cleaning to run and remove the entry, still get a cache HIT because the stale entry was not removed
854 name
= 'stale-not-expunged.cache.tests.powerdns.com.'
855 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
856 response
= dns
. message
. make_response ( query
)
857 rrset
= dns
. rrset
. from_text ( name
,
862 response
. answer
. append ( rrset
)
865 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
866 self
. assertTrue ( receivedQuery
)
867 self
. assertTrue ( receivedResponse
)
868 receivedQuery
. id = query
. id
869 self
. assertEquals ( query
, receivedQuery
)
870 self
. assertEquals ( response
, receivedResponse
)
872 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" misses \" ]" ). strip ( " \n " )), 1 )
874 # next queries should hit the cache
875 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
876 self
. assertEquals ( receivedResponse
, response
)
877 # the cache should have one entry
878 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" entries \" ]" ). strip ( " \n " )), 1 )
879 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" hits \" ]" ). strip ( " \n " )), 1 )
881 # ok, we mark the backend as down
882 self
. sendConsoleCommand ( "getServer(0):setDown()" )
883 # and we wait for the entry to expire
885 # wait a bit more to be sure that the cache cleaning algo has been run
887 # the cache should NOT be empty because the removal of the expired entry should have been prevented
888 # since all backends for this pool are down
889 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" entries \" ]" ). strip ( " \n " )), 1 )
891 # we should get a HIT
892 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
893 self
. assertEquals ( receivedResponse
, response
)
895 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" misses \" ]" ). strip ( " \n " )), 1 )
896 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" hits \" ]" ). strip ( " \n " )), 2 )
899 for key
in self
._ responsesCounter
:
900 total
+= self
._ responsesCounter
[ key
]
902 self
. assertEquals ( total
, misses
)
904 class TestCacheManagement ( DNSDistTest
):
906 _consoleKey
= DNSDistTest
. generateConsoleKey ()
907 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
908 _config_params
= [ '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
909 _config_template
= """
910 pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
911 getPool(""):setCache(pc)
913 controlSocket("127.0.0.1: %d ")
914 newServer{address="127.0.0.1: %d "}
916 def testCacheExpunge ( self
):
923 name
= 'expunge.cache.tests.powerdns.com.'
924 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
925 response
= dns
. message
. make_response ( query
)
926 rrset
= dns
. rrset
. from_text ( name
,
931 response
. answer
. append ( rrset
)
934 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
935 self
. assertTrue ( receivedQuery
)
936 self
. assertTrue ( receivedResponse
)
937 receivedQuery
. id = query
. id
938 self
. assertEquals ( query
, receivedQuery
)
939 self
. assertEquals ( response
, receivedResponse
)
942 # next queries should hit the cache
943 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
944 self
. assertEquals ( receivedResponse
, response
)
946 # remove cached entries
947 self
. sendConsoleCommand ( "getPool( \"\" ):getCache():expunge(0)" )
950 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
951 self
. assertTrue ( receivedQuery
)
952 self
. assertTrue ( receivedResponse
)
953 receivedQuery
. id = query
. id
954 self
. assertEquals ( query
, receivedQuery
)
955 self
. assertEquals ( response
, receivedResponse
)
958 # next queries should hit the cache again
959 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
960 self
. assertEquals ( receivedResponse
, response
)
963 for key
in self
._ responsesCounter
:
964 total
+= self
._ responsesCounter
[ key
]
966 self
. assertEquals ( total
, misses
)
968 def testCacheExpungeByName ( self
):
970 Cache: Expunge by name
975 name
= 'expungebyname.cache.tests.powerdns.com.'
976 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
977 response
= dns
. message
. make_response ( query
)
978 rrset
= dns
. rrset
. from_text ( name
,
983 response
. answer
. append ( rrset
)
985 name2
= 'expungebynameother.cache.tests.powerdns.com.'
986 query2
= dns
. message
. make_query ( name2
, 'A' , 'IN' )
987 response2
= dns
. message
. make_response ( query2
)
988 rrset2
= dns
. rrset
. from_text ( name2
,
993 response2
. answer
. append ( rrset2
)
996 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
997 self
. assertTrue ( receivedQuery
)
998 self
. assertTrue ( receivedResponse
)
999 receivedQuery
. id = query
. id
1000 self
. assertEquals ( query
, receivedQuery
)
1001 self
. assertEquals ( response
, receivedResponse
)
1004 # next queries should hit the cache
1005 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1006 self
. assertEquals ( receivedResponse
, response
)
1008 # cache another entry
1009 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query2
, response2
)
1010 self
. assertTrue ( receivedQuery
)
1011 self
. assertTrue ( receivedResponse
)
1012 receivedQuery
. id = query2
. id
1013 self
. assertEquals ( query2
, receivedQuery
)
1014 self
. assertEquals ( response2
, receivedResponse
)
1017 # queries for name and name 2 should hit the cache
1018 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1019 self
. assertEquals ( receivedResponse
, response
)
1021 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1022 self
. assertEquals ( receivedResponse
, response2
)
1024 # remove cached entries from name
1025 self
. sendConsoleCommand ( "getPool( \"\" ):getCache():expungeByName(newDNSName( \" " + name
+ " \" ))" )
1028 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1029 self
. assertTrue ( receivedQuery
)
1030 self
. assertTrue ( receivedResponse
)
1031 receivedQuery
. id = query
. id
1032 self
. assertEquals ( query
, receivedQuery
)
1033 self
. assertEquals ( response
, receivedResponse
)
1036 # next queries for name should hit the cache again
1037 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1038 self
. assertEquals ( receivedResponse
, response
)
1040 # queries for name2 should still hit the cache
1041 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1042 self
. assertEquals ( receivedResponse
, response2
)
1045 for key
in self
._ responsesCounter
:
1046 total
+= self
._ responsesCounter
[ key
]
1048 self
. assertEquals ( total
, misses
)
1050 def testCacheExpungeByNameAndType ( self
):
1052 Cache: Expunge by name and type
1057 name
= 'expungebynameandtype.cache.tests.powerdns.com.'
1058 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1059 response
= dns
. message
. make_response ( query
)
1060 rrset
= dns
. rrset
. from_text ( name
,
1065 response
. answer
. append ( rrset
)
1067 query2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1068 response2
= dns
. message
. make_response ( query2
)
1069 rrset2
= dns
. rrset
. from_text ( name
,
1074 response2
. answer
. append ( rrset2
)
1077 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1078 self
. assertTrue ( receivedQuery
)
1079 self
. assertTrue ( receivedResponse
)
1080 receivedQuery
. id = query
. id
1081 self
. assertEquals ( query
, receivedQuery
)
1082 self
. assertEquals ( response
, receivedResponse
)
1085 # next queries should hit the cache
1086 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1087 self
. assertEquals ( receivedResponse
, response
)
1089 # cache another entry
1090 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query2
, response2
)
1091 self
. assertTrue ( receivedQuery
)
1092 self
. assertTrue ( receivedResponse
)
1093 receivedQuery
. id = query2
. id
1094 self
. assertEquals ( query2
, receivedQuery
)
1095 self
. assertEquals ( response2
, receivedResponse
)
1098 # queries for name A and AAAA should hit the cache
1099 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1100 self
. assertEquals ( receivedResponse
, response
)
1102 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1103 self
. assertEquals ( receivedResponse
, response2
)
1105 # remove cached entries from name A
1106 self
. sendConsoleCommand ( "getPool( \"\" ):getCache():expungeByName(newDNSName( \" " + name
+ " \" ), DNSQType.A)" )
1109 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1110 self
. assertTrue ( receivedQuery
)
1111 self
. assertTrue ( receivedResponse
)
1112 receivedQuery
. id = query
. id
1113 self
. assertEquals ( query
, receivedQuery
)
1114 self
. assertEquals ( response
, receivedResponse
)
1117 # next queries for name A should hit the cache again
1118 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1119 self
. assertEquals ( receivedResponse
, response
)
1121 # queries for name AAAA should still hit the cache
1122 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1123 self
. assertEquals ( receivedResponse
, response2
)
1126 for key
in self
._ responsesCounter
:
1127 total
+= self
._ responsesCounter
[ key
]
1128 self
. assertEquals ( total
, misses
)
1130 def testCacheExpungeByNameAndSuffix ( self
):
1132 Cache: Expunge by name
1137 name
= 'expungebyname.suffix.cache.tests.powerdns.com.'
1138 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1139 response
= dns
. message
. make_response ( query
)
1140 rrset
= dns
. rrset
. from_text ( name
,
1145 response
. answer
. append ( rrset
)
1147 name2
= 'expungebyname.suffixother.cache.tests.powerdns.com.'
1148 query2
= dns
. message
. make_query ( name2
, 'A' , 'IN' )
1149 response2
= dns
. message
. make_response ( query2
)
1150 rrset2
= dns
. rrset
. from_text ( name2
,
1155 response2
. answer
. append ( rrset2
)
1158 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1159 self
. assertTrue ( receivedQuery
)
1160 self
. assertTrue ( receivedResponse
)
1161 receivedQuery
. id = query
. id
1162 self
. assertEquals ( query
, receivedQuery
)
1163 self
. assertEquals ( response
, receivedResponse
)
1166 # next queries should hit the cache
1167 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1168 self
. assertEquals ( receivedResponse
, response
)
1170 # cache another entry
1171 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query2
, response2
)
1172 self
. assertTrue ( receivedQuery
)
1173 self
. assertTrue ( receivedResponse
)
1174 receivedQuery
. id = query2
. id
1175 self
. assertEquals ( query2
, receivedQuery
)
1176 self
. assertEquals ( response2
, receivedResponse
)
1179 # queries for name and name 2 should hit the cache
1180 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1181 self
. assertEquals ( receivedResponse
, response
)
1183 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1184 self
. assertEquals ( receivedResponse
, response2
)
1186 # remove cached entries from name
1187 self
. sendConsoleCommand ( "getPool( \"\" ):getCache():expungeByName(newDNSName( \" suffix.cache.tests.powerdns.com. \" ), DNSQType.ANY, true)" )
1190 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1191 self
. assertTrue ( receivedQuery
)
1192 self
. assertTrue ( receivedResponse
)
1193 receivedQuery
. id = query
. id
1194 self
. assertEquals ( query
, receivedQuery
)
1195 self
. assertEquals ( response
, receivedResponse
)
1198 # next queries for name should hit the cache again
1199 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1200 self
. assertEquals ( receivedResponse
, response
)
1202 # queries for name2 should still hit the cache
1203 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1204 self
. assertEquals ( receivedResponse
, response2
)
1207 for key
in self
._ responsesCounter
:
1208 total
+= self
._ responsesCounter
[ key
]
1210 self
. assertEquals ( total
, misses
)
1212 def testCacheExpungeByNameAndTypeAndSuffix ( self
):
1214 Cache: Expunge by name and type
1219 name
= 'expungebynameandtype.suffixtype.cache.tests.powerdns.com.'
1220 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1221 response
= dns
. message
. make_response ( query
)
1222 rrset
= dns
. rrset
. from_text ( name
,
1227 response
. answer
. append ( rrset
)
1229 query2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1230 response2
= dns
. message
. make_response ( query2
)
1231 rrset2
= dns
. rrset
. from_text ( name
,
1236 response2
. answer
. append ( rrset2
)
1239 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1240 self
. assertTrue ( receivedQuery
)
1241 self
. assertTrue ( receivedResponse
)
1242 receivedQuery
. id = query
. id
1243 self
. assertEquals ( query
, receivedQuery
)
1244 self
. assertEquals ( response
, receivedResponse
)
1247 # next queries should hit the cache
1248 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1249 self
. assertEquals ( receivedResponse
, response
)
1251 # cache another entry
1252 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query2
, response2
)
1253 self
. assertTrue ( receivedQuery
)
1254 self
. assertTrue ( receivedResponse
)
1255 receivedQuery
. id = query2
. id
1256 self
. assertEquals ( query2
, receivedQuery
)
1257 self
. assertEquals ( response2
, receivedResponse
)
1260 # queries for name A and AAAA should hit the cache
1261 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1262 self
. assertEquals ( receivedResponse
, response
)
1264 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1265 self
. assertEquals ( receivedResponse
, response2
)
1267 # remove cached entries from name A
1268 self
. sendConsoleCommand ( "getPool( \"\" ):getCache():expungeByName(newDNSName( \" suffixtype.cache.tests.powerdns.com. \" ), DNSQType.A, true)" )
1271 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1272 self
. assertTrue ( receivedQuery
)
1273 self
. assertTrue ( receivedResponse
)
1274 receivedQuery
. id = query
. id
1275 self
. assertEquals ( query
, receivedQuery
)
1276 self
. assertEquals ( response
, receivedResponse
)
1279 # next queries for name A should hit the cache again
1280 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1281 self
. assertEquals ( receivedResponse
, response
)
1283 # queries for name AAAA should still hit the cache
1284 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1285 self
. assertEquals ( receivedResponse
, response2
)
1288 for key
in self
._ responsesCounter
:
1289 total
+= self
._ responsesCounter
[ key
]
1290 self
. assertEquals ( total
, misses
)
1292 class TestCachingTTL ( DNSDistTest
):
1294 _maxCacheTTL
= 86400
1296 _config_params
= [ '_maxCacheTTL' , '_minCacheTTL' , '_testServerPort' ]
1297 _config_template
= """
1298 pc = newPacketCache(1000, {maxTTL= %d , minTTL= %d })
1299 getPool(""):setCache(pc)
1300 newServer{address="127.0.0.1: %d "}
1302 def testCacheShortTTL ( self
):
1304 Cache: Entries with a TTL shorter than minTTL
1309 name
= 'ttltooshort.cache.tests.powerdns.com.'
1310 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1311 response
= dns
. message
. make_response ( query
)
1312 rrset
= dns
. rrset
. from_text ( name
,
1317 response
. answer
. append ( rrset
)
1320 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1321 self
. assertTrue ( receivedQuery
)
1322 self
. assertTrue ( receivedResponse
)
1323 receivedQuery
. id = query
. id
1324 self
. assertEquals ( query
, receivedQuery
)
1325 self
. assertEquals ( response
, receivedResponse
)
1326 for an
in receivedResponse
. answer
:
1327 self
. assertEquals ( an
. ttl
, ttl
)
1330 # We should not have been cached
1331 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1332 self
. assertTrue ( receivedQuery
)
1333 self
. assertTrue ( receivedResponse
)
1334 receivedQuery
. id = query
. id
1335 self
. assertEquals ( query
, receivedQuery
)
1336 self
. assertEquals ( response
, receivedResponse
)
1337 for an
in receivedResponse
. answer
:
1338 self
. assertEquals ( an
. ttl
, ttl
)
1342 for key
in self
._ responsesCounter
:
1343 total
+= self
._ responsesCounter
[ key
]
1345 self
. assertEquals ( total
, misses
)
1347 def testCacheNXWithNoRR ( self
):
1349 Cache: NX with no RR
1353 name
= 'nxwithnorr.cache.tests.powerdns.com.'
1354 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1355 response
= dns
. message
. make_response ( query
)
1356 response
. set_rcode ( dns
. rcode
. NXDOMAIN
)
1359 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1360 self
. assertTrue ( receivedQuery
)
1361 self
. assertTrue ( receivedResponse
)
1362 receivedQuery
. id = query
. id
1363 self
. assertEquals ( query
, receivedQuery
)
1364 self
. assertEquals ( response
, receivedResponse
)
1367 # We should not have been cached
1368 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1369 self
. assertTrue ( receivedQuery
)
1370 self
. assertTrue ( receivedResponse
)
1371 receivedQuery
. id = query
. id
1372 self
. assertEquals ( query
, receivedQuery
)
1373 self
. assertEquals ( response
, receivedResponse
)
1377 for key
in self
._ responsesCounter
:
1378 total
+= self
._ responsesCounter
[ key
]
1380 self
. assertEquals ( total
, misses
)
1382 class TestCachingLongTTL ( DNSDistTest
):
1385 _config_params
= [ '_maxCacheTTL' , '_testServerPort' ]
1386 _config_template
= """
1387 pc = newPacketCache(1000, {maxTTL= %d })
1388 getPool(""):setCache(pc)
1389 newServer{address="127.0.0.1: %d "}
1391 def testCacheLongTTL ( self
):
1393 Cache: Entries with a longer TTL than the maximum
1398 name
= 'longttl.cache.tests.powerdns.com.'
1399 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1400 response
= dns
. message
. make_response ( query
)
1401 rrset
= dns
. rrset
. from_text ( name
,
1406 response
. answer
. append ( rrset
)
1409 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1410 self
. assertTrue ( receivedQuery
)
1411 self
. assertTrue ( receivedResponse
)
1412 receivedQuery
. id = query
. id
1413 self
. assertEquals ( query
, receivedQuery
)
1414 self
. assertEquals ( response
, receivedResponse
)
1415 for an
in receivedResponse
. answer
:
1416 self
. assertEquals ( an
. ttl
, ttl
)
1419 # next queries should hit the cache
1420 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1421 self
. assertEquals ( receivedResponse
, response
)
1422 for an
in receivedResponse
. answer
:
1423 self
. assertTrue ( an
. ttl
<= ttl
)
1425 time
. sleep ( self
._ maxCacheTTL
+ 1 )
1427 # we should not have cached for longer than max cache
1428 # so it should be a miss
1429 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1430 self
. assertTrue ( receivedQuery
)
1431 self
. assertTrue ( receivedResponse
)
1432 receivedQuery
. id = query
. id
1433 self
. assertEquals ( query
, receivedQuery
)
1434 self
. assertEquals ( response
, receivedResponse
)
1435 for an
in receivedResponse
. answer
:
1436 self
. assertEquals ( an
. ttl
, ttl
)
1440 for key
in self
._ responsesCounter
:
1441 total
+= self
._ responsesCounter
[ key
]
1443 self
. assertEquals ( total
, misses
)
1445 class TestCachingFailureTTL ( DNSDistTest
):
1447 _failureCacheTTL
= 2
1448 _config_params
= [ '_failureCacheTTL' , '_testServerPort' ]
1449 _config_template
= """
1450 pc = newPacketCache(1000, {maxTTL=86400, minTTL=0, temporaryFailureTTL= %d , staleTTL=60})
1451 getPool(""):setCache(pc)
1452 newServer{address="127.0.0.1: %d "}
1454 def testCacheServFailTTL ( self
):
1460 name
= 'servfail.failure.cache.tests.powerdns.com.'
1461 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1462 response
= dns
. message
. make_response ( query
)
1463 response
. set_rcode ( dns
. rcode
. SERVFAIL
)
1466 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1467 self
. assertTrue ( receivedQuery
)
1468 self
. assertTrue ( receivedResponse
)
1469 receivedQuery
. id = query
. id
1470 self
. assertEquals ( query
, receivedQuery
)
1471 self
. assertEquals ( response
, receivedResponse
)
1474 # next queries should hit the cache
1475 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1476 self
. assertEquals ( receivedResponse
, response
)
1478 time
. sleep ( self
._ failureCacheTTL
+ 1 )
1480 # we should not have cached for longer than failure cache
1481 # so it should be a miss
1482 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1483 self
. assertTrue ( receivedQuery
)
1484 self
. assertTrue ( receivedResponse
)
1485 receivedQuery
. id = query
. id
1486 self
. assertEquals ( query
, receivedQuery
)
1487 self
. assertEquals ( response
, receivedResponse
)
1491 for key
in self
._ responsesCounter
:
1492 total
+= self
._ responsesCounter
[ key
]
1494 self
. assertEquals ( total
, misses
)
1496 def testCacheRefusedTTL ( self
):
1502 name
= 'refused.failure.cache.tests.powerdns.com.'
1503 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1504 response
= dns
. message
. make_response ( query
)
1505 response
. set_rcode ( dns
. rcode
. REFUSED
)
1508 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1509 self
. assertTrue ( receivedQuery
)
1510 self
. assertTrue ( receivedResponse
)
1511 receivedQuery
. id = query
. id
1512 self
. assertEquals ( query
, receivedQuery
)
1513 self
. assertEquals ( response
, receivedResponse
)
1516 # next queries should hit the cache
1517 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1518 self
. assertEquals ( receivedResponse
, response
)
1520 time
. sleep ( self
._ failureCacheTTL
+ 1 )
1522 # we should not have cached for longer than failure cache
1523 # so it should be a miss
1524 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1525 self
. assertTrue ( receivedQuery
)
1526 self
. assertTrue ( receivedResponse
)
1527 receivedQuery
. id = query
. id
1528 self
. assertEquals ( query
, receivedQuery
)
1529 self
. assertEquals ( response
, receivedResponse
)
1533 for key
in self
._ responsesCounter
:
1534 total
+= self
._ responsesCounter
[ key
]
1536 self
. assertEquals ( total
, misses
)
1538 def testCacheHeaderOnlyRefusedTTL ( self
):
1540 Cache: Header-Only Refused TTL
1544 name
= 'header-only-refused.failure.cache.tests.powerdns.com.'
1545 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1546 response
= dns
. message
. make_response ( query
)
1547 response
. set_rcode ( dns
. rcode
. REFUSED
)
1548 response
. question
= []
1551 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1552 self
. assertTrue ( receivedQuery
)
1553 self
. assertTrue ( receivedResponse
)
1554 receivedQuery
. id = query
. id
1555 self
. assertEquals ( query
, receivedQuery
)
1556 self
. assertEquals ( response
, receivedResponse
)
1559 # next queries should hit the cache
1560 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1561 self
. assertEquals ( receivedResponse
, response
)
1563 time
. sleep ( self
._ failureCacheTTL
+ 1 )
1565 # we should not have cached for longer than failure cache
1566 # so it should be a miss
1567 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1568 self
. assertTrue ( receivedQuery
)
1569 self
. assertTrue ( receivedResponse
)
1570 receivedQuery
. id = query
. id
1571 self
. assertEquals ( query
, receivedQuery
)
1572 self
. assertEquals ( response
, receivedResponse
)
1576 for key
in self
._ responsesCounter
:
1577 total
+= self
._ responsesCounter
[ key
]
1579 self
. assertEquals ( total
, misses
)
1581 class TestCachingNegativeTTL ( DNSDistTest
):
1584 _config_params
= [ '_negCacheTTL' , '_testServerPort' ]
1585 _config_template
= """
1586 pc = newPacketCache(1000, {maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false, numberOfShards=1, deferrableInsertLock=true, maxNegativeTTL= %d })
1587 getPool(""):setCache(pc)
1588 newServer{address="127.0.0.1: %d "}
1591 def testCacheNegativeTTLNXDomain ( self
):
1593 Cache: Negative TTL on NXDOMAIN
1597 name
= 'nxdomain.negativettl.cache.tests.powerdns.com.'
1598 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1599 response
= dns
. message
. make_response ( query
)
1600 response
. set_rcode ( dns
. rcode
. NXDOMAIN
)
1601 soa
= dns
. rrset
. from_text ( name
,
1605 'ns.' + name
+ ' hostmaster.' + name
+ ' 1 3600 3600 3600 60' )
1606 response
. authority
. append ( soa
)
1609 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1610 self
. assertTrue ( receivedQuery
)
1611 self
. assertTrue ( receivedResponse
)
1612 receivedQuery
. id = query
. id
1613 self
. assertEquals ( query
, receivedQuery
)
1614 self
. assertEquals ( response
, receivedResponse
)
1617 # next queries should hit the cache
1618 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1619 self
. assertEquals ( receivedResponse
, response
)
1621 time
. sleep ( self
._ negCacheTTL
+ 1 )
1623 # we should not have cached for longer than the negative TTL
1624 # so it should be a miss
1625 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1626 self
. assertTrue ( receivedQuery
)
1627 self
. assertTrue ( receivedResponse
)
1628 receivedQuery
. id = query
. id
1629 self
. assertEquals ( query
, receivedQuery
)
1630 self
. assertEquals ( response
, receivedResponse
)
1634 for key
in self
._ responsesCounter
:
1635 total
+= self
._ responsesCounter
[ key
]
1637 self
. assertEquals ( total
, misses
)
1639 def testCacheNegativeTTLNoData ( self
):
1641 Cache: Negative TTL on NoData
1645 name
= 'nodata.negativettl.cache.tests.powerdns.com.'
1646 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1647 response
= dns
. message
. make_response ( query
)
1648 response
. set_rcode ( dns
. rcode
. NOERROR
)
1649 soa
= dns
. rrset
. from_text ( name
,
1653 'ns.' + name
+ ' hostmaster.' + name
+ ' 1 3600 3600 3600 60' )
1654 response
. authority
. append ( soa
)
1657 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1658 self
. assertTrue ( receivedQuery
)
1659 self
. assertTrue ( receivedResponse
)
1660 receivedQuery
. id = query
. id
1661 self
. assertEquals ( query
, receivedQuery
)
1662 self
. assertEquals ( response
, receivedResponse
)
1665 # next queries should hit the cache
1666 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1667 self
. assertEquals ( receivedResponse
, response
)
1669 time
. sleep ( self
._ negCacheTTL
+ 1 )
1671 # we should not have cached for longer than the negativel TTL
1672 # so it should be a miss
1673 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1674 self
. assertTrue ( receivedQuery
)
1675 self
. assertTrue ( receivedResponse
)
1676 receivedQuery
. id = query
. id
1677 self
. assertEquals ( query
, receivedQuery
)
1678 self
. assertEquals ( response
, receivedResponse
)
1682 for key
in self
._ responsesCounter
:
1683 total
+= self
._ responsesCounter
[ key
]
1685 self
. assertEquals ( total
, misses
)
1687 class TestCachingDontAge ( DNSDistTest
):
1689 _config_template
= """
1690 pc = newPacketCache(100, {maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=true})
1691 getPool(""):setCache(pc)
1692 newServer{address="127.0.0.1: %d "}
1694 def testCacheDoesntDecreaseTTL ( self
):
1696 Cache: Cache doesn't decrease TTL with 'don't age' set
1698 dnsdist is configured to cache entries but without aging the TTL,
1699 we are sending one request (cache miss) and verify that the cache
1700 hits don't have a decreasing TTL.
1704 name
= 'cachedoesntdecreasettl.cache-dont-age.tests.powerdns.com.'
1705 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1706 response
= dns
. message
. make_response ( query
)
1707 rrset
= dns
. rrset
. from_text ( name
,
1712 response
. answer
. append ( rrset
)
1714 # first query to fill the cache
1715 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1716 self
. assertTrue ( receivedQuery
)
1717 self
. assertTrue ( receivedResponse
)
1718 receivedQuery
. id = query
. id
1719 self
. assertEquals ( query
, receivedQuery
)
1720 self
. assertEquals ( receivedResponse
, response
)
1723 # next queries should hit the cache
1724 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1725 self
. assertEquals ( receivedResponse
, response
)
1726 for an
in receivedResponse
. answer
:
1727 self
. assertTrue ( an
. ttl
== ttl
)
1729 # now we wait a bit for the TTL to decrease
1732 # next queries should hit the cache
1733 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1734 self
. assertEquals ( receivedResponse
, response
)
1735 for an
in receivedResponse
. answer
:
1736 self
. assertTrue ( an
. ttl
== ttl
)
1739 for key
in self
._ responsesCounter
:
1740 total
+= self
._ responsesCounter
[ key
]
1742 self
. assertEquals ( total
, misses
)
1744 class TestCachingECSWithoutPoolECS ( DNSDistTest
):
1746 _consoleKey
= DNSDistTest
. generateConsoleKey ()
1747 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
1748 _config_params
= [ '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
1749 _config_template
= """
1750 pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
1751 getPool(""):setCache(pc)
1753 controlSocket("127.0.0.1: %d ")
1754 newServer{address="127.0.0.1: %d ", useClientSubnet=true}
1757 def testCached ( self
):
1759 Cache: Cached entry with ECS is a miss when no backend are available
1762 name
= 'cached.cache-ecs-without-pool-ecs.tests.powerdns.com.'
1763 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1764 response
= dns
. message
. make_response ( query
)
1765 rrset
= dns
. rrset
. from_text ( name
,
1770 response
. answer
. append ( rrset
)
1772 # first query to fill the cache
1773 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1774 sender
= getattr ( self
, method
)
1775 ( receivedQuery
, receivedResponse
) = sender ( query
, response
)
1776 self
. assertTrue ( receivedQuery
)
1777 self
. assertTrue ( receivedResponse
)
1778 receivedQuery
. id = query
. id
1779 self
. assertEquals ( query
, receivedQuery
)
1780 self
. assertEquals ( receivedResponse
, response
)
1782 # next queries should hit the cache
1783 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1784 sender
= getattr ( self
, method
)
1785 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
1786 self
. assertEquals ( receivedResponse
, response
)
1788 # we mark the backend as down
1789 self
. sendConsoleCommand ( "getServer(0):setDown()" )
1791 # we should NOT get a cached entry since it has ECS and we haven't asked the pool
1792 # to add ECS when no backend is up
1793 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1794 sender
= getattr ( self
, method
)
1795 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
1796 self
. assertEquals ( receivedResponse
, None )
1798 class TestCachingECSWithPoolECS ( DNSDistTest
):
1800 _consoleKey
= DNSDistTest
. generateConsoleKey ()
1801 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
1802 _config_params
= [ '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
1803 _config_template
= """
1804 pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
1805 getPool(""):setCache(pc)
1806 getPool(""):setECS(true)
1808 controlSocket("127.0.0.1: %d ")
1809 newServer{address="127.0.0.1: %d ", useClientSubnet=true}
1812 def testCached ( self
):
1814 Cache: Cached entry with ECS is a hit when no backend are available
1817 name
= 'cached.cache-ecs-with-pool-ecs.tests.powerdns.com.'
1818 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1819 response
= dns
. message
. make_response ( query
)
1820 rrset
= dns
. rrset
. from_text ( name
,
1825 response
. answer
. append ( rrset
)
1827 # first query to fill the cache
1828 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1829 sender
= getattr ( self
, method
)
1830 ( receivedQuery
, receivedResponse
) = sender ( query
, response
)
1831 self
. assertTrue ( receivedQuery
)
1832 self
. assertTrue ( receivedResponse
)
1833 receivedQuery
. id = query
. id
1834 self
. assertEquals ( query
, receivedQuery
)
1835 self
. assertEquals ( receivedResponse
, response
)
1837 # next queries should hit the cache
1838 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1839 sender
= getattr ( self
, method
)
1840 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
1841 self
. assertEquals ( receivedResponse
, response
)
1843 # we mark the backend as down
1844 self
. sendConsoleCommand ( "getServer(0):setDown()" )
1846 # we should STILL get a cached entry since it has ECS and we have asked the pool
1847 # to add ECS when no backend is up
1848 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1849 sender
= getattr ( self
, method
)
1850 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
1851 self
. assertEquals ( receivedResponse
, response
)
1853 class TestCachingCollisionNoECSParsing ( DNSDistTest
):
1855 _config_template
= """
1856 pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
1857 getPool(""):setCache(pc)
1858 newServer{address="127.0.0.1: %d "}
1861 def testCacheCollisionNoECSParsing ( self
):
1863 Cache: Collision with no ECS parsing
1865 name
= 'collision-no-ecs-parsing.cache.tests.powerdns.com.'
1866 ecso
= clientsubnetoption
. ClientSubnetOption ( '10.0.188.3' , 32 )
1867 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
1868 query
. flags
= dns
. flags
. RD
1869 response
= dns
. message
. make_response ( query
)
1870 rrset
= dns
. rrset
. from_text ( name
,
1875 response
. answer
. append ( rrset
)
1877 # first query should to fill the cache
1878 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1879 self
. assertTrue ( receivedQuery
)
1880 self
. assertTrue ( receivedResponse
)
1881 receivedQuery
. id = query
. id
1882 self
. assertEquals ( query
, receivedQuery
)
1883 self
. assertEquals ( receivedResponse
, response
)
1885 # second query will hash to the same key, triggering a collision which
1886 # will not be detected because the qname, qtype, qclass and flags will
1887 # match and EDNS Client Subnet parsing has not been enabled
1888 ecso2
= clientsubnetoption
. ClientSubnetOption ( '10.0.192.138' , 32 )
1889 query2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso2
], payload
= 512 )
1890 query2
. flags
= dns
. flags
. RD
1891 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1892 receivedResponse
. id = response
. id
1893 self
. assertEquals ( receivedResponse
, response
)
1895 class TestCachingCollisionWithECSParsing ( DNSDistTest
):
1897 _config_template
= """
1898 pc = newPacketCache(100, {maxTTL=86400, minTTL=1, temporaryFailureTTL=60, staleTTL=60, dontAge=false, numberOfShards=1, deferrableInsertLock=true, maxNegativeTTL=3600, parseECS=true})
1899 getPool(""):setCache(pc)
1900 newServer{address="127.0.0.1: %d "}
1903 def testCacheCollisionWithECSParsing ( self
):
1905 Cache: Collision with ECS parsing
1907 name
= 'collision-with-ecs-parsing.cache.tests.powerdns.com.'
1908 ecso
= clientsubnetoption
. ClientSubnetOption ( '10.0.115.61' , 32 )
1909 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
1910 query
. flags
= dns
. flags
. RD
1911 response
= dns
. message
. make_response ( query
)
1912 rrset
= dns
. rrset
. from_text ( name
,
1917 response
. answer
. append ( rrset
)
1919 # first query should to fill the cache
1920 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1921 self
. assertTrue ( receivedQuery
)
1922 self
. assertTrue ( receivedResponse
)
1923 receivedQuery
. id = query
. id
1924 self
. assertEquals ( query
, receivedQuery
)
1925 self
. assertEquals ( receivedResponse
, response
)
1927 # second query will hash to the same key, triggering a collision which
1928 # _will_ be detected this time because the qname, qtype, qclass and flags will
1929 # match but EDNS Client Subnet parsing is now enabled and will detect the issue
1930 ecso2
= clientsubnetoption
. ClientSubnetOption ( '10.0.143.21' , 32 )
1931 query2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso2
], payload
= 512 )
1932 query2
. flags
= dns
. flags
. RD
1933 response2
= dns
. message
. make_response ( query2
)
1934 rrset
= dns
. rrset
. from_text ( name
,
1939 response2
. answer
. append ( rrset
)
1940 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query2
, response2
)
1941 self
. assertEquals ( receivedResponse
, response2
)
1943 class TestCachingScopeZero ( DNSDistTest
):
1945 _config_template
= """
1946 -- Be careful to enable ECS parsing in the packet cache, otherwise scope zero is disabled
1947 pc = newPacketCache(100, {maxTTL=86400, minTTL=1, temporaryFailureTTL=60, staleTTL=60, dontAge=false, numberOfShards=1, deferrableInsertLock=true, maxNegativeTTL=3600, parseECS=true})
1948 getPool(""):setCache(pc)
1949 newServer{address="127.0.0.1: %d ", useClientSubnet=true}
1950 -- to simulate a second client coming from a different IP address,
1951 -- we will force the ECS value added to the query if RD is set (note that we need
1952 -- to unset it using rules before the first cache lookup)
1953 addAction(RDRule(), SetECSAction("192.0.2.1/32"))
1954 addAction(RDRule(), NoRecurseAction())
1957 def testScopeZero ( self
):
1959 Cache: Test the scope-zero feature, backend returns a scope of zero
1962 name
= 'scope-zero.cache.tests.powerdns.com.'
1963 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1964 query
. flags
&= ~dns
. flags
. RD
1965 ecso
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.0' , 24 )
1966 expectedQuery
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
1967 expectedQuery
. flags
&= ~dns
. flags
. RD
1968 ecsoResponse
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.1' , 24 , 0 )
1969 expectedResponse
= dns
. message
. make_response ( query
)
1970 scopedResponse
= dns
. message
. make_response ( query
)
1971 scopedResponse
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse
])
1972 rrset
= dns
. rrset
. from_text ( name
,
1977 scopedResponse
. answer
. append ( rrset
)
1978 expectedResponse
. answer
. append ( rrset
)
1980 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1981 sender
= getattr ( self
, method
)
1982 ( receivedQuery
, receivedResponse
) = sender ( query
, scopedResponse
)
1983 receivedQuery
. id = expectedQuery
. id
1984 self
. checkMessageEDNSWithECS ( expectedQuery
, receivedQuery
)
1985 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
1987 # next query should hit the cache, nothing special about that
1988 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1989 sender
= getattr ( self
, method
)
1990 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
1991 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
1993 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1994 query
. flags
&= dns
. flags
. RD
1995 # next query FROM A DIFFERENT CLIENT since RD is now set should STILL hit the cache
1996 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1997 sender
= getattr ( self
, method
)
1998 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
1999 receivedResponse
. id = expectedResponse
. id
2000 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
2002 name
= 'scope-zero-with-ecs.cache.tests.powerdns.com.'
2003 ecso
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.1' , 24 )
2004 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
2005 query
. flags
&= ~dns
. flags
. RD
2006 expectedQuery
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
2007 expectedQuery
. flags
&= ~dns
. flags
. RD
2008 expectedResponse
= dns
. message
. make_response ( query
)
2009 expectedResponse
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse
])
2010 expectedResponse
. answer
. append ( rrset
)
2011 scopedResponse
= dns
. message
. make_response ( query
)
2012 scopedResponse
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse
])
2013 scopedResponse
. answer
. append ( rrset
)
2014 # this query has ECS, it should NOT be able to use the scope-zero cached entry since the hash will be
2016 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2017 sender
= getattr ( self
, method
)
2018 ( receivedQuery
, receivedResponse
) = sender ( query
, scopedResponse
)
2019 receivedQuery
. id = expectedQuery
. id
2020 self
. checkMessageEDNSWithECS ( expectedQuery
, receivedQuery
)
2021 self
. checkMessageEDNSWithECS ( receivedResponse
, expectedResponse
)
2023 # it should still have been cached, though, so the next query should be a hit
2024 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2025 sender
= getattr ( self
, method
)
2026 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
2027 self
. checkMessageEDNSWithECS ( receivedResponse
, expectedResponse
)
2029 def testScopeNotZero ( self
):
2031 Cache: Test the scope-zero feature, backend returns a scope of non-zero
2034 name
= 'scope-not-zero.cache.tests.powerdns.com.'
2035 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
2036 query
. flags
&= ~dns
. flags
. RD
2037 ecso
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.0' , 24 )
2038 expectedQuery
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
2039 expectedQuery
. flags
&= ~dns
. flags
. RD
2040 ecso2
= clientsubnetoption
. ClientSubnetOption ( '192.0.2.1' , 32 )
2041 expectedQuery2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso2
], payload
= 512 )
2042 expectedQuery2
. flags
&= ~dns
. flags
. RD
2043 ecsoResponse
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.1' , 24 , 24 )
2044 ecsoResponse2
= clientsubnetoption
. ClientSubnetOption ( '192.0.2.1' , 32 , 24 )
2045 rrset
= dns
. rrset
. from_text ( name
,
2050 expectedResponse
= dns
. message
. make_response ( query
)
2051 expectedResponse
. answer
. append ( rrset
)
2052 scopedResponse
= dns
. message
. make_response ( query
)
2053 scopedResponse
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse
])
2054 scopedResponse
. answer
. append ( rrset
)
2055 scopedResponse2
= dns
. message
. make_response ( query
)
2056 scopedResponse2
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse2
])
2057 scopedResponse2
. answer
. append ( rrset
)
2059 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2060 sender
= getattr ( self
, method
)
2061 ( receivedQuery
, receivedResponse
) = sender ( query
, scopedResponse
)
2062 receivedQuery
. id = expectedQuery
. id
2063 self
. checkMessageEDNSWithECS ( expectedQuery
, receivedQuery
)
2064 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
2066 # next query should hit the cache, nothing special about that
2067 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2068 sender
= getattr ( self
, method
)
2069 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
2070 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
2072 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
2073 query
. flags
&= dns
. flags
. RD
2074 expectedResponse
= dns
. message
. make_response ( query
)
2075 expectedResponse
. answer
. append ( rrset
)
2076 # next query FROM A DIFFERENT CLIENT since RD is now set should NOT hit the cache
2077 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2078 sender
= getattr ( self
, method
)
2079 ( receivedQuery
, receivedResponse
) = sender ( query
, scopedResponse2
)
2080 receivedQuery
. id = expectedQuery2
. id
2081 self
. checkMessageEDNSWithECS ( expectedQuery2
, receivedQuery
)
2082 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
2084 def testNoECS ( self
):
2086 Cache: Test the scope-zero feature, backend returns no ECS at all
2089 name
= 'scope-zero-no-ecs.cache.tests.powerdns.com.'
2090 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
2091 query
. flags
&= ~dns
. flags
. RD
2092 ecso
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.0' , 24 )
2093 expectedQuery
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
2094 expectedQuery
. flags
&= ~dns
. flags
. RD
2095 ecso2
= clientsubnetoption
. ClientSubnetOption ( '192.0.2.1' , 32 )
2096 expectedQuery2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso2
], payload
= 512 )
2097 expectedQuery2
. flags
&= ~dns
. flags
. RD
2098 rrset
= dns
. rrset
. from_text ( name
,
2103 response
= dns
. message
. make_response ( query
)
2104 response
. answer
. append ( rrset
)
2106 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2107 sender
= getattr ( self
, method
)
2108 ( receivedQuery
, receivedResponse
) = sender ( query
, response
)
2109 receivedQuery
. id = expectedQuery
. id
2110 self
. checkMessageEDNSWithECS ( expectedQuery
, receivedQuery
)
2111 self
. checkMessageNoEDNS ( receivedResponse
, response
)
2113 # next query should hit the cache, nothing special about that
2114 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2115 sender
= getattr ( self
, method
)
2116 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
2117 self
. checkMessageNoEDNS ( receivedResponse
, response
)
2119 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
2120 query
. flags
&= dns
. flags
. RD
2121 response
= dns
. message
. make_response ( query
)
2122 response
. answer
. append ( rrset
)
2123 # next query FROM A DIFFERENT CLIENT since RD is now set should NOT hit the cache
2124 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2125 sender
= getattr ( self
, method
)
2126 ( receivedQuery
, receivedResponse
) = sender ( query
, response
)
2127 receivedQuery
. id = expectedQuery2
. id
2128 self
. checkMessageEDNSWithECS ( expectedQuery2
, receivedQuery
)
2129 self
. checkMessageNoEDNS ( receivedResponse
, response
)
2131 class TestCachingScopeZeroButNoSubnetcheck ( DNSDistTest
):
2133 _config_template
= """
2134 -- We disable ECS parsing in the packet cache, meaning scope zero is disabled
2135 pc = newPacketCache(100, {maxTTL=86400, minTTL=1, temporaryFailureTTL=60, staleTTL=60, dontAge=false, numberOfShards=1, deferrableInsertLock=true, maxNegativeTTL=3600, parseECS=false})
2136 getPool(""):setCache(pc)
2137 newServer{address="127.0.0.1: %d ", useClientSubnet=true}
2138 -- to simulate a second client coming from a different IP address,
2139 -- we will force the ECS value added to the query if RD is set (note that we need
2140 -- to unset it using rules before the first cache lookup)
2141 addAction(RDRule(), SetECSAction("192.0.2.1/32"))
2142 addAction(RDRule(), NoRecurseAction())
2145 def testScopeZero ( self
):
2147 Cache: Test that the scope-zero feature is disabled when ECS parsing is not enabled in the cache
2150 name
= 'scope-zero-no-subnet.cache.tests.powerdns.com.'
2151 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
2152 query
. flags
&= ~dns
. flags
. RD
2153 ecso
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.0' , 24 )
2154 expectedQuery
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
2155 expectedQuery
. flags
&= ~dns
. flags
. RD
2156 ecso2
= clientsubnetoption
. ClientSubnetOption ( '192.0.2.1' , 32 )
2157 expectedQuery2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso2
], payload
= 512 )
2158 expectedQuery2
. flags
&= ~dns
. flags
. RD
2159 ecsoResponse
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.1' , 24 , 0 )
2160 expectedResponse
= dns
. message
. make_response ( query
)
2161 scopedResponse
= dns
. message
. make_response ( query
)
2162 scopedResponse
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse
])
2163 rrset
= dns
. rrset
. from_text ( name
,
2168 scopedResponse
. answer
. append ( rrset
)
2169 expectedResponse
. answer
. append ( rrset
)
2171 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2172 sender
= getattr ( self
, method
)
2173 ( receivedQuery
, receivedResponse
) = sender ( query
, scopedResponse
)
2174 receivedQuery
. id = expectedQuery
. id
2175 self
. checkMessageEDNSWithECS ( expectedQuery
, receivedQuery
)
2176 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
2178 # next query should hit the cache, nothing special about that
2179 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2180 sender
= getattr ( self
, method
)
2181 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
2182 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
2184 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
2185 query
. flags
&= dns
. flags
. RD
2186 response
= dns
. message
. make_response ( query
)
2187 response
. answer
. append ( rrset
)
2188 # next query FROM A DIFFERENT CLIENT since RD is now set should NOT hit the cache
2189 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2190 sender
= getattr ( self
, method
)
2191 ( receivedQuery
, receivedResponse
) = sender ( query
, response
)
2192 receivedQuery
. id = expectedQuery2
. id
2193 self
. checkMessageEDNSWithECS ( expectedQuery2
, receivedQuery
)
2194 self
. checkMessageNoEDNS ( receivedResponse
, response
)