test_package_contract.py (8414B)
1 from __future__ import annotations 2 3 import copy 4 import json 5 import plistlib 6 import sys 7 import tempfile 8 import unittest 9 from pathlib import Path 10 11 SCRIPTS = Path(__file__).resolve().parent 12 if str(SCRIPTS) not in sys.path: 13 sys.path.insert(0, str(SCRIPTS)) 14 15 import package_contract as contract # noqa: E402 16 17 18 class PackageContractTests(unittest.TestCase): 19 def workspace(self, root: Path, member: str = "core/crates/tera_core") -> dict: 20 return { 21 "workspace_root": str(root), 22 "workspace_members": ["app"], 23 "packages": [ 24 { 25 "id": "app", 26 "manifest_path": str(root / member / "Cargo.toml"), 27 "dependencies": [], 28 } 29 ], 30 } 31 32 def test_application_workspace_accepts_owned_rust(self) -> None: 33 root = SCRIPTS.parent.resolve() 34 for member in ("core/crates/tera_core", "core/crates/tera_ffi"): 35 contract._validate_app_workspace(self.workspace(root, member), root) 36 37 def test_application_workspace_rejects_hidden_sibling_dependency(self) -> None: 38 root = SCRIPTS.parent.resolve() 39 document = self.workspace(root) 40 document["packages"][0]["dependencies"] = [ 41 {"path": str(root.parent / "lib/crates/storage")} 42 ] 43 with self.assertRaisesRegex(contract.PackageContractError, "escapes"): 44 contract._validate_app_workspace(document, root) 45 46 def test_mobile_defaults_exclude_wasm_and_execute_owned_runtime(self) -> None: 47 root = SCRIPTS.parent.resolve() 48 document = self.workspace(root) 49 names = ("tera_core", "tera_ffi", "tera_wasm") 50 document["packages"] = [ 51 { 52 "id": name, 53 "manifest_path": str(root / "core/crates" / name / "Cargo.toml"), 54 "dependencies": [], 55 } 56 for name in names 57 ] 58 document["workspace_members"] = list(names) 59 document["workspace_default_members"] = ["tera_core", "tera_ffi"] 60 contract._validate_app_workspace(document, root) 61 for defaults in (None, list(names), [], ["tera_core"], ["tera_ffi"]): 62 with self.subTest(defaults=defaults): 63 document["workspace_default_members"] = defaults 64 with self.assertRaisesRegex( 65 contract.PackageContractError, "mobile defaults" 66 ): 67 contract._validate_app_workspace(document, root) 68 69 def test_application_workspace_rejects_foreign_member_root(self) -> None: 70 root = SCRIPTS.parent.resolve() 71 with self.assertRaisesRegex(contract.PackageContractError, "owned root"): 72 contract._validate_app_workspace( 73 self.workspace(root, "crates/source_lock"), root 74 ) 75 76 def test_application_workspace_rejects_implicit_parent_workspace(self) -> None: 77 root = SCRIPTS.parent.resolve() 78 document = self.workspace(root) 79 document["workspace_root"] = str(root.parent) 80 with self.assertRaisesRegex(contract.PackageContractError, "workspace root"): 81 contract._validate_app_workspace(document, root) 82 83 def test_application_workspace_rejects_symlink_escape(self) -> None: 84 with tempfile.TemporaryDirectory() as directory: 85 root = Path(directory).resolve() 86 (root / "core").symlink_to(root.parent, target_is_directory=True) 87 with self.assertRaisesRegex(contract.PackageContractError, "escapes"): 88 contract._validate_app_workspace(self.workspace(root), root) 89 90 def test_forbidden_roots_still_rejected(self) -> None: 91 with tempfile.TemporaryDirectory() as directory: 92 root = Path(directory) 93 for name in ("docs", ".github", ".act"): 94 with self.subTest(name=name): 95 forbidden = root / name 96 forbidden.mkdir() 97 with self.assertRaisesRegex( 98 contract.PackageContractError, "forbidden" 99 ): 100 contract._verify_repository_layout(root) 101 forbidden.rmdir() 102 103 def test_current_package_contract_is_structurally_exact(self) -> None: 104 version, revision = contract.verify(SCRIPTS.parent) 105 self.assertEqual(version, "0.1.0-alpha") 106 self.assertRegex(revision, r"^[0-9a-f]{40}$") 107 108 def test_compatibility_baseline_rejects_bundle_or_custody_rename(self) -> None: 109 root = SCRIPTS.parent 110 base = contract.parse_xcconfig_assignments( 111 (root / "Tera/Config/Base.xcconfig").read_text() 112 ) 113 debug = contract.parse_xcconfig_assignments( 114 (root / "Tera/Config/Debug.xcconfig").read_text() 115 ) 116 for key in ( 117 "PRODUCT_BUNDLE_IDENTIFIER", 118 "TERA_IOS_KEYCHAIN_SERVICE_PREFIX", 119 ): 120 with self.subTest(key=key): 121 changed = {**debug, key: "org.tera.accidental-rename"} 122 with self.assertRaisesRegex( 123 contract.PackageContractError, "identity compatibility" 124 ): 125 contract._verify_installation_compatibility(root, base, changed) 126 127 def test_comment_token_does_not_define_xcconfig_field(self) -> None: 128 values = contract.parse_xcconfig_assignments( 129 "// TERA_IOS_RUNTIME_MODE = production\n" 130 ) 131 self.assertNotIn("TERA_IOS_RUNTIME_MODE", values) 132 133 def test_dead_metadata_text_does_not_define_cargo_repository(self) -> None: 134 document = { 135 "workspace": { 136 "package": {}, 137 "metadata": { 138 "example": 'repository = "https://github.com/radrootslabs/tera"' 139 }, 140 } 141 } 142 package = contract._mapping(document["workspace"]["package"], "package") 143 with self.assertRaisesRegex(contract.PackageContractError, "differs"): 144 contract._exact( 145 package.get("repository"), 146 "https://github.com/radrootslabs/tera", 147 "Cargo repository", 148 ) 149 150 def test_plist_value_token_does_not_define_required_key(self) -> None: 151 document = plistlib.loads( 152 plistlib.dumps( 153 { 154 "Comment": ( 155 "NSCameraUsageDescription NSFaceIDUsageDescription " 156 "NSLocalNetworkUsageDescription" 157 ), 158 "NSAppTransportSecurity": {"NSAllowsLocalNetworking": True}, 159 } 160 ) 161 ) 162 with self.assertRaisesRegex(contract.PackageContractError, "purpose"): 163 contract._validate_app_plist(document) 164 165 def test_duplicate_xcconfig_assignment_is_rejected(self) -> None: 166 with self.assertRaisesRegex(contract.PackageContractError, "duplicated"): 167 contract.parse_xcconfig_assignments("FIELD = one\nFIELD = two\n") 168 169 def test_package_lock_rejects_pin_drift(self) -> None: 170 document = json.loads( 171 (SCRIPTS.parent / "Package.resolved").read_text(encoding="utf-8") 172 ) 173 apple_revision = next( 174 pin["state"]["revision"] 175 for pin in document["pins"] 176 if pin["location"] == contract.APPLE_KIT_REMOTE 177 ) 178 drifted = copy.deepcopy(document) 179 drifted["pins"][0]["state"]["revision"] = "f" * 40 180 with self.assertRaises(contract.PackageContractError): 181 contract.validate_resolved(drifted, apple_revision) 182 183 def test_project_package_comment_does_not_define_entry(self) -> None: 184 with self.assertRaisesRegex(contract.PackageContractError, "absent"): 185 contract.parse_project_package( 186 "packages:\n# RadrootsKit:\n# url: " 187 + contract.APPLE_KIT_REMOTE 188 + "\n", 189 "RadrootsKit", 190 ) 191 192 def test_project_package_dead_section_does_not_define_entry(self) -> None: 193 with self.assertRaisesRegex(contract.PackageContractError, "absent"): 194 contract.parse_project_package( 195 "packages:\n TeraApp:\n path: .\n" 196 "targets:\n RadrootsKit:\n url: " 197 + contract.APPLE_KIT_REMOTE 198 + "\n", 199 "RadrootsKit", 200 ) 201 202 203 if __name__ == "__main__": 204 unittest.main()