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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.