blob: 37f51760fbc7aea9415534ab17033e6f4d3c4443 [file] [log] [blame]
Patrick Williams92b42cb2022-09-03 06:53:57 -05001#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6import os
7import socketserver
8import subprocess
9
10from oeqa.selftest.case import OESelftestTestCase
11from oeqa.utils.commands import bitbake, get_bb_var, runqemu
12
Andrew Geissler87f5cff2022-09-30 13:13:31 -050013
Patrick Williams92b42cb2022-09-03 06:53:57 -050014class Debuginfod(OESelftestTestCase):
Andrew Geissler517393d2023-01-13 08:55:19 -060015
16 def wait_for_debuginfod(self, port):
17 """
18 debuginfod takes time to scan the packages and requesting too early may
19 result in a test failure if the right packages haven't been scanned yet.
20
21 Request the metrics endpoint periodically and wait for there to be no
22 busy scanning threads.
23
24 Returns True if debuginfod is ready, False if we timed out
25 """
26 import time, urllib
27
28 # Wait a minute
29 countdown = 6
30 delay = 10
31
32 while countdown:
33 time.sleep(delay)
34 try:
35 with urllib.request.urlopen("http://localhost:%d/metrics" % port) as f:
36 lines = f.read().decode("ascii").splitlines()
37 if "thread_busy{role=\"scan\"} 0" in lines:
38 return True
39 except urllib.error.URLError as e:
40 self.logger.error(e)
41 countdown -= 1
42 return False
43
44
Patrick Williams92b42cb2022-09-03 06:53:57 -050045 def test_debuginfod(self):
Andrew Geissler87f5cff2022-09-30 13:13:31 -050046 self.write_config(
47 """
Patrick Williams92b42cb2022-09-03 06:53:57 -050048DISTRO_FEATURES:append = " debuginfod"
49CORE_IMAGE_EXTRA_INSTALL += "elfutils"
Andrew Geissler87f5cff2022-09-30 13:13:31 -050050 """
51 )
Patrick Williams92b42cb2022-09-03 06:53:57 -050052 bitbake("core-image-minimal elfutils-native:do_addto_recipe_sysroot")
53
54 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "elfutils-native")
Andrew Geissler87f5cff2022-09-30 13:13:31 -050055 cmd = [
56 os.path.join(native_sysroot, "usr", "bin", "debuginfod"),
57 "--verbose",
Andrew Geissler517393d2023-01-13 08:55:19 -060058 # In-memory database, this is a one-shot test
Andrew Geissler87f5cff2022-09-30 13:13:31 -050059 "--database=:memory:",
Andrew Geissler517393d2023-01-13 08:55:19 -060060 # Don't use all the host cores
61 "--concurrency=8",
62 "--connection-pool=8",
63 # Disable rescanning, this is a one-shot test
64 "--rescan-time=0",
65 "--groom-time=0",
Andrew Geissler87f5cff2022-09-30 13:13:31 -050066 get_bb_var("DEPLOY_DIR"),
67 ]
Andrew Geissler517393d2023-01-13 08:55:19 -060068
69 format = get_bb_var("PACKAGE_CLASSES").split()[0]
70 if format == "package_deb":
71 cmd.append("--scan-deb-dir")
72 elif format == "package_ipk":
73 cmd.append("--scan-deb-dir")
74 elif format == "package_rpm":
75 cmd.append("--scan-rpm-dir")
76 else:
77 self.fail("Unknown package class %s" % format)
78
Patrick Williams92b42cb2022-09-03 06:53:57 -050079 # Find a free port
80 with socketserver.TCPServer(("localhost", 0), None) as s:
81 port = s.server_address[1]
82 cmd.append("--port=%d" % port)
83
84 try:
Andrew Geissler517393d2023-01-13 08:55:19 -060085 # Remove DEBUGINFOD_URLS from the environment so we don't try
86 # looking in the distro debuginfod
87 env = os.environ.copy()
88 if "DEBUGINFOD_URLS" in env:
89 del env["DEBUGINFOD_URLS"]
90
91 self.logger.info(f"Starting server {cmd}")
92 debuginfod = subprocess.Popen(cmd, env=env)
Patrick Williams92b42cb2022-09-03 06:53:57 -050093
94 with runqemu("core-image-minimal", runqemuparams="nographic") as qemu:
Andrew Geissler517393d2023-01-13 08:55:19 -060095 self.assertTrue(self.wait_for_debuginfod(port))
96
Andrew Geissler87f5cff2022-09-30 13:13:31 -050097 cmd = (
98 "DEBUGINFOD_URLS=http://%s:%d/ debuginfod-find debuginfo /usr/bin/debuginfod"
99 % (qemu.server_ip, port)
100 )
Andrew Geissler517393d2023-01-13 08:55:19 -0600101 self.logger.info(f"Starting client {cmd}")
Patrick Williams92b42cb2022-09-03 06:53:57 -0500102 status, output = qemu.run_serial(cmd)
103 # This should be more comprehensive
104 self.assertIn("/.cache/debuginfod_client/", output)
105 finally:
106 debuginfod.kill()