]> 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:40:13 +0000 (12:40 -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.

(cherry picked from commit 1b22985f2d67b6dd43259e3c6b853498f1cff712)

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