SHA256
Mac Node bootstrap and checkout now pass, but Apple-tool preflight stalled after Xcode version output for twenty minutes. Add per-command deadlines and diagnostics without changing licenses/host settings; fourteen preflight/probe regressions pass. Record successful Android build/upload, downloaded APK signature/version and emulator install/launch, and unchanged missing-KVM matrix failures. No Apple app success is claimed.
94 lines
4.4 KiB
Python
94 lines
4.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Test runner prerequisite decisions with fake tools, not actual Apple SDKs."""
|
|
import os
|
|
import importlib.util
|
|
from pathlib import Path
|
|
import shlex
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
|
|
SCRIPT = Path(__file__).with_name("check-ci-runner.sh")
|
|
SPEC = importlib.util.spec_from_file_location("apple_tools", SCRIPT.with_name("check-apple-tools.py"))
|
|
APPLE_TOOLS = importlib.util.module_from_spec(SPEC)
|
|
SPEC.loader.exec_module(APPLE_TOOLS)
|
|
|
|
|
|
class RunnerPrerequisiteTests(unittest.TestCase):
|
|
def run_check(self, mode, system="Linux", architecture="x86_64", missing=None, broken_xcode=False, broken_xcrun=False):
|
|
base = "/tmp/opencode" if Path("/tmp/opencode").exists() else None
|
|
with tempfile.TemporaryDirectory(prefix="yuvomi-runner-test-", dir=base) as temporary:
|
|
directory = Path(temporary)
|
|
for name in ["git", "curl", "unzip", "python3", "xcodebuild", "xcrun"]:
|
|
if name == missing:
|
|
continue
|
|
path = directory / name
|
|
status = 1 if (name == "xcodebuild" and broken_xcode or name == "xcrun" and broken_xcrun) else 0
|
|
path.write_text(f"#!/bin/sh\nexec {shlex.quote(sys.executable)} \"$@\"\n" if name == "python3"
|
|
else f"#!/bin/sh\nexit {status}\n")
|
|
path.chmod(0o700)
|
|
uname = directory / "uname"
|
|
uname.write_text('#!/bin/sh\ncase "$1" in -s) echo "$TEST_SYSTEM";; -m) echo "$TEST_ARCH";; esac\n')
|
|
uname.chmod(0o700)
|
|
return subprocess.run(["/bin/bash", str(SCRIPT), mode], capture_output=True, text=True,
|
|
env={**os.environ, "PATH": temporary, "TEST_SYSTEM": system,
|
|
"TEST_ARCH": architecture})
|
|
|
|
def test_android_accepts_linux_x64(self):
|
|
self.assertEqual(self.run_check("android").returncode, 0)
|
|
|
|
def test_android_rejects_arm(self):
|
|
self.assertNotEqual(self.run_check("android", architecture="aarch64").returncode, 0)
|
|
|
|
def test_android_rejects_macos(self):
|
|
self.assertNotEqual(self.run_check("android", system="Darwin").returncode, 0)
|
|
|
|
def test_ios_accepts_native_arm_with_tools(self):
|
|
self.assertEqual(self.run_check("ios", system="Darwin", architecture="arm64").returncode, 0)
|
|
|
|
def test_ios_rejects_rosetta_or_intel(self):
|
|
self.assertNotEqual(self.run_check("ios", system="Darwin").returncode, 0)
|
|
|
|
def test_ios_rejects_linux(self):
|
|
self.assertNotEqual(self.run_check("ios", architecture="arm64").returncode, 0)
|
|
|
|
def test_missing_python_is_actionable(self):
|
|
result = self.run_check("android", missing="python3")
|
|
self.assertNotEqual(result.returncode, 0)
|
|
self.assertIn("install python3", result.stderr)
|
|
|
|
def test_missing_full_xcode_fails(self):
|
|
result = self.run_check("ios", system="Darwin", architecture="arm64", missing="xcodebuild")
|
|
self.assertNotEqual(result.returncode, 0)
|
|
self.assertIn("full Xcode", result.stderr)
|
|
|
|
def test_broken_xcode_fails(self):
|
|
self.assertNotEqual(self.run_check("ios", system="Darwin", architecture="arm64",
|
|
broken_xcode=True).returncode, 0)
|
|
|
|
def test_unknown_mode_fails(self):
|
|
self.assertNotEqual(self.run_check("other").returncode, 0)
|
|
|
|
def test_missing_xcrun_is_actionable(self):
|
|
result = self.run_check("ios", system="Darwin", architecture="arm64", missing="xcrun")
|
|
self.assertNotEqual(result.returncode, 0)
|
|
self.assertIn("Cannot start xcrun", result.stderr)
|
|
|
|
def test_broken_xcrun_is_not_a_pass(self):
|
|
result = self.run_check("ios", system="Darwin", architecture="arm64", broken_xcrun=True)
|
|
self.assertNotEqual(result.returncode, 0)
|
|
self.assertIn("xcrun --find swift exited 1", result.stderr)
|
|
|
|
def test_unresponsive_apple_probe_times_out_with_guidance(self):
|
|
with self.assertRaisesRegex(RuntimeError, "interactive login session"):
|
|
APPLE_TOOLS.probe([sys.executable, "-c", "import time; time.sleep(30)"], timeout=0.05)
|
|
|
|
def test_apple_probe_preserves_tool_failure_diagnostic(self):
|
|
with self.assertRaisesRegex(RuntimeError, "fixture tool failure"):
|
|
APPLE_TOOLS.probe([sys.executable, "-c", "import sys; sys.exit('fixture tool failure')"])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|