field_ios

In-the-field app for Radroots on iOS
git clone https://radroots.dev/git/field_ios.git
Log | Files | Refs | README | LICENSE

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()