]>
Commit | Line | Data |
---|---|---|
903853f4 | 1 | #!/usr/bin/env python |
1ea747c0 | 2 | import base64 |
903853f4 RG |
3 | import time |
4 | import dns | |
5 | from dnsdisttests import DNSDistTest | |
6 | ||
7 | class 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 | |
a2ff35e3 | 17 | addAction("nocachevialua.cache.tests.powerdns.com.", LuaAction(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 | ||
357 | class 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 | |
414 | class 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 | |
485 | class 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 | ||
535 | class 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 | ||
596 | class 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) | |
490dc586 RG |
815 | self.assertEquals(receivedResponse, response2) |
816 | ||
817 | total = 0 | |
818 | for key in self._responsesCounter: | |
819 | total += self._responsesCounter[key] | |
820 | self.assertEquals(total, misses) | |
821 | ||
822 | def testCacheExpungeByNameAndSuffix(self): | |
823 | """ | |
824 | Cache: Expunge by name | |
825 | ||
826 | """ | |
827 | misses = 0 | |
828 | ttl = 600 | |
829 | name = 'expungebyname.suffix.cache.tests.powerdns.com.' | |
830 | query = dns.message.make_query(name, 'A', 'IN') | |
831 | response = dns.message.make_response(query) | |
832 | rrset = dns.rrset.from_text(name, | |
833 | ttl, | |
834 | dns.rdataclass.IN, | |
835 | dns.rdatatype.A, | |
836 | '127.0.0.1') | |
837 | response.answer.append(rrset) | |
838 | ||
839 | name2 = 'expungebyname.suffixother.cache.tests.powerdns.com.' | |
840 | query2 = dns.message.make_query(name2, 'A', 'IN') | |
841 | response2 = dns.message.make_response(query2) | |
842 | rrset2 = dns.rrset.from_text(name2, | |
843 | ttl, | |
844 | dns.rdataclass.IN, | |
845 | dns.rdatatype.A, | |
846 | '127.0.0.1') | |
847 | response2.answer.append(rrset2) | |
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 | misses += 1 | |
857 | ||
858 | # next queries should hit the cache | |
859 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
860 | self.assertEquals(receivedResponse, response) | |
861 | ||
862 | # cache another entry | |
863 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query2, response2) | |
864 | self.assertTrue(receivedQuery) | |
865 | self.assertTrue(receivedResponse) | |
866 | receivedQuery.id = query2.id | |
867 | self.assertEquals(query2, receivedQuery) | |
868 | self.assertEquals(response2, receivedResponse) | |
869 | misses += 1 | |
870 | ||
871 | # queries for name and name 2 should hit the cache | |
872 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
873 | self.assertEquals(receivedResponse, response) | |
874 | ||
875 | (_, receivedResponse) = self.sendUDPQuery(query2, response=None, useQueue=False) | |
876 | self.assertEquals(receivedResponse, response2) | |
877 | ||
878 | # remove cached entries from name | |
879 | self.sendConsoleCommand("getPool(\"\"):getCache():expungeByName(newDNSName(\"suffix.cache.tests.powerdns.com.\"), dnsdist.ANY, true)") | |
880 | ||
881 | # Miss for name | |
882 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
883 | self.assertTrue(receivedQuery) | |
884 | self.assertTrue(receivedResponse) | |
885 | receivedQuery.id = query.id | |
886 | self.assertEquals(query, receivedQuery) | |
887 | self.assertEquals(response, receivedResponse) | |
888 | misses += 1 | |
889 | ||
890 | # next queries for name should hit the cache again | |
891 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
892 | self.assertEquals(receivedResponse, response) | |
893 | ||
894 | # queries for name2 should still hit the cache | |
895 | (_, receivedResponse) = self.sendUDPQuery(query2, response=None, useQueue=False) | |
896 | self.assertEquals(receivedResponse, response2) | |
897 | ||
898 | total = 0 | |
899 | for key in self._responsesCounter: | |
900 | total += self._responsesCounter[key] | |
901 | ||
902 | self.assertEquals(total, misses) | |
903 | ||
904 | def testCacheExpungeByNameAndTypeAndSuffix(self): | |
905 | """ | |
906 | Cache: Expunge by name and type | |
907 | ||
908 | """ | |
909 | misses = 0 | |
910 | ttl = 600 | |
911 | name = 'expungebynameandtype.suffixtype.cache.tests.powerdns.com.' | |
912 | query = dns.message.make_query(name, 'A', 'IN') | |
913 | response = dns.message.make_response(query) | |
914 | rrset = dns.rrset.from_text(name, | |
915 | ttl, | |
916 | dns.rdataclass.IN, | |
917 | dns.rdatatype.A, | |
918 | '127.0.0.1') | |
919 | response.answer.append(rrset) | |
920 | ||
921 | query2 = dns.message.make_query(name, 'AAAA', 'IN') | |
922 | response2 = dns.message.make_response(query2) | |
923 | rrset2 = dns.rrset.from_text(name, | |
924 | ttl, | |
925 | dns.rdataclass.IN, | |
926 | dns.rdatatype.AAAA, | |
927 | '::1') | |
928 | response2.answer.append(rrset2) | |
929 | ||
930 | # Miss | |
931 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
932 | self.assertTrue(receivedQuery) | |
933 | self.assertTrue(receivedResponse) | |
934 | receivedQuery.id = query.id | |
935 | self.assertEquals(query, receivedQuery) | |
936 | self.assertEquals(response, receivedResponse) | |
937 | misses += 1 | |
938 | ||
939 | # next queries should hit the cache | |
940 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
941 | self.assertEquals(receivedResponse, response) | |
942 | ||
943 | # cache another entry | |
944 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query2, response2) | |
945 | self.assertTrue(receivedQuery) | |
946 | self.assertTrue(receivedResponse) | |
947 | receivedQuery.id = query2.id | |
948 | self.assertEquals(query2, receivedQuery) | |
949 | self.assertEquals(response2, receivedResponse) | |
950 | misses += 1 | |
951 | ||
952 | # queries for name A and AAAA should hit the cache | |
953 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
954 | self.assertEquals(receivedResponse, response) | |
955 | ||
956 | (_, receivedResponse) = self.sendUDPQuery(query2, response=None, useQueue=False) | |
957 | self.assertEquals(receivedResponse, response2) | |
958 | ||
959 | # remove cached entries from name A | |
960 | self.sendConsoleCommand("getPool(\"\"):getCache():expungeByName(newDNSName(\"suffixtype.cache.tests.powerdns.com.\"), dnsdist.A, true)") | |
961 | ||
962 | # Miss for name A | |
963 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
964 | self.assertTrue(receivedQuery) | |
965 | self.assertTrue(receivedResponse) | |
966 | receivedQuery.id = query.id | |
967 | self.assertEquals(query, receivedQuery) | |
968 | self.assertEquals(response, receivedResponse) | |
969 | misses += 1 | |
970 | ||
971 | # next queries for name A should hit the cache again | |
972 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
973 | self.assertEquals(receivedResponse, response) | |
974 | ||
975 | # queries for name AAAA should still hit the cache | |
976 | (_, receivedResponse) = self.sendUDPQuery(query2, response=None, useQueue=False) | |
1ea747c0 RG |
977 | self.assertEquals(receivedResponse, response2) |
978 | ||
979 | total = 0 | |
02bbf9eb RG |
980 | for key in self._responsesCounter: |
981 | total += self._responsesCounter[key] | |
1ea747c0 | 982 | self.assertEquals(total, misses) |
cc8cefe1 RG |
983 | |
984 | class TestCachingTTL(DNSDistTest): | |
985 | ||
986 | _maxCacheTTL = 86400 | |
987 | _minCacheTTL = 600 | |
988 | _config_params = ['_maxCacheTTL', '_minCacheTTL', '_testServerPort'] | |
989 | _config_template = """ | |
990 | pc = newPacketCache(1000, %s, %s) | |
991 | getPool(""):setCache(pc) | |
992 | newServer{address="127.0.0.1:%s"} | |
993 | """ | |
994 | def testCacheShortTTL(self): | |
995 | """ | |
996 | Cache: Entries with a TTL shorter than minTTL | |
997 | ||
998 | """ | |
999 | misses = 0 | |
1000 | ttl = 60 | |
1001 | name = 'ttltooshort.cache.tests.powerdns.com.' | |
1002 | query = dns.message.make_query(name, 'A', 'IN') | |
1003 | response = dns.message.make_response(query) | |
1004 | rrset = dns.rrset.from_text(name, | |
1005 | ttl, | |
1006 | dns.rdataclass.IN, | |
1007 | dns.rdatatype.A, | |
1008 | '127.0.0.1') | |
1009 | response.answer.append(rrset) | |
1010 | ||
1011 | # Miss | |
1012 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
1013 | self.assertTrue(receivedQuery) | |
1014 | self.assertTrue(receivedResponse) | |
1015 | receivedQuery.id = query.id | |
1016 | self.assertEquals(query, receivedQuery) | |
1017 | self.assertEquals(response, receivedResponse) | |
1018 | for an in receivedResponse.answer: | |
1019 | self.assertEquals(an.ttl, ttl) | |
1020 | misses += 1 | |
1021 | ||
1022 | # We should not have been cached | |
1023 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
1024 | self.assertTrue(receivedQuery) | |
1025 | self.assertTrue(receivedResponse) | |
1026 | receivedQuery.id = query.id | |
1027 | self.assertEquals(query, receivedQuery) | |
1028 | self.assertEquals(response, receivedResponse) | |
1029 | for an in receivedResponse.answer: | |
1030 | self.assertEquals(an.ttl, ttl) | |
1031 | misses += 1 | |
1032 | ||
1033 | total = 0 | |
1034 | for key in self._responsesCounter: | |
1035 | total += self._responsesCounter[key] | |
1036 | ||
1037 | self.assertEquals(total, misses) | |
1038 | ||
a3824e43 RG |
1039 | def testCacheNXWithNoRR(self): |
1040 | """ | |
1041 | Cache: NX with no RR | |
1042 | ||
1043 | """ | |
1044 | misses = 0 | |
1045 | name = 'nxwithnorr.cache.tests.powerdns.com.' | |
1046 | query = dns.message.make_query(name, 'A', 'IN') | |
1047 | response = dns.message.make_response(query) | |
1048 | response.set_rcode(dns.rcode.NXDOMAIN) | |
1049 | ||
1050 | # Miss | |
1051 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
1052 | self.assertTrue(receivedQuery) | |
1053 | self.assertTrue(receivedResponse) | |
1054 | receivedQuery.id = query.id | |
1055 | self.assertEquals(query, receivedQuery) | |
1056 | self.assertEquals(response, receivedResponse) | |
1057 | misses += 1 | |
1058 | ||
1059 | # We should not have been cached | |
1060 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
1061 | self.assertTrue(receivedQuery) | |
1062 | self.assertTrue(receivedResponse) | |
1063 | receivedQuery.id = query.id | |
1064 | self.assertEquals(query, receivedQuery) | |
1065 | self.assertEquals(response, receivedResponse) | |
1066 | misses += 1 | |
1067 | ||
1068 | total = 0 | |
1069 | for key in self._responsesCounter: | |
1070 | total += self._responsesCounter[key] | |
1071 | ||
1072 | self.assertEquals(total, misses) | |
1073 | ||
cc8cefe1 RG |
1074 | class TestCachingLongTTL(DNSDistTest): |
1075 | ||
1076 | _maxCacheTTL = 2 | |
1077 | _config_params = ['_maxCacheTTL', '_testServerPort'] | |
1078 | _config_template = """ | |
1079 | pc = newPacketCache(1000, %s) | |
1080 | getPool(""):setCache(pc) | |
1081 | newServer{address="127.0.0.1:%s"} | |
1082 | """ | |
1083 | def testCacheLongTTL(self): | |
1084 | """ | |
1085 | Cache: Entries with a longer TTL than the maximum | |
1086 | ||
1087 | """ | |
1088 | misses = 0 | |
1089 | ttl = 172800 | |
1090 | name = 'longttl.cache.tests.powerdns.com.' | |
1091 | query = dns.message.make_query(name, 'A', 'IN') | |
1092 | response = dns.message.make_response(query) | |
1093 | rrset = dns.rrset.from_text(name, | |
1094 | ttl, | |
1095 | dns.rdataclass.IN, | |
1096 | dns.rdatatype.A, | |
1097 | '127.0.0.1') | |
1098 | response.answer.append(rrset) | |
1099 | ||
1100 | # Miss | |
1101 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
1102 | self.assertTrue(receivedQuery) | |
1103 | self.assertTrue(receivedResponse) | |
1104 | receivedQuery.id = query.id | |
1105 | self.assertEquals(query, receivedQuery) | |
1106 | self.assertEquals(response, receivedResponse) | |
1107 | for an in receivedResponse.answer: | |
1108 | self.assertEquals(an.ttl, ttl) | |
1109 | misses += 1 | |
1110 | ||
1111 | # next queries should hit the cache | |
1112 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
1113 | self.assertEquals(receivedResponse, response) | |
1114 | for an in receivedResponse.answer: | |
1115 | self.assertTrue(an.ttl <= ttl) | |
1116 | ||
1117 | time.sleep(self._maxCacheTTL + 1) | |
1118 | ||
1119 | # we should not have cached for longer than max cache | |
1120 | # so it should be a miss | |
1121 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
1122 | self.assertTrue(receivedQuery) | |
1123 | self.assertTrue(receivedResponse) | |
1124 | receivedQuery.id = query.id | |
1125 | self.assertEquals(query, receivedQuery) | |
1126 | self.assertEquals(response, receivedResponse) | |
1127 | for an in receivedResponse.answer: | |
1128 | self.assertEquals(an.ttl, ttl) | |
1129 | misses += 1 | |
1130 | ||
1131 | total = 0 | |
1132 | for key in self._responsesCounter: | |
1133 | total += self._responsesCounter[key] | |
1134 | ||
1135 | self.assertEquals(total, misses) | |
2714396e RG |
1136 | |
1137 | class TestCachingFailureTTL(DNSDistTest): | |
1138 | ||
1139 | _failureCacheTTL = 2 | |
1140 | _config_params = ['_failureCacheTTL', '_testServerPort'] | |
1141 | _config_template = """ | |
1142 | pc = newPacketCache(1000, 86400, 0, %d, 60) | |
1143 | getPool(""):setCache(pc) | |
1144 | newServer{address="127.0.0.1:%s"} | |
1145 | """ | |
1146 | def testCacheServFailTTL(self): | |
1147 | """ | |
1148 | Cache: ServFail TTL | |
1149 | ||
1150 | """ | |
1151 | misses = 0 | |
1152 | name = 'servfail.failure.cache.tests.powerdns.com.' | |
1153 | query = dns.message.make_query(name, 'A', 'IN') | |
1154 | response = dns.message.make_response(query) | |
1155 | response.set_rcode(dns.rcode.SERVFAIL) | |
1156 | ||
1157 | # Miss | |
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) | |
1164 | misses += 1 | |
1165 | ||
1166 | # next queries should hit the cache | |
1167 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
1168 | self.assertEquals(receivedResponse, response) | |
1169 | ||
1170 | time.sleep(self._failureCacheTTL + 1) | |
1171 | ||
1172 | # we should not have cached for longer than failure cache | |
1173 | # so it should be a miss | |
1174 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
1175 | self.assertTrue(receivedQuery) | |
1176 | self.assertTrue(receivedResponse) | |
1177 | receivedQuery.id = query.id | |
1178 | self.assertEquals(query, receivedQuery) | |
1179 | self.assertEquals(response, receivedResponse) | |
1180 | misses += 1 | |
1181 | ||
1182 | total = 0 | |
1183 | for key in self._responsesCounter: | |
1184 | total += self._responsesCounter[key] | |
1185 | ||
1186 | self.assertEquals(total, misses) | |
1187 | ||
1188 | def testCacheRefusedTTL(self): | |
1189 | """ | |
1190 | Cache: Refused TTL | |
1191 | ||
1192 | """ | |
1193 | misses = 0 | |
1194 | name = 'refused.failure.cache.tests.powerdns.com.' | |
1195 | query = dns.message.make_query(name, 'A', 'IN') | |
1196 | response = dns.message.make_response(query) | |
1197 | response.set_rcode(dns.rcode.REFUSED) | |
1198 | ||
1199 | # Miss | |
1200 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
1201 | self.assertTrue(receivedQuery) | |
1202 | self.assertTrue(receivedResponse) | |
1203 | receivedQuery.id = query.id | |
1204 | self.assertEquals(query, receivedQuery) | |
1205 | self.assertEquals(response, receivedResponse) | |
1206 | misses += 1 | |
1207 | ||
1208 | # next queries should hit the cache | |
1209 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
1210 | self.assertEquals(receivedResponse, response) | |
1211 | ||
1212 | time.sleep(self._failureCacheTTL + 1) | |
1213 | ||
1214 | # we should not have cached for longer than failure cache | |
1215 | # so it should be a miss | |
1216 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
1217 | self.assertTrue(receivedQuery) | |
1218 | self.assertTrue(receivedResponse) | |
1219 | receivedQuery.id = query.id | |
1220 | self.assertEquals(query, receivedQuery) | |
1221 | self.assertEquals(response, receivedResponse) | |
1222 | misses += 1 | |
1223 | ||
1224 | total = 0 | |
1225 | for key in self._responsesCounter: | |
1226 | total += self._responsesCounter[key] | |
1227 | ||
1228 | self.assertEquals(total, misses) | |
1229 | ||
1230 | def testCacheHeaderOnlyRefusedTTL(self): | |
1231 | """ | |
1232 | Cache: Header-Only Refused TTL | |
1233 | ||
1234 | """ | |
1235 | misses = 0 | |
1236 | name = 'header-only-refused.failure.cache.tests.powerdns.com.' | |
1237 | query = dns.message.make_query(name, 'A', 'IN') | |
1238 | response = dns.message.make_response(query) | |
1239 | response.set_rcode(dns.rcode.REFUSED) | |
1240 | response.question = [] | |
1241 | ||
1242 | # Miss | |
1243 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
1244 | self.assertTrue(receivedQuery) | |
1245 | self.assertTrue(receivedResponse) | |
1246 | receivedQuery.id = query.id | |
1247 | self.assertEquals(query, receivedQuery) | |
1248 | self.assertEquals(response, receivedResponse) | |
1249 | misses += 1 | |
1250 | ||
1251 | # next queries should hit the cache | |
1252 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
1253 | self.assertEquals(receivedResponse, response) | |
1254 | ||
1255 | time.sleep(self._failureCacheTTL + 1) | |
1256 | ||
1257 | # we should not have cached for longer than failure cache | |
1258 | # so it should be a miss | |
1259 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
1260 | self.assertTrue(receivedQuery) | |
1261 | self.assertTrue(receivedResponse) | |
1262 | receivedQuery.id = query.id | |
1263 | self.assertEquals(query, receivedQuery) | |
1264 | self.assertEquals(response, receivedResponse) | |
1265 | misses += 1 | |
1266 | ||
1267 | total = 0 | |
1268 | for key in self._responsesCounter: | |
1269 | total += self._responsesCounter[key] | |
1270 | ||
1271 | self.assertEquals(total, misses) | |
2b67180c RG |
1272 | |
1273 | class TestCachingDontAge(DNSDistTest): | |
1274 | ||
1275 | _config_template = """ | |
1276 | pc = newPacketCache(100, 86400, 0, 60, 60, true) | |
1277 | getPool(""):setCache(pc) | |
1278 | newServer{address="127.0.0.1:%s"} | |
1279 | """ | |
1280 | def testCacheDoesntDecreaseTTL(self): | |
1281 | """ | |
1282 | Cache: Cache doesn't decrease TTL with 'don't age' set | |
1283 | ||
1284 | dnsdist is configured to cache entries but without aging the TTL, | |
1285 | we are sending one request (cache miss) and verify that the cache | |
1286 | hits don't have a decreasing TTL. | |
1287 | """ | |
1288 | ttl = 600 | |
1289 | misses = 0 | |
1290 | name = 'cachedoesntdecreasettl.cache-dont-age.tests.powerdns.com.' | |
1291 | query = dns.message.make_query(name, 'AAAA', 'IN') | |
1292 | response = dns.message.make_response(query) | |
1293 | rrset = dns.rrset.from_text(name, | |
1294 | ttl, | |
1295 | dns.rdataclass.IN, | |
1296 | dns.rdatatype.AAAA, | |
1297 | '::1') | |
1298 | response.answer.append(rrset) | |
1299 | ||
1300 | # first query to fill the cache | |
1301 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
1302 | self.assertTrue(receivedQuery) | |
1303 | self.assertTrue(receivedResponse) | |
1304 | receivedQuery.id = query.id | |
1305 | self.assertEquals(query, receivedQuery) | |
1306 | self.assertEquals(receivedResponse, response) | |
1307 | misses += 1 | |
1308 | ||
1309 | # next queries should hit the cache | |
1310 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
1311 | self.assertEquals(receivedResponse, response) | |
1312 | for an in receivedResponse.answer: | |
1313 | self.assertTrue(an.ttl == ttl) | |
1314 | ||
1315 | # now we wait a bit for the TTL to decrease | |
1316 | time.sleep(1) | |
1317 | ||
1318 | # next queries should hit the cache | |
1319 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
1320 | self.assertEquals(receivedResponse, response) | |
1321 | for an in receivedResponse.answer: | |
1322 | self.assertTrue(an.ttl == ttl) | |
1323 | ||
1324 | total = 0 | |
1325 | for key in self._responsesCounter: | |
1326 | total += self._responsesCounter[key] | |
1327 | ||
1328 | self.assertEquals(total, misses) |