diff mbox series

oeqa/selftest/debuginfod: improve testcase

Message ID 20230110162037.3524842-1-ross.burton@arm.com
State New
Headers show
Series oeqa/selftest/debuginfod: improve testcase | expand

Commit Message

Ross Burton Jan. 10, 2023, 4:20 p.m. UTC
Primarily, before running the debuginfod-find tool, check that the
debuginfod server has finished sweeping the deploy directory.  If we
make the request too soon then there's a rare chance that we run the
client before it has scanned the right packages, and the log gets
swamped with warnings from sqlite due to a race.

Also:
- unset DEBUGINFOD_URLS so the debuginfod doesn't proxy to an upstream
  server provided by the host distro
- Lower concurrency to reduce system load and handle systems with lower
  maximum open file counts but lots of cores (as the concurrency means
  cores*2*2 open files)
- Set the refresh times to 0 so we never rescan during the test
- Only scan the packages for the format which the image is using
- Log the commands that are being invoked

Signed-off-by: Ross Burton <ross.burton@arm.com>
---
 meta/lib/oeqa/selftest/cases/debuginfod.py | 67 +++++++++++++++++++---
 1 file changed, 59 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/meta/lib/oeqa/selftest/cases/debuginfod.py b/meta/lib/oeqa/selftest/cases/debuginfod.py
index 3c401192829..37f51760fbc 100644
--- a/meta/lib/oeqa/selftest/cases/debuginfod.py
+++ b/meta/lib/oeqa/selftest/cases/debuginfod.py
@@ -12,6 +12,36 @@  from oeqa.utils.commands import bitbake, get_bb_var, runqemu
 
 
 class Debuginfod(OESelftestTestCase):
+
+    def wait_for_debuginfod(self, port):
+        """
+        debuginfod takes time to scan the packages and requesting too early may
+        result in a test failure if the right packages haven't been scanned yet.
+
+        Request the metrics endpoint periodically and wait for there to be no
+        busy scanning threads.
+
+        Returns True if debuginfod is ready, False if we timed out
+        """
+        import time, urllib
+
+        # Wait a minute
+        countdown = 6
+        delay = 10
+
+        while countdown:
+            time.sleep(delay)
+            try:
+                with urllib.request.urlopen("http://localhost:%d/metrics" % port) as f:
+                    lines = f.read().decode("ascii").splitlines()
+                    if "thread_busy{role=\"scan\"} 0" in lines:
+                        return True
+            except urllib.error.URLError as e:
+                self.logger.error(e)
+            countdown -= 1
+        return False
+
+
     def test_debuginfod(self):
         self.write_config(
             """
@@ -25,29 +55,50 @@  CORE_IMAGE_EXTRA_INSTALL += "elfutils"
         cmd = [
             os.path.join(native_sysroot, "usr", "bin", "debuginfod"),
             "--verbose",
+            # In-memory database, this is a one-shot test
             "--database=:memory:",
+            # Don't use all the host cores
+            "--concurrency=8",
+            "--connection-pool=8",
+            # Disable rescanning, this is a one-shot test
+            "--rescan-time=0",
+            "--groom-time=0",
             get_bb_var("DEPLOY_DIR"),
         ]
-        for format in get_bb_var("PACKAGE_CLASSES").split():
-            if format == "package_deb":
-                cmd.append("--scan-deb-dir")
-            elif format == "package_ipk":
-                cmd.append("--scan-deb-dir")
-            elif format == "package_rpm":
-                cmd.append("--scan-rpm-dir")
+
+        format = get_bb_var("PACKAGE_CLASSES").split()[0]
+        if format == "package_deb":
+            cmd.append("--scan-deb-dir")
+        elif format == "package_ipk":
+            cmd.append("--scan-deb-dir")
+        elif format == "package_rpm":
+            cmd.append("--scan-rpm-dir")
+        else:
+            self.fail("Unknown package class %s" % format)
+
         # Find a free port
         with socketserver.TCPServer(("localhost", 0), None) as s:
             port = s.server_address[1]
             cmd.append("--port=%d" % port)
 
         try:
-            debuginfod = subprocess.Popen(cmd)
+            # Remove DEBUGINFOD_URLS from the environment so we don't try
+            # looking in the distro debuginfod
+            env = os.environ.copy()
+            if "DEBUGINFOD_URLS" in env:
+                del env["DEBUGINFOD_URLS"]
+
+            self.logger.info(f"Starting server {cmd}")
+            debuginfod = subprocess.Popen(cmd, env=env)
 
             with runqemu("core-image-minimal", runqemuparams="nographic") as qemu:
+                self.assertTrue(self.wait_for_debuginfod(port))
+
                 cmd = (
                     "DEBUGINFOD_URLS=http://%s:%d/ debuginfod-find debuginfo /usr/bin/debuginfod"
                     % (qemu.server_ip, port)
                 )
+                self.logger.info(f"Starting client {cmd}")
                 status, output = qemu.run_serial(cmd)
                 # This should be more comprehensive
                 self.assertIn("/.cache/debuginfod_client/", output)