]> git.ipfire.org Git - thirdparty/dnspython.git/commitdiff
In tests, work around musl libc and docker issues.
authorBob Halley <halley@dnspython.org>
Sat, 27 Jan 2024 20:38:03 +0000 (12:38 -0800)
committerBob Halley <halley@dnspython.org>
Sat, 27 Jan 2024 20:38:03 +0000 (12:38 -0800)
Specifically: musl libc's getaddrinfo behavior always returns
a canonical name.

Docker's resolver proxy doesn't do dangling CNAMEs correctly
and also answers NXDOMAIN in some cases where it should say
no error, no data.

tests/test_async.py
tests/test_resolver.py
tests/test_resolver_override.py
tests/util.py

index ac32431c28907ada331df27b4dd143edb96bf871..7c432ff57458ad6b8efc9a01216630e7222104f2 100644 (file)
@@ -53,6 +53,10 @@ try:
 except Exception:
     pass
 
+# Docker too!  It not only has problems with dangling CNAME, but also says NXDOMAIN when
+# it should say no error no data.
+_is_docker = tests.util.is_docker()
+
 query_addresses = []
 family = socket.AF_UNSPEC
 if tests.util.have_ipv4():
@@ -235,8 +239,10 @@ class AsyncTests(unittest.TestCase):
                 dns.reversename.from_address("8.8.8.8")
             )
 
-        with self.assertRaises(dns.resolver.NoAnswer):
-            self.async_run(run5)
+        if not _is_docker:
+            # docker returns NXDOMAIN!
+            with self.assertRaises(dns.resolver.NoAnswer):
+                self.async_run(run5)
 
     def testCanonicalNameNoCNAME(self):
         cname = dns.name.from_text("www.google.com")
@@ -255,7 +261,9 @@ class AsyncTests(unittest.TestCase):
 
         self.assertEqual(self.async_run(run), cname)
 
-    @unittest.skipIf(_systemd_resolved_present, "systemd-resolved in use")
+    @unittest.skipIf(
+        _systemd_resolved_present or _is_docker, "systemd-resolved or docker in use"
+    )
     def testCanonicalNameDangling(self):
         name = dns.name.from_text("dangling-cname.dnspython.org")
         cname = dns.name.from_text("dangling-target.dnspython.org")
index 903780863c2590cb30ba0b139f9b1fb3abc22d73..9550e87bd20255e5b285c7c034957660a03bd852 100644 (file)
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-from io import StringIO
 import selectors
-import sys
 import socket
+import sys
 import time
 import unittest
-import pytest
+from io import StringIO
 from unittest.mock import patch
 
+import pytest
+
 import dns.e164
 import dns.message
 import dns.name
@@ -61,6 +62,10 @@ try:
 except Exception:
     pass
 
+# Docker too!  It not only has problems with dangling CNAME, but also says NXDOMAIN when
+# it should say no error no data.
+_is_docker = tests.util.is_docker()
+
 
 resolv_conf = """
     /t/t
@@ -690,8 +695,10 @@ class LiveResolverTests(unittest.TestCase):
         with self.assertRaises(dns.resolver.NXDOMAIN):
             dns.resolver.resolve_name("nxdomain.dnspython.org")
 
-        with self.assertRaises(dns.resolver.NoAnswer):
-            dns.resolver.resolve_name(dns.reversename.from_address("8.8.8.8"))
+        if not _is_docker:
+            # We skip docker as it says NXDOMAIN!
+            with self.assertRaises(dns.resolver.NoAnswer):
+                dns.resolver.resolve_name(dns.reversename.from_address("8.8.8.8"))
 
     @patch.object(dns.message.Message, "use_edns")
     def testResolveEdnsOptions(self, message_use_edns_mock):
@@ -792,7 +799,9 @@ class LiveResolverTests(unittest.TestCase):
         cname = dns.name.from_text("dmfrjf4ips8xa.cloudfront.net")
         self.assertEqual(dns.resolver.canonical_name(name), cname)
 
-    @unittest.skipIf(_systemd_resolved_present, "systemd-resolved in use")
+    @unittest.skipIf(
+        _systemd_resolved_present or _is_docker, "systemd-resolved or docker in use"
+    )
     def testCanonicalNameDangling(self):
         name = dns.name.from_text("dangling-cname.dnspython.org")
         cname = dns.name.from_text("dangling-target.dnspython.org")
index aed7a53d10726e2bae1d0e5fbb931bb26fd0bf97..be9e53f27aa7424bb4b6504f9853f2befe46a3f2 100644 (file)
@@ -69,7 +69,7 @@ class OverrideSystemResolverTestCase(unittest.TestCase):
         dns.resolver.restore_system_resolver()
         self.assertTrue(socket.getaddrinfo is dns.resolver._original_getaddrinfo)
 
-    def equivalent_info(self, a, b):
+    def equivalent_info(self, a, b, q):
         if len(a) != len(b):
             return False
         for x in a:
@@ -78,16 +78,21 @@ class OverrideSystemResolverTestCase(unittest.TestCase):
                 # looking for a zero protocol.
                 y = (x[0], x[1], 0, x[3], x[4])
                 if y not in b:
-                    print("NOT EQUIVALENT")
-                    print(a)
-                    print(b)
-                    return False
+                    # musl libc insists on always providing a canonical name, so
+                    # accept that too.
+                    y = (x[0], x[1], x[2], q, x[4])
+                    if y not in b:
+                        print("NOT EQUIVALENT")
+                        print(a)
+                        print(b)
+                        return False
         return True
 
     def equivalent(self, *args, **kwargs):
+        q = args[0]
         a = socket.getaddrinfo(*args, **kwargs)
         b = dns.resolver._original_getaddrinfo(*args, **kwargs)
-        return self.equivalent_info(a, b)
+        return self.equivalent_info(a, b, q)
 
     @unittest.skipIf(
         sys.platform == "win32", "avoid windows original getaddrinfo issues"
@@ -139,7 +144,7 @@ class OverrideSystemResolverTestCase(unittest.TestCase):
     def test_getaddrinfo_service(self):
         a = socket.getaddrinfo("dns.google", "domain")
         b = socket.getaddrinfo("dns.google", 53)
-        self.assertTrue(self.equivalent_info(a, b))
+        self.assertTrue(self.equivalent_info(a, b, "dns.google"))
         try:
             socket.getaddrinfo("dns.google", "domain", flags=socket.AI_NUMERICSERV)
             self.assertTrue(False)  # should not happen!
index 5518b4185c4482dfd2d1fdeb293bfe0a48cb7082..9f0d3f464cd95b451db77e425d03e3999d3bd0b6 100644 (file)
@@ -18,7 +18,6 @@
 import enum
 import inspect
 import os
-import socket
 
 import dns.message
 import dns.name
@@ -123,3 +122,12 @@ def check_enum_exports(module, eq_callback, only=None):
         for flag, value in attr.__members__.items():
             # print(module, flag, value)
             eq_callback(getattr(module, flag), value)
+
+
+def is_docker() -> bool:
+    # There are a lot of answers to "am I runnning in a container" and none appear
+    # to work reliably, so we're settling for "am I running in docker?"
+    try:
+        return os.path.isfile("/.dockerenv")
+    except Exception:
+        return False