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_ffi_installed.py (5140B)


      1 from __future__ import annotations
      2 
      3 import copy
      4 import shutil
      5 import sys
      6 import tempfile
      7 import unittest
      8 from pathlib import Path
      9 from unittest.mock import patch
     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 ffi_artifacts as artifacts  # noqa: E402
     16 import ffi_installed as installed  # noqa: E402
     17 import ffi_provenance as provenance  # noqa: E402
     18 import ffi_source as source  # noqa: E402
     19 import test_ffi_artifacts as fixtures  # noqa: E402
     20 
     21 
     22 class InstalledArtifactTests(unittest.TestCase):
     23     def setUp(self) -> None:
     24         fixture = fixtures.NativeArtifactTests()
     25         fixture.setUp()
     26         self.addCleanup(fixture.doCleanups)
     27         temporary = tempfile.TemporaryDirectory()
     28         self.addCleanup(temporary.cleanup)
     29         self.root = Path(temporary.name).resolve()
     30         self.manifest = installed.installed_manifest(
     31             artifacts.check(fixture.root, fixture.records)
     32         )
     33         for relative, destination in installed.installed_paths().items():
     34             path = self.root / destination
     35             path.parent.mkdir(parents=True, exist_ok=True)
     36             shutil.copyfile(fixture.root / relative, path)
     37         (self.root / installed.MANIFEST).write_bytes(provenance.encoded(self.manifest))
     38 
     39     def test_installed_inventory_retains_exact_candidate_file_identities(self) -> None:
     40         installed.verify_files(self.root, self.manifest)
     41         self.assertEqual(len(self.manifest["files"]), 13)
     42         self.assertEqual(
     43             self.manifest["disposition"], "local_installed_not_release_qualified"
     44         )
     45 
     46     def test_missing_or_tampered_installed_library_is_rejected(self) -> None:
     47         library = (
     48             self.root / "Tera/Frameworks/TeraFFI.xcframework/ios-arm64/libtera_ffi.a"
     49         )
     50         library.write_bytes(b"tampered synthetic verifier fixture")
     51         with self.assertRaisesRegex(source.ProvenanceError, "bytes are stale"):
     52             installed.verify_files(self.root, self.manifest)
     53         library.unlink()
     54         with self.assertRaisesRegex(source.ProvenanceError, "missing"):
     55             installed.verify_files(self.root, self.manifest)
     56 
     57     def test_extra_generated_source_cannot_survive_an_install(self) -> None:
     58         (self.root / "Tera/Generated/LegacyBindings.swift").write_text("// synthetic\n")
     59         with self.assertRaisesRegex(source.ProvenanceError, "inventory differs"):
     60             installed.verify_files(self.root, self.manifest)
     61 
     62     def test_manifest_cannot_substitute_an_installed_file_hash(self) -> None:
     63         changed = copy.deepcopy(self.manifest)
     64         changed["files"][0]["sha256"] = "f" * 64
     65         with self.assertRaisesRegex(source.ProvenanceError, "manifest differs"):
     66             installed.verify_files(self.root, changed)
     67 
     68     def test_symlinked_installed_source_is_rejected(self) -> None:
     69         path = self.root / "Tera/Generated/TeraKitBindings.swift"
     70         path.unlink()
     71         path.symlink_to(self.root / installed.MANIFEST)
     72         with self.assertRaisesRegex(source.ProvenanceError, "symlink"):
     73             installed.verify_files(self.root, self.manifest)
     74 
     75     def test_symlinked_parent_is_rejected_before_any_installation_swap(self) -> None:
     76         with tempfile.TemporaryDirectory() as temporary:
     77             outside = Path(temporary) / "Tera"
     78             (self.root / "Tera").rename(outside)
     79             (self.root / "Tera").symlink_to(outside, target_is_directory=True)
     80             original = (outside / "Generated/TeraKitBindings.swift").read_bytes()
     81             previous = self.root / "previous-unused"
     82             with self.assertRaisesRegex(
     83                 source.ProvenanceError, "path contains a symlink"
     84             ):
     85                 installed.replace_installation(
     86                     self.root, self.root / "stage-unused", previous
     87                 )
     88             self.assertFalse(previous.exists())
     89             self.assertEqual(
     90                 (outside / "Generated/TeraKitBindings.swift").read_bytes(), original
     91             )
     92 
     93     def test_failed_final_source_check_restores_the_prior_installation(self) -> None:
     94         staging = self.root / "stage"
     95         previous = self.root / "previous"
     96         before = {
     97             p.relative_to(self.root): p.read_bytes()
     98             for p in self.root.rglob("*")
     99             if p.is_file()
    100         }
    101         for relative, data in before.items():
    102             path = staging / relative
    103             path.parent.mkdir(parents=True, exist_ok=True)
    104             path.write_bytes(data + b"new synthetic generation")
    105         (staging / installed.LOCK).write_text("new lock\n")
    106         with patch.object(
    107             installed, "check", side_effect=source.ProvenanceError("source changed")
    108         ):
    109             with self.assertRaisesRegex(source.ProvenanceError, "source changed"):
    110                 installed.replace_installation(self.root, staging, previous)
    111         for relative, data in before.items():
    112             self.assertEqual((self.root / relative).read_bytes(), data)
    113         self.assertFalse((self.root / installed.LOCK).exists())
    114 
    115 
    116 if __name__ == "__main__":
    117     unittest.main()