import json import subprocess import sys import tempfile import unittest from pathlib import Path from tools.new_device import build_parser, run_generation from tools.new_device import run_online_bootstrap from core.device_profile import DeviceProfileGenerator class FakeResponse: def __init__(self, status_code, payload): self.status_code = status_code self.ok = 200 <= status_code < 300 self._payload = payload self.text = json.dumps(payload) def json(self): return self._payload class NewDeviceDfpCliTests(unittest.TestCase): def test_cli_writes_dfp_dry_run_requests(self): with tempfile.TemporaryDirectory() as tmp: out_dir = Path(tmp) / "devices" result = subprocess.run( [ sys.executable, "tools/new_device.py", "--count", "1", "--out-dir", str(out_dir), "--seed", "1", "--env", "--dfp-dry-run", "--force", ], check=False, cwd=Path(__file__).resolve().parents[1], text=True, capture_output=True, ) self.assertEqual(result.returncode, 0, result.stderr) request_path = out_dir / "device_001_dfp_requests.json" self.assertTrue(request_path.exists()) data = json.loads(request_path.read_text(encoding="utf-8")) self.assertIn("unified_fetch", data) self.assertIn("unified_check_repair", data) self.assertIn("gdfp_report", data) def test_parser_accepts_online_flag(self): args = build_parser().parse_args(["--online"]) self.assertTrue(args.online) def test_online_bootstrap_posts_requests_and_updates_profile(self): profile = DeviceProfileGenerator(seed=20260711).new_profile() calls = [] def fake_post(url, data, headers, timeout): calls.append((url, data, headers, timeout)) if "/unifiedId/fetch/" in url: return FakeResponse( 200, { "result": 1, "cloud_did": "ANDROID_f05497e9cef09a7f", "did_tag": 2, }, ) if "/unifiedId/checkRepair" in url: return FakeResponse( 200, { "result": 1, "error_msg": "", "action": 0, }, ) if "/gdfp/report/" in url: return FakeResponse( 200, { "result": 1, "egid": "DFPD5DAB4376320DEA4F0DDFEA76E0B216F894BF2247BD8F6DA8B77AD981AF68", }, ) raise AssertionError(f"unexpected URL: {url}") result = run_online_bootstrap(profile, timeout=7, post_func=fake_post) self.assertEqual(len(calls), 3) self.assertIn("/unifiedId/fetch/", calls[0][0]) self.assertIn("/unifiedId/checkRepair", calls[1][0]) self.assertIn("/gdfp/report/", calls[2][0]) self.assertEqual(calls[0][3], 7) self.assertEqual(profile.did, "ANDROID_f05497e9cef09a7f") self.assertEqual(profile.cdid_tag, 2) self.assertEqual( profile.egid, "DFPD5DAB4376320DEA4F0DDFEA76E0B216F894BF2247BD8F6DA8B77AD981AF68", ) self.assertEqual(result["identity"]["did"], profile.did) self.assertIn("unified_fetch", result["requests"]) self.assertIn("gdfp_report", result["responses"]) def test_run_generation_online_writes_response_and_updated_profile(self): with tempfile.TemporaryDirectory() as tmp: out_dir = Path(tmp) / "devices" def fake_post(url, data, headers, timeout): if "/unifiedId/fetch/" in url: return FakeResponse( 200, { "result": 1, "cloud_did": "ANDROID_f05497e9cef09a7f", "did_tag": 2, }, ) if "/unifiedId/checkRepair" in url: return FakeResponse( 200, { "result": 1, "error_msg": "", "action": 0, }, ) return FakeResponse( 200, { "result": 1, "egid": "DFPD5DAB4376320DEA4F0DDFEA76E0B216F894BF2247BD8F6DA8B77AD981AF68", }, ) args = build_parser().parse_args( [ "--count", "1", "--out-dir", str(out_dir), "--seed", "1", "--env", "--online", "--force", ] ) run_generation(args, post_func=fake_post) profile_data = json.loads((out_dir / "device_001.json").read_text(encoding="utf-8")) online_data = json.loads((out_dir / "device_001_dfp_online.json").read_text(encoding="utf-8")) env_text = (out_dir / "device_001.env").read_text(encoding="utf-8") self.assertEqual(profile_data["did"], "ANDROID_f05497e9cef09a7f") self.assertEqual( profile_data["egid"], "DFPD5DAB4376320DEA4F0DDFEA76E0B216F894BF2247BD8F6DA8B77AD981AF68", ) self.assertEqual(online_data["identity"]["did"], profile_data["did"]) self.assertIn("unified_check_repair", online_data["requests"]) self.assertIn("KS_DID=ANDROID_f05497e9cef09a7f", env_text) if __name__ == "__main__": unittest.main()