]> git.ipfire.org Git - thirdparty/pdns.git/blame - regression-tests.dnsdist/test_Caching.py
Merge pull request #4967 from jsoref/spelling
[thirdparty/pdns.git] / regression-tests.dnsdist / test_Caching.py
CommitLineData
903853f4 1#!/usr/bin/env python
1ea747c0 2import base64
903853f4
RG
3import time
4import dns
5from dnsdisttests import DNSDistTest
6
7class TestCaching(DNSDistTest):
8
9 _config_template = """
fe1c60f2 10 pc = newPacketCache(100, 86400, 1)
903853f4
RG
11 getPool(""):setCache(pc)
12 addAction(makeRule("nocache.cache.tests.powerdns.com."), SkipCacheAction())
816dff3d
RG
13 function skipViaLua(dq)
14 dq.skipCache = true
15 return DNSAction.None, ""
16 end
17 addLuaAction("nocachevialua.cache.tests.powerdns.com.", skipViaLua)
903853f4
RG
18 newServer{address="127.0.0.1:%s"}
19 """
fe1c60f2 20
903853f4
RG
21 def testCached(self):
22 """
23 Cache: Served from cache
24
25 dnsdist is configured to cache entries, we are sending several
26 identical requests and checking that the backend only receive
27 the first one.
28 """
29 numberOfQueries = 10
30 name = 'cached.cache.tests.powerdns.com.'
31 query = dns.message.make_query(name, 'AAAA', 'IN')
32 response = dns.message.make_response(query)
33 rrset = dns.rrset.from_text(name,
34 3600,
35 dns.rdataclass.IN,
36 dns.rdatatype.AAAA,
37 '::1')
38 response.answer.append(rrset)
39
40 # first query to fill the cache
41 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
42 self.assertTrue(receivedQuery)
43 self.assertTrue(receivedResponse)
44 receivedQuery.id = query.id
45 self.assertEquals(query, receivedQuery)
46 self.assertEquals(receivedResponse, response)
47
48 for _ in range(numberOfQueries):
49 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
50 self.assertEquals(receivedResponse, response)
51
52 total = 0
02bbf9eb
RG
53 for key in self._responsesCounter:
54 total += self._responsesCounter[key]
903853f4
RG
55 TestCaching._responsesCounter[key] = 0
56
57 self.assertEquals(total, 1)
58
59 # TCP should not be cached
60 # first query to fill the cache
61 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
62 self.assertTrue(receivedQuery)
63 self.assertTrue(receivedResponse)
64 receivedQuery.id = query.id
65 self.assertEquals(query, receivedQuery)
66 self.assertEquals(receivedResponse, response)
67
68 for _ in range(numberOfQueries):
69 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
70 self.assertEquals(receivedResponse, response)
71
72 total = 0
02bbf9eb
RG
73 for key in self._responsesCounter:
74 total += self._responsesCounter[key]
903853f4
RG
75 TestCaching._responsesCounter[key] = 0
76
77 self.assertEquals(total, 1)
78
79 def testSkipCache(self):
80 """
81 Cache: SkipCacheAction
82
83 dnsdist is configured to not cache entries for nocache.cache.tests.powerdns.com.
84 we are sending several requests and checking that the backend get them all.
85 """
86 name = 'nocache.cache.tests.powerdns.com.'
87 numberOfQueries = 10
88 query = dns.message.make_query(name, 'AAAA', 'IN')
89 response = dns.message.make_response(query)
816dff3d
RG
90 rrset = dns.rrset.from_text(name,
91 3600,
92 dns.rdataclass.IN,
93 dns.rdatatype.AAAA,
94 '::1')
95 response.answer.append(rrset)
96
97 for _ in range(numberOfQueries):
98 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
99 self.assertTrue(receivedQuery)
100 self.assertTrue(receivedResponse)
101 receivedQuery.id = query.id
102 self.assertEquals(query, receivedQuery)
103 self.assertEquals(receivedResponse, response)
104
105 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
106 self.assertTrue(receivedQuery)
107 self.assertTrue(receivedResponse)
108 receivedQuery.id = query.id
109 self.assertEquals(query, receivedQuery)
110 self.assertEquals(receivedResponse, response)
111
02bbf9eb
RG
112 for key in self._responsesCounter:
113 value = self._responsesCounter[key]
816dff3d
RG
114 self.assertEquals(value, numberOfQueries)
115
116 def testSkipCacheViaLua(self):
117 """
118 Cache: SkipCache via Lua
119
120 dnsdist is configured to not cache entries for nocachevialua.cache.tests.powerdns.com.
121 we are sending several requests and checking that the backend get them all.
122 """
123 name = 'nocachevialua.cache.tests.powerdns.com.'
124 numberOfQueries = 10
125 query = dns.message.make_query(name, 'AAAA', 'IN')
126 response = dns.message.make_response(query)
903853f4
RG
127 rrset = dns.rrset.from_text(name,
128 3600,
129 dns.rdataclass.IN,
130 dns.rdatatype.AAAA,
131 '::1')
132 response.answer.append(rrset)
133
134 for _ in range(numberOfQueries):
135 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
136 self.assertTrue(receivedQuery)
137 self.assertTrue(receivedResponse)
138 receivedQuery.id = query.id
139 self.assertEquals(query, receivedQuery)
140 self.assertEquals(receivedResponse, response)
141
142 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
143 self.assertTrue(receivedQuery)
144 self.assertTrue(receivedResponse)
145 receivedQuery.id = query.id
146 self.assertEquals(query, receivedQuery)
147 self.assertEquals(receivedResponse, response)
148
02bbf9eb
RG
149 for key in self._responsesCounter:
150 value = self._responsesCounter[key]
903853f4
RG
151 self.assertEquals(value, numberOfQueries)
152
153 def testCacheExpiration(self):
154 """
155 Cache: Cache expiration
156
157 dnsdist is configured to cache entries, we are sending one request
158 (cache miss) with a very short TTL, checking that the next requests
159 are cached. Then we wait for the TTL to expire, check that the
160 next request is a miss but the following one a hit.
161 """
162 ttl = 2
163 misses = 0
164 name = 'cacheexpiration.cache.tests.powerdns.com.'
165 query = dns.message.make_query(name, 'AAAA', 'IN')
166 response = dns.message.make_response(query)
167 rrset = dns.rrset.from_text(name,
168 ttl,
169 dns.rdataclass.IN,
170 dns.rdatatype.AAAA,
171 '::1')
172 response.answer.append(rrset)
173
174 # first query to fill the cache
175 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
176 self.assertTrue(receivedQuery)
177 self.assertTrue(receivedResponse)
178 receivedQuery.id = query.id
179 self.assertEquals(query, receivedQuery)
180 self.assertEquals(receivedResponse, response)
181 misses += 1
182
183 # next queries should hit the cache
184 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
185 self.assertEquals(receivedResponse, response)
186
187 # now we wait a bit for the cache entry to expire
188 time.sleep(ttl + 1)
189
190 # next query should be a miss, fill the cache again
191 (receivedQuery, receivedResponse) = self.sendUDPQuery(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)
197 misses += 1
198
199 # following queries should hit the cache again
200 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
201 self.assertEquals(receivedResponse, response)
202
203 total = 0
02bbf9eb
RG
204 for key in self._responsesCounter:
205 total += self._responsesCounter[key]
903853f4
RG
206
207 self.assertEquals(total, misses)
208
209 def testCacheExpirationDifferentSets(self):
210 """
211 Cache: Cache expiration with different sets
212
213 dnsdist is configured to cache entries, we are sending one request
214 (cache miss) whose response has a long and a very short TTL,
215 checking that the next requests are cached. Then we wait for the
216 short TTL to expire, check that the
217 next request is a miss but the following one a hit.
218 """
219 ttl = 2
220 misses = 0
221 name = 'cacheexpirationdifferentsets.cache.tests.powerdns.com.'
222 query = dns.message.make_query(name, 'AAAA', 'IN')
223 response = dns.message.make_response(query)
224 rrset = dns.rrset.from_text(name,
225 ttl,
226 dns.rdataclass.IN,
227 dns.rdatatype.CNAME,
228 'cname.cacheexpirationdifferentsets.cache.tests.powerdns.com.')
229 response.answer.append(rrset)
230 rrset = dns.rrset.from_text('cname.cacheexpirationdifferentsets.cache.tests.powerdns.com.',
231 ttl + 3600,
232 dns.rdataclass.IN,
233 dns.rdatatype.A,
234 '192.2.0.1')
235 response.additional.append(rrset)
236
237 # first query to fill the cache
238 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
239 self.assertTrue(receivedQuery)
240 self.assertTrue(receivedResponse)
241 receivedQuery.id = query.id
242 self.assertEquals(query, receivedQuery)
243 self.assertEquals(receivedResponse, response)
244 misses += 1
245
246 # next queries should hit the cache
247 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
248 self.assertEquals(receivedResponse, response)
249
250 # now we wait a bit for the cache entry to expire
251 time.sleep(ttl + 1)
252
253 # next query should be a miss, fill the cache again
254 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
255 self.assertTrue(receivedQuery)
256 self.assertTrue(receivedResponse)
257 receivedQuery.id = query.id
258 self.assertEquals(query, receivedQuery)
259 self.assertEquals(receivedResponse, response)
260 misses += 1
261
262 # following queries should hit the cache again
263 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
264 self.assertEquals(receivedResponse, response)
265
266 total = 0
02bbf9eb
RG
267 for key in self._responsesCounter:
268 total += self._responsesCounter[key]
903853f4
RG
269
270 self.assertEquals(total, misses)
271
272 def testCacheDecreaseTTL(self):
273 """
274 Cache: Cache decreases TTL
275
276 dnsdist is configured to cache entries, we are sending one request
277 (cache miss) and verify that the cache hits have a decreasing TTL.
278 """
279 ttl = 600
280 misses = 0
281 name = 'cachedecreasettl.cache.tests.powerdns.com.'
282 query = dns.message.make_query(name, 'AAAA', 'IN')
283 response = dns.message.make_response(query)
284 rrset = dns.rrset.from_text(name,
285 ttl,
286 dns.rdataclass.IN,
287 dns.rdatatype.AAAA,
288 '::1')
289 response.answer.append(rrset)
290
291 # first query to fill the cache
292 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
293 self.assertTrue(receivedQuery)
294 self.assertTrue(receivedResponse)
295 receivedQuery.id = query.id
296 self.assertEquals(query, receivedQuery)
297 self.assertEquals(receivedResponse, response)
298 misses += 1
299
300 # next queries should hit the cache
301 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
302 self.assertEquals(receivedResponse, response)
303 for an in receivedResponse.answer:
304 self.assertTrue(an.ttl <= ttl)
305
306 # now we wait a bit for the TTL to decrease
307 time.sleep(1)
308
309 # next queries should hit the cache
310 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
311 self.assertEquals(receivedResponse, response)
312 for an in receivedResponse.answer:
313 self.assertTrue(an.ttl < ttl)
314
315 total = 0
02bbf9eb
RG
316 for key in self._responsesCounter:
317 total += self._responsesCounter[key]
903853f4
RG
318
319 self.assertEquals(total, misses)
320
321 def testCacheDifferentCase(self):
322 """
323 Cache: Cache matches different case
324
325 dnsdist is configured to cache entries, we are sending one request
326 (cache miss) and verify that the same one with a different case
327 matches.
328 """
329 ttl = 600
330 name = 'cachedifferentcase.cache.tests.powerdns.com.'
331 differentCaseName = 'CacheDifferentCASE.cache.tests.powerdns.com.'
332 query = dns.message.make_query(name, 'AAAA', 'IN')
333 differentCaseQuery = dns.message.make_query(differentCaseName, 'AAAA', 'IN')
334 response = dns.message.make_response(query)
335 differentCaseResponse = dns.message.make_response(differentCaseQuery)
336 rrset = dns.rrset.from_text(name,
337 ttl,
338 dns.rdataclass.IN,
339 dns.rdatatype.AAAA,
340 '::1')
341 response.answer.append(rrset)
342 differentCaseResponse.answer.append(rrset)
343
344 # first query to fill the cache
345 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
346 self.assertTrue(receivedQuery)
347 self.assertTrue(receivedResponse)
348 receivedQuery.id = query.id
349 self.assertEquals(query, receivedQuery)
350 self.assertEquals(receivedResponse, response)
351
352 # different case query should still hit the cache
353 (_, receivedResponse) = self.sendUDPQuery(differentCaseQuery, response=None, useQueue=False)
354 self.assertEquals(receivedResponse, differentCaseResponse)
355
356
357class TestCachingWithExistingEDNS(DNSDistTest):
358
359 _config_template = """
360 pc = newPacketCache(5, 86400, 1)
361 getPool(""):setCache(pc)
362 newServer{address="127.0.0.1:%s"}
363 """
364 def testCacheWithEDNS(self):
365 """
366 Cache: Cache should not match different EDNS value
367
368 dnsdist is configured to cache entries, we are sending one request
369 (cache miss) and verify that the same one with a different EDNS UDP
370 Payload size is not served from the cache.
371 """
372 misses = 0
373 name = 'cachedifferentedns.cache.tests.powerdns.com.'
374 query = dns.message.make_query(name, 'A', 'IN', use_edns=True, payload=512)
375 response = dns.message.make_response(query)
376 rrset = dns.rrset.from_text(name,
377 3600,
378 dns.rdataclass.IN,
379 dns.rdatatype.A,
380 '127.0.0.1')
381 response.answer.append(rrset)
382
383 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
384 self.assertTrue(receivedQuery)
385 self.assertTrue(receivedResponse)
386 receivedQuery.id = query.id
387 self.assertEquals(query, receivedQuery)
388 self.assertEquals(response, receivedResponse)
389 misses += 1
390
391 query = dns.message.make_query(name, 'A', 'IN', use_edns=True, payload=4096)
392 response = dns.message.make_response(query)
393 rrset = dns.rrset.from_text(name,
394 3600,
395 dns.rdataclass.IN,
396 dns.rdatatype.A,
397 '127.0.0.1')
398 response.answer.append(rrset)
399
400 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
401 self.assertTrue(receivedQuery)
402 self.assertTrue(receivedResponse)
403 receivedQuery.id = query.id
404 self.assertEquals(query, receivedQuery)
405 self.assertEquals(response, receivedResponse)
406 misses += 1
407
408 total = 0
02bbf9eb
RG
409 for key in self._responsesCounter:
410 total += self._responsesCounter[key]
903853f4
RG
411
412 self.assertEquals(total, misses)
fe1c60f2
RG
413
414class TestCachingCacheFull(DNSDistTest):
415
416 _config_template = """
417 pc = newPacketCache(1, 86400, 1)
418 getPool(""):setCache(pc)
419 newServer{address="127.0.0.1:%s"}
420 """
421 def testCacheFull(self):
422 """
423 Cache: No new entries are cached when the cache is full
424
425 """
426 misses = 0
427 name = 'cachenotfullyet.cache.tests.powerdns.com.'
428 query = dns.message.make_query(name, 'A', 'IN')
429 response = dns.message.make_response(query)
430 rrset = dns.rrset.from_text(name,
431 3600,
432 dns.rdataclass.IN,
433 dns.rdatatype.A,
434 '127.0.0.1')
435 response.answer.append(rrset)
436
437 # Miss
438 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
439 self.assertTrue(receivedQuery)
440 self.assertTrue(receivedResponse)
441 receivedQuery.id = query.id
442 self.assertEquals(query, receivedQuery)
443 self.assertEquals(response, receivedResponse)
444 misses += 1
445
446 # next queries should hit the cache
447 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
448 self.assertEquals(receivedResponse, response)
449
450 # ok, now the cache is full, send another query
451 name = 'cachefull.cache.tests.powerdns.com.'
452 query = dns.message.make_query(name, 'AAAA', 'IN')
453 response = dns.message.make_response(query)
454 rrset = dns.rrset.from_text(name,
455 3600,
456 dns.rdataclass.IN,
457 dns.rdatatype.AAAA,
458 '::1')
459 response.answer.append(rrset)
460
461 # Miss
462 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
463 self.assertTrue(receivedQuery)
464 self.assertTrue(receivedResponse)
465 receivedQuery.id = query.id
466 self.assertEquals(query, receivedQuery)
467 self.assertEquals(response, receivedResponse)
468 misses += 1
469
470 # next queries should NOT hit the cache
471 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
472 self.assertTrue(receivedQuery)
473 self.assertTrue(receivedResponse)
474 receivedQuery.id = query.id
475 self.assertEquals(query, receivedQuery)
476 self.assertEquals(response, receivedResponse)
477 misses += 1
478
479 total = 0
02bbf9eb
RG
480 for key in self._responsesCounter:
481 total += self._responsesCounter[key]
fe1c60f2
RG
482
483 self.assertEquals(total, misses)
1ea747c0
RG
484
485class TestCachingNoStale(DNSDistTest):
486
487 _consoleKey = DNSDistTest.generateConsoleKey()
488 _consoleKeyB64 = base64.b64encode(_consoleKey)
489 _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort']
490 _config_template = """
491 pc = newPacketCache(100, 86400, 1)
492 getPool(""):setCache(pc)
493 setKey("%s")
494 controlSocket("127.0.0.1:%s")
495 newServer{address="127.0.0.1:%s"}
496 """
497 def testCacheNoStale(self):
498 """
499 Cache: Cache entry, set backend down, we should not get a stale entry
500
501 """
502 ttl = 1
503 name = 'nostale.cache.tests.powerdns.com.'
504 query = dns.message.make_query(name, 'A', 'IN')
505 response = dns.message.make_response(query)
506 rrset = dns.rrset.from_text(name,
507 1,
508 dns.rdataclass.IN,
509 dns.rdatatype.A,
510 '127.0.0.1')
511 response.answer.append(rrset)
512
513 # Miss
514 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
515 self.assertTrue(receivedQuery)
516 self.assertTrue(receivedResponse)
517 receivedQuery.id = query.id
518 self.assertEquals(query, receivedQuery)
519 self.assertEquals(response, receivedResponse)
520
521 # next queries should hit the cache
522 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
523 self.assertEquals(receivedResponse, response)
524
525 # ok, we mark the backend as down
526 self.sendConsoleCommand("getServer(0):setDown()")
527 # and we wait for the entry to expire
528 time.sleep(ttl + 1)
529
530 # we should NOT get a cached, stale, entry
531 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
532 self.assertEquals(receivedResponse, None)
533
534
535class TestCachingStale(DNSDistTest):
536
537 _consoleKey = DNSDistTest.generateConsoleKey()
538 _consoleKeyB64 = base64.b64encode(_consoleKey)
539 _staleCacheTTL = 60
540 _config_params = ['_staleCacheTTL', '_consoleKeyB64', '_consolePort', '_testServerPort']
541 _config_template = """
542 pc = newPacketCache(100, 86400, 1, %s)
543 getPool(""):setCache(pc)
544 setStaleCacheEntriesTTL(600)
545 setKey("%s")
546 controlSocket("127.0.0.1:%s")
547 newServer{address="127.0.0.1:%s"}
548 """
549 def testCacheStale(self):
550 """
551 Cache: Cache entry, set backend down, get stale entry
552
553 """
554 misses = 0
555 ttl = 1
556 name = 'stale.cache.tests.powerdns.com.'
557 query = dns.message.make_query(name, 'A', 'IN')
558 response = dns.message.make_response(query)
559 rrset = dns.rrset.from_text(name,
560 ttl,
561 dns.rdataclass.IN,
562 dns.rdatatype.A,
563 '127.0.0.1')
564 response.answer.append(rrset)
565
566 # Miss
567 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
568 self.assertTrue(receivedQuery)
569 self.assertTrue(receivedResponse)
570 receivedQuery.id = query.id
571 self.assertEquals(query, receivedQuery)
572 self.assertEquals(response, receivedResponse)
573 misses += 1
574
575 # next queries should hit the cache
576 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
577 self.assertEquals(receivedResponse, response)
578
579 # ok, we mark the backend as down
580 self.sendConsoleCommand("getServer(0):setDown()")
581 # and we wait for the entry to expire
582 time.sleep(ttl + 1)
583
584 # we should get a cached, stale, entry
585 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
586 self.assertEquals(receivedResponse, response)
587 for an in receivedResponse.answer:
588 self.assertEquals(an.ttl, self._staleCacheTTL)
589
590 total = 0
02bbf9eb
RG
591 for key in self._responsesCounter:
592 total += self._responsesCounter[key]
1ea747c0
RG
593
594 self.assertEquals(total, misses)
595
596class TestCacheManagement(DNSDistTest):
597
598 _consoleKey = DNSDistTest.generateConsoleKey()
599 _consoleKeyB64 = base64.b64encode(_consoleKey)
600 _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort']
601 _config_template = """
602 pc = newPacketCache(100, 86400, 1)
603 getPool(""):setCache(pc)
604 setKey("%s")
605 controlSocket("127.0.0.1:%s")
606 newServer{address="127.0.0.1:%s"}
607 """
608 def testCacheExpunge(self):
609 """
610 Cache: Expunge
611
612 """
613 misses = 0
614 ttl = 600
615 name = 'expunge.cache.tests.powerdns.com.'
616 query = dns.message.make_query(name, 'A', 'IN')
617 response = dns.message.make_response(query)
618 rrset = dns.rrset.from_text(name,
619 ttl,
620 dns.rdataclass.IN,
621 dns.rdatatype.A,
622 '127.0.0.1')
623 response.answer.append(rrset)
624
625 # Miss
626 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
627 self.assertTrue(receivedQuery)
628 self.assertTrue(receivedResponse)
629 receivedQuery.id = query.id
630 self.assertEquals(query, receivedQuery)
631 self.assertEquals(response, receivedResponse)
632 misses += 1
633
634 # next queries should hit the cache
635 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
636 self.assertEquals(receivedResponse, response)
637
638 # remove cached entries
639 self.sendConsoleCommand("getPool(\"\"):getCache():expunge(0)")
640
641 # Miss
642 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
643 self.assertTrue(receivedQuery)
644 self.assertTrue(receivedResponse)
645 receivedQuery.id = query.id
646 self.assertEquals(query, receivedQuery)
647 self.assertEquals(response, receivedResponse)
648 misses += 1
649
650 # next queries should hit the cache again
651 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
652 self.assertEquals(receivedResponse, response)
653
654 total = 0
02bbf9eb
RG
655 for key in self._responsesCounter:
656 total += self._responsesCounter[key]
1ea747c0
RG
657
658 self.assertEquals(total, misses)
659
660 def testCacheExpungeByName(self):
661 """
662 Cache: Expunge by name
663
664 """
665 misses = 0
666 ttl = 600
667 name = 'expungebyname.cache.tests.powerdns.com.'
668 query = dns.message.make_query(name, 'A', 'IN')
669 response = dns.message.make_response(query)
670 rrset = dns.rrset.from_text(name,
671 ttl,
672 dns.rdataclass.IN,
673 dns.rdatatype.A,
674 '127.0.0.1')
675 response.answer.append(rrset)
676
677 name2 = 'expungebynameother.cache.tests.powerdns.com.'
678 query2 = dns.message.make_query(name2, 'A', 'IN')
679 response2 = dns.message.make_response(query2)
680 rrset2 = dns.rrset.from_text(name2,
681 ttl,
682 dns.rdataclass.IN,
683 dns.rdatatype.A,
684 '127.0.0.1')
685 response2.answer.append(rrset2)
686
687 # Miss
688 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
689 self.assertTrue(receivedQuery)
690 self.assertTrue(receivedResponse)
691 receivedQuery.id = query.id
692 self.assertEquals(query, receivedQuery)
693 self.assertEquals(response, receivedResponse)
694 misses += 1
695
696 # next queries should hit the cache
697 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
698 self.assertEquals(receivedResponse, response)
699
700 # cache another entry
701 (receivedQuery, receivedResponse) = self.sendUDPQuery(query2, response2)
702 self.assertTrue(receivedQuery)
703 self.assertTrue(receivedResponse)
704 receivedQuery.id = query2.id
705 self.assertEquals(query2, receivedQuery)
706 self.assertEquals(response2, receivedResponse)
707 misses += 1
708
709 # queries for name and name 2 should hit the cache
710 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
711 self.assertEquals(receivedResponse, response)
712
713 (_, receivedResponse) = self.sendUDPQuery(query2, response=None, useQueue=False)
714 self.assertEquals(receivedResponse, response2)
715
716 # remove cached entries from name
717 self.sendConsoleCommand("getPool(\"\"):getCache():expungeByName(newDNSName(\"" + name + "\"))")
718
719 # Miss for name
720 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
721 self.assertTrue(receivedQuery)
722 self.assertTrue(receivedResponse)
723 receivedQuery.id = query.id
724 self.assertEquals(query, receivedQuery)
725 self.assertEquals(response, receivedResponse)
726 misses += 1
727
728 # next queries for name should hit the cache again
729 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
730 self.assertEquals(receivedResponse, response)
731
732 # queries for name2 should still hit the cache
733 (_, receivedResponse) = self.sendUDPQuery(query2, response=None, useQueue=False)
734 self.assertEquals(receivedResponse, response2)
735
736 total = 0
02bbf9eb
RG
737 for key in self._responsesCounter:
738 total += self._responsesCounter[key]
1ea747c0
RG
739
740 self.assertEquals(total, misses)
741
742 def testCacheExpungeByNameAndType(self):
743 """
744 Cache: Expunge by name and type
745
746 """
747 misses = 0
748 ttl = 600
749 name = 'expungebynameandtype.cache.tests.powerdns.com.'
750 query = dns.message.make_query(name, 'A', 'IN')
751 response = dns.message.make_response(query)
752 rrset = dns.rrset.from_text(name,
753 ttl,
754 dns.rdataclass.IN,
755 dns.rdatatype.A,
756 '127.0.0.1')
757 response.answer.append(rrset)
758
759 query2 = dns.message.make_query(name, 'AAAA', 'IN')
760 response2 = dns.message.make_response(query2)
761 rrset2 = dns.rrset.from_text(name,
762 ttl,
763 dns.rdataclass.IN,
764 dns.rdatatype.AAAA,
765 '::1')
766 response2.answer.append(rrset2)
767
768 # Miss
769 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
770 self.assertTrue(receivedQuery)
771 self.assertTrue(receivedResponse)
772 receivedQuery.id = query.id
773 self.assertEquals(query, receivedQuery)
774 self.assertEquals(response, receivedResponse)
775 misses += 1
776
777 # next queries should hit the cache
778 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
779 self.assertEquals(receivedResponse, response)
780
781 # cache another entry
782 (receivedQuery, receivedResponse) = self.sendUDPQuery(query2, response2)
783 self.assertTrue(receivedQuery)
784 self.assertTrue(receivedResponse)
785 receivedQuery.id = query2.id
786 self.assertEquals(query2, receivedQuery)
787 self.assertEquals(response2, receivedResponse)
788 misses += 1
789
790 # queries for name A and AAAA should hit the cache
791 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
792 self.assertEquals(receivedResponse, response)
793
794 (_, receivedResponse) = self.sendUDPQuery(query2, response=None, useQueue=False)
795 self.assertEquals(receivedResponse, response2)
796
797 # remove cached entries from name A
798 self.sendConsoleCommand("getPool(\"\"):getCache():expungeByName(newDNSName(\"" + name + "\"), dnsdist.A)")
799
800 # Miss for name A
801 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
802 self.assertTrue(receivedQuery)
803 self.assertTrue(receivedResponse)
804 receivedQuery.id = query.id
805 self.assertEquals(query, receivedQuery)
806 self.assertEquals(response, receivedResponse)
807 misses += 1
808
809 # next queries for name A should hit the cache again
810 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
811 self.assertEquals(receivedResponse, response)
812
813 # queries for name AAAA should still hit the cache
814 (_, receivedResponse) = self.sendUDPQuery(query2, response=None, useQueue=False)
815 self.assertEquals(receivedResponse, response2)
816
817 total = 0
02bbf9eb
RG
818 for key in self._responsesCounter:
819 total += self._responsesCounter[key]
1ea747c0 820 self.assertEquals(total, misses)
cc8cefe1
RG
821
822class TestCachingTTL(DNSDistTest):
823
824 _maxCacheTTL = 86400
825 _minCacheTTL = 600
826 _config_params = ['_maxCacheTTL', '_minCacheTTL', '_testServerPort']
827 _config_template = """
828 pc = newPacketCache(1000, %s, %s)
829 getPool(""):setCache(pc)
830 newServer{address="127.0.0.1:%s"}
831 """
832 def testCacheShortTTL(self):
833 """
834 Cache: Entries with a TTL shorter than minTTL
835
836 """
837 misses = 0
838 ttl = 60
839 name = 'ttltooshort.cache.tests.powerdns.com.'
840 query = dns.message.make_query(name, 'A', 'IN')
841 response = dns.message.make_response(query)
842 rrset = dns.rrset.from_text(name,
843 ttl,
844 dns.rdataclass.IN,
845 dns.rdatatype.A,
846 '127.0.0.1')
847 response.answer.append(rrset)
848
849 # Miss
850 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
851 self.assertTrue(receivedQuery)
852 self.assertTrue(receivedResponse)
853 receivedQuery.id = query.id
854 self.assertEquals(query, receivedQuery)
855 self.assertEquals(response, receivedResponse)
856 for an in receivedResponse.answer:
857 self.assertEquals(an.ttl, ttl)
858 misses += 1
859
860 # We should not have been cached
861 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
862 self.assertTrue(receivedQuery)
863 self.assertTrue(receivedResponse)
864 receivedQuery.id = query.id
865 self.assertEquals(query, receivedQuery)
866 self.assertEquals(response, receivedResponse)
867 for an in receivedResponse.answer:
868 self.assertEquals(an.ttl, ttl)
869 misses += 1
870
871 total = 0
872 for key in self._responsesCounter:
873 total += self._responsesCounter[key]
874
875 self.assertEquals(total, misses)
876
877class TestCachingLongTTL(DNSDistTest):
878
879 _maxCacheTTL = 2
880 _config_params = ['_maxCacheTTL', '_testServerPort']
881 _config_template = """
882 pc = newPacketCache(1000, %s)
883 getPool(""):setCache(pc)
884 newServer{address="127.0.0.1:%s"}
885 """
886 def testCacheLongTTL(self):
887 """
888 Cache: Entries with a longer TTL than the maximum
889
890 """
891 misses = 0
892 ttl = 172800
893 name = 'longttl.cache.tests.powerdns.com.'
894 query = dns.message.make_query(name, 'A', 'IN')
895 response = dns.message.make_response(query)
896 rrset = dns.rrset.from_text(name,
897 ttl,
898 dns.rdataclass.IN,
899 dns.rdatatype.A,
900 '127.0.0.1')
901 response.answer.append(rrset)
902
903 # Miss
904 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
905 self.assertTrue(receivedQuery)
906 self.assertTrue(receivedResponse)
907 receivedQuery.id = query.id
908 self.assertEquals(query, receivedQuery)
909 self.assertEquals(response, receivedResponse)
910 for an in receivedResponse.answer:
911 self.assertEquals(an.ttl, ttl)
912 misses += 1
913
914 # next queries should hit the cache
915 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
916 self.assertEquals(receivedResponse, response)
917 for an in receivedResponse.answer:
918 self.assertTrue(an.ttl <= ttl)
919
920 time.sleep(self._maxCacheTTL + 1)
921
922 # we should not have cached for longer than max cache
923 # so it should be a miss
924 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
925 self.assertTrue(receivedQuery)
926 self.assertTrue(receivedResponse)
927 receivedQuery.id = query.id
928 self.assertEquals(query, receivedQuery)
929 self.assertEquals(response, receivedResponse)
930 for an in receivedResponse.answer:
931 self.assertEquals(an.ttl, ttl)
932 misses += 1
933
934 total = 0
935 for key in self._responsesCounter:
936 total += self._responsesCounter[key]
937
938 self.assertEquals(total, misses)
2714396e
RG
939
940class TestCachingFailureTTL(DNSDistTest):
941
942 _failureCacheTTL = 2
943 _config_params = ['_failureCacheTTL', '_testServerPort']
944 _config_template = """
945 pc = newPacketCache(1000, 86400, 0, %d, 60)
946 getPool(""):setCache(pc)
947 newServer{address="127.0.0.1:%s"}
948 """
949 def testCacheServFailTTL(self):
950 """
951 Cache: ServFail TTL
952
953 """
954 misses = 0
955 name = 'servfail.failure.cache.tests.powerdns.com.'
956 query = dns.message.make_query(name, 'A', 'IN')
957 response = dns.message.make_response(query)
958 response.set_rcode(dns.rcode.SERVFAIL)
959
960 # Miss
961 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
962 self.assertTrue(receivedQuery)
963 self.assertTrue(receivedResponse)
964 receivedQuery.id = query.id
965 self.assertEquals(query, receivedQuery)
966 self.assertEquals(response, receivedResponse)
967 misses += 1
968
969 # next queries should hit the cache
970 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
971 self.assertEquals(receivedResponse, response)
972
973 time.sleep(self._failureCacheTTL + 1)
974
975 # we should not have cached for longer than failure cache
976 # so it should be a miss
977 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
978 self.assertTrue(receivedQuery)
979 self.assertTrue(receivedResponse)
980 receivedQuery.id = query.id
981 self.assertEquals(query, receivedQuery)
982 self.assertEquals(response, receivedResponse)
983 misses += 1
984
985 total = 0
986 for key in self._responsesCounter:
987 total += self._responsesCounter[key]
988
989 self.assertEquals(total, misses)
990
991 def testCacheRefusedTTL(self):
992 """
993 Cache: Refused TTL
994
995 """
996 misses = 0
997 name = 'refused.failure.cache.tests.powerdns.com.'
998 query = dns.message.make_query(name, 'A', 'IN')
999 response = dns.message.make_response(query)
1000 response.set_rcode(dns.rcode.REFUSED)
1001
1002 # Miss
1003 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
1004 self.assertTrue(receivedQuery)
1005 self.assertTrue(receivedResponse)
1006 receivedQuery.id = query.id
1007 self.assertEquals(query, receivedQuery)
1008 self.assertEquals(response, receivedResponse)
1009 misses += 1
1010
1011 # next queries should hit the cache
1012 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
1013 self.assertEquals(receivedResponse, response)
1014
1015 time.sleep(self._failureCacheTTL + 1)
1016
1017 # we should not have cached for longer than failure cache
1018 # so it should be a miss
1019 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
1020 self.assertTrue(receivedQuery)
1021 self.assertTrue(receivedResponse)
1022 receivedQuery.id = query.id
1023 self.assertEquals(query, receivedQuery)
1024 self.assertEquals(response, receivedResponse)
1025 misses += 1
1026
1027 total = 0
1028 for key in self._responsesCounter:
1029 total += self._responsesCounter[key]
1030
1031 self.assertEquals(total, misses)
1032
1033 def testCacheHeaderOnlyRefusedTTL(self):
1034 """
1035 Cache: Header-Only Refused TTL
1036
1037 """
1038 misses = 0
1039 name = 'header-only-refused.failure.cache.tests.powerdns.com.'
1040 query = dns.message.make_query(name, 'A', 'IN')
1041 response = dns.message.make_response(query)
1042 response.set_rcode(dns.rcode.REFUSED)
1043 response.question = []
1044
1045 # Miss
1046 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
1047 self.assertTrue(receivedQuery)
1048 self.assertTrue(receivedResponse)
1049 receivedQuery.id = query.id
1050 self.assertEquals(query, receivedQuery)
1051 self.assertEquals(response, receivedResponse)
1052 misses += 1
1053
1054 # next queries should hit the cache
1055 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
1056 self.assertEquals(receivedResponse, response)
1057
1058 time.sleep(self._failureCacheTTL + 1)
1059
1060 # we should not have cached for longer than failure cache
1061 # so it should be a miss
1062 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
1063 self.assertTrue(receivedQuery)
1064 self.assertTrue(receivedResponse)
1065 receivedQuery.id = query.id
1066 self.assertEquals(query, receivedQuery)
1067 self.assertEquals(response, receivedResponse)
1068 misses += 1
1069
1070 total = 0
1071 for key in self._responsesCounter:
1072 total += self._responsesCounter[key]
1073
1074 self.assertEquals(total, misses)