"""A packaged app must load resources after its original build tree is gone.""" import plistlib import json from pathlib import Path import shutil import struct import subprocess import tempfile import unittest import zlib class BundleMacTests(unittest.TestCase): def test_relocated_resource_bundle_and_deployment_target(self): tool = Path(__file__).resolve().parents[1] / "bundle-mac.py" with tempfile.TemporaryDirectory(prefix="native-bundle-test-") as temporary: root = Path(temporary) source = root / "apple/Sources/Probe" (source / "Resources").mkdir(parents=True) (root / "apple/Package.swift").write_text('''// swift-tools-version: 5.9 import PackageDescription let package = Package(name: "Probe", platforms: [.macOS("26.0")], products: [.executable(name: "ProbeMac", targets: ["Probe"])], dependencies: [.package(name: "native", path: SHARED_NATIVE_PATH)], targets: [.executableTarget(name: "Probe", dependencies: [.product(name: "RastrilloMacUpdates", package: "native")], resources: [.process("Resources")])]) '''.replace('SHARED_NATIVE_PATH', json.dumps(str(tool.parents[1])))) (source / "main.swift").write_text('''import Foundation import RastrilloMacUpdates let updater = MainActor.assumeIsolated { NativeUpdater() } MainActor.assumeIsolated { precondition(!updater.isConfigured) _ = NativeUpdateCommands(updater: updater).body } let resources = Bundle.main.url(forResource: "Probe_Probe", withExtension: "bundle").flatMap(Bundle.init(url:)) ?? Bundle.module guard let url = resources.url(forResource: "sentinel", withExtension: "txt"), let text = try? String(contentsOf: url, encoding: .utf8) else { exit(7) } print(text) ''') (source / "Resources/sentinel.txt").write_text("portable native resources") icons = root / "ios/Assets.xcassets/AppIcon.appiconset" icons.mkdir(parents=True) def chunk(kind, payload): return struct.pack(">I", len(payload)) + kind + payload + struct.pack(">I", zlib.crc32(kind + payload)) png = b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", struct.pack(">IIBBBBB", 1024, 1024, 8, 6, 0, 0, 0)) png += chunk(b"IDAT", zlib.compress((b"\0" + b"\x30\x70\xb0\xff" * 1024) * 1024)) + chunk(b"IEND", b"") (icons / "AppIcon.png").write_bytes(png) # An app that draws no Lucide icon carries no Lucide notice: the # notice is copied only when the app has one to give. subprocess.run(["python3", str(tool), str(root), "Probe"], check=True, stdout=subprocess.DEVNULL) self.assertFalse((root / "build/Oficina Probe.app/Contents/Resources/LICENSE.lucide").exists()) (root / "LICENSE.lucide").write_text("Synthetic packaging test fixture") subprocess.run(["python3", str(tool), str(root), "Probe"], check=True, stdout=subprocess.DEVNULL) self.assertEqual((root / "build/Oficina Probe.app/Contents/Resources/LICENSE.lucide").read_text(), "Synthetic packaging test fixture") app = root / "relocated/Probe.app" app.parent.mkdir() shutil.move(root / "build/Oficina Probe.app", app) shutil.rmtree(root / "apple") info = plistlib.loads((app / "Contents/Info.plist").read_bytes()) self.assertEqual(info["LSMinimumSystemVersion"], "26.0") output = subprocess.check_output([str(app / "Contents/MacOS/ProbeMac")], text=True) self.assertEqual(output.strip(), "portable native resources") subprocess.run(["codesign", "--verify", "--strict", "--deep", str(app)], check=True) def test_an_app_that_draws_lucide_cannot_lose_its_notice(self): """A notice owed and missing stops the bundle rather than shipping without it.""" tool = Path(__file__).resolve().parents[1] / "bundle-mac.py" with tempfile.TemporaryDirectory(prefix="native-bundle-lucide-") as temporary: root = Path(temporary) source = root / "apple/Sources/Probe" source.mkdir(parents=True) (root / "apple/Package.swift").write_text("// swift-tools-version: 5.9\n") # A Lucide drawing in the app's sources, and no LICENSE.lucide. (source / "Icons.swift").write_text("// Path drawn from Lucide's \"file-text\" icon.\nlet x = 1\n") result = subprocess.run(["python3", str(tool), str(root), "Probe"], capture_output=True, text=True) self.assertNotEqual(result.returncode, 0) self.assertIn("LICENSE.lucide", result.stderr) self.assertIn("Icons.swift", result.stderr) self.assertFalse((root / "build").exists(), "nothing is built before the refusal") if __name__ == "__main__": unittest.main()