#!/usr/bin/env python3 """Launch a relocated release archive without access to SwiftPM build fallbacks. Run on a logged-in Mac. No files in the source/build directories are modified. The test terminates only the app process it launches. """ import argparse import json from pathlib import Path import plistlib import subprocess import tempfile import time parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("archive", type=Path) args = parser.parse_args() with tempfile.TemporaryDirectory(prefix="oficina-sheets-launch-") as directory: root = Path(directory) subprocess.run(["ditto", "-x", "-k", str(args.archive.resolve()), str(root)], check=True) apps = list(root.glob("*.app")) assert len(apps) == 1, "Expected one application in release archive" app = apps[0] info = plistlib.loads((app / "Contents/Info.plist").read_bytes()) executable = app / "Contents/MacOS" / info["CFBundleExecutable"] strings = subprocess.check_output(["strings", str(executable)], text=True).splitlines() fallbacks = {line.split("/.build/", 1)[0] + "/.build" for line in strings if line.startswith("/") and "/.build/" in line and line.endswith(".bundle")} assert fallbacks, "No SwiftPM fallback paths found; review test coverage" profile = '(version 1)(allow default)' + ''.join( f'(deny file-read* (subpath {json.dumps(path)}))' for path in sorted(fallbacks)) probe = root / "windows.swift" probe.write_text('''import CoreGraphics import Foundation let pid = Int(CommandLine.arguments[1])! let windows = CGWindowListCopyWindowInfo(.optionAll, kCGNullWindowID) as? [[String: Any]] ?? [] let found = windows.contains { window in guard window[kCGWindowOwnerPID as String] as? Int == pid, window[kCGWindowLayer as String] as? Int == 0, let bounds = window[kCGWindowBounds as String] as? [String: Any], let width = bounds["Width"] as? Double, let height = bounds["Height"] as? Double else { return false } return width >= 300 && height >= 100 // Signed-out account chooser is compact. } exit(found ? 0 : 1) ''') subprocess.run(["swiftc", str(probe), "-o", str(root / "windows")], check=True) with (root / "launch.log").open("w+") as log: process = subprocess.Popen(["sandbox-exec", "-p", profile, str(executable), "-ApplePersistenceIgnoreState", "YES"], stdout=log, stderr=log) try: found = False deadline = time.monotonic() + 12 while time.monotonic() < deadline: if process.poll() is not None: log.seek(0) raise RuntimeError(f"App exited with {process.returncode}: {log.read()}") if subprocess.run([str(root / "windows"), str(process.pid)]).returncode == 0: found = True time.sleep(0.25) assert found, "App survived but did not create a normal window" print(f'PASS: {info["CFBundleName"]} {info["CFBundleShortVersionString"]} ' f'({info["CFBundleVersion"]}) opens a window with build-directory access denied') finally: if process.poll() is None: process.terminate() try: process.wait(timeout=5) except subprocess.TimeoutExpired: process.kill() process.wait()