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