From: Anders Heimer <anders.heimer@est.tech>
To: openembedded-core@lists.openembedded.org
Cc: Anders Heimer <anders.heimer@est.tech>
Subject: [PATCH 2/2] oeqa/oelib: add copydebugsources tests
Date: Tue, 16 Jun 2026 10:25:16 +0200 [thread overview]
Message-ID: <20260616082516.1553768-3-anders.heimer@est.tech> (raw)
In-Reply-To: <20260616082516.1553768-1-anders.heimer@est.tech>
Cover debug source copying, ignored source paths and externalsrc
relocation.
AI-Generated: Claude Opus 4.6
Signed-off-by: Anders Heimer <anders.heimer@est.tech>
---
meta/lib/oeqa/selftest/cases/oelib/package.py | 239 ++++++++++++++++++
1 file changed, 239 insertions(+)
create mode 100644 meta/lib/oeqa/selftest/cases/oelib/package.py
diff --git a/meta/lib/oeqa/selftest/cases/oelib/package.py b/meta/lib/oeqa/selftest/cases/oelib/package.py
new file mode 100644
index 0000000000..39c7d0661d
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/oelib/package.py
@@ -0,0 +1,239 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import shutil
+import tempfile
+from unittest.case import TestCase
+
+class FakeDataStore:
+ def __init__(self, values):
+ self.values = values
+
+ def getVar(self, name):
+ return self.values.get(name)
+
+ def expand(self, value):
+ for name, replacement in self.values.items():
+ value = value.replace("${%s}" % name, replacement)
+ return value
+
+class TestCopyDebugSources(TestCase):
+ def setUp(self):
+ for tool in ("sort", "egrep", "fgrep", "sed", "cpio", "find", "mv"):
+ if shutil.which(tool) is None:
+ self.skipTest("Required tool %s not found" % tool)
+
+ def copydebugsources(self, debugsrcdir, sources, d):
+ try:
+ import oe.package
+ except ImportError:
+ self.skipTest("Cannot import oe.package")
+
+ oe.package.copydebugsources(debugsrcdir, sources, d)
+
+ def test_copydebugsources_copies_files_and_dereferences_links(self):
+ with tempfile.TemporaryDirectory(prefix="oe-test-package-") as tmpdir:
+ source_root = os.path.join(tmpdir, "source")
+ second_source_root = os.path.join(tmpdir, "second-source")
+ workdir = os.path.join(tmpdir, "work")
+ pkgd = os.path.join(tmpdir, "pkgd")
+ debugsrcdir = "/usr/src/debug/testpkg/1.0"
+ second_debugsrcdir = "/usr/src/debug/secondpkg/1.0"
+
+ os.makedirs(os.path.join(source_root, "nested"))
+ os.makedirs(second_source_root)
+ os.makedirs(workdir)
+ os.makedirs(pkgd)
+
+ normal = os.path.join(source_root, "nested", "normal.c")
+ special = os.path.join(source_root, "nested", "name with ; spaces.c")
+ leading_dash = os.path.join(source_root, "nested", "-leading-dash.c")
+ target = os.path.join(source_root, "nested", "target.c")
+ link = os.path.join(source_root, "nested", "link.c")
+ ignored_src = os.path.join(source_root, "recipe-sysroot", "ignored.c")
+ second = os.path.join(second_source_root, "second.c")
+
+ with open(normal, "w") as f:
+ f.write("normal\n")
+ with open(special, "w") as f:
+ f.write("special\n")
+ with open(leading_dash, "w") as f:
+ f.write("leading dash\n")
+ with open(target, "w") as f:
+ f.write("target\n")
+ os.symlink("target.c", link)
+ os.makedirs(os.path.dirname(ignored_src))
+ with open(ignored_src, "w") as f:
+ f.write("ignored\n")
+ with open(second, "w") as f:
+ f.write("second\n")
+
+ sources = [
+ os.path.join(debugsrcdir, "nested", "normal.c"),
+ os.path.join(debugsrcdir, "nested", "name with ; spaces.c"),
+ os.path.join(debugsrcdir, "nested", "-leading-dash.c"),
+ os.path.join(debugsrcdir, "nested", "link.c"),
+ os.path.join(debugsrcdir, "recipe-sysroot", "ignored.c"),
+ os.path.join(second_debugsrcdir, "second.c"),
+ "<internal>",
+ ]
+ d = FakeDataStore({
+ "WORKDIR": workdir,
+ "PKGD": pkgd,
+ "STRIP": "strip",
+ "OBJCOPY": "objcopy",
+ "S": os.path.join(workdir, "source"),
+ "CFLAGS": (
+ "-ffile-prefix-map=%s=%s "
+ "-ffile-prefix-map=%s=%s"
+ ) % (
+ source_root,
+ debugsrcdir,
+ second_source_root,
+ second_debugsrcdir,
+ ),
+ })
+
+ self.copydebugsources(debugsrcdir, sources, d)
+
+ copied_normal = os.path.join(pkgd, debugsrcdir.lstrip("/"),
+ "nested", "normal.c")
+ copied_special = os.path.join(pkgd, debugsrcdir.lstrip("/"),
+ "nested", "name with ; spaces.c")
+ copied_leading_dash = os.path.join(pkgd, debugsrcdir.lstrip("/"),
+ "nested", "-leading-dash.c")
+ copied_link = os.path.join(pkgd, debugsrcdir.lstrip("/"),
+ "nested", "link.c")
+ copied_second = os.path.join(pkgd, second_debugsrcdir.lstrip("/"),
+ "second.c")
+ ignored = os.path.join(pkgd, debugsrcdir.lstrip("/"),
+ "recipe-sysroot", "ignored.c")
+
+ with open(copied_normal) as f:
+ self.assertEqual(f.read(), "normal\n")
+ with open(copied_special) as f:
+ self.assertEqual(f.read(), "special\n")
+ with open(copied_leading_dash) as f:
+ self.assertEqual(f.read(), "leading dash\n")
+ with open(copied_link) as f:
+ self.assertEqual(f.read(), "target\n")
+ with open(copied_second) as f:
+ self.assertEqual(f.read(), "second\n")
+ self.assertFalse(os.path.islink(copied_link))
+ self.assertFalse(os.path.exists(ignored))
+
+ def test_copydebugsources_ignores_missing_destroot(self):
+ with tempfile.TemporaryDirectory(prefix="oe-test-package-") as tmpdir:
+ source_root = os.path.join(tmpdir, "source")
+ workdir = os.path.join(tmpdir, "work")
+ pkgd = os.path.join(tmpdir, "pkgd")
+ debugsrcdir = "/usr/src/debug/testpkg/1.0"
+ mapped_debugsrcdir = os.path.join(debugsrcdir, "mapped")
+
+ os.makedirs(source_root)
+ os.makedirs(workdir)
+ os.makedirs(pkgd)
+
+ sources = [
+ os.path.join(mapped_debugsrcdir, "recipe-sysroot", "ignored.c"),
+ "<internal>",
+ "<built-in>",
+ ]
+ d = FakeDataStore({
+ "WORKDIR": workdir,
+ "PKGD": pkgd,
+ "STRIP": "strip",
+ "OBJCOPY": "objcopy",
+ "S": os.path.join(workdir, "source"),
+ "CFLAGS": "-ffile-prefix-map=%s=%s" % (
+ source_root,
+ mapped_debugsrcdir,
+ ),
+ })
+
+ self.copydebugsources(debugsrcdir, sources, d)
+
+ self.assertFalse(os.path.exists(pkgd + mapped_debugsrcdir))
+ self.assertFalse(os.path.exists(pkgd + debugsrcdir))
+
+ def test_copydebugsources_moves_externalsrc_relocation(self):
+ with tempfile.TemporaryDirectory(prefix="oe-test-package-") as tmpdir:
+ source_root = os.path.join(tmpdir, "external-[source]")
+ workdir = os.path.join(tmpdir, "work")
+ pkgd = os.path.join(tmpdir, "pkgd")
+ debugsrcdir = "/usr/src/debug/testpkg/1.0"
+
+ os.makedirs(source_root)
+ os.makedirs(workdir)
+ os.makedirs(pkgd)
+
+ source = os.path.join(source_root, "real.c")
+ with open(source, "w") as f:
+ f.write("real\n")
+
+ relocation = pkgd + debugsrcdir + source_root
+ relocated_name = "-relocated with ; spaces.c"
+ os.makedirs(relocation)
+ with open(os.path.join(relocation, relocated_name), "w") as f:
+ f.write("relocated\n")
+
+ sources = [os.path.join(debugsrcdir, "real.c")]
+ d = FakeDataStore({
+ "WORKDIR": workdir,
+ "PKGD": pkgd,
+ "STRIP": "strip",
+ "OBJCOPY": "objcopy",
+ "S": source_root,
+ "CFLAGS": "-ffile-prefix-map=%s=%s" % (source_root, debugsrcdir),
+ })
+
+ self.copydebugsources(debugsrcdir, sources, d)
+
+ copied_source = os.path.join(pkgd, debugsrcdir.lstrip("/"), "real.c")
+ moved_source = os.path.join(pkgd, debugsrcdir.lstrip("/"), relocated_name)
+
+ with open(copied_source) as f:
+ self.assertEqual(f.read(), "real\n")
+ with open(moved_source) as f:
+ self.assertEqual(f.read(), "relocated\n")
+ self.assertFalse(os.path.exists(relocation))
+
+ def test_copydebugsources_ignores_empty_externalsrc_relocation(self):
+ with tempfile.TemporaryDirectory(prefix="oe-test-package-") as tmpdir:
+ source_root = os.path.join(tmpdir, "external-source")
+ workdir = os.path.join(tmpdir, "work")
+ pkgd = os.path.join(tmpdir, "pkgd")
+ debugsrcdir = "/usr/src/debug/testpkg/1.0"
+
+ os.makedirs(source_root)
+ os.makedirs(workdir)
+ os.makedirs(pkgd)
+
+ source = os.path.join(source_root, "real.c")
+ with open(source, "w") as f:
+ f.write("real\n")
+
+ relocation = pkgd + debugsrcdir + source_root
+ os.makedirs(relocation)
+
+ sources = [os.path.join(debugsrcdir, "real.c")]
+ d = FakeDataStore({
+ "WORKDIR": workdir,
+ "PKGD": pkgd,
+ "STRIP": "strip",
+ "OBJCOPY": "objcopy",
+ "S": source_root,
+ "CFLAGS": "-ffile-prefix-map=%s=%s" % (source_root, debugsrcdir),
+ })
+
+ self.copydebugsources(debugsrcdir, sources, d)
+
+ copied_source = os.path.join(pkgd, debugsrcdir.lstrip("/"), "real.c")
+
+ with open(copied_source) as f:
+ self.assertEqual(f.read(), "real\n")
+ self.assertFalse(os.path.exists(relocation))
prev parent reply other threads:[~2026-06-16 8:25 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-16 8:25 [PATCH 0/2] package: replace copydebugsources shell pipelines with Popen Anders Heimer
2026-06-16 8:25 ` [PATCH 1/2] " Anders Heimer
2026-06-16 12:12 ` [OE-core] " Paul Barker
2026-06-16 13:35 ` Anders Heimer
2026-06-16 13:42 ` Paul Barker
2026-06-16 13:44 ` Richard Purdie
2026-06-16 14:13 ` Anders Heimer
2026-06-16 8:25 ` Anders Heimer [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260616082516.1553768-3-anders.heimer@est.tech \
--to=anders.heimer@est.tech \
--cc=openembedded-core@lists.openembedded.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox