feat(k1): stabilize LAB bridge and isolate onboard device integration
This commit is contained in:
@@ -5256,11 +5256,14 @@ def test_ble_scan_operation_id_is_exactly_once_and_request_bound(
|
||||
if on_admitted is not None:
|
||||
on_admitted()
|
||||
transport_calls += 1
|
||||
return _ble_scan_result("exactly-once-device")
|
||||
return {
|
||||
**_ble_scan_result("exactly-once-device"),
|
||||
"discovery_timing": {"scan_elapsed_ms": 7100, "scan_extended": True},
|
||||
}
|
||||
|
||||
monkeypatch.setattr(facade_module, "scan", successful_scan)
|
||||
operation_id = "op-00000000-0000-4000-8000-000000000001"
|
||||
request = BleScanRequest(duration_seconds=6.0, operation_id=operation_id)
|
||||
request = BleScanRequest(operation_id=operation_id)
|
||||
|
||||
first = asyncio.run(service.scan_ble(request))
|
||||
repeated = asyncio.run(service.scan_ble(request))
|
||||
@@ -5271,8 +5274,10 @@ def test_ble_scan_operation_id_is_exactly_once_and_request_bound(
|
||||
assert first["last_operation"]["result"] == {
|
||||
"candidate_count": 1,
|
||||
"likely_k1_candidate_count": 1,
|
||||
"duration_seconds": 6.0,
|
||||
"duration_seconds": 20.0,
|
||||
"discovery_generation": 1,
|
||||
"scan_elapsed_ms": 7100,
|
||||
"scan_extended": True,
|
||||
}
|
||||
assert repeated["last_operation"]["operation_id"] == operation_id
|
||||
with pytest.raises(ValueError, match="different request"):
|
||||
@@ -21315,6 +21320,61 @@ def test_network_provisioning_rejects_an_ipv4_owned_by_the_local_host(
|
||||
assert "lab-network" not in caplog.text
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("att_code", "public_code"),
|
||||
[(4, "k1-wifi-network-not-found"), (6, "k1-wifi-credentials-required")],
|
||||
)
|
||||
def test_station_reply_preserves_ambiguity_and_explains_wifi_failure(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
tmp_path: Path,
|
||||
att_code: int,
|
||||
public_code: str,
|
||||
) -> None:
|
||||
from bleak.exc import BleakGATTProtocolError
|
||||
|
||||
service, _ = service_with_fake_runtime(tmp_path)
|
||||
_set_scanned_devices(service, [{"device_id": "k1-a"}])
|
||||
calls = 0
|
||||
|
||||
async def rejected_write(
|
||||
*_: object, on_write_dispatch: Any = None, **__: object,
|
||||
) -> dict[str, Any]:
|
||||
nonlocal calls
|
||||
calls += 1
|
||||
on_write_dispatch(_wifi_status_read(None, device_id="k1-a")["status"], "with_response")
|
||||
exc = BleakGATTProtocolError(att_code)
|
||||
exc.operation_stage = "gatt-write" # type: ignore[attr-defined]
|
||||
exc.device_write_attempted = True # type: ignore[attr-defined]
|
||||
exc.device_write_confirmed = False # type: ignore[attr-defined]
|
||||
exc.att_error_code = att_code # type: ignore[attr-defined]
|
||||
exc.att_error_name = exc.code.name # type: ignore[attr-defined]
|
||||
exc.resolved_write_mode = "with_response" # type: ignore[attr-defined]
|
||||
exc.frame_length = 99 # type: ignore[attr-defined]
|
||||
raise exc
|
||||
|
||||
monkeypatch.setattr(facade_module, "provision_wifi_once", rejected_write)
|
||||
with pytest.raises(BleakGATTProtocolError):
|
||||
asyncio.run(service.connect(_connect_request(
|
||||
device_id="k1-a", ssid="lab-network",
|
||||
password=SecretStr(PRIMARY_TEST_CREDENTIAL),
|
||||
compatibility_attestation=ATTESTATION,
|
||||
idempotency_key="explicit-station-rejection",
|
||||
)))
|
||||
state = service.state()
|
||||
operation = next(item for item in state["operations"] if item["action"] == "network.provision")
|
||||
error = operation["error"]
|
||||
assert calls == 1
|
||||
assert operation["status"] == "failed"
|
||||
assert error["code"] == public_code
|
||||
assert error["transport_error_code"] == "BleakGATTProtocolError"
|
||||
assert error["ble_att_error_code"] == att_code
|
||||
assert error["safe_to_retry"] is False
|
||||
assert error["device_write_confirmed"] is False
|
||||
assert error["side_effect_status"] == "unknown"
|
||||
assert state["connection_attempt"]["public_error_code"] == public_code
|
||||
assert state["network_mutation_ledger"]["status"] == "unresolved"
|
||||
|
||||
|
||||
def test_ambiguous_ble_write_is_audit_only_for_next_explicit_intent(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
tmp_path: Path,
|
||||
|
||||
Reference in New Issue
Block a user