Files
workinf_Blender_Wasm/my-tools/test_wbv2_local.py
mes123456 f3e21c6b98
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
chore: checkpoint web Blender migration source, tools and docs
Accumulated uncommitted work: GHOST Web backend, WebGL/GPU web layer,
web workflow engine and protocol, tooling, docs and task records.
Large generated evidence, user-testing archives, build snapshots and
imported test assets remain untracked.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-11-10 11:18:01 +08:00

116 lines
6.4 KiB
Python

"""Local supervisor regressions; fixtures do not claim Blender coverage."""
import contextlib
import io
import unittest
from unittest.mock import patch
import test_wbv2_autopilot as fixtures
from wbv2_autopilot import sha, write_json
class LocalWorkflowTests(unittest.TestCase):
setUp = fixtures.SupervisorTests.setUp
file = fixtures.SupervisorTests.file
ready_result = fixtures.SupervisorTests.ready_result
def local_contract(self):
self.policy["modelExecution"] = "disabled"
result = self.ready_result(self.runner.directory / "old")
contract_path = "local-contract.json"
self.file("my-tools/wbv2_validation.py", "# fixture\n")
self.policy["localWorkflows"] = {self.job["id"]: contract_path}
contract = {"task": self.task, "job": self.job["id"], "parentSha256": self.context["parentSha256"], "result": result}
write_json(self.root / contract_path, contract)
return contract
def test_local_workflow_never_calls_model_and_writes_fresh_receipts(self):
self.local_contract()
with patch.object(self.runner, "worker", side_effect=AssertionError("model forbidden")), patch.object(self.runner, "worker_prompt", side_effect=AssertionError("prompt forbidden")), contextlib.redirect_stdout(io.StringIO()):
self.assertTrue(self.runner.attempt(self.context, self.job))
self.assertTrue(self.runner.receipt_valid(self.runner.state["jobs"][self.job["id"]]))
self.assertEqual(0, self.runner.state["tokensUsed"])
def test_model_execution_is_denied_at_all_entrypoints(self):
self.policy["modelExecution"] = "disabled"
with self.assertRaisesRegex(ValueError, "disabled"):
self.runner.worker("source", self.runner.directory)
with self.assertRaisesRegex(ValueError, "disabled"):
self.runner.worker_prompt(self.context, self.job, self.runner.directory, {})
with self.assertRaisesRegex(ValueError, "disabled"):
self.runner.run_process(["codex", "exec"], self.root, self.runner.directory / "model.log", 1)
def test_local_contract_cannot_advance_or_change_parent(self):
contract = self.local_contract()
contract["parentSha256"] = "0" * 64
write_json(self.root / "local-contract.json", contract)
with self.assertRaisesRegex(ValueError, "parent changed"):
self.runner.local_result(self.context, self.job, self.runner.directory / "fresh")
def test_scheduler_selects_only_registered_unverified_local_jobs(self):
self.local_contract()
unknown = {"id": "NO-LOCAL-CONTRACT"}
self.assertEqual(self.job, self.runner.choose_job([unknown, self.job]))
self.runner.state["jobs"][self.job["id"]] = {"state": "blocked", "localContractSha256": sha(self.root / "local-contract.json")}
self.assertIsNone(self.runner.choose_job([unknown, self.job]))
def test_local_plan_discovery_and_changed_contract_retry(self):
contract = self.local_contract()
self.policy["localWorkflows"] = {}
location = self.runner.directory / "local-plans" / (self.job["id"] + ".json")
write_json(location, contract)
self.assertEqual(self.job, self.runner.choose_job([self.job]))
self.runner.state["jobs"][self.job["id"]] = {"state": "blocked", "localContractSha256": sha(location)}
self.assertIsNone(self.runner.choose_job([self.job]))
contract["maintenanceRevision"] = 2
write_json(location, contract)
self.assertEqual(self.job, self.runner.choose_job([self.job]))
def test_behavior_pending_does_not_starve_the_next_workflow(self):
contract = self.local_contract()
next_job = {"id": "NEXT-JOB", "ownedPaths": []}
self.policy["localWorkflows"]["NEXT-JOB"] = "next-contract.json"
write_json(self.root / "next-contract.json", {**contract, "job": "NEXT-JOB"})
self.runner.state["jobs"][self.job["id"]] = {
"state": "behavior_pending", "localContractSha256": sha(self.root / "local-contract.json")}
self.assertEqual(next_job, self.runner.choose_job([self.job, next_job]))
contract["revision"] = 2
write_json(self.root / "local-contract.json", contract)
self.assertEqual(self.job, self.runner.choose_job([self.job, next_job]))
def test_model_process_is_denied_even_with_legacy_policy(self):
self.policy["modelExecution"] = "enabled"
with self.assertRaisesRegex(ValueError, "disabled"):
self.runner.run_process(["codex", "exec"], self.root, self.runner.directory / "model.log", 1)
def test_receipt_producer_mismatch_is_reported_before_cache(self):
self.local_contract()
script = (self.root / "check.py").read_text()
self.file("check.py", script.replace("'unitIds': ['operator:TEST']", "'unitIds': ['operator:WRONG']"))
with contextlib.redirect_stdout(io.StringIO()):
self.assertFalse(self.runner.attempt(self.context, self.job))
reason = self.runner.state["jobs"][self.job["id"]]["reason"]
self.assertIn("binding mismatch before cache", reason)
self.assertIn("operator:WRONG", reason)
def test_missing_receipt_names_the_producing_check(self):
self.local_contract()
self.file("check.py", "print('No receipt emitted')\n")
with contextlib.redirect_stdout(io.StringIO()):
self.assertFalse(self.runner.attempt(self.context, self.job))
reason = self.runner.state["jobs"][self.job["id"]]["reason"]
self.assertIn("missing runtime receipt: case=positive check=native", reason)
def test_local_environment_is_applied_and_supervisor_receipts_win(self):
self.local_contract()
contract = self.runner.local_result(self.context, self.job, self.runner.directory / "copy")
contract["checks"][0]["argv"] = ["env", "WEB_TEST_PORT=5297", "WBV2_RECEIPT_DIR=/tmp/stale", "python3", "check.py"]
write_json(self.root / "local-contract.json", {"task": self.task, "job": self.job["id"], "parentSha256": self.context["parentSha256"], "result": contract})
with patch.object(self.runner, "run_process", wraps=self.runner.run_process) as run, contextlib.redirect_stdout(io.StringIO()):
self.assertTrue(self.runner.attempt(self.context, self.job))
self.assertEqual("5297", run.call_args.kwargs["env"]["WEB_TEST_PORT"])
self.assertNotEqual("/tmp/stale", run.call_args.kwargs["env"]["WBV2_RECEIPT_DIR"])
if __name__ == "__main__":
unittest.main()