Harden RF node control and agent updates

This commit is contained in:
LittleSam129
2026-09-30 11:42:19 +03:00
parent a94f2db4ee
commit 0d6fff224e
34 changed files with 14010 additions and 0 deletions

View File

@@ -0,0 +1,824 @@
"""Software-only tests for the fixed-command RX HTTP agent."""
from __future__ import annotations
import argparse
from datetime import datetime, timedelta, timezone
import hashlib
import json
from pathlib import Path
import shutil
from typing import Sequence
import pytest
import tools.rf001_agent_update as update_module
import tools.rf001_rx_http_agent as agent_module
from tools.rf001_http_control import PROTOCOL_VERSION, ProtocolError
from tools.rf001_rx_http_agent import (
CommandResult,
collect_inventory,
execute_task,
normalized_agent_id,
read_git_metadata,
)
def fake_runner(arguments: Sequence[str], timeout: float) -> CommandResult:
del timeout
command = list(arguments)
if command == ["hostname"]:
stdout = "User-PC"
elif command == ["whoami"]:
stdout = "user-pc\\professional"
elif command[0] == "git":
stdout = "fake-git-read-only-result"
elif command[0].lower().endswith("hackrf_info.exe"):
stdout = "hackrf_info version: 2024.02.1"
else: # pragma: no cover - protects the test allowlist
raise AssertionError(f"unexpected command: {command}")
return CommandResult(command, 0, stdout, "")
def test_agent_id_is_normalized_without_shell_content() -> None:
assert normalized_agent_id("User-PC") == "user-pc"
assert normalized_agent_id(" RX Laptop! ") == "rx-laptop"
def test_inventory_runs_only_fixed_read_only_commands(tmp_path: Path) -> None:
repository = tmp_path / "repo"
repository.mkdir()
hackrf_info = tmp_path / "hackrf_info.exe"
hackrf_info.write_bytes(b"")
inventory, errors = collect_inventory(
repository,
include_hackrf_info=True,
hackrf_info_path=hackrf_info,
command_runner=fake_runner,
)
assert errors == []
assert inventory["rf_tx"] == 0
assert inventory["hostname_command"]["stdout"] == "User-PC"
assert inventory["whoami_command"]["stdout"] == "user-pc\\professional"
assert inventory["hackrf_info"]["executed"] is True
assert inventory["hackrf_info"]["rf_tx"] == 0
def test_agent_rejects_unknown_task_and_rf_tx(tmp_path: Path) -> None:
base_task: dict[str, object] = {
"protocol_version": PROTOCOL_VERSION,
"task_id": "INVENTORY_TEST_001",
"kind": "INVENTORY",
"agent_id": "rx-user-pc",
"created_at": "2026-09-23T00:00:00+00:00",
"include_hackrf_info": False,
"rf_tx": 0,
}
unknown = dict(base_task)
unknown["kind"] = "SHELL"
with pytest.raises(ProtocolError, match="unsupported task kind"):
execute_task(
unknown,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
command_runner=fake_runner,
)
transmit = dict(base_task)
transmit["rf_tx"] = 1
with pytest.raises(ProtocolError, match="rf_tx = 0"):
execute_task(
transmit,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
command_runner=fake_runner,
)
def test_agent_dispatches_fixed_capture_diagnostics_without_hardware(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
calls: list[tuple[Path, str, str, str]] = []
def diagnostics(
work_root: Path,
session_id: str,
tx_started_at: str,
tx_finished_at: str,
) -> tuple[dict[str, object], list[str]]:
calls.append((work_root, session_id, tx_started_at, tx_finished_at))
return {
"session_id": session_id,
"hardware_accessed": False,
"rf_tx": 0,
"report": {"detected_preambles": 0},
}, []
monkeypatch.setattr(agent_module, "read_capture_diagnostics", diagnostics)
session_id = "RF001A_20260925T104504Z_5FA2C83B"
task = {
"protocol_version": PROTOCOL_VERSION,
"task_id": "DIAG_TEST_001",
"kind": "CAPTURE_DIAGNOSTICS",
"agent_id": "rx-user-pc",
"created_at": "2026-09-25T10:51:00+00:00",
"session_id": session_id,
"tx_started_at": "2026-09-25T10:46:54+00:00",
"tx_finished_at": "2026-09-25T10:46:56+00:00",
"rf_tx": 0,
}
result = execute_task(
task,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
work_root=tmp_path / "runtime",
command_runner=fake_runner,
)
assert result["status"] == "COMPLETE"
assert result["result"]["hardware_accessed"] is False
assert result["rf_tx"] == 0
assert calls == [
(
tmp_path / "runtime",
session_id,
"2026-09-25T10:46:54+00:00",
"2026-09-25T10:46:56+00:00",
)
]
def _write_git_metadata(repository: Path, head: str) -> None:
git_dir = repository / ".git"
ref = git_dir / "refs" / "heads" / "video-development"
ref.parent.mkdir(parents=True)
(git_dir / "HEAD").write_text(
"ref: refs/heads/video-development\n",
encoding="ascii",
)
ref.write_text(head + "\n", encoding="ascii")
def test_read_git_metadata_without_git_executable(tmp_path: Path) -> None:
repository = tmp_path / "repo"
repository.mkdir()
head = "a94f2db4ee8377201a97263166cb09431df5f5d6"
_write_git_metadata(repository, head)
metadata = read_git_metadata(repository)
assert metadata["branch"] == "video-development"
assert metadata["head"] == head
assert metadata["status"] == "NOT_RUN_NO_GIT_EXECUTABLE"
def test_read_git_metadata_from_linked_worktree(tmp_path: Path) -> None:
repository = tmp_path / "worktree"
repository.mkdir()
common = tmp_path / "main.git"
worktree_git = common / "worktrees" / "worktree"
worktree_git.mkdir(parents=True)
(repository / ".git").write_text(
f"gitdir: {worktree_git}\n",
encoding="utf-8",
)
(worktree_git / "commondir").write_text("../..\n", encoding="ascii")
(worktree_git / "HEAD").write_text(
"ref: refs/heads/video-development\n",
encoding="ascii",
)
head = "a94f2db4ee8377201a97263166cb09431df5f5d6"
ref = common / "refs" / "heads" / "video-development"
ref.parent.mkdir(parents=True)
ref.write_text(head + "\n", encoding="ascii")
metadata = read_git_metadata(repository)
assert metadata["git_dir"] == str(worktree_git.resolve())
assert metadata["common_dir"] == str(common.resolve())
assert metadata["branch"] == "video-development"
assert metadata["head"] == head
def test_offline_verify_is_fixed_software_only_task(tmp_path: Path) -> None:
repository = tmp_path / "repo"
repository.mkdir()
head = "a94f2db4ee8377201a97263166cb09431df5f5d6"
_write_git_metadata(repository, head)
(repository / "tools").mkdir()
(repository / "configs" / "rf").mkdir(parents=True)
for relative in (
Path("tools/rf001a_prepare.py"),
Path("tools/qpsk_rf_rx.py"),
Path("configs/rf/rf001a_truth_metadata.json"),
):
(repository / relative).write_text("fixture\n", encoding="utf-8")
commands: list[list[str]] = []
def offline_runner(arguments: Sequence[str], timeout: float) -> CommandResult:
del timeout
command = list(arguments)
commands.append(command)
if "rf001a_prepare.py" in command[4]:
output = Path(command[command.index("--output-dir") + 1])
output.mkdir()
(output / "tx_waveform.cs8").write_bytes(b"fixture")
(output / "tx_metadata.json").write_text("{}", encoding="utf-8")
elif "rf001_offline_decode.py" in command[4]:
report = Path(command[command.index("--report") + 1])
report.write_text(
'{"crc_valid_packets": 100, "exact_packets": 100}',
encoding="utf-8",
)
else: # pragma: no cover - protects the fixed command contract
raise AssertionError(command)
return CommandResult(command, 0, "PASS", "")
task = {
"protocol_version": PROTOCOL_VERSION,
"task_id": "OFFLINE_TEST_001",
"kind": "OFFLINE_VERIFY",
"agent_id": "rx-user-pc",
"created_at": "2026-09-23T00:00:00+00:00",
"expected_head": head,
"rf_tx": 0,
}
result = execute_task(
task,
agent_id="rx-user-pc",
repository=repository,
hackrf_info_path=None,
work_root=tmp_path / "runtime",
command_runner=offline_runner,
)
assert result["status"] == "COMPLETE"
assert result["result"]["hardware_accessed"] is False
assert result["result"]["crc_valid_packets"] == 100
assert result["result"]["exact_packets"] == 100
assert "--repository" in commands[1]
assert all("hackrf" not in Path(command[0]).name.lower() for command in commands)
assert all("-t" not in command for command in commands)
assert result["rf_tx"] == 0
def _sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def _staircase_fixture(
tmp_path: Path,
) -> tuple[Path, dict[str, object], Path, Path]:
work_root = tmp_path / "runtime"
session_id = "RF001A_20260925T125829Z_227EADB4"
session_directory = work_root / "rx_capture" / session_id
session_directory.mkdir(parents=True)
capture = session_directory / "rf001a_ota_capture.cs8"
capture.write_bytes(b"fixed-rx-capture")
reference = work_root / "references" / "lab065_reference_staircase.cs8"
reference.parent.mkdir(parents=True)
reference.write_bytes(b"fixed-staircase-reference")
task: dict[str, object] = {
"protocol_version": PROTOCOL_VERSION,
"task_id": "STAIRCASE_TEST_001",
"kind": "STAIRCASE_SEARCH",
"agent_id": "rx-user-pc",
"created_at": "2026-09-28T12:00:00+00:00",
"session_id": session_id,
"expected_rx_sha256": _sha256(capture),
"expected_reference_sha256": _sha256(reference),
"hardware_accessed": False,
"automatic_retry": False,
"rf_tx": 0,
}
return work_root, task, capture, reference
def _write_staircase_report(arguments: Sequence[str]) -> Path:
command = list(arguments)
report_path = Path(command[command.index("--report") + 1])
report = {
"analyzer_version": "test",
"mode": "OFFLINE_REFERENCE_STAIRCASE_SEARCH",
"capture_sha256": command[command.index("--capture-sha256") + 1],
"reference_sha256": _sha256(
Path(command[command.index("--reference") + 1])
),
"search": {
"coverage_start_sample": 0,
"coverage_stop_sample": 8,
"coverage_seconds": 0.000001,
"coverage_complete": True,
"source_samples_processed": 8,
"frequency_grid_hz": [-3.0, 0.0, 3.0],
"background_score_p99": 0.01,
"candidates": [],
},
"verifications": [],
"verdict": "NOT_DETECTED",
"verdict_reasons": ["NO_CANDIDATES"],
"analysis_seconds": 1.25,
"peak_process_memory_bytes": 1234,
"peak_additional_memory_bytes": 456,
"hardware_accessed": False,
"rf_tx": 0,
}
report_path.write_text(json.dumps(report), encoding="utf-8")
return report_path
def test_staircase_task_rejects_invalid_session_and_hashes(tmp_path: Path) -> None:
work_root, task, _capture, _reference = _staircase_fixture(tmp_path)
invalid_session = dict(task, session_id="..\\outside")
with pytest.raises(ProtocolError, match="session_id"):
execute_task(
invalid_session,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
work_root=work_root,
)
for field in ("expected_rx_sha256", "expected_reference_sha256"):
invalid_hash = dict(task)
invalid_hash[field] = "invalid"
with pytest.raises(ProtocolError, match=field):
execute_task(
invalid_hash,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
work_root=work_root,
)
def test_staircase_hash_mismatch_does_not_start_child(tmp_path: Path) -> None:
work_root, task, _capture, _reference = _staircase_fixture(tmp_path)
calls: list[list[str]] = []
def forbidden_runner(arguments: Sequence[str], timeout: float) -> CommandResult:
del timeout
calls.append(list(arguments))
raise AssertionError("child process must not run after a hash mismatch")
for field in ("expected_rx_sha256", "expected_reference_sha256"):
changed = dict(task)
changed[field] = "0" * 64
result = execute_task(
changed,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
work_root=work_root,
command_runner=forbidden_runner,
)
assert result["status"] == "FAILED"
assert result["result"]["reference_detection"] == "EXECUTION_FAILED"
assert calls == []
def test_staircase_repeat_reuses_existing_report_without_child(
tmp_path: Path,
) -> None:
work_root, task, _capture, _reference = _staircase_fixture(tmp_path)
calls: list[list[str]] = []
def analyzer_runner(arguments: Sequence[str], timeout: float) -> CommandResult:
assert timeout == 43_200.0
calls.append(list(arguments))
_write_staircase_report(arguments)
assert "hackrf" not in " ".join(arguments).lower()
return CommandResult(list(arguments), 0, "REFERENCE STAIRCASE = NOT_DETECTED", "")
first = execute_task(
task,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
work_root=work_root,
command_runner=analyzer_runner,
)
second = execute_task(
task,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
work_root=work_root,
command_runner=lambda *_args: (_ for _ in ()).throw(
AssertionError("existing report must not start another child")
),
)
assert first["status"] == "COMPLETE"
assert first["result"]["hardware_accessed"] is False
assert first["result"]["rf_tx"] == 0
assert first["result"]["reused_existing_report"] is False
assert second["status"] == "COMPLETE"
assert second["result"]["reused_existing_report"] is True
assert len(calls) == 1
def test_staircase_child_failure_is_execution_failed(tmp_path: Path) -> None:
work_root, task, _capture, _reference = _staircase_fixture(tmp_path)
def failed_runner(arguments: Sequence[str], timeout: float) -> CommandResult:
del timeout
return CommandResult(list(arguments), 9, "", "fixed failure")
result = execute_task(
task,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
work_root=work_root,
command_runner=failed_runner,
)
assert result["status"] == "FAILED"
assert result["result"]["reference_detection"] == "EXECUTION_FAILED"
assert result["result"]["hardware_accessed"] is False
assert result["result"]["rf_tx"] == 0
assert "exited with 9" in result["errors"][0]
def _update_fixture(
tmp_path: Path,
) -> tuple[
Path,
bytes,
dict[str, object],
dict[str, object],
argparse.Namespace,
]:
source = tmp_path / "source"
for index, relative in enumerate(update_module.RELEASE_SOURCE_FILES.values()):
path = source / relative
path.parent.mkdir(parents=True, exist_ok=True)
content = f"# fixed update fixture {index}\n"
if relative == update_module.RELEASE_SOURCE_FILES[
"app/tools/rf001_rx_http_agent.py"
]:
content += 'AGENT_VERSION = "2026.09.29.2"\n'
path.write_text(content, encoding="utf-8")
release_id = "rf001-agent-2026.09.29.2"
package = tmp_path / f"{release_id}.zip"
inspection = update_module.build_release_archive(
source,
package,
release_id=release_id,
agent_version="2026.09.29.2",
protocol_version=PROTOCOL_VERSION,
)
manifest: dict[str, object] = {
**inspection.descriptor(),
"package_kind": "AGENT_RELEASE",
}
token = b"fixed-test-token-0123456789abcdef"
task: dict[str, object] = {
"protocol_version": PROTOCOL_VERSION,
"task_id": "UPDATE_TEST_001",
"kind": "UPDATE_AGENT",
"agent_id": "rx-user-pc",
"created_at": datetime.now(timezone.utc).isoformat(),
"release_id": release_id,
"agent_version": "2026.09.29.2",
"package_sha256": inspection.package_sha256,
"package_bytes": inspection.package_bytes,
"content_manifest_sha256": inspection.content_manifest_sha256,
"compatible_protocol_version": PROTOCOL_VERSION,
"approval_expires_at": (
datetime.now(timezone.utc) + timedelta(hours=1)
).isoformat(),
"automatic_retry": False,
"hardware_accessed": False,
"rf_tx": 0,
}
install_root = tmp_path / "install"
install_root.mkdir()
launcher_status = install_root / "launcher_status.json"
launcher_status.write_text(
json.dumps(
{
"active_release_id": "rf001-agent-2026.09.29.1",
"active_agent_version": "2026.09.29.1",
"rf_tx": 0,
}
),
encoding="utf-8",
)
arguments = argparse.Namespace(
agent_id="rx-user-pc",
server="http://127.0.0.1:8765",
timeout=1.0,
install_root=install_root,
launcher_request=install_root / "launcher_request.json",
launcher_status=launcher_status,
release_id="rf001-agent-2026.09.29.1",
)
return package, token, task, manifest, arguments
def _successful_self_test(
arguments: Sequence[str], timeout: float
) -> CommandResult:
assert timeout == 120.0
assert "hackrf" not in " ".join(arguments).lower()
return CommandResult(list(arguments), 0, "SELF TEST = PASS", "")
def test_agent_stages_authenticated_update_and_reuses_it(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
package, token, task, manifest, arguments = _update_fixture(tmp_path)
downloads: list[Path] = []
monkeypatch.setattr(
agent_module,
"request_json",
lambda *_args, **_kwargs: {
"manifest": manifest,
"manifest_signature": update_module.sign_update_manifest(token, manifest),
},
)
def download(
_server: str,
_token: bytes,
_target: str,
destination: Path,
**_kwargs: object,
) -> None:
downloads.append(destination)
shutil.copyfile(package, destination)
monkeypatch.setattr(agent_module, "request_file", download)
result, errors, request = agent_module.stage_agent_update(
task,
arguments=arguments,
token=token,
command_runner=_successful_self_test,
)
assert errors == []
assert result["update_status"] == "STAGED"
assert result["hardware_accessed"] is False
assert result["rf_tx"] == 0
assert request is not None
assert len(downloads) == 1
result, errors, repeated_request = agent_module.stage_agent_update(
task,
arguments=arguments,
token=token,
command_runner=lambda *_args: (_ for _ in ()).throw(
AssertionError("an already staged release must not run again")
),
)
assert errors == []
assert result["update_status"] == "ALREADY_STAGED"
assert repeated_request is not None
assert {
key: value
for key, value in repeated_request.items()
if key != "requested_at"
} == {key: value for key, value in request.items() if key != "requested_at"}
assert len(downloads) == 1
def test_agent_rejects_bad_update_signature_sha_and_protocol(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
_package, token, task, manifest, arguments = _update_fixture(tmp_path)
network_downloads: list[str] = []
monkeypatch.setattr(
agent_module,
"request_json",
lambda *_args, **_kwargs: {
"manifest": manifest,
"manifest_signature": "0" * 64,
},
)
monkeypatch.setattr(
agent_module,
"request_file",
lambda *_args, **_kwargs: network_downloads.append("called"),
)
result, errors, request = agent_module.stage_agent_update(
task,
arguments=arguments,
token=token,
command_runner=_successful_self_test,
)
assert result["update_status"] == "EXECUTION_FAILED"
assert any("signature mismatch" in error for error in errors)
assert request is None
assert network_downloads == []
incompatible = dict(task, compatible_protocol_version=PROTOCOL_VERSION + 1)
_result, errors, _request = agent_module.stage_agent_update(
incompatible,
arguments=arguments,
token=token,
command_runner=_successful_self_test,
)
assert any("incompatible" in error for error in errors)
changed_sha = dict(task, package_sha256="0" * 64)
signed = update_module.sign_update_manifest(token, manifest)
monkeypatch.setattr(
agent_module,
"request_json",
lambda *_args, **_kwargs: {
"manifest": manifest,
"manifest_signature": signed,
},
)
_result, errors, _request = agent_module.stage_agent_update(
changed_sha,
arguments=arguments,
token=token,
command_runner=_successful_self_test,
)
assert any("field mismatch: package_sha256" in error for error in errors)
assert network_downloads == []
def test_agent_retries_one_interrupted_download_then_stages(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
package, token, task, manifest, arguments = _update_fixture(tmp_path)
monkeypatch.setattr(
agent_module,
"request_json",
lambda *_args, **_kwargs: {
"manifest": manifest,
"manifest_signature": update_module.sign_update_manifest(token, manifest),
},
)
calls = 0
def interrupted_then_complete(
_server: str,
_token: bytes,
_target: str,
destination: Path,
**_kwargs: object,
) -> None:
nonlocal calls
calls += 1
if calls == 1:
destination.write_bytes(b"partial")
raise OSError("fixed interrupted transfer")
shutil.copyfile(package, destination)
monkeypatch.setattr(agent_module, "request_file", interrupted_then_complete)
result, errors, request = agent_module.stage_agent_update(
task,
arguments=arguments,
token=token,
command_runner=_successful_self_test,
)
assert errors == []
assert result["update_status"] == "STAGED"
assert request is not None
assert calls == 2
state = json.loads(
(
arguments.install_root
/ "staging"
/ str(task["task_id"])
/ "download_state.json"
).read_text(encoding="utf-8")
)
assert state["network_attempts"] == 2
def test_agent_does_not_exceed_persisted_download_attempt_limit(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
_package, token, task, manifest, arguments = _update_fixture(tmp_path)
monkeypatch.setattr(
agent_module,
"request_json",
lambda *_args, **_kwargs: {
"manifest": manifest,
"manifest_signature": update_module.sign_update_manifest(token, manifest),
},
)
calls = 0
def always_interrupted(*_args: object, **_kwargs: object) -> None:
nonlocal calls
calls += 1
raise OSError("fixed interrupted transfer")
monkeypatch.setattr(agent_module, "request_file", always_interrupted)
for _ in range(2):
result, errors, request = agent_module.stage_agent_update(
task,
arguments=arguments,
token=token,
command_runner=_successful_self_test,
)
assert result["update_status"] == "EXECUTION_FAILED"
assert errors
assert request is None
assert calls == 2
def test_agent_restart_does_not_duplicate_background_analyzer(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
work_root, task, _capture, _reference = _staircase_fixture(tmp_path)
starts: list[list[str]] = []
class FakeProcess:
pid = 4242
def fake_popen(arguments: Sequence[str], **_kwargs: object) -> FakeProcess:
starts.append(list(arguments))
return FakeProcess()
monkeypatch.setattr(agent_module.subprocess, "Popen", fake_popen)
pointer = agent_module.start_staircase_background_job(
task,
agent_id="rx-user-pc",
work_root=work_root,
)
assert pointer["pid"] == 4242
with pytest.raises(RuntimeError, match="already active"):
agent_module.start_staircase_background_job(
task,
agent_id="rx-user-pc",
work_root=work_root,
)
assert len(starts) == 1
assert pointer["hardware_accessed"] is False
assert pointer["rf_tx"] == 0
def test_completed_background_result_survives_network_loss(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
work_root, task, _capture, _reference = _staircase_fixture(tmp_path)
directory = work_root / "agent_jobs" / str(task["task_id"])
directory.mkdir(parents=True)
pointer = {
"schema_version": 1,
"task": task,
"pid": 999999,
"started_at": datetime.now(timezone.utc).isoformat(),
"automatic_retry": False,
"hardware_accessed": False,
"rf_tx": 0,
}
agent_module.atomic_write_json(
work_root / "agent_jobs" / "active_job.json", pointer
)
result = {
"protocol_version": PROTOCOL_VERSION,
"task_id": task["task_id"],
"agent_id": "rx-user-pc",
"status": "COMPLETE",
"result": {"hardware_accessed": False, "rf_tx": 0},
"errors": [],
"rf_tx": 0,
}
agent_module.atomic_write_json(directory / "result.json", result)
arguments = argparse.Namespace(
work_root=work_root,
server="http://127.0.0.1:8765",
timeout=1.0,
)
monkeypatch.setattr(
agent_module,
"request_json",
lambda *_args, **_kwargs: (_ for _ in ()).throw(
OSError("fixed network loss")
),
)
with pytest.raises(OSError, match="network loss"):
agent_module.deliver_background_result(arguments, b"token", pointer)
assert (work_root / "agent_jobs" / "active_job.json").is_file()
assert (directory / "result.json").is_file()
monkeypatch.setattr(
agent_module,
"request_json",
lambda *_args, **_kwargs: {"accepted": True, "rf_tx": 0},
)
assert agent_module.deliver_background_result(arguments, b"token", pointer)
assert not (work_root / "agent_jobs" / "active_job.json").exists()
assert (directory / "delivered_job.json").is_file()
assert (directory / "result.json").is_file()