]> git.ipfire.org Git - thirdparty/pdns.git/blame - regression-tests.dnsdist/test_Caching.py
dnsdist: Add/fix cache cleaning options
[thirdparty/pdns.git] / regression-tests.dnsdist / test_Caching.py
CommitLineData
903853f4
RG
1#!/usr/bin/env python
2import time
3import dns
4from dnsdisttests import DNSDistTest
5
6class TestCaching(DNSDistTest):
7
8 _config_template = """
fe1c60f2 9 pc = newPacketCache(100, 86400, 1)
903853f4
RG
10 getPool(""):setCache(pc)
11 addAction(makeRule("nocache.cache.tests.powerdns.com."), SkipCacheAction())
12 newServer{address="127.0.0.1:%s"}
13 """
fe1c60f2 14
903853f4
RG
15 def testCached(self):
16 """
17 Cache: Served from cache
18
19 dnsdist is configured to cache entries, we are sending several
20 identical requests and checking that the backend only receive
21 the first one.
22 """
23 numberOfQueries = 10
24 name = 'cached.cache.tests.powerdns.com.'
25 query = dns.message.make_query(name, 'AAAA', 'IN')
26 response = dns.message.make_response(query)
27 rrset = dns.rrset.from_text(name,
28 3600,
29 dns.rdataclass.IN,
30 dns.rdatatype.AAAA,
31 '::1')
32 response.answer.append(rrset)
33
34 # first query to fill the cache
35 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
36 self.assertTrue(receivedQuery)
37 self.assertTrue(receivedResponse)
38 receivedQuery.id = query.id
39 self.assertEquals(query, receivedQuery)
40 self.assertEquals(receivedResponse, response)
41
42 for _ in range(numberOfQueries):
43 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
44 self.assertEquals(receivedResponse, response)
45
46 total = 0
47 for key in TestCaching._responsesCounter:
48 total += TestCaching._responsesCounter[key]
49 TestCaching._responsesCounter[key] = 0
50
51 self.assertEquals(total, 1)
52
53 # TCP should not be cached
54 # first query to fill the cache
55 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
56 self.assertTrue(receivedQuery)
57 self.assertTrue(receivedResponse)
58 receivedQuery.id = query.id
59 self.assertEquals(query, receivedQuery)
60 self.assertEquals(receivedResponse, response)
61
62 for _ in range(numberOfQueries):
63 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
64 self.assertEquals(receivedResponse, response)
65
66 total = 0
67 for key in TestCaching._responsesCounter:
68 total += TestCaching._responsesCounter[key]
69 TestCaching._responsesCounter[key] = 0
70
71 self.assertEquals(total, 1)
72
73 def testSkipCache(self):
74 """
75 Cache: SkipCacheAction
76
77 dnsdist is configured to not cache entries for nocache.cache.tests.powerdns.com.
78 we are sending several requests and checking that the backend get them all.
79 """
80 name = 'nocache.cache.tests.powerdns.com.'
81 numberOfQueries = 10
82 query = dns.message.make_query(name, 'AAAA', 'IN')
83 response = dns.message.make_response(query)
84 rrset = dns.rrset.from_text(name,
85 3600,
86 dns.rdataclass.IN,
87 dns.rdatatype.AAAA,
88 '::1')
89 response.answer.append(rrset)
90
91 for _ in range(numberOfQueries):
92 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
93 self.assertTrue(receivedQuery)
94 self.assertTrue(receivedResponse)
95 receivedQuery.id = query.id
96 self.assertEquals(query, receivedQuery)
97 self.assertEquals(receivedResponse, response)
98
99 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
100 self.assertTrue(receivedQuery)
101 self.assertTrue(receivedResponse)
102 receivedQuery.id = query.id
103 self.assertEquals(query, receivedQuery)
104 self.assertEquals(receivedResponse, response)
105
106 for key in TestCaching._responsesCounter:
107 value = TestCaching._responsesCounter[key]
108 self.assertEquals(value, numberOfQueries)
109
110 def testCacheExpiration(self):
111 """
112 Cache: Cache expiration
113
114 dnsdist is configured to cache entries, we are sending one request
115 (cache miss) with a very short TTL, checking that the next requests
116 are cached. Then we wait for the TTL to expire, check that the
117 next request is a miss but the following one a hit.
118 """
119 ttl = 2
120 misses = 0
121 name = 'cacheexpiration.cache.tests.powerdns.com.'
122 query = dns.message.make_query(name, 'AAAA', 'IN')
123 response = dns.message.make_response(query)
124 rrset = dns.rrset.from_text(name,
125 ttl,
126 dns.rdataclass.IN,
127 dns.rdatatype.AAAA,
128 '::1')
129 response.answer.append(rrset)
130
131 # first query to fill the cache
132 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
133 self.assertTrue(receivedQuery)
134 self.assertTrue(receivedResponse)
135 receivedQuery.id = query.id
136 self.assertEquals(query, receivedQuery)
137 self.assertEquals(receivedResponse, response)
138 misses += 1
139
140 # next queries should hit the cache
141 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
142 self.assertEquals(receivedResponse, response)
143
144 # now we wait a bit for the cache entry to expire
145 time.sleep(ttl + 1)
146
147 # next query should be a miss, fill the cache again
148 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
149 self.assertTrue(receivedQuery)
150 self.assertTrue(receivedResponse)
151 receivedQuery.id = query.id
152 self.assertEquals(query, receivedQuery)
153 self.assertEquals(receivedResponse, response)
154 misses += 1
155
156 # following queries should hit the cache again
157 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
158 self.assertEquals(receivedResponse, response)
159
160 total = 0
161 for key in TestCaching._responsesCounter:
162 total += TestCaching._responsesCounter[key]
163
164 self.assertEquals(total, misses)
165
166 def testCacheExpirationDifferentSets(self):
167 """
168 Cache: Cache expiration with different sets
169
170 dnsdist is configured to cache entries, we are sending one request
171 (cache miss) whose response has a long and a very short TTL,
172 checking that the next requests are cached. Then we wait for the
173 short TTL to expire, check that the
174 next request is a miss but the following one a hit.
175 """
176 ttl = 2
177 misses = 0
178 name = 'cacheexpirationdifferentsets.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,
182 ttl,
183 dns.rdataclass.IN,
184 dns.rdatatype.CNAME,
185 'cname.cacheexpirationdifferentsets.cache.tests.powerdns.com.')
186 response.answer.append(rrset)
187 rrset = dns.rrset.from_text('cname.cacheexpirationdifferentsets.cache.tests.powerdns.com.',
188 ttl + 3600,
189 dns.rdataclass.IN,
190 dns.rdatatype.A,
191 '192.2.0.1')
192 response.additional.append(rrset)
193
194 # first query to fill the cache
195 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
196 self.assertTrue(receivedQuery)
197 self.assertTrue(receivedResponse)
198 receivedQuery.id = query.id
199 self.assertEquals(query, receivedQuery)
200 self.assertEquals(receivedResponse, response)
201 misses += 1
202
203 # next queries should hit the cache
204 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
205 self.assertEquals(receivedResponse, response)
206
207 # now we wait a bit for the cache entry to expire
208 time.sleep(ttl + 1)
209
210 # next query should be a miss, fill the cache again
211 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
212 self.assertTrue(receivedQuery)
213 self.assertTrue(receivedResponse)
214 receivedQuery.id = query.id
215 self.assertEquals(query, receivedQuery)
216 self.assertEquals(receivedResponse, response)
217 misses += 1
218
219 # following queries should hit the cache again
220 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
221 self.assertEquals(receivedResponse, response)
222
223 total = 0
224 for key in TestCaching._responsesCounter:
225 total += TestCaching._responsesCounter[key]
226
227 self.assertEquals(total, misses)
228
229 def testCacheDecreaseTTL(self):
230 """
231 Cache: Cache decreases TTL
232
233 dnsdist is configured to cache entries, we are sending one request
234 (cache miss) and verify that the cache hits have a decreasing TTL.
235 """
236 ttl = 600
237 misses = 0
238 name = 'cachedecreasettl.cache.tests.powerdns.com.'
239 query = dns.message.make_query(name, 'AAAA', 'IN')
240 response = dns.message.make_response(query)
241 rrset = dns.rrset.from_text(name,
242 ttl,
243 dns.rdataclass.IN,
244 dns.rdatatype.AAAA,
245 '::1')
246 response.answer.append(rrset)
247
248 # first query to fill the cache
249 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
250 self.assertTrue(receivedQuery)
251 self.assertTrue(receivedResponse)
252 receivedQuery.id = query.id
253 self.assertEquals(query, receivedQuery)
254 self.assertEquals(receivedResponse, response)
255 misses += 1
256
257 # next queries should hit the cache
258 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
259 self.assertEquals(receivedResponse, response)
260 for an in receivedResponse.answer:
261 self.assertTrue(an.ttl <= ttl)
262
263 # now we wait a bit for the TTL to decrease
264 time.sleep(1)
265
266 # next queries should hit the cache
267 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
268 self.assertEquals(receivedResponse, response)
269 for an in receivedResponse.answer:
270 self.assertTrue(an.ttl < ttl)
271
272 total = 0
273 for key in TestCaching._responsesCounter:
274 total += TestCaching._responsesCounter[key]
275
276 self.assertEquals(total, misses)
277
278 def testCacheDifferentCase(self):
279 """
280 Cache: Cache matches different case
281
282 dnsdist is configured to cache entries, we are sending one request
283 (cache miss) and verify that the same one with a different case
284 matches.
285 """
286 ttl = 600
287 name = 'cachedifferentcase.cache.tests.powerdns.com.'
288 differentCaseName = 'CacheDifferentCASE.cache.tests.powerdns.com.'
289 query = dns.message.make_query(name, 'AAAA', 'IN')
290 differentCaseQuery = dns.message.make_query(differentCaseName, 'AAAA', 'IN')
291 response = dns.message.make_response(query)
292 differentCaseResponse = dns.message.make_response(differentCaseQuery)
293 rrset = dns.rrset.from_text(name,
294 ttl,
295 dns.rdataclass.IN,
296 dns.rdatatype.AAAA,
297 '::1')
298 response.answer.append(rrset)
299 differentCaseResponse.answer.append(rrset)
300
301 # first query to fill the cache
302 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
303 self.assertTrue(receivedQuery)
304 self.assertTrue(receivedResponse)
305 receivedQuery.id = query.id
306 self.assertEquals(query, receivedQuery)
307 self.assertEquals(receivedResponse, response)
308
309 # different case query should still hit the cache
310 (_, receivedResponse) = self.sendUDPQuery(differentCaseQuery, response=None, useQueue=False)
311 self.assertEquals(receivedResponse, differentCaseResponse)
312
313
314class TestCachingWithExistingEDNS(DNSDistTest):
315
316 _config_template = """
317 pc = newPacketCache(5, 86400, 1)
318 getPool(""):setCache(pc)
319 newServer{address="127.0.0.1:%s"}
320 """
321 def testCacheWithEDNS(self):
322 """
323 Cache: Cache should not match different EDNS value
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 EDNS UDP
327 Payload size is not served from the cache.
328 """
329 misses = 0
330 name = 'cachedifferentedns.cache.tests.powerdns.com.'
331 query = dns.message.make_query(name, 'A', 'IN', use_edns=True, payload=512)
332 response = dns.message.make_response(query)
333 rrset = dns.rrset.from_text(name,
334 3600,
335 dns.rdataclass.IN,
336 dns.rdatatype.A,
337 '127.0.0.1')
338 response.answer.append(rrset)
339
340 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
341 self.assertTrue(receivedQuery)
342 self.assertTrue(receivedResponse)
343 receivedQuery.id = query.id
344 self.assertEquals(query, receivedQuery)
345 self.assertEquals(response, receivedResponse)
346 misses += 1
347
348 query = dns.message.make_query(name, 'A', 'IN', use_edns=True, payload=4096)
349 response = dns.message.make_response(query)
350 rrset = dns.rrset.from_text(name,
351 3600,
352 dns.rdataclass.IN,
353 dns.rdatatype.A,
354 '127.0.0.1')
355 response.answer.append(rrset)
356
357 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
358 self.assertTrue(receivedQuery)
359 self.assertTrue(receivedResponse)
360 receivedQuery.id = query.id
361 self.assertEquals(query, receivedQuery)
362 self.assertEquals(response, receivedResponse)
363 misses += 1
364
365 total = 0
366 for key in TestCachingWithExistingEDNS._responsesCounter:
367 total += TestCachingWithExistingEDNS._responsesCounter[key]
368
369 self.assertEquals(total, misses)
fe1c60f2
RG
370
371class TestCachingCacheFull(DNSDistTest):
372
373 _config_template = """
374 pc = newPacketCache(1, 86400, 1)
375 getPool(""):setCache(pc)
376 newServer{address="127.0.0.1:%s"}
377 """
378 def testCacheFull(self):
379 """
380 Cache: No new entries are cached when the cache is full
381
382 """
383 misses = 0
384 name = 'cachenotfullyet.cache.tests.powerdns.com.'
385 query = dns.message.make_query(name, 'A', 'IN')
386 response = dns.message.make_response(query)
387 rrset = dns.rrset.from_text(name,
388 3600,
389 dns.rdataclass.IN,
390 dns.rdatatype.A,
391 '127.0.0.1')
392 response.answer.append(rrset)
393
394 # Miss
395 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
396 self.assertTrue(receivedQuery)
397 self.assertTrue(receivedResponse)
398 receivedQuery.id = query.id
399 self.assertEquals(query, receivedQuery)
400 self.assertEquals(response, receivedResponse)
401 misses += 1
402
403 # next queries should hit the cache
404 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
405 self.assertEquals(receivedResponse, response)
406
407 # ok, now the cache is full, send another query
408 name = 'cachefull.cache.tests.powerdns.com.'
409 query = dns.message.make_query(name, 'AAAA', 'IN')
410 response = dns.message.make_response(query)
411 rrset = dns.rrset.from_text(name,
412 3600,
413 dns.rdataclass.IN,
414 dns.rdatatype.AAAA,
415 '::1')
416 response.answer.append(rrset)
417
418 # Miss
419 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
420 self.assertTrue(receivedQuery)
421 self.assertTrue(receivedResponse)
422 receivedQuery.id = query.id
423 self.assertEquals(query, receivedQuery)
424 self.assertEquals(response, receivedResponse)
425 misses += 1
426
427 # next queries should NOT hit the cache
428 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
429 self.assertTrue(receivedQuery)
430 self.assertTrue(receivedResponse)
431 receivedQuery.id = query.id
432 self.assertEquals(query, receivedQuery)
433 self.assertEquals(response, receivedResponse)
434 misses += 1
435
436 total = 0
437 for key in TestCachingCacheFull._responsesCounter:
438 total += TestCachingCacheFull._responsesCounter[key]
439
440 self.assertEquals(total, misses)