67 lines
3.0 KiB
Python
67 lines
3.0 KiB
Python
|
|
"""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()
|