from __future__ import annotations import json import shutil import unittest from pathlib import Path from uuid import uuid4 from scripts.generate_component_inventory import ( canonical_name, component, file_component, ocr_runtime_components, parse_lockfile, requirement_names, ) class ComponentInventoryTests(unittest.TestCase): def setUp(self) -> None: self.fixture_root = ( Path(__file__).resolve().parent / f".component-inventory-test-{uuid4().hex}" ) self.fixture_root.mkdir() def tearDown(self) -> None: shutil.rmtree(self.fixture_root, ignore_errors=True) def test_python_package_names_are_canonicalized_for_purls(self) -> None: self.assertEqual(canonical_name("python_multipart"), "python-multipart") self.assertEqual(canonical_name("Pillow"), "pillow") def test_requirements_parser_ignores_comments_and_extras(self) -> None: requirements = self.fixture_root / "requirements.txt" requirements.write_text( "fastapi>=0.1\nuvicorn[standard]>=0.2 # comment\n# skip\n", encoding="utf-8", ) self.assertEqual(requirement_names(requirements), {"fastapi", "uvicorn"}) def test_pub_lock_parser_keeps_scope_source_and_version(self) -> None: lockfile = self.fixture_root / "pubspec.lock" lockfile.write_text( """# Generated by pub packages: demo_package: dependency: direct main source: hosted version: \"1.2.3\" flutter: dependency: direct main source: sdk version: \"0.0.0\" sdks: dart: \"^3.0.0\" """, encoding="utf-8", ) self.assertEqual( parse_lockfile(lockfile), [ { "name": "demo_package", "dependency": "direct main", "source": "hosted", "version": "1.2.3", }, { "name": "flutter", "dependency": "direct main", "source": "sdk", "version": "0.0.0", }, ], ) def test_component_records_license_file_hash_as_evidence(self) -> None: license_file = self.fixture_root / "LICENSE" license_file.write_text("sample notice\n", encoding="utf-8") result = component( ecosystem="pub", name="demo_package", version="1.2.3", scope="direct main", raw_license="See included LICENSE", license_source="test fixture", license_file=license_file, ) self.assertEqual(result["purl"], "pkg:pub/demo_package@1.2.3") self.assertTrue( any( property_item["name"] == "inventory.license_file_sha256" for property_item in result["properties"] ) ) self.assertEqual(json.loads(json.dumps(result)), result) def test_runtime_file_component_records_sha256_and_review_status(self) -> None: artifact = self.fixture_root / "model.pth" artifact.write_bytes(b"model fixture") result = file_component( artifact, name="EasyOCR model model.pth", component_type="machine-learning-model", scope="local-runtime-artifact", license_status="human review required", ) self.assertEqual(result["type"], "machine-learning-model") self.assertEqual( result["hashes"], [{"alg": "SHA-256", "content": "21249a290a4255a0f3ee6685ff7933bffa241c3e35bb13a52dc0c7a679bed3b2"}], ) self.assertIn( {"name": "inventory.license_status", "value": "human review required"}, result["properties"], ) def test_ocr_inventory_includes_present_weights_and_reports_missing_english(self) -> None: model_dir = self.fixture_root / "models" model_dir.mkdir() (model_dir / "arabic.pth").write_bytes(b"arabic weights") (model_dir / "craft_mlt_25k.pth").write_bytes(b"detection weights") (model_dir / "arabic.pth.backup").write_bytes(b"backup") (model_dir / "temp.zip").write_bytes(b"download fragment") artifacts, missing = ocr_runtime_components(model_dir) self.assertEqual( {artifact["name"] for artifact in artifacts}, {"EasyOCR model arabic.pth", "EasyOCR model craft_mlt_25k.pth"}, ) self.assertEqual(missing, ["english_g2.pth"]) for artifact in artifacts: properties = {item["name"]: item["value"] for item in artifact["properties"]} self.assertEqual( properties["inventory.license_status"], "model redistribution terms not established; human review required", ) self.assertEqual( properties["inventory.evidence.upstream_manifest"], "easyocr==1.7.2 config.py", ) self.assertEqual(properties["inventory.evidence.upstream_md5_match"], "false") if __name__ == "__main__": unittest.main()