From: Remi Gacogne Date: Thu, 25 Feb 2016 16:51:24 +0000 (+0100) Subject: dnsdist: Fix cache tests. Clean tests backends. X-Git-Tag: rec-4.0.0-alpha2~59^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F3458%2Fhead;p=thirdparty%2Fpdns.git dnsdist: Fix cache tests. Clean tests backends. Several issues: - the cache tests used a vey small cache, not large enough for the number of responses we expected to cache during the test suite - this was hidden by the default response from the backends matching what the test expected - and by the backends not counting properly what looked like a health check but wasn't. --- diff --git a/regression-tests.dnsdist/dnscrypt.py b/regression-tests.dnsdist/dnscrypt.py index 60070bb4e5..f46bd6df78 100644 --- a/regression-tests.dnsdist/dnscrypt.py +++ b/regression-tests.dnsdist/dnscrypt.py @@ -1,13 +1,13 @@ #!/usr/bin/env python2 -import dns -import dns.message import socket import struct import time +import dns +import dns.message import libnacl import libnacl.utils -class DNSCryptResolverCertificate: +class DNSCryptResolverCertificate(object): DNSCRYPT_CERT_MAGIC = '\x44\x4e\x53\x43' DNSCRYPT_ES_VERSION = '\x00\x01' DNSCRYPT_PROTOCOL_MIN_VERSION = '\x00\x00' @@ -44,7 +44,7 @@ class DNSCryptResolverCertificate: validUntil = struct.unpack_from("!I", orig[48:52])[0] return DNSCryptResolverCertificate(serial, validFrom, validUntil, resolverPK, clientMagic) -class DNSCryptClient: +class DNSCryptClient(object): DNSCRYPT_NONCE_SIZE = 24 DNSCRYPT_MAC_SIZE = 16 DNSCRYPT_PADDED_BLOCK_SIZE = 64 diff --git a/regression-tests.dnsdist/dnsdisttests.py b/regression-tests.dnsdist/dnsdisttests.py index 4f186de94a..816b61d683 100644 --- a/regression-tests.dnsdist/dnsdisttests.py +++ b/regression-tests.dnsdist/dnsdisttests.py @@ -112,12 +112,34 @@ class DNSDistTest(unittest.TestCase): cls._dnsdist.wait() @classmethod - def ResponderIncrementCounter(cls): + def _ResponderIncrementCounter(cls): if threading.currentThread().name in cls._responsesCounter: cls._responsesCounter[threading.currentThread().name] += 1 else: cls._responsesCounter[threading.currentThread().name] = 1 + @classmethod + def _getResponse(cls, request): + response = None + if len(request.question) != 1: + print("Skipping query with question count %d" % (len(request.question))) + return None + healthcheck = not str(request.question[0].name).endswith('tests.powerdns.com.') + if not healthcheck: + cls._ResponderIncrementCounter() + if not cls._toResponderQueue.empty(): + response = cls._toResponderQueue.get(True, cls._queueTimeout) + if response: + response = copy.copy(response) + response.id = request.id + cls._fromResponderQueue.put(request, True, cls._queueTimeout) + + if not response: + # unexpected query, or health check + response = dns.message.make_response(request) + + return response + @classmethod def UDPResponder(cls, port): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) @@ -126,38 +148,9 @@ class DNSDistTest(unittest.TestCase): while True: data, addr = sock.recvfrom(4096) request = dns.message.from_wire(data) - answered = False - if len(request.question) != 1: - print("Skipping query with question count %d" % (len(request.question))) + response = cls._getResponse(request) + if not response: continue - if str(request.question[0].name).endswith('tests.powerdns.com.') and not cls._toResponderQueue.empty(): - response = cls._toResponderQueue.get(True, cls._queueTimeout) - if response: - response = copy.copy(response) - response.id = request.id - cls._fromResponderQueue.put(request, True, cls._queueTimeout) - cls.ResponderIncrementCounter() - answered = True - - if not answered: - # unexpected query, or health check - response = dns.message.make_response(request) - rrset = None - if request.question[0].rdclass == dns.rdataclass.IN: - if request.question[0].rdtype == dns.rdatatype.A: - rrset = dns.rrset.from_text(request.question[0].name, - 3600, - request.question[0].rdclass, - request.question[0].rdtype, - '127.0.0.1') - elif request.question[0].rdtype == dns.rdatatype.AAAA: - rrset = dns.rrset.from_text(request.question[0].name, - 3600, - request.question[0].rdclass, - request.question[0].rdtype, - '::1') - if rrset: - response.answer.append(rrset) sock.settimeout(2.0) sock.sendto(response.to_wire(), addr) @@ -176,44 +169,15 @@ class DNSDistTest(unittest.TestCase): sock.listen(100) while True: - answered = False (conn, _) = sock.accept() conn.settimeout(2.0) data = conn.recv(2) (datalen,) = struct.unpack("!H", data) data = conn.recv(datalen) request = dns.message.from_wire(data) - if len(request.question) != 1: - print("Skipping query with question count %d" % (len(request.question))) + response = cls._getResponse(request) + if not response: continue - if str(request.question[0].name).endswith('tests.powerdns.com.') and not cls._toResponderQueue.empty(): - response = cls._toResponderQueue.get(True, cls._queueTimeout) - if response: - response = copy.copy(response) - response.id = request.id - cls._fromResponderQueue.put(request, True, cls._queueTimeout) - cls.ResponderIncrementCounter() - answered = True - - if not answered: - # unexpected query, or health check - response = dns.message.make_response(request) - rrset = None - if request.question[0].rdclass == dns.rdataclass.IN: - if request.question[0].rdtype == dns.rdatatype.A: - rrset = dns.rrset.from_text(request.question[0].name, - 3600, - request.question[0].rdclass, - request.question[0].rdtype, - '127.0.0.1') - elif request.question[0].rdtype == dns.rdatatype.AAAA: - rrset = dns.rrset.from_text(request.question[0].name, - 3600, - request.question[0].rdclass, - request.question[0].rdtype, - '::1') - if rrset: - response.answer.append(rrset) wire = response.to_wire() conn.send(struct.pack("!H", len(wire))) @@ -294,4 +258,4 @@ class DNSDistTest(unittest.TestCase): self._toResponderQueue.get(False) while not self._fromResponderQueue.empty(): - self._toResponderQueue.get(False) + self._fromResponderQueue.get(False) diff --git a/regression-tests.dnsdist/pylintrc b/regression-tests.dnsdist/pylintrc new file mode 100644 index 0000000000..83a00d22f5 --- /dev/null +++ b/regression-tests.dnsdist/pylintrc @@ -0,0 +1,2 @@ +[MESSAGES CONTROL] +disable=invalid-name, missing-docstring, line-too-long, superfluous-parens \ No newline at end of file diff --git a/regression-tests.dnsdist/test_Caching.py b/regression-tests.dnsdist/test_Caching.py index ecb15edfcb..e9335c4aef 100644 --- a/regression-tests.dnsdist/test_Caching.py +++ b/regression-tests.dnsdist/test_Caching.py @@ -6,11 +6,12 @@ from dnsdisttests import DNSDistTest class TestCaching(DNSDistTest): _config_template = """ - pc = newPacketCache(5, 86400, 1) + pc = newPacketCache(100, 86400, 1) getPool(""):setCache(pc) addAction(makeRule("nocache.cache.tests.powerdns.com."), SkipCacheAction()) newServer{address="127.0.0.1:%s"} """ + def testCached(self): """ Cache: Served from cache @@ -366,3 +367,74 @@ class TestCachingWithExistingEDNS(DNSDistTest): total += TestCachingWithExistingEDNS._responsesCounter[key] self.assertEquals(total, misses) + +class TestCachingCacheFull(DNSDistTest): + + _config_template = """ + pc = newPacketCache(1, 86400, 1) + getPool(""):setCache(pc) + newServer{address="127.0.0.1:%s"} + """ + def testCacheFull(self): + """ + Cache: No new entries are cached when the cache is full + + """ + misses = 0 + name = 'cachenotfullyet.cache.tests.powerdns.com.' + query = dns.message.make_query(name, 'A', 'IN') + response = dns.message.make_response(query) + rrset = dns.rrset.from_text(name, + 3600, + dns.rdataclass.IN, + dns.rdatatype.A, + '127.0.0.1') + response.answer.append(rrset) + + # Miss + (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) + self.assertTrue(receivedQuery) + self.assertTrue(receivedResponse) + receivedQuery.id = query.id + self.assertEquals(query, receivedQuery) + self.assertEquals(response, receivedResponse) + misses += 1 + + # next queries should hit the cache + (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) + self.assertEquals(receivedResponse, response) + + # ok, now the cache is full, send another query + name = 'cachefull.cache.tests.powerdns.com.' + query = dns.message.make_query(name, 'AAAA', 'IN') + response = dns.message.make_response(query) + rrset = dns.rrset.from_text(name, + 3600, + dns.rdataclass.IN, + dns.rdatatype.AAAA, + '::1') + response.answer.append(rrset) + + # Miss + (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) + self.assertTrue(receivedQuery) + self.assertTrue(receivedResponse) + receivedQuery.id = query.id + self.assertEquals(query, receivedQuery) + self.assertEquals(response, receivedResponse) + misses += 1 + + # next queries should NOT hit the cache + (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) + self.assertTrue(receivedQuery) + self.assertTrue(receivedResponse) + receivedQuery.id = query.id + self.assertEquals(query, receivedQuery) + self.assertEquals(response, receivedResponse) + misses += 1 + + total = 0 + for key in TestCachingCacheFull._responsesCounter: + total += TestCachingCacheFull._responsesCounter[key] + + self.assertEquals(total, misses) diff --git a/regression-tests.dnsdist/test_CheckConfig.py b/regression-tests.dnsdist/test_CheckConfig.py index 2034fc8511..71a7132bce 100644 --- a/regression-tests.dnsdist/test_CheckConfig.py +++ b/regression-tests.dnsdist/test_CheckConfig.py @@ -6,7 +6,8 @@ import sys class TestCheckConfig(unittest.TestCase): - def tryDNSDist(self, configTemplate, shouldBeSuccessful=True): + @staticmethod + def tryDNSDist(configTemplate, shouldBeSuccessful=True): conffile = 'dnsdist_test.conf' with open(conffile, 'w') as conf: conf.write("-- Autogenerated by dnsdisttests.py\n") diff --git a/regression-tests.dnsdist/test_EdnsClientSubnet.py b/regression-tests.dnsdist/test_EdnsClientSubnet.py index 020545825d..3b4386a8ca 100644 --- a/regression-tests.dnsdist/test_EdnsClientSubnet.py +++ b/regression-tests.dnsdist/test_EdnsClientSubnet.py @@ -13,15 +13,6 @@ class TestEdnsClientSubnetNoOverride(DNSDistTest): _config_template = """ truncateTC(true) - block=newDNSName("powerdns.org.") - function blockFilter(dq) - if(dq.qname:isPartOf(block)) - then - print("Blocking *.powerdns.org") - return true - end - return false - end newServer{address="127.0.0.1:%s", useClientSubnet=true} """ @@ -142,15 +133,6 @@ class TestEdnsClientSubnetOverride(DNSDistTest): _config_template = """ truncateTC(true) - block=newDNSName("powerdns.org.") - function blockFilter(dq) - if(dq.qname:isPartOf(block)) - then - print("Blocking *.powerdns.org") - return true - end - return false - end setECSOverride(true) setECSSourcePrefixV4(24) setECSSourcePrefixV6(56) diff --git a/regression-tests.dnsdist/test_Spoofing.py b/regression-tests.dnsdist/test_Spoofing.py index 0af9a109ec..cc817462d4 100644 --- a/regression-tests.dnsdist/test_Spoofing.py +++ b/regression-tests.dnsdist/test_Spoofing.py @@ -241,14 +241,14 @@ class TestSpoofingSpoof(DNSDistTest): # dnsdist set RA = RD for spoofed responses query.flags &= ~dns.flags.RD expectedResponse = dns.message.make_response(query) - + rrset = dns.rrset.from_text(name, 60, dns.rdataclass.IN, dns.rdatatype.A, '192.0.2.2', '192.0.2.1') expectedResponse.answer.append(rrset) - + rrset = dns.rrset.from_text(name, 60, dns.rdataclass.IN,