scripts/test_m2image_compliance.py
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env python3
import importlib.util
import json
import tempfile
import unittest
from pathlib import Path
MODULE_PATH = Path(__file__).with_name("m2image_compliance.py")
spec = importlib.util.spec_from_file_location("m2image_compliance", MODULE_PATH)
assert spec and spec.loader
compliance = importlib.util.module_from_spec(spec)
spec.loader.exec_module(compliance)
def spdx(packages, distribution="alpine"):
return {
"spdxVersion": "SPDX-2.3",
"packages": [
{
"name": f"{distribution}-image",
"versionInfo": "1",
"comment": f"distribution={distribution}; architecture=x86_64",
},
*packages,
],
}
class M2ImageComplianceTests(unittest.TestCase):
def test_source_map_requires_source_identity(self):
doc = spdx([{"name": "busybox", "versionInfo": "1.37.0-r31"}])
with self.assertRaisesRegex(ValueError, "missing source-package identity"):
compliance.source_map(doc)
def test_source_map_records_exact_alpine_commit(self):
doc = spdx(
[
{
"name": "busybox",
"versionInfo": "1.37.0-r31",
"comment": (
"package-manager-license=GPL-2.0-only; source-package=busybox; "
"source-version=1.37.0-r31; "
"source-commit=0123456789abcdef0123456789abcdef01234567"
),
}
]
)
mapped = compliance.source_map(doc)["packages"][0]
self.assertEqual(mapped["declaredLicense"], "GPL-2.0-only")
self.assertEqual(mapped["source"]["sourcePackage"], "busybox")
self.assertEqual(mapped["source"]["sourceVersion"], "1.37.0-r31")
self.assertEqual(
mapped["source"]["repositoryCommit"],
"0123456789abcdef0123456789abcdef01234567",
)
self.assertTrue(mapped["source"]["metadataUrl"].endswith("0123456789abcdef0123456789abcdef01234567"))
def test_source_map_preserves_binary_package_architecture_from_purl(self):
doc = spdx(
[
{
"name": "filesystem",
"versionInfo": "3.16-5.el9",
"externalRefs": [
{
"referenceCategory": "PACKAGE_MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:rpm/rocky/filesystem@3.16-5.el9?arch=noarch",
}
],
"comment": "source-package=filesystem-3.16-5.el9.src.rpm",
}
],
distribution="rocky",
)
result = compliance.source_map(doc)
self.assertEqual(result["image"]["architecture"], "x86_64")
self.assertEqual(result["packages"][0]["architecture"], "noarch")
def test_ubuntu_and_rocky_resolvers_preserve_source_evidence(self):
ubuntu = {
"spdxVersion": "SPDX-2.3",
"packages": [
{
"name": "ubuntu-26.04",
"versionInfo": "26.04",
"comment": "distribution=ubuntu; architecture=x86_64",
},
{
"name": "linux-image-virtual",
"versionInfo": "7.0.0-30.30",
"comment": "source-package=linux-meta; source-version=7.0.0.30.30",
},
],
}
rocky = {
"spdxVersion": "SPDX-2.3",
"packages": [
{
"name": "rocky-9.8",
"versionInfo": "9.8",
"comment": "distribution=rocky; architecture=x86_64",
},
{
"name": "kernel-core",
"versionInfo": "0:5.14.0-687.41.1.el9_8",
"comment": "source-package=kernel-5.14.0-687.41.1.el9_8.src.rpm",
},
],
}
ubuntu_source = compliance.source_map(ubuntu)["packages"][0]["source"]
rocky_source = compliance.source_map(rocky)["packages"][0]["source"]
self.assertEqual(ubuntu_source["sourcePackage"], "linux-meta")
self.assertEqual(ubuntu_source["sourceVersion"], "7.0.0.30.30")
self.assertIn("launchpad.net/ubuntu/+source/linux-meta/", ubuntu_source["metadataUrl"])
self.assertEqual(
rocky_source["sourceArtifact"],
"kernel-5.14.0-687.41.1.el9_8.src.rpm",
)
def test_rocky_gpg_pubkey_records_explicit_non_source_disposition(self):
doc = spdx(
[
{
"name": "gpg-pubkey",
"versionInfo": "0:350d275d-627e00a1",
"comment": "source-disposition=rpm-key-metadata",
}
],
distribution="rocky",
)
mapped = compliance.source_map(doc)["packages"][0]
self.assertEqual(mapped["sourceDisposition"], "rpm-key-metadata")
self.assertNotIn("source", mapped)
def test_non_source_disposition_is_narrowly_scoped(self):
doc = spdx(
[
{
"name": "bash",
"versionInfo": "5.1",
"comment": "source-disposition=rpm-key-metadata",
}
],
distribution="rocky",
)
with self.assertRaisesRegex(ValueError, "unsupported source-disposition"):
compliance.source_map(doc)
def test_bundle_copies_guest_legal_material_and_canonical_gpl(self):
with tempfile.TemporaryDirectory() as tmpdir:
tmp = Path(tmpdir)
legal = tmp / "guest"
(legal / "usr/share/licenses/busybox").mkdir(parents=True)
(legal / "usr/share/licenses/busybox/COPYING").write_text("guest gpl\n")
(legal / "usr/share/doc/curl").mkdir(parents=True)
(legal / "usr/share/doc/curl/copyright").write_text("curl notice\n")
(legal / "usr/share/doc/curl/changelog.gz").write_bytes(b"not legal evidence")
gpl = tmp / "GPL-2.0-only.txt"
gpl.write_text("canonical gpl\n")
sbom_path = tmp / "sbom.json"
sbom_path.write_text(
json.dumps(
spdx(
[
{
"name": "busybox",
"versionInfo": "1.37.0-r31",
"comment": "package-manager-license=GPL-2.0-only; source-package=busybox",
}
]
)
)
)
out = tmp / "bundle"
summary = compliance.build_bundle(
spdx_path=sbom_path,
legal_root=legal,
gpl2_text=gpl,
output_dir=out,
)
self.assertEqual(summary["packageCount"], 1)
self.assertEqual(summary["guestLegalFileCount"], 2)
self.assertTrue((out / "licenses/GPL-2.0-only.txt").is_file())
self.assertTrue((out / "licenses/guest/usr/share/licenses/busybox/COPYING").is_file())
self.assertTrue((out / "licenses/guest/usr/share/doc/curl/copyright").is_file())
self.assertFalse((out / "licenses/guest/usr/share/doc/curl/changelog.gz").exists())
index = json.loads((out / "licenses/index.json").read_text())
self.assertEqual(len(index["files"]), 3)
self.assertTrue(all(item["sha256"] for item in index["files"]))
self.assertEqual(
(out / "sbom.spdx.json").read_bytes(), sbom_path.read_bytes()
)
def test_bundle_is_deterministic_for_same_inputs(self):
with tempfile.TemporaryDirectory() as tmpdir:
tmp = Path(tmpdir)
legal = tmp / "guest"
(legal / "usr/share/common-licenses").mkdir(parents=True)
(legal / "usr/share/common-licenses/GPL-2").write_text("gpl common\n")
gpl = tmp / "GPL.txt"
gpl.write_text("canonical\n")
sbom_path = tmp / "sbom.json"
sbom_path.write_text(
json.dumps(
spdx(
[
{
"name": "busybox",
"versionInfo": "1",
"comment": "source-package=busybox",
}
]
),
sort_keys=True,
)
)
first = tmp / "first"
second = tmp / "second"
compliance.build_bundle(
spdx_path=sbom_path, legal_root=legal, gpl2_text=gpl, output_dir=first
)
compliance.build_bundle(
spdx_path=sbom_path, legal_root=legal, gpl2_text=gpl, output_dir=second
)
for rel in ("bundle.json", "source-map.json", "licenses/index.json", "README.txt"):
self.assertEqual((first / rel).read_bytes(), (second / rel).read_bytes())
if __name__ == "__main__":
unittest.main()