"""Same-certificate upgrade test on our dedicated emulator; never a phone. Seeds only a synthetic non-authenticating session. Does not alter host networking or request a production account. Run after building/signing the test APK. """ import datetime import hashlib import json from pathlib import Path import subprocess ROOT = Path(__file__).resolve().parents[1] ADB = ROOT / ".tools/android-sdk/platform-tools/adb.exe" PACKAGE = "cn.toplc.zonghengjia" SERIAL = "emulator-5554" def adb(*args, timeout=60): return subprocess.run([str(ADB), "-s", SERIAL, *map(str, args)], capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=timeout, check=True, creationflags=subprocess.CREATE_NO_WINDOW).stdout def instrument(method): result = adb("shell", "am", "instrument", "-w", "-r", "-e", "oldVersion", "1.0.2", "-e", "newVersion", "1.0.3", "-e", "class", "com.v2ray.ang.ucvl.UpgradeSmokeTest#" + method, PACKAGE + ".test/androidx.test.runner.AndroidJUnitRunner", timeout=90) if "OK (1 test)" not in result: raise RuntimeError("Instrumentation failed: " + result[-3000:]) def main(): assert adb("shell", "getprop", "ro.kernel.qemu").strip() == "1", "Dedicated emulator only" assert "ucvl_acceptance" in adb("emu", "avd", "name"), "Unexpected emulator image" assert adb("shell", "getprop", "sys.boot_completed").strip() == "1", "Emulator has not booted" old = ROOT / "releases/UCVL-Zonghengjia-1.0.2-android-universal.apk" new = ROOT / "releases/UCVL-Zonghengjia-1.0.3-android-universal.apk" test = ROOT / "releases/app-playstore-release-androidTest-1.0.3.apk" assert all(path.is_file() for path in [old, new, test]) evidence = ROOT / "acceptance/upgrade-1.0.3.json" report = {"timestamp": datetime.datetime.now().astimezone().isoformat(), "serial": SERIAL, "old_version": "1.0.2", "new_version": "1.0.3", "passed": False, "physical_device_tested": False, "host_network_modified": False, "authenticated_vpn_connection_tested": False, "steps": []} try: adb("shell", "am", "force-stop", PACKAGE) assert "Success" in adb("install", "-r", old) assert "Success" in adb("install", "-r", test) instrument("seedUpgrade") report["steps"].append("seed_synthetic_session_on_1.0.2") assert "Success" in adb("install", "-r", new) instrument("verifyUpgrade") report["steps"].append("cover_upgrade_preserves_encrypted_session_login_and_device_id") instrument("loginVisibleAndEmptyFormIsSafe") report["steps"].append("login_visible_empty_submission_safe_fixture_cleared") report["apk_sha256"] = hashlib.sha256(new.read_bytes()).hexdigest() report["passed"] = True finally: adb("shell", "am", "force-stop", PACKAGE) evidence.write_text(json.dumps(report, indent=2), encoding="utf-8") print(json.dumps(report)) if __name__ == "__main__": main()