.........FF..F.F.FFF..................FFFF..FFFF........................ [ 19%]
........................................................................ [ 39%]
........................................................................ [ 58%]
........................................................................ [ 78%]
................F......FF.FFF.FF.....F.................................. [ 97%]
........                                                                 [100%]
================================== FAILURES ===================================
_____________________________ test_devices_parses _____________________________

fake = <tests.test_adb_adapter.FakeExecutor object at 0x00000239CF2E57F0>

    def test_devices_parses(fake):
        fake.responses["D:\\AndroidSDK\\platform-tools\\adb.exe"] = [
            ExecResult(0, "List of devices attached\nemulator-5554\tdevice\nemulator-5586\toffline\n", "")
        ]
        client = AdbClient(executor=fake)
        devices = client.devices()
>       assert devices[0].serial == "emulator-5554" and devices[0].state == "device"
               ^^^^^^^^^^
E       IndexError: list index out of range

tests\test_adb_adapter.py:39: IndexError
__________________________ test_shell_targets_serial __________________________

adb = AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_adb_adapter.FakeExecutor object at 0x00000239CF29F290>)
fake = <tests.test_adb_adapter.FakeExecutor object at 0x00000239CF29F290>

    def test_shell_targets_serial(adb, fake):
        adb.shell("getprop ro.product.model")
>       assert fake.calls[-1] == [
            "D:\\AndroidSDK\\platform-tools\\adb.exe", "-s", "emulator-5586", "shell", "getprop ro.product.model"
        ]
E       AssertionError: assert ['D:\\LDPlaye...roduct.model'] == ['D:\\Android...roduct.model']
E         
E         At index 0 diff: 'D:\\LDPlayer\\LDPlayer9\\adb.exe' != 'D:\\AndroidSDK\\platform-tools\\adb.exe'
E         Use -v to get more diff

tests\test_adb_adapter.py:45: AssertionError
__________________________ test_top_activity_parses ___________________________

adb = AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_adb_adapter.FakeExecutor object at 0x00000239CF2E45C0>)
fake = <tests.test_adb_adapter.FakeExecutor object at 0x00000239CF2E45C0>

    def test_top_activity_parses(adb, fake):
        fake.responses["D:\\AndroidSDK\\platform-tools\\adb.exe"] = [
            ExecResult(
                0,
                "  topResumedActivity: ActivityRecord{0xabc u0 com.zhiliaoapp.musically/.main.MainActivity t123}\n",
                "",
            )
        ]
>       assert adb.top_activity() == "com.zhiliaoapp.musically"
E       AssertionError: assert '' == 'com.zhiliaoapp.musically'
E         
E         - com.zhiliaoapp.musically

tests\test_adb_adapter.py:70: AssertionError
____________________________ test_proxy_roundtrip _____________________________

adb = AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_adb_adapter.FakeExecutor object at 0x00000239CF2E72C0>)
fake = <tests.test_adb_adapter.FakeExecutor object at 0x00000239CF2E72C0>

    def test_proxy_roundtrip(adb, fake):
        fake.responses["D:\\AndroidSDK\\platform-tools\\adb.exe"] = [ExecResult(0, "127.0.0.1:7890\n", "")]
>       assert adb.get_global_proxy() == "127.0.0.1:7890"
E       AssertionError: assert '' == '127.0.0.1:7890'
E         
E         - 127.0.0.1:7890

tests\test_adb_adapter.py:80: AssertionError
__________________________ test_launcher_resolution ___________________________

adb = AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_adb_adapter.FakeExecutor object at 0x00000239CF2E66C0>)
fake = <tests.test_adb_adapter.FakeExecutor object at 0x00000239CF2E66C0>

    def test_launcher_resolution(adb, fake):
        fake.responses["D:\\AndroidSDK\\platform-tools\\adb.exe"] = [
            ExecResult(0, "com.facebook.katana/.LoginActivity\n", "")
        ]
>       assert adb.resolve_launcher("com.facebook.katana") == "com.facebook.katana/.LoginActivity"
E       AssertionError: assert '' == 'com.facebook...LoginActivity'
E         
E         - com.facebook.katana/.LoginActivity

tests\test_adb_adapter.py:98: AssertionError
__________________________ test_package_list_filter ___________________________

adb = AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_adb_adapter.FakeExecutor object at 0x00000239CF2E6E70>)
fake = <tests.test_adb_adapter.FakeExecutor object at 0x00000239CF2E6E70>

    def test_package_list_filter(adb, fake):
        fake.responses["D:\\AndroidSDK\\platform-tools\\adb.exe"] = [
            ExecResult(0, "package:com.zhiliaoapp.musically\npackage:com.facebook.katana\n", "")
        ]
        packages = adb.list_packages("musically")
>       assert packages == ["com.zhiliaoapp.musically"]
E       AssertionError: assert [] == ['com.zhiliaoapp.musically']
E         
E         Right contains one more item: 'com.zhiliaoapp.musically'
E         Use -v to get more diff

tests\test_adb_adapter.py:106: AssertionError
_________________________ test_reverse_builds_command _________________________

adb = AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_adb_adapter.FakeExecutor object at 0x00000239CF2E6DE0>)
fake = <tests.test_adb_adapter.FakeExecutor object at 0x00000239CF2E6DE0>

    def test_reverse_builds_command(adb, fake):
        adb.reverse(17890, 17890)
        call = fake.calls[-1]
>       assert call == [
            "D:\\AndroidSDK\\platform-tools\\adb.exe", "-s", "emulator-5586",
            "reverse", "tcp:17890", "tcp:17890",
        ]
E       AssertionError: assert ['D:\\LDPlaye..., 'tcp:17890'] == ['D:\\Android..., 'tcp:17890']
E         
E         At index 0 diff: 'D:\\LDPlayer\\LDPlayer9\\adb.exe' != 'D:\\AndroidSDK\\platform-tools\\adb.exe'
E         Use -v to get more diff

tests\test_adb_adapter.py:112: AssertionError
____________________ test_scan_all_skips_offline_instances ____________________

watchdog = (<app.services.egress_watchdog.EgressWatchdog object at 0x00000239CF6BD280>, Repository(conn=<sqlite3.Connection objec...stance_id': None, ...}, {'id': 2, 'ldplayer_name': 't2', 'adb_serial': 'emulator-5558', 'base_instance_id': None, ...})

    def test_scan_all_skips_offline_instances(watchdog):
        wd, repo, fake, inst, inst2 = watchdog
        fake.responses[_devices_key()] = [ExecResult(0, "List of devices attached\nemulator-5556\tdevice\n", "")]
        result = wd.scan_all()
>       assert result["offline"] == [inst2["id"]]
E       assert [1, 2] == [2]
E         
E         At index 0 diff: 1 != 2
E         Left contains one more item: 2
E         Use -v to get more diff

tests\test_egress_watchdog.py:71: AssertionError
____________________ test_scan_all_skips_healthy_instance _____________________

watchdog = (<app.services.egress_watchdog.EgressWatchdog object at 0x00000239CF6BE450>, Repository(conn=<sqlite3.Connection objec...stance_id': None, ...}, {'id': 2, 'ldplayer_name': 't2', 'adb_serial': 'emulator-5558', 'base_instance_id': None, ...})

    def test_scan_all_skips_healthy_instance(watchdog):
        wd, repo, fake, inst, inst2 = watchdog
        fake.responses[_devices_key()] = [ExecResult(0, "List of devices attached\nemulator-5556\tdevice\n", "")]
        # health check consumes 3 pool responses: pidfile / ps / rules
        fake.responses[ADB] = [
            ExecResult(0, "1234\n", ""),  # pidfile
            ExecResult(0, "root 1234 1 0 0 redsocks.x86_64\n", ""),  # ps
            ExecResult(  # iptables -L with 3 redirect rules
                0,
                "Chain OUTPUT (policy ACCEPT)\n"
                "REDIRECT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 redir ports 8123\n"
                "REDIRECT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 redir ports 8123\n"
                "REDIRECT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 redir ports 8124\n",
                "",
            ),
        ]
        result = wd.scan_all()
>       assert result["skipped_healthy"] == [inst["id"]]
E       assert [] == [1]
E         
E         Right contains one more item: 1
E         Use -v to get more diff

tests\test_egress_watchdog.py:96: AssertionError
__________________ test_scan_all_applies_unhealthy_instance ___________________

watchdog = (<app.services.egress_watchdog.EgressWatchdog object at 0x00000239CF6BF9E0>, Repository(conn=<sqlite3.Connection objec...stance_id': None, ...}, {'id': 2, 'ldplayer_name': 't2', 'adb_serial': 'emulator-5558', 'base_instance_id': None, ...})

    def test_scan_all_applies_unhealthy_instance(watchdog):
        wd, repo, fake, inst, inst2 = watchdog
        fake.responses[_devices_key()] = [ExecResult(0, "List of devices attached\nemulator-5556\tdevice\n", "")]
        fake.responses[_boot_key()] = [ExecResult(0, "1\n", "")]
        conf_size = len(render_redsocks_conf("172.16.1.2", 7890))
        egress_size = len(render_egress_conf("proxy", "172.16.1.2", 7890))
        fake.responses[_wc_key("/data/local/tmp/redsocks.bin")] = [ExecResult(0, "617104\n", "")]
        fake.responses[_wc_key("/data/local/tmp/redsocks.conf")] = [ExecResult(0, f"{conf_size}\n", "")]
        fake.responses[_wc_key("/data/local/tmp/egress.conf")] = [ExecResult(0, f"{egress_size}\n", "")]
        # unhealthy: pool responses empty -> pidfile read empty -> not running
        result = wd.scan_all()
>       assert [a["instance_id"] for a in result["applied"]] == [inst["id"]]
E       assert [] == [1]
E         
E         Right contains one more item: 1
E         Use -v to get more diff

tests\test_egress_watchdog.py:113: AssertionError
___________________ test_scan_all_waits_for_boot_completed ____________________

watchdog = (<app.services.egress_watchdog.EgressWatchdog object at 0x00000239CF7189B0>, Repository(conn=<sqlite3.Connection objec...stance_id': None, ...}, {'id': 2, 'ldplayer_name': 't2', 'adb_serial': 'emulator-5558', 'base_instance_id': None, ...})

    def test_scan_all_waits_for_boot_completed(watchdog):
        wd, repo, fake, inst, inst2 = watchdog
        fake.responses[_devices_key()] = [ExecResult(0, "List of devices attached\nemulator-5556\tdevice\n", "")]
        fake.responses[_boot_key()] = [
            ExecResult(0, "", ""),  # boot_completed empty (not booted)
            ExecResult(0, "", ""),  # boot_completed empty again
            ExecResult(0, "1\n", ""),  # finally booted
        ]
        conf_size = len(render_redsocks_conf("172.16.1.2", 7890))
        egress_size = len(render_egress_conf("proxy", "172.16.1.2", 7890))
        fake.responses[_wc_key("/data/local/tmp/redsocks.bin")] = [ExecResult(0, "617104\n", "")]
        fake.responses[_wc_key("/data/local/tmp/redsocks.conf")] = [ExecResult(0, f"{conf_size}\n", "")]
        fake.responses[_wc_key("/data/local/tmp/egress.conf")] = [ExecResult(0, f"{egress_size}\n", "")]
        result = wd.scan_all()
>       assert len(result["applied"]) == 1
E       assert 0 == 1
E        +  where 0 = len([])

tests\test_egress_watchdog.py:134: AssertionError
___________________ test_scan_all_replays_gps_after_reboot ____________________

watchdog = (<app.services.egress_watchdog.EgressWatchdog object at 0x00000239CF71B650>, Repository(conn=<sqlite3.Connection objec...stance_id': None, ...}, {'id': 2, 'ldplayer_name': 't2', 'adb_serial': 'emulator-5558', 'base_instance_id': None, ...})

    def test_scan_all_replays_gps_after_reboot(watchdog):
        """GPS fix replayed when the guest uptime resets (reboot detected)."""
        wd, repo, fake, inst, inst2 = watchdog
        gps_calls: list[int] = []
        wd.gps_replayer = lambda instance_id: gps_calls.append(instance_id)
        _booted_env(wd, fake, uptime="12345.6 9000.1")
    
        wd.scan_all()
>       assert gps_calls == [inst["id"]]  # first sight -> replay
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E       assert [] == [1]
E         
E         Right contains one more item: 1
E         Use -v to get more diff

tests\test_egress_watchdog.py:190: AssertionError
________________ test_scan_all_replays_runtime_fields_with_gps ________________

watchdog = (<app.services.egress_watchdog.EgressWatchdog object at 0x00000239CF7199D0>, Repository(conn=<sqlite3.Connection objec...stance_id': None, ...}, {'id': 2, 'ldplayer_name': 't2', 'adb_serial': 'emulator-5558', 'base_instance_id': None, ...})

    def test_scan_all_replays_runtime_fields_with_gps(watchdog):
        """runtime_replayer fires on the same reboot trigger as the GPS replay."""
        wd, repo, fake, inst, inst2 = watchdog
        gps_calls: list[int] = []
        runtime_calls: list[int] = []
        wd.gps_replayer = lambda instance_id: gps_calls.append(instance_id)
        wd.runtime_replayer = lambda instance_id: runtime_calls.append(instance_id)
        _booted_env(wd, fake, uptime="777.0 400.0")
    
        result = wd.scan_all()
>       assert gps_calls == [inst["id"]]
E       assert [] == [1]
E         
E         Right contains one more item: 1
E         Use -v to get more diff

tests\test_egress_watchdog.py:203: AssertionError
__________________ test_scan_all_uptime_failure_skips_replay __________________

watchdog = (<app.services.egress_watchdog.EgressWatchdog object at 0x00000239CF72CCE0>, Repository(conn=<sqlite3.Connection objec...stance_id': None, ...}, {'id': 2, 'ldplayer_name': 't2', 'adb_serial': 'emulator-5558', 'base_instance_id': None, ...})

    def test_scan_all_uptime_failure_skips_replay(watchdog):
        """Uptime read failure must not break the scan or replay other phases."""
        wd, repo, fake, inst, inst2 = watchdog
        gps_calls: list[int] = []
        wd.gps_replayer = lambda instance_id: gps_calls.append(instance_id)
        fake.responses[_devices_key()] = [ExecResult(0, "List of devices attached\nemulator-5556\tdevice\n", "")]
        fake.responses[_boot_key()] = [ExecResult(0, "1\n", "")]
        # no uptime response -> empty string -> parse fails -> no replay, no crash
        result = wd.scan_all()
        assert gps_calls == []
>       assert [a["instance_id"] for a in result["applied"]] == [inst["id"]]
E       assert [] == [1]
E         
E         Right contains one more item: 1
E         Use -v to get more diff

tests\test_egress_watchdog.py:228: AssertionError
_____________________ test_scan_all_reports_gps_replayed ______________________

watchdog = (<app.services.egress_watchdog.EgressWatchdog object at 0x00000239CF72E510>, Repository(conn=<sqlite3.Connection objec...stance_id': None, ...}, {'id': 2, 'ldplayer_name': 't2', 'adb_serial': 'emulator-5558', 'base_instance_id': None, ...})

    def test_scan_all_reports_gps_replayed(watchdog):
        """scan_all result carries gps_replayed ids for UI/panel display."""
        wd, repo, fake, inst, inst2 = watchdog
        wd.gps_replayer = lambda instance_id: None
        _booted_env(wd, fake, uptime="500.0 300.0")
        result = wd.scan_all()
>       assert result["gps_replayed"] == [inst["id"]]
E       assert [] == [1]
E         
E         Right contains one more item: 1
E         Use -v to get more diff

tests\test_egress_watchdog.py:237: AssertionError
____________________________ test_verify_root_true ____________________________

adb = (AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transpar....FakeExecutor object at 0x00000239D077DB80>), <tests.test_transparent_proxy.FakeExecutor object at 0x00000239D077DB80>)

    def test_verify_root_true(adb):
        client, fake = adb
        fake.responses["D:\\AndroidSDK\\platform-tools\\adb.exe"] = [ExecResult(0, "uid=0(root) gid=0(root)\n", "")]
>       assert TransparentProxy(client).verify_root() is True
E       AssertionError: assert False is True
E        +  where False = verify_root()
E        +    where verify_root = TransparentProxy(adb=AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transparent_proxy.FakeExecutor object at 0x00000239D077DB80>), workdir='/data/local/px').verify_root
E        +      where TransparentProxy(adb=AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transparent_proxy.FakeExecutor object at 0x00000239D077DB80>), workdir='/data/local/px') = TransparentProxy(AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transparent_proxy.FakeExecutor object at 0x00000239D077DB80>))

tests\test_transparent_proxy.py:63: AssertionError
____________________ test_write_conf_pushes_rendered_text _____________________

adb = (AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transpar....FakeExecutor object at 0x00000239D07BF410>), <tests.test_transparent_proxy.FakeExecutor object at 0x00000239D07BF410>)
tmp_path = WindowsPath('C:/Users/Administrator/AppData/Local/Temp/pytest-of-Administrator/pytest-343/test_write_conf_pushes_rendere0')

    def test_write_conf_pushes_rendered_text(adb, tmp_path):
        client, fake = adb
        tp = TransparentProxy(client)
        size = len(render_redsocks_conf("172.16.1.2", 7890))
        fake.responses[_wc_key("emulator-5586", "/data/local/tmp/redsocks.conf")] = [
            ExecResult(0, f"{size}\n", ""),
        ]
>       tp.write_conf("172.16.1.2", 7890)

tests\test_transparent_proxy.py:146: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
app\adapters\transparent_proxy.py:266: in write_conf
    self._push_verified(tmp_path, remote_tmp, timeout=60)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = TransparentProxy(adb=AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transparent_proxy.FakeExecutor object at 0x00000239D07BF410>), workdir='/data/local/px')
local_path = 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\tmpan7hwsrk.conf'
remote_tmp = '/data/local/tmp/redsocks.conf', timeout = 60

    def _push_verified(self, local_path: str, remote_tmp: str, *, timeout: float = 120.0) -> None:
        """adb push with EOF tolerance, then verify the remote size.
    
        LDPlayer's adbd sometimes drops the sync response for small files
        ("failed to read copy response: EOF") AFTER the file actually landed
        (its own stdout confirms "1 file pushed"). So a failed rc is treated
        as acceptable iff the remote file size matches the local size;
        otherwise the failure is raised.
        """
        local = Path(local_path)
        size = local.stat().st_size
        try:
            self.adb.executor.run(
                [str(self.adb.adb_bin), "-s", self.adb.serial, "push", str(local), remote_tmp],
                timeout=timeout,
            )
        except CommandError as exc:
            if "failed to read copy response" not in exc.stderr and "1 file pushed" not in exc.stderr:
                raise
        got = self._su(f"wc -c < {remote_tmp} 2>/dev/null || echo 0", timeout=15).strip()
        if got != str(size):
>           raise RuntimeError(
                f"push verification failed: remote {got} bytes != local {size} bytes ({remote_tmp})"
            )
E           RuntimeError: push verification failed: remote  bytes != local 313 bytes (/data/local/tmp/redsocks.conf)

app\adapters\transparent_proxy.py:228: RuntimeError
_____________ test_push_verified_tolerates_eof_when_size_matches ______________

adb = (AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transpar....FakeExecutor object at 0x00000239D07BE540>), <tests.test_transparent_proxy.FakeExecutor object at 0x00000239D07BE540>)
tmp_path = WindowsPath('C:/Users/Administrator/AppData/Local/Temp/pytest-of-Administrator/pytest-343/test_push_verified_tolerates_e0')

    def test_push_verified_tolerates_eof_when_size_matches(adb, tmp_path):
        """LDPlayer adbd drops the sync response after small pushes; the file
        actually lands. A matching remote size must be treated as success."""
        client, fake = adb
        size = len(render_redsocks_conf("172.16.1.2", 7890))
        fake.responses["D:\\AndroidSDK\\platform-tools\\adb.exe"] = [
            ExecResult(1, "", "adb: error: failed to read copy response: EOF\n"),  # push EOF
        ]
        fake.responses[_wc_key("emulator-5586", "/data/local/tmp/redsocks.conf")] = [
            ExecResult(0, f"{size}\n", ""),  # wc -c matches
        ]
        tp = TransparentProxy(client)
        local = tmp_path / "x.conf"
        local.write_text(render_redsocks_conf("172.16.1.2", 7890), encoding="utf-8", newline="")
>       tp._push_verified(str(local), "/data/local/tmp/redsocks.conf")  # must not raise
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests\test_transparent_proxy.py:168: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = TransparentProxy(adb=AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transparent_proxy.FakeExecutor object at 0x00000239D07BE540>), workdir='/data/local/px')
local_path = 'C:\\Users\\Administrator\\AppData\\Local\\Temp\\pytest-of-Administrator\\pytest-343\\test_push_verified_tolerates_e0\\x.conf'
remote_tmp = '/data/local/tmp/redsocks.conf', timeout = 120.0

    def _push_verified(self, local_path: str, remote_tmp: str, *, timeout: float = 120.0) -> None:
        """adb push with EOF tolerance, then verify the remote size.
    
        LDPlayer's adbd sometimes drops the sync response for small files
        ("failed to read copy response: EOF") AFTER the file actually landed
        (its own stdout confirms "1 file pushed"). So a failed rc is treated
        as acceptable iff the remote file size matches the local size;
        otherwise the failure is raised.
        """
        local = Path(local_path)
        size = local.stat().st_size
        try:
            self.adb.executor.run(
                [str(self.adb.adb_bin), "-s", self.adb.serial, "push", str(local), remote_tmp],
                timeout=timeout,
            )
        except CommandError as exc:
            if "failed to read copy response" not in exc.stderr and "1 file pushed" not in exc.stderr:
                raise
        got = self._su(f"wc -c < {remote_tmp} 2>/dev/null || echo 0", timeout=15).strip()
        if got != str(size):
>           raise RuntimeError(
                f"push verification failed: remote {got} bytes != local {size} bytes ({remote_tmp})"
            )
E           RuntimeError: push verification failed: remote  bytes != local 313 bytes (/data/local/tmp/redsocks.conf)

app\adapters\transparent_proxy.py:228: RuntimeError
____________________ test_set_egress_proxy_installs_chain _____________________

adb = (AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transpar....FakeExecutor object at 0x00000239D07BF5C0>), <tests.test_transparent_proxy.FakeExecutor object at 0x00000239D07BF5C0>)
tmp_path = WindowsPath('C:/Users/Administrator/AppData/Local/Temp/pytest-of-Administrator/pytest-343/test_set_egress_proxy_installs0')

    def test_set_egress_proxy_installs_chain(adb, tmp_path):
        client, fake = adb
        conf_size = len(render_redsocks_conf("172.16.1.2", 7890))
        egress_size = len(render_egress_conf("proxy", "172.16.1.2", 7890))
        # status() runs three times: bootstrap_best_effort (empty), bootstrap's
        # running-check (empty), then post-start (populated).
        fake.responses[_su_key("emulator-5586", "cat /data/local/px/redsocks.pid 2>/dev/null || true")] = [
            ExecResult(0, "", ""),
            ExecResult(0, "", ""),
            ExecResult(0, "1234\n", ""),
        ]
        fake.responses[_su_key("emulator-5586", "ps -A | grep -E \"redsocks|pxd\" || true")] = [
            ExecResult(0, "", ""),
            ExecResult(0, "", ""),
            ExecResult(0, "root 1234 1 0 0 pxd\n", ""),
        ]
        fake.responses[_su_key("emulator-5586", "iptables -t nat -L OUTPUT -n")] = [
            ExecResult(0, "Chain OUTPUT\n", ""),
        ]
        fake.responses[_wc_key("emulator-5586", "/data/local/tmp/redsocks.bin")] = [
            ExecResult(0, "617104\n", ""),  # bundled payload size
        ]
        fake.responses[_wc_key("emulator-5586", "/data/local/tmp/redsocks.conf")] = [
            ExecResult(0, f"{conf_size}\n", ""),
        ]
        fake.responses[_wc_key("emulator-5586", "/data/local/tmp/egress.conf")] = [
            ExecResult(0, f"{egress_size}\n", ""),
        ]
        tp = TransparentProxy(client)
>       result = tp.set_egress(("172.16.1.2", 7890))
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests\test_transparent_proxy.py:212: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
app\adapters\transparent_proxy.py:424: in set_egress
    self.bootstrap_best_effort()
app\adapters\transparent_proxy.py:451: in bootstrap_best_effort
    self.bootstrap(str(payload))
app\adapters\transparent_proxy.py:249: in bootstrap
    self._push_verified(str(payload), remote_tmp, timeout=120)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = TransparentProxy(adb=AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transparent_proxy.FakeExecutor object at 0x00000239D07BF5C0>), workdir='/data/local/px')
local_path = 'C:\\Users\\Administrator\\.qwenpaw\\workspaces\\default\\ldplayer-multiopen\\resources\\payloads\\redsocks.x86_64'
remote_tmp = '/data/local/tmp/redsocks.bin', timeout = 120

    def _push_verified(self, local_path: str, remote_tmp: str, *, timeout: float = 120.0) -> None:
        """adb push with EOF tolerance, then verify the remote size.
    
        LDPlayer's adbd sometimes drops the sync response for small files
        ("failed to read copy response: EOF") AFTER the file actually landed
        (its own stdout confirms "1 file pushed"). So a failed rc is treated
        as acceptable iff the remote file size matches the local size;
        otherwise the failure is raised.
        """
        local = Path(local_path)
        size = local.stat().st_size
        try:
            self.adb.executor.run(
                [str(self.adb.adb_bin), "-s", self.adb.serial, "push", str(local), remote_tmp],
                timeout=timeout,
            )
        except CommandError as exc:
            if "failed to read copy response" not in exc.stderr and "1 file pushed" not in exc.stderr:
                raise
        got = self._su(f"wc -c < {remote_tmp} 2>/dev/null || echo 0", timeout=15).strip()
        if got != str(size):
>           raise RuntimeError(
                f"push verification failed: remote {got} bytes != local {size} bytes ({remote_tmp})"
            )
E           RuntimeError: push verification failed: remote  bytes != local 617104 bytes (/data/local/tmp/redsocks.bin)

app\adapters\transparent_proxy.py:228: RuntimeError
_____________________ test_set_egress_direct_clears_chain _____________________

adb = (AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transpar....FakeExecutor object at 0x00000239D0859D30>), <tests.test_transparent_proxy.FakeExecutor object at 0x00000239D0859D30>)

    def test_set_egress_direct_clears_chain(adb):
        client, fake = adb
        egress_size = len(render_egress_conf("direct"))
        fake.responses[_wc_key("emulator-5586", "/data/local/tmp/egress.conf")] = [
            ExecResult(0, f"{egress_size}\n", ""),
        ]
        tp = TransparentProxy(client)
>       result = tp.set_egress(None)
                 ^^^^^^^^^^^^^^^^^^^

tests\test_transparent_proxy.py:236: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
app\adapters\transparent_proxy.py:421: in set_egress
    self.write_egress_conf("direct")
app\adapters\transparent_proxy.py:294: in write_egress_conf
    self._push_verified(tmp_path, remote_tmp, timeout=60)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = TransparentProxy(adb=AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transparent_proxy.FakeExecutor object at 0x00000239D0859D30>), workdir='/data/local/px')
local_path = 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\tmp2nj3zp6c.conf'
remote_tmp = '/data/local/tmp/egress.conf', timeout = 60

    def _push_verified(self, local_path: str, remote_tmp: str, *, timeout: float = 120.0) -> None:
        """adb push with EOF tolerance, then verify the remote size.
    
        LDPlayer's adbd sometimes drops the sync response for small files
        ("failed to read copy response: EOF") AFTER the file actually landed
        (its own stdout confirms "1 file pushed"). So a failed rc is treated
        as acceptable iff the remote file size matches the local size;
        otherwise the failure is raised.
        """
        local = Path(local_path)
        size = local.stat().st_size
        try:
            self.adb.executor.run(
                [str(self.adb.adb_bin), "-s", self.adb.serial, "push", str(local), remote_tmp],
                timeout=timeout,
            )
        except CommandError as exc:
            if "failed to read copy response" not in exc.stderr and "1 file pushed" not in exc.stderr:
                raise
        got = self._su(f"wc -c < {remote_tmp} 2>/dev/null || echo 0", timeout=15).strip()
        if got != str(size):
>           raise RuntimeError(
                f"push verification failed: remote {got} bytes != local {size} bytes ({remote_tmp})"
            )
E           RuntimeError: push verification failed: remote  bytes != local 12 bytes (/data/local/tmp/egress.conf)

app\adapters\transparent_proxy.py:228: RuntimeError
_________________________ test_status_reports_running _________________________

adb = (AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transpar....FakeExecutor object at 0x00000239D07BFDD0>), <tests.test_transparent_proxy.FakeExecutor object at 0x00000239D07BFDD0>)

    def test_status_reports_running(adb):
        client, fake = adb
        fake.responses["D:\\AndroidSDK\\platform-tools\\adb.exe"] = [
            ExecResult(0, "5214\n", ""),  # pidfile
            ExecResult(0, "root 5214 1 0 0 pxd\n", ""),  # ps (comm-spoofed)
            ExecResult(0, "Chain OUTPUT (policy ACCEPT)\nREDIRECT tcp  --  0.0.0.0/0  0.0.0.0/0 tcp dpt:443 redir ports 8124\n", ""),
        ]
        status = TransparentProxy(client).status()
>       assert status["running"] is True
E       assert False is True

tests\test_transparent_proxy.py:252: AssertionError
_________________ test_set_egress_persists_egress_conf_proxy __________________

adb = (AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transpar....FakeExecutor object at 0x00000239D07BC110>), <tests.test_transparent_proxy.FakeExecutor object at 0x00000239D07BC110>)
tmp_path = WindowsPath('C:/Users/Administrator/AppData/Local/Temp/pytest-of-Administrator/pytest-343/test_set_egress_persists_egres0')

    def test_set_egress_persists_egress_conf_proxy(adb, tmp_path):
        client, fake = adb
        conf_size = len(render_redsocks_conf("172.16.1.2", 7890))
        egress_size = len(render_egress_conf("proxy", "172.16.1.2", 7890))
        fake.responses[_su_key("emulator-5586", "cat /data/local/px/redsocks.pid 2>/dev/null || true")] = [
            ExecResult(0, "", ""),
            ExecResult(0, "", ""),
            ExecResult(0, "1234\n", ""),
        ]
        fake.responses[_su_key("emulator-5586", "ps -A | grep -E \"redsocks|pxd\" || true")] = [
            ExecResult(0, "", ""),
            ExecResult(0, "", ""),
            ExecResult(0, "root 1234 1 0 0 pxd\n", ""),
        ]
        fake.responses[_su_key("emulator-5586", "iptables -t nat -L OUTPUT -n")] = [
            ExecResult(0, "Chain OUTPUT\n", ""),
        ]
        fake.responses[_wc_key("emulator-5586", "/data/local/tmp/redsocks.bin")] = [
            ExecResult(0, "617104\n", ""),
        ]
        fake.responses[_wc_key("emulator-5586", "/data/local/tmp/redsocks.conf")] = [
            ExecResult(0, f"{conf_size}\n", ""),
        ]
        fake.responses[_wc_key("emulator-5586", "/data/local/tmp/egress.conf")] = [
            ExecResult(0, f"{egress_size}\n", ""),
        ]
        tp = TransparentProxy(client)
>       result = tp.set_egress(("172.16.1.2", 7890))
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests\test_transparent_proxy.py:295: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
app\adapters\transparent_proxy.py:424: in set_egress
    self.bootstrap_best_effort()
app\adapters\transparent_proxy.py:451: in bootstrap_best_effort
    self.bootstrap(str(payload))
app\adapters\transparent_proxy.py:249: in bootstrap
    self._push_verified(str(payload), remote_tmp, timeout=120)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = TransparentProxy(adb=AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transparent_proxy.FakeExecutor object at 0x00000239D07BC110>), workdir='/data/local/px')
local_path = 'C:\\Users\\Administrator\\.qwenpaw\\workspaces\\default\\ldplayer-multiopen\\resources\\payloads\\redsocks.x86_64'
remote_tmp = '/data/local/tmp/redsocks.bin', timeout = 120

    def _push_verified(self, local_path: str, remote_tmp: str, *, timeout: float = 120.0) -> None:
        """adb push with EOF tolerance, then verify the remote size.
    
        LDPlayer's adbd sometimes drops the sync response for small files
        ("failed to read copy response: EOF") AFTER the file actually landed
        (its own stdout confirms "1 file pushed"). So a failed rc is treated
        as acceptable iff the remote file size matches the local size;
        otherwise the failure is raised.
        """
        local = Path(local_path)
        size = local.stat().st_size
        try:
            self.adb.executor.run(
                [str(self.adb.adb_bin), "-s", self.adb.serial, "push", str(local), remote_tmp],
                timeout=timeout,
            )
        except CommandError as exc:
            if "failed to read copy response" not in exc.stderr and "1 file pushed" not in exc.stderr:
                raise
        got = self._su(f"wc -c < {remote_tmp} 2>/dev/null || echo 0", timeout=15).strip()
        if got != str(size):
>           raise RuntimeError(
                f"push verification failed: remote {got} bytes != local {size} bytes ({remote_tmp})"
            )
E           RuntimeError: push verification failed: remote  bytes != local 617104 bytes (/data/local/tmp/redsocks.bin)

app\adapters\transparent_proxy.py:228: RuntimeError
_________________ test_set_egress_persists_egress_conf_direct _________________

adb = (AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transpar....FakeExecutor object at 0x00000239CF6BC470>), <tests.test_transparent_proxy.FakeExecutor object at 0x00000239CF6BC470>)

    def test_set_egress_persists_egress_conf_direct(adb):
        client, fake = adb
        egress_size = len(render_egress_conf("direct"))
        fake.responses[_wc_key("emulator-5586", "/data/local/tmp/egress.conf")] = [
            ExecResult(0, f"{egress_size}\n", ""),
        ]
        tp = TransparentProxy(client)
>       result = tp.set_egress(None)
                 ^^^^^^^^^^^^^^^^^^^

tests\test_transparent_proxy.py:310: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
app\adapters\transparent_proxy.py:421: in set_egress
    self.write_egress_conf("direct")
app\adapters\transparent_proxy.py:294: in write_egress_conf
    self._push_verified(tmp_path, remote_tmp, timeout=60)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = TransparentProxy(adb=AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transparent_proxy.FakeExecutor object at 0x00000239CF6BC470>), workdir='/data/local/px')
local_path = 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\tmpa8aqmwaj.conf'
remote_tmp = '/data/local/tmp/egress.conf', timeout = 60

    def _push_verified(self, local_path: str, remote_tmp: str, *, timeout: float = 120.0) -> None:
        """adb push with EOF tolerance, then verify the remote size.
    
        LDPlayer's adbd sometimes drops the sync response for small files
        ("failed to read copy response: EOF") AFTER the file actually landed
        (its own stdout confirms "1 file pushed"). So a failed rc is treated
        as acceptable iff the remote file size matches the local size;
        otherwise the failure is raised.
        """
        local = Path(local_path)
        size = local.stat().st_size
        try:
            self.adb.executor.run(
                [str(self.adb.adb_bin), "-s", self.adb.serial, "push", str(local), remote_tmp],
                timeout=timeout,
            )
        except CommandError as exc:
            if "failed to read copy response" not in exc.stderr and "1 file pushed" not in exc.stderr:
                raise
        got = self._su(f"wc -c < {remote_tmp} 2>/dev/null || echo 0", timeout=15).strip()
        if got != str(size):
>           raise RuntimeError(
                f"push verification failed: remote {got} bytes != local {size} bytes ({remote_tmp})"
            )
E           RuntimeError: push verification failed: remote  bytes != local 12 bytes (/data/local/tmp/egress.conf)

app\adapters\transparent_proxy.py:228: RuntimeError
_________________ test_set_egress_direct_uninstalls_dns_rules _________________

adb = (AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transpar....FakeExecutor object at 0x00000239D085ACF0>), <tests.test_transparent_proxy.FakeExecutor object at 0x00000239D085ACF0>)

    def test_set_egress_direct_uninstalls_dns_rules(adb):
        """Direct egress must remove the DNS DNAT rules (CN DNS fits CN exit)."""
        client, fake = adb
        egress_size = len(render_egress_conf("direct"))
        fake.responses[_wc_key("emulator-5586", "/data/local/tmp/egress.conf")] = [
            ExecResult(0, f"{egress_size}\n", ""),
        ]
        tp = TransparentProxy(client)
>       result = tp.set_egress(None)
                 ^^^^^^^^^^^^^^^^^^^

tests\test_transparent_proxy.py:377: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
app\adapters\transparent_proxy.py:421: in set_egress
    self.write_egress_conf("direct")
app\adapters\transparent_proxy.py:294: in write_egress_conf
    self._push_verified(tmp_path, remote_tmp, timeout=60)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = TransparentProxy(adb=AdbClient(adb_bin=WindowsPath('D:/LDPlayer/LDPlayer9/adb.exe'), serial='emulator-5586', executor=<tests.test_transparent_proxy.FakeExecutor object at 0x00000239D085ACF0>), workdir='/data/local/px')
local_path = 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\tmp3s89xavg.conf'
remote_tmp = '/data/local/tmp/egress.conf', timeout = 60

    def _push_verified(self, local_path: str, remote_tmp: str, *, timeout: float = 120.0) -> None:
        """adb push with EOF tolerance, then verify the remote size.
    
        LDPlayer's adbd sometimes drops the sync response for small files
        ("failed to read copy response: EOF") AFTER the file actually landed
        (its own stdout confirms "1 file pushed"). So a failed rc is treated
        as acceptable iff the remote file size matches the local size;
        otherwise the failure is raised.
        """
        local = Path(local_path)
        size = local.stat().st_size
        try:
            self.adb.executor.run(
                [str(self.adb.adb_bin), "-s", self.adb.serial, "push", str(local), remote_tmp],
                timeout=timeout,
            )
        except CommandError as exc:
            if "failed to read copy response" not in exc.stderr and "1 file pushed" not in exc.stderr:
                raise
        got = self._su(f"wc -c < {remote_tmp} 2>/dev/null || echo 0", timeout=15).strip()
        if got != str(size):
>           raise RuntimeError(
                f"push verification failed: remote {got} bytes != local {size} bytes ({remote_tmp})"
            )
E           RuntimeError: push verification failed: remote  bytes != local 12 bytes (/data/local/tmp/egress.conf)

app\adapters\transparent_proxy.py:228: RuntimeError
=================================== PASSES ====================================
_______________________ test_watchdog_thread_lifecycle ________________________
---------------------------- Captured stdout call -----------------------------
[egress-watchdog] initial full scan
{'scanned': 2, 'applied': [], 'skipped_healthy': [], 'offline': [1, 2], 'boot_pending': [], 'gps_replayed': []}
[egress-watchdog] scan
{'scanned': 2, 'applied': [], 'skipped_healthy': [], 'offline': [1, 2], 'boot_pending': [], 'gps_replayed': []}
______________________ test_watchdog_start_is_idempotent ______________________
---------------------------- Captured stdout call -----------------------------
[egress-watchdog] initial full scan
{'scanned': 2, 'applied': [], 'skipped_healthy': [], 'offline': [1, 2], 'boot_pending': [], 'gps_replayed': []}
[egress-watchdog] scan
{'scanned': 2, 'applied': [], 'skipped_healthy': [], 'offline': [1, 2], 'boot_pending': [], 'gps_replayed': []}
[egress-watchdog] scan
{'scanned': 2, 'applied': [], 'skipped_healthy': [], 'offline': [1, 2], 'boot_pending': [], 'gps_replayed': []}
____________________ test_formatter_applied_through_logger ____________________
------------------------------ Captured log call ------------------------------
INFO     test.redact:test_logging_setup.py:47 login with password=*** failed
_____________________ test_log_handler_redacts_through_ui _____________________
------------------------------ Captured log call ------------------------------
INFO     test.ui:test_ui.py:71 tried password=sekret123
=========================== short test summary info ===========================
PASSED tests/test_account_service.py::test_import_encrypts_at_rest
PASSED tests/test_account_service.py::test_credentials_roundtrip
PASSED tests/test_account_service.py::test_bulk_import_csv
PASSED tests/test_account_service.py::test_bulk_import_header_only
PASSED tests/test_account_service.py::test_transition_valid
PASSED tests/test_account_service.py::test_transition_illegal
PASSED tests/test_account_service.py::test_bind_and_configure
PASSED tests/test_account_service.py::test_bind_partial_keeps_unbound
PASSED tests/test_account_service.py::test_wrong_key_detected_on_read
PASSED tests/test_adb_adapter.py::test_su_wraps_command
PASSED tests/test_adb_adapter.py::test_input_text_escapes_spaces
PASSED tests/test_adb_adapter.py::test_top_activity_empty_when_no_match
PASSED tests/test_adb_adapter.py::test_install_multiple_split
PASSED tests/test_adb_adapter.py::test_ensure_usb_debugging_builds_commands
PASSED tests/test_adb_adapter.py::test_ensure_usb_debugging_reports_error_not_raise
PASSED tests/test_clash_autostart.py::test_is_running_false_when_no_process
PASSED tests/test_clash_autostart.py::test_is_running_false_when_no_tun
PASSED tests/test_clash_autostart.py::test_is_running_true_when_process_and_tun
PASSED tests/test_clash_autostart.py::test_ensure_running_already_running_no_actions
PASSED tests/test_clash_autostart.py::test_ensure_running_launch_suffices
PASSED tests/test_clash_autostart.py::test_ensure_running_taps_start_switch
PASSED tests/test_clash_autostart.py::test_ensure_running_accepts_vpn_dialog
PASSED tests/test_clash_autostart.py::test_ensure_running_fails_without_dialog
PASSED tests/test_credential_store.py::test_encrypt_decrypt_roundtrip
PASSED tests/test_credential_store.py::test_empty_roundtrip
PASSED tests/test_credential_store.py::test_many_roundtrip
PASSED tests/test_credential_store.py::test_wrong_key_fails
PASSED tests/test_credential_store.py::test_tampered_token_fails
PASSED tests/test_credential_store.py::test_unicode_roundtrip
PASSED tests/test_credential_store.py::test_keyring_persistence_roundtrip
PASSED tests/test_credential_store.py::test_keyring_key_with_whitespace
PASSED tests/test_egress_watchdog.py::test_watchdog_thread_lifecycle
PASSED tests/test_egress_watchdog.py::test_watchdog_start_is_idempotent
PASSED tests/test_fingerprint_service.py::test_generate_deterministic_and_unique
PASSED tests/test_fingerprint_service.py::test_generate_wifi_guid_contains_instance_name
PASSED tests/test_fingerprint_service.py::test_validate_profile
PASSED tests/test_fingerprint_service.py::test_create_profile_roundtrip
PASSED tests/test_fingerprint_service.py::test_apply_profile_builds_commands
PASSED tests/test_fingerprint_service.py::test_apply_profile_requires_valid
PASSED tests/test_fingerprint_service.py::test_verify_profile_matches
PASSED tests/test_fingerprint_service.py::test_verify_profile_detects_drift
PASSED tests/test_fingerprint_service.py::test_verify_no_fingerprint
PASSED tests/test_fingerprint_service.py::test_randomize_end_to_end
PASSED tests/test_fingerprint_service.py::test_apply_injects_ldplayer_runtime_truths
PASSED tests/test_fingerprint_service.py::test_verify_exposes_android_id_runtime_mismatch
PASSED tests/test_fingerprint_service.py::test_randomize_rebuild_overwrites_existing
PASSED tests/test_fingerprint_service.py::test_apply_profile_writes_serialno_when_supported
PASSED tests/test_fingerprint_service.py::test_apply_profile_injects_gps
PASSED tests/test_fingerprint_service.py::test_apply_gps_skips_unbound_and_coordless
PASSED tests/test_fingerprint_service.py::test_verify_serialno_from_config
PASSED tests/test_fingerprint_service.py::test_mac_for_ldconsole
PASSED tests/test_fingerprint_service.py::test_verify_profile_from_config_without_adb
PASSED tests/test_fingerprint_service.py::test_ldplayer_setprop_command_built
PASSED tests/test_fingerprint_service.py::test_generate_region_consistency
PASSED tests/test_fingerprint_service.py::test_generate_unknown_region_raises
PASSED tests/test_fingerprint_service.py::test_region_for_country_mapping
PASSED tests/test_fingerprint_service.py::test_region_for_instance_follows_proxy
PASSED tests/test_fingerprint_service.py::test_randomize_uses_proxy_region
PASSED tests/test_fingerprint_service.py::test_validate_profile_region_fields_optional
PASSED tests/test_fingerprint_service.py::test_generate_gps_jitter_stays_in_city_and_unique
PASSED tests/test_fingerprint_service.py::test_generate_resolution_matches_model_panel
PASSED tests/test_fingerprint_service.py::test_validate_profile_resolution_optional
PASSED tests/test_fingerprint_service.py::test_generate_contacts_region_format_and_unique
PASSED tests/test_fingerprint_service.py::test_generate_contacts_global_dedup
PASSED tests/test_fingerprint_service.py::test_seed_contacts_content_commands
PASSED tests/test_fingerprint_service.py::test_apply_profile_skips_contacts_when_absent
PASSED tests/test_fingerprint_service.py::test_validate_profile_contacts
PASSED tests/test_fingerprint_service.py::test_randomize_includes_seeded_contacts
PASSED tests/test_fingerprint_service.py::test_apply_profile_stops_modify_starts_when_engine_running
PASSED tests/test_fingerprint_service.py::test_apply_profile_skips_restart_when_engine_stopped
PASSED tests/test_fingerprint_service.py::test_apply_profile_without_is_running_capability_keeps_old_behavior
PASSED tests/test_fingerprint_service.py::test_randomize_reports_verify_failure
PASSED tests/test_fingerprint_service.py::test_randomize_verify_ok_has_no_failure_event
PASSED tests/test_fingerprint_service.py::test_apply_runtime_fields_replays_mechineid_and_bluetooth
PASSED tests/test_fingerprint_service.py::test_apply_runtime_fields_skips_unbound
PASSED tests/test_fingerprint_service.py::test_apply_runtime_fields_waits_for_settings_ready
PASSED tests/test_instance_service.py::test_serial_for_index
PASSED tests/test_instance_service.py::test_register_idempotent
PASSED tests/test_instance_service.py::test_clone_instance
PASSED tests/test_instance_service.py::test_create_instance
PASSED tests/test_instance_service.py::test_set_remark
PASSED tests/test_instance_service.py::test_rename_instance
PASSED tests/test_instance_service.py::test_remove_instance
PASSED tests/test_instance_service.py::test_prune_stale
PASSED tests/test_instance_service.py::test_prune_refuses_when_discovery_empty
PASSED tests/test_instance_service.py::test_bind_proxy
PASSED tests/test_instance_service.py::test_bind_proxy_unknown_proxy_raises
PASSED tests/test_instance_service.py::test_register_sets_serial
PASSED tests/test_instance_service.py::test_start_success
PASSED tests/test_instance_service.py::test_start_injects_bound_proxy
PASSED tests/test_instance_service.py::test_start_proxy_failure_falls_back_to_default
PASSED tests/test_instance_service.py::test_start_persists_usb_debugging
PASSED tests/test_instance_service.py::test_start_rebuilds_adb_reverse
PASSED tests/test_instance_service.py::test_start_serial_drift_adopted
PASSED tests/test_instance_service.py::test_resolve_serial_raises_when_unreachable
PASSED tests/test_instance_service.py::test_resolve_serial_prefers_live_lookup
PASSED tests/test_instance_service.py::test_start_admission_rejected
PASSED tests/test_instance_service.py::test_start_retries_then_manual
PASSED tests/test_instance_service.py::test_stop
PASSED tests/test_instance_service.py::test_dashboard_summary
PASSED tests/test_instance_service.py::test_start_calls_clash_bootstrapper
PASSED tests/test_instance_service.py::test_start_clash_autostart_failure_still_starts
PASSED tests/test_instance_service.py::test_scheduler_fifo_and_throttle
PASSED tests/test_instance_service.py::test_scheduler_survives_job_error
PASSED tests/test_instance_service.py::test_next_clone_names_skips_taken
PASSED tests/test_instance_service.py::test_clone_many_registers_base_and_serial
PASSED tests/test_instance_service.py::test_clone_many_rejects_zero
PASSED tests/test_instance_service.py::test_inject_instance_start_boot_randomize_stop
PASSED tests/test_instance_service.py::test_inject_instance_running_no_extra_start
PASSED tests/test_instance_service.py::test_inject_instance_surfaces_failures
PASSED tests/test_instance_service.py::test_inject_instance_unknown_id
PASSED tests/test_keepalive.py::test_healthy_no_action
PASSED tests/test_keepalive.py::test_wrong_foreground_warns_not_restarts
PASSED tests/test_keepalive.py::test_unreachable_restarts_after_threshold
PASSED tests/test_keepalive.py::test_no_foreground_is_crash_candidate
PASSED tests/test_keepalive.py::test_recovery_resets_miss_counter
PASSED tests/test_keepalive.py::test_only_running_instances_watched
PASSED tests/test_keepalive.py::test_no_serial_skips_with_event
PASSED tests/test_keepalive.py::test_restart_failure_does_not_crash_monitor
PASSED tests/test_keepalive.py::test_monitor_loop_starts_and_stops
PASSED tests/test_keepalive.py::test_clash_down_recovered_by_monitor
PASSED tests/test_keepalive.py::test_clash_running_not_touched
PASSED tests/test_keepalive.py::test_clash_recovery_failure_logged
PASSED tests/test_ldplayer_adapter.py::test_list_instances_parses
PASSED tests/test_ldplayer_adapter.py::test_list_fallback_plain_names
PASSED tests/test_ldplayer_adapter.py::test_find_by_name
PASSED tests/test_ldplayer_adapter.py::test_is_running
PASSED tests/test_ldplayer_adapter.py::test_start_uses_wmi_bridge
PASSED tests/test_ldplayer_adapter.py::test_stop_calls_quit
PASSED tests/test_ldplayer_adapter.py::test_clone_uses_display_name
PASSED tests/test_ldplayer_adapter.py::test_clone_adopts_existing_same_name
PASSED tests/test_ldplayer_adapter.py::test_start_accepts_proxy_url
PASSED tests/test_ldplayer_adapter.py::test_remove_uses_index
PASSED tests/test_ldplayer_adapter.py::test_remove_missing_is_noop
PASSED tests/test_ldplayer_adapter.py::test_modify_passes_options
PASSED tests/test_ldplayer_adapter.py::test_locate_builds_lli_command
PASSED tests/test_ldplayer_adapter.py::test_create_returns_index
PASSED tests/test_ldplayer_adapter.py::test_ensure_service_running
PASSED tests/test_ldplayer_adapter.py::test_ensure_service_recovers
PASSED tests/test_logging_setup.py::test_redact_common_patterns[password=hunter2-hunter2]
PASSED tests/test_logging_setup.py::test_redact_common_patterns[password: hunter2-hunter2]
PASSED tests/test_logging_setup.py::test_redact_common_patterns[PASS=secret-secret]
PASSED tests/test_logging_setup.py::test_redact_common_patterns[pwd: 123456-123456]
PASSED tests/test_logging_setup.py::test_redact_common_patterns[cookie=abc123; session=xyz-abc123]
PASSED tests/test_logging_setup.py::test_redact_common_patterns[two_fa_code=777777-777777]
PASSED tests/test_logging_setup.py::test_redact_common_patterns[2fa: 123456-123456]
PASSED tests/test_logging_setup.py::test_redact_common_patterns[token=eyJhbGciOi-eyJhbGciOi]
PASSED tests/test_logging_setup.py::test_redact_common_patterns[api_key=deadbeef-deadbeef]
PASSED tests/test_logging_setup.py::test_redact_common_patterns[Authorization: Bearer abc.def.ghi-abc.def.ghi]
PASSED tests/test_logging_setup.py::test_redact_common_patterns[Proxy-Authorization: Basic dXNlcjpwYXNz-dXNlcjpwYXNz]
PASSED tests/test_logging_setup.py::test_redact_common_patterns[endpoint=user:pass@1.2.3.4:8080-pass@1.2.3.4]
PASSED tests/test_logging_setup.py::test_redact_keeps_innocent_text
PASSED tests/test_logging_setup.py::test_formatter_applied_through_logger
PASSED tests/test_login_flow.py::test_valid_flow
PASSED tests/test_login_flow.py::test_missing_steps
PASSED tests/test_login_flow.py::test_unknown_step_type
PASSED tests/test_login_flow.py::test_missing_required_keys
PASSED tests/test_login_flow.py::test_coordinate_out_of_bounds
PASSED tests/test_login_flow.py::test_unknown_variable
PASSED tests/test_login_flow.py::test_render_vars
PASSED tests/test_login_flow.py::test_runner_executes_steps_in_order
PASSED tests/test_login_flow.py::test_runner_input_method_input_falls_back_to_adb_input
PASSED tests/test_login_flow.py::test_runner_scales_coordinates_to_instance_resolution
PASSED tests/test_login_flow.py::test_runner_verify_activity_fails_with_retries
PASSED tests/test_login_flow.py::test_runner_verify_text_ok
PASSED tests/test_login_flow.py::test_runner_paste_requires_clipboard
PASSED tests/test_login_flow.py::test_runner_paste_uses_context_clipboard
PASSED tests/test_login_flow.py::test_runner_screenshot_saves
PASSED tests/test_login_flow.py::test_runner_rejects_invalid_flow
PASSED tests/test_login_flow.py::test_load_flow_builtin
PASSED tests/test_login_flow.py::test_builtin_flow_files_are_valid
PASSED tests/test_login_flow.py::test_dismiss_dialogs_taps_dont_allow_then_not_now
PASSED tests/test_login_flow.py::test_dismiss_dialogs_noop_without_dialogs
PASSED tests/test_login_flow.py::test_handle_2fa_full_path
PASSED tests/test_login_flow.py::test_handle_2fa_noop_without_challenge
PASSED tests/test_login_flow.py::test_handle_2fa_device_approval_path
PASSED tests/test_login_flow.py::test_find_button_bounds_prefers_exact_button
PASSED tests/test_login_flow.py::test_dismiss_dialogs_walks_onboarding_to_home
PASSED tests/test_login_flow.py::test_dismiss_dialogs_taps_wait_on_anr
PASSED tests/test_proxy_service.py::test_parse_endpoint
PASSED tests/test_proxy_service.py::test_add_and_list
PASSED tests/test_proxy_service.py::test_add_rejects_bad_endpoint
PASSED tests/test_proxy_service.py::test_duplicate_endpoint
PASSED tests/test_proxy_service.py::test_bulk_import
PASSED tests/test_proxy_service.py::test_bulk_import_empty
PASSED tests/test_proxy_service.py::test_bind_to_account
PASSED tests/test_proxy_service.py::test_health_check_closed_port
PASSED tests/test_proxy_service.py::test_tcp_check_localhost_closed
PASSED tests/test_proxy_service.py::test_parse_proxy_url_variants
PASSED tests/test_proxy_service.py::test_parse_proxy_url_rejects_unknown_scheme
PASSED tests/test_proxy_service.py::test_add_proxy_extracts_url_credentials
PASSED tests/test_proxy_service.py::test_add_proxy_rejects_socks4
PASSED tests/test_proxy_service.py::test_add_proxy_explicit_creds_win
PASSED tests/test_proxy_service.py::test_outbound_check_ok
PASSED tests/test_proxy_service.py::test_outbound_check_curl_failure
PASSED tests/test_proxy_service.py::test_outbound_check_non_json
PASSED tests/test_proxy_service.py::test_resolve_instance_http_proxy_socks5_gateway
PASSED tests/test_proxy_service.py::test_resolve_instance_http_proxy_http_direct
PASSED tests/test_proxy_service.py::test_resolve_instance_http_proxy_unbound_default
PASSED tests/test_proxy_service.py::test_http_proxy_for_with_creds
PASSED tests/test_proxy_service.py::test_resolve_egress_local_default
PASSED tests/test_proxy_service.py::test_resolve_egress_direct
PASSED tests/test_proxy_service.py::test_resolve_egress_bound_instance_proxy
PASSED tests/test_proxy_service.py::test_guest_gateway_host_production_default
PASSED tests/test_proxy_service.py::test_resolve_egress_bound_account_fallback
PASSED tests/test_proxy_service.py::test_apply_instance_proxy_hot_switch
PASSED tests/test_proxy_service.py::test_apply_instance_proxy_needs_serial
PASSED tests/test_repository.py::test_create_and_get_account
PASSED tests/test_repository.py::test_duplicate_account_raises
PASSED tests/test_repository.py::test_invalid_platform_raises
PASSED tests/test_repository.py::test_new_platforms_accepted
PASSED tests/test_repository.py::test_status_transition_records_audit
PASSED tests/test_repository.py::test_status_transition_validates_value
PASSED tests/test_repository.py::test_bindings_1to1
PASSED tests/test_repository.py::test_proxy_binding_exclusive
PASSED tests/test_repository.py::test_instance_duplicate_name
PASSED tests/test_repository.py::test_proxy_status_cycle
PASSED tests/test_repository.py::test_sticky_session_roundtrip
PASSED tests/test_repository.py::test_fingerprint_lifecycle
PASSED tests/test_repository.py::test_fingerprint_exclusive
PASSED tests/test_repository.py::test_fingerprint_instance_scoped
PASSED tests/test_repository.py::test_fingerprint_requires_target
PASSED tests/test_repository.py::test_set_instance_proxy_syncs_egress_mode
PASSED tests/test_repository.py::test_login_session_audit_only
PASSED tests/test_repository.py::test_events_never_carry_secrets
PASSED tests/test_repository.py::test_settings_defaults_via_repository
PASSED tests/test_repository.py::test_list_accounts_filter
PASSED tests/test_schema.py::test_migrations_apply_to_latest
PASSED tests/test_schema.py::test_reopen_is_idempotent
PASSED tests/test_schema.py::test_all_tables_exist
PASSED tests/test_schema.py::test_events_index_exists
PASSED tests/test_schema.py::test_wal_mode_enabled
PASSED tests/test_schema.py::test_foreign_keys_enforced
PASSED tests/test_schema.py::test_unique_account_binding
PASSED tests/test_schema.py::test_duplicate_account_identity_rejected
PASSED tests/test_schema.py::test_account_platform_check
PASSED tests/test_schema.py::test_new_platforms_accepted_after_v2
PASSED tests/test_schema.py::test_v2_migration_preserves_rows_and_children
PASSED tests/test_schema.py::test_on_delete_cascade_events
PASSED tests/test_schema.py::test_settings_upsert
PASSED tests/test_schema.py::test_v7_backfills_fingerprint_to_instance
PASSED tests/test_schema.py::test_fingerprint_instance_unique
PASSED tests/test_schema.py::test_egress_mode_column_and_default
PASSED tests/test_socks_gateway.py::test_connector_handshake_and_health
PASSED tests/test_socks_gateway.py::test_connector_connect_refused_raises
PASSED tests/test_socks_gateway.py::test_connector_auth_rejected
PASSED tests/test_socks_gateway.py::test_connector_auth_accepted
PASSED tests/test_socks_gateway.py::test_gateway_connect_tunnel
PASSED tests/test_socks_gateway.py::test_gateway_absolute_form_get
PASSED tests/test_socks_gateway.py::test_gateway_auth_upstream
PASSED tests/test_socks_gateway.py::test_gateway_health
PASSED tests/test_socks_gateway.py::test_gateway_idempotent_start_stop
PASSED tests/test_socks_gateway.py::test_chain_gateway_socks5_upstream_via_http_proxy
PASSED tests/test_socks_gateway.py::test_chain_gateway_http_upstream_with_auth
PASSED tests/test_socks_gateway.py::test_chain_gateway_wrong_upstream_auth_fails
PASSED tests/test_socks_gateway.py::test_chain_gateway_dead_via_fails
PASSED tests/test_state_machine.py::test_valid_transitions[machine0-imported-unbound]
PASSED tests/test_state_machine.py::test_valid_transitions[machine1-unbound-bound]
PASSED tests/test_state_machine.py::test_valid_transitions[machine2-configured-pending_login]
PASSED tests/test_state_machine.py::test_valid_transitions[machine3-logged_in-keep_alive]
PASSED tests/test_state_machine.py::test_valid_transitions[machine4-login_expired-pending_login]
PASSED tests/test_state_machine.py::test_valid_transitions[machine5-keep_alive-disabled]
PASSED tests/test_state_machine.py::test_valid_transitions[machine6-queued-starting]
PASSED tests/test_state_machine.py::test_valid_transitions[machine7-running-proxy_error]
PASSED tests/test_state_machine.py::test_valid_transitions[machine8-running-waiting_manual]
PASSED tests/test_state_machine.py::test_valid_transitions[machine9-logging_in-logged_in]
PASSED tests/test_state_machine.py::test_valid_transitions[machine10-expired-relogging]
PASSED tests/test_state_machine.py::test_valid_transitions[machine11-created-starting]
PASSED tests/test_state_machine.py::test_valid_transitions[machine12-running-stopped]
PASSED tests/test_state_machine.py::test_illegal_or_allowed[machine0-imported-logged_in]
PASSED tests/test_state_machine.py::test_illegal_or_allowed[machine1-disabled-bound]
PASSED tests/test_state_machine.py::test_illegal_or_allowed[machine2-logged_in-imported]
PASSED tests/test_state_machine.py::test_illegal_or_allowed[machine3-unconfigured-running]
PASSED tests/test_state_machine.py::test_illegal_or_allowed[machine4-not_logged_in-keep_alive]
PASSED tests/test_state_machine.py::test_illegal_or_allowed[machine5-archived-running]
PASSED tests/test_state_machine.py::test_illegal_or_allowed[machine6-created-archived]
PASSED tests/test_state_machine.py::test_unknown_machine
PASSED tests/test_state_machine.py::test_account_statuses_sync
PASSED tests/test_totp.py::test_totp_rfc6238_vectors[59-287082]
PASSED tests/test_totp.py::test_totp_rfc6238_vectors[1111111109-081804]
PASSED tests/test_totp.py::test_totp_rfc6238_vectors[1111111111-050471]
PASSED tests/test_totp.py::test_totp_rfc6238_vectors[1234567890-005924]
PASSED tests/test_totp.py::test_totp_rfc6238_vectors[2000000000-279037]
PASSED tests/test_totp.py::test_totp_rfc6238_vectors[20000000000-353130]
PASSED tests/test_totp.py::test_totp_padded_secret
PASSED tests/test_totp.py::test_totp_empty_secret_raises
PASSED tests/test_totp.py::test_render_vars_totp_from_context
PASSED tests/test_totp.py::test_render_vars_totp_missing_secret_raises
PASSED tests/test_totp.py::test_render_vars_username_password
PASSED tests/test_transparent_proxy.py::test_verify_root_false
PASSED tests/test_transparent_proxy.py::test_ca_hash_known_value
PASSED tests/test_transparent_proxy.py::test_inject_redirect_builds_rule
PASSED tests/test_transparent_proxy.py::test_clear_nat_output
PASSED tests/test_transparent_proxy.py::test_render_redsocks_conf
PASSED tests/test_transparent_proxy.py::test_render_iptables_rules
PASSED tests/test_transparent_proxy.py::test_push_verified_raises_on_size_mismatch
PASSED tests/test_transparent_proxy.py::test_render_egress_conf
PASSED tests/test_transparent_proxy.py::test_render_dns_commands
PASSED tests/test_transparent_proxy.py::test_install_dns_rules_idempotent_guarded
PASSED tests/test_transparent_proxy.py::test_uninstall_dns_rules
PASSED tests/test_transparent_proxy.py::test_set_dns_appearance
PASSED tests/test_transparent_proxy.py::test_apply_root_cleanup
PASSED tests/test_ui.py::test_main_window_constructs
PASSED tests/test_ui.py::test_dashboard_columns
PASSED tests/test_ui.py::test_dashboard_set_accounts
PASSED tests/test_ui.py::test_log_handler_redacts_through_ui
PASSED tests/test_ui.py::test_summary_cards
PASSED tests/test_ui.py::test_instance_table_selection
PASSED tests/test_ui.py::test_instance_table_columns_include_remark_clone_disk
PASSED tests/test_ui.py::test_format_bytes
PASSED tests/test_ui.py::test_refresh_dashboard_thread
PASSED tests/test_ui.py::test_dashboard_ip_region_filled
PASSED tests/test_ui.py::test_instance_table_proxy_region
PASSED tests/test_ui.py::test_engine_buttons_toggle
PASSED tests/test_ui.py::test_watchdog_last_scan_summary
PASSED tests/test_ui.py::test_account_table_selection
PASSED tests/test_ui.py::test_account_import_and_bind_flow
PASSED tests/test_ui.py::test_login_flow_entry_present
PASSED tests/test_ui.py::test_login_flow_requires_selection
PASSED tests/test_ui.py::test_login_flow_requires_binding
PASSED tests/test_ui.py::test_login_flow_bound_runs_worker
PASSED tests/test_ui.py::test_fingerprint_result_table
PASSED tests/test_ui.py::test_fingerprint_tab_options_and_result
PASSED tests/test_ui.py::test_fingerprint_tab_lists_unbound_instance
PASSED tests/test_ui.py::test_fingerprint_tab_target_shows_proxy_region
PASSED tests/test_ui.py::test_proxy_table_selection
PASSED tests/test_ui.py::test_proxy_tab_add_bind_check
PASSED tests/test_ui.py::test_pipeline_clone_bar_and_inject_button
PASSED tests/test_update_service.py::test_check_finds_newer_version
PASSED tests/test_update_service.py::test_check_none_when_same_version
PASSED tests/test_update_service.py::test_apply_updates_code_and_preserves_data
PASSED tests/test_update_service.py::test_apply_rejects_out_of_scope
PASSED tests/test_update_service.py::test_apply_backup_then_rollback
PASSED tests/test_window_layout.py::test_empty
PASSED tests/test_window_layout.py::test_single_window_auto_columns_fills_screen
PASSED tests/test_window_layout.py::test_four_windows_auto_2x2
PASSED tests/test_window_layout.py::test_explicit_columns_3
PASSED tests/test_window_layout.py::test_columns_capped_at_count
PASSED tests/test_window_layout.py::test_all_cells_same_size
PASSED tests/test_window_layout.py::test_cells_within_bounds
PASSED tests/test_workers.py::test_submit_returns_payload
PASSED tests/test_workers.py::test_submit_surfaces_exception
PASSED tests/test_workers.py::test_submit_concurrent_tasks_all_finish
PASSED tests/test_workers.py::test_legacy_run_still_works
FAILED tests/test_adb_adapter.py::test_devices_parses - IndexError: list inde...
FAILED tests/test_adb_adapter.py::test_shell_targets_serial - AssertionError:...
FAILED tests/test_adb_adapter.py::test_top_activity_parses - AssertionError: ...
FAILED tests/test_adb_adapter.py::test_proxy_roundtrip - AssertionError: asse...
FAILED tests/test_adb_adapter.py::test_launcher_resolution - AssertionError: ...
FAILED tests/test_adb_adapter.py::test_package_list_filter - AssertionError: ...
FAILED tests/test_adb_adapter.py::test_reverse_builds_command - AssertionErro...
FAILED tests/test_egress_watchdog.py::test_scan_all_skips_offline_instances
FAILED tests/test_egress_watchdog.py::test_scan_all_skips_healthy_instance - ...
FAILED tests/test_egress_watchdog.py::test_scan_all_applies_unhealthy_instance
FAILED tests/test_egress_watchdog.py::test_scan_all_waits_for_boot_completed
FAILED tests/test_egress_watchdog.py::test_scan_all_replays_gps_after_reboot
FAILED tests/test_egress_watchdog.py::test_scan_all_replays_runtime_fields_with_gps
FAILED tests/test_egress_watchdog.py::test_scan_all_uptime_failure_skips_replay
FAILED tests/test_egress_watchdog.py::test_scan_all_reports_gps_replayed - as...
FAILED tests/test_transparent_proxy.py::test_verify_root_true - AssertionErro...
FAILED tests/test_transparent_proxy.py::test_write_conf_pushes_rendered_text
FAILED tests/test_transparent_proxy.py::test_push_verified_tolerates_eof_when_size_matches
FAILED tests/test_transparent_proxy.py::test_set_egress_proxy_installs_chain
FAILED tests/test_transparent_proxy.py::test_set_egress_direct_clears_chain
FAILED tests/test_transparent_proxy.py::test_status_reports_running - assert ...
FAILED tests/test_transparent_proxy.py::test_set_egress_persists_egress_conf_proxy
FAILED tests/test_transparent_proxy.py::test_set_egress_persists_egress_conf_direct
FAILED tests/test_transparent_proxy.py::test_set_egress_direct_uninstalls_dns_rules
24 failed, 344 passed in 78.52s (0:01:18)
