From 4b07fa531dd75359dacf23ca6bfa103fdd593227 Mon Sep 17 00:00:00 2001 From: Bob Halley Date: Tue, 16 Jun 2020 16:51:10 -0700 Subject: [PATCH] Improve resolver coverage by: Testing more stuff. Ignoring coverage of Windows as we have no way to integrate coverage data from windows test runs at this time. Ignoring other not important things. --- dns/resolver.py | 27 +++++++++++---------------- tests/test_doh.py | 18 +++++++++++++++++- tests/test_resolver.py | 16 +++++++--------- 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/dns/resolver.py b/dns/resolver.py index 1fe92249..53ef68d3 100644 --- a/dns/resolver.py +++ b/dns/resolver.py @@ -26,7 +26,7 @@ import warnings try: import threading as _threading except ImportError: - import dummy_threading as _threading # type: ignore + import dummy_threading as _threading # type: ignore # pragma: no cover import dns.exception import dns.flags @@ -42,7 +42,7 @@ import dns.reversename import dns.tsig if sys.platform == 'win32': - import winreg + import winreg # pragma: no cover class NXDOMAIN(dns.exception.DNSException): """The DNS query name does not exist.""" @@ -251,7 +251,7 @@ class Answer: break self.expiration = time.time() + min_ttl - def __getattr__(self, attr): + def __getattr__(self, attr): # pragma: no cover if attr == 'name': return self.rrset.name elif attr == 'ttl': @@ -368,12 +368,6 @@ class LRUCacheNode: self.prev = self self.next = self - def link_before(self, node): - self.prev = node.prev - self.next = node - node.prev.next = self - node.prev = self - def link_after(self, node): self.prev = node self.next = node.next @@ -785,7 +779,7 @@ class Resolver: if len(self.nameservers) == 0: raise NoResolverConfiguration - def _determine_split_char(self, entry): + def _determine_split_char(self, entry): # pragma: no cover # # The windows registry irritatingly changes the list element # delimiter in between ' ' and ',' (and vice-versa) in various @@ -800,7 +794,7 @@ class Resolver: split_char = ' ' return split_char - def _config_win32_nameservers(self, nameservers): + def _config_win32_nameservers(self, nameservers): # pragma: no cover # we call str() on nameservers to convert it from unicode to ascii nameservers = str(nameservers) split_char = self._determine_split_char(nameservers) @@ -809,11 +803,11 @@ class Resolver: if ns not in self.nameservers: self.nameservers.append(ns) - def _config_win32_domain(self, domain): + def _config_win32_domain(self, domain): # pragma: no cover # we call str() on domain to convert it from unicode to ascii self.domain = dns.name.from_text(str(domain)) - def _config_win32_search(self, search): + def _config_win32_search(self, search): # pragma: no cover # we call str() on search to convert it from unicode to ascii search = str(search) split_char = self._determine_split_char(search) @@ -822,7 +816,7 @@ class Resolver: if s not in self.search: self.search.append(dns.name.from_text(s)) - def _config_win32_fromkey(self, key, always_try_domain): + def _config_win32_fromkey(self, key, always_try_domain): # pragma: no cover try: servers, rtype = winreg.QueryValueEx(key, 'NameServer') except WindowsError: # pylint: disable=undefined-variable @@ -856,7 +850,7 @@ class Resolver: if search: self._config_win32_search(search) - def read_registry(self): + def read_registry(self): # pragma: no cover """Extract resolver configuration from the Windows registry.""" lm = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) @@ -902,7 +896,8 @@ class Resolver: finally: lm.Close() - def _win32_is_nic_enabled(self, lm, guid, interface_key): + def _win32_is_nic_enabled(self, lm, guid, + interface_key): # pragma: no cover # Look in the Windows Registry to determine whether the network # interface corresponding to the given guid is enabled. # diff --git a/tests/test_doh.py b/tests/test_doh.py index 11831a6b..f4fdae28 100644 --- a/tests/test_doh.py +++ b/tests/test_doh.py @@ -18,9 +18,10 @@ import unittest import random import socket +import dns.message import dns.query import dns.rdatatype -import dns.message +import dns.resolver if dns.query.have_doh: import requests @@ -121,5 +122,20 @@ class DNSOverHTTPSTestCase(unittest.TestCase): r = dns.query.https(q, nameserver_url) self.assertTrue(q.is_response(r)) + def test_resolver(self): + res = dns.resolver.Resolver() + res.nameservers = ['https://dns.google/dns-query'] + answer = res.resolve('dns.google', 'A') + seen = set([rdata.address for rdata in answer]) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + + def test_resolver_bad_scheme(self): + res = dns.resolver.Resolver() + res.nameservers = ['bogus://dns.google/dns-query'] + def bad(): + answer = res.resolve('dns.google', 'A') + self.assertRaises(dns.resolver.NoNameservers, bad) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_resolver.py b/tests/test_resolver.py index 309a89d7..cf5118fa 100644 --- a/tests/test_resolver.py +++ b/tests/test_resolver.py @@ -339,22 +339,20 @@ class BaseResolverTests(unittest.TestCase): qnames = res._get_qnames_to_try(qname, None) self.assertEqual(qnames, [qname]) +@unittest.skipIf(not _network_available, "Internet not reachable") class LiveResolverTests(unittest.TestCase): - @unittest.skipIf(not _network_available, "Internet not reachable") def testZoneForName1(self): name = dns.name.from_text('www.dnspython.org.') ezname = dns.name.from_text('dnspython.org.') zname = dns.resolver.zone_for_name(name) self.assertEqual(zname, ezname) - @unittest.skipIf(not _network_available, "Internet not reachable") def testZoneForName2(self): name = dns.name.from_text('a.b.www.dnspython.org.') ezname = dns.name.from_text('dnspython.org.') zname = dns.resolver.zone_for_name(name) self.assertEqual(zname, ezname) - @unittest.skipIf(not _network_available, "Internet not reachable") def testZoneForName3(self): name = dns.name.from_text('dnspython.org.') ezname = dns.name.from_text('dnspython.org.') @@ -367,26 +365,28 @@ class LiveResolverTests(unittest.TestCase): dns.resolver.zone_for_name(name) self.assertRaises(dns.resolver.NotAbsolute, bad) - @unittest.skipIf(not _network_available, "Internet not reachable") def testResolve(self): answer = dns.resolver.resolve('dns.google.', 'A') seen = set([rdata.address for rdata in answer]) self.assertTrue('8.8.8.8' in seen) self.assertTrue('8.8.4.4' in seen) - @unittest.skipIf(not _network_available, "Internet not reachable") + def testResolveTCP(self): + answer = dns.resolver.resolve('dns.google.', 'A', tcp=True) + seen = set([rdata.address for rdata in answer]) + self.assertTrue('8.8.8.8' in seen) + self.assertTrue('8.8.4.4' in seen) + def testResolveAddress(self): answer = dns.resolver.resolve_address('8.8.8.8') dnsgoogle = dns.name.from_text('dns.google.') self.assertEqual(answer[0].target, dnsgoogle) - @unittest.skipIf(not _network_available, "Internet not reachable") def testResolveNodataException(self): def bad(): dns.resolver.resolve('dnspython.org.', 'TYPE3') # obsolete MB self.assertRaises(dns.resolver.NoAnswer, bad) - @unittest.skipIf(not _network_available, "Internet not reachable") def testResolveNodataAnswer(self): qname = dns.name.from_text('dnspython.org') qclass = dns.rdataclass.from_text('IN') @@ -396,7 +396,6 @@ class LiveResolverTests(unittest.TestCase): lambda: answer.response.find_rrset(answer.response.answer, qname, qclass, qtype)) - @unittest.skipIf(not _network_available, "Internet not reachable") def testResolveNXDOMAIN(self): qname = dns.name.from_text('nxdomain.dnspython.org') qclass = dns.rdataclass.from_text('IN') @@ -405,7 +404,6 @@ class LiveResolverTests(unittest.TestCase): answer = dns.resolver.resolve(qname, qtype) self.assertRaises(dns.resolver.NXDOMAIN, bad) - @unittest.skipIf(not _network_available, "Internet not reachable") def testResolveCacheHit(self): res = dns.resolver.Resolver() res.cache = dns.resolver.Cache() -- 2.47.3