refactor: unify impl operation gates and correction verification
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
"""Regression tests for main-owned rework publication integration."""
|
||||
import copy
|
||||
import hashlib
|
||||
import sys
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest.mock import Mock
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
SCRIPT = ROOT / "agents/impl/skills/gitea-issue-rework/scripts"
|
||||
sys.path.insert(0, str(SCRIPT))
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
import rework_publication as pub
|
||||
from harness.lib import impl_operation as ops
|
||||
|
||||
HEAD = "a" * 40
|
||||
|
||||
def expected():
|
||||
# Generate through the canonical renderer to avoid hand-authored bodies.
|
||||
import rework_comment as rc
|
||||
d = dict(owner="o", repository="r", issue=4, pr=5, review=6,
|
||||
reviewed_head="b"*40, final_head=HEAD, contract_sha256="c"*64,
|
||||
result="partial", findings=[dict(id="F1", status="resolved", classification="valid_fix",
|
||||
changes="changed safely", verification="checks pass", reason="verified")],
|
||||
local_checks="pass", runtime_browser="not run", commit_status="없음", actions_runs="없음")
|
||||
dd, vals, fs, extras, cs, ar = rc.canon(d)
|
||||
body = rc.render_body(dd, vals, fs, extras, cs, ar)
|
||||
rh = hashlib.sha256(body.encode()).hexdigest()
|
||||
corr = hashlib.sha256("\0".join(["o", "r", "4", "5", "6", "b"*40, HEAD, "c"*64]).encode()).hexdigest()
|
||||
marker = f"<!-- gitea-agent:implementation-rework/v1 owner=o repository=r issue=4 pr=5 review=6 reviewed-head={'b'*40} head={HEAD} contract-sha256={'c'*64} result-sha256={rh} correlation={corr} -->\n"
|
||||
return dict(body=body+marker, marker=marker, marker_free_body=body, result_sha256=rh, correlation=corr,
|
||||
target=dict(owner="o", repository="r", issue=4, pr=5), review=6,
|
||||
reviewed_head="b"*40, head=HEAD, contract_sha256="c"*64)
|
||||
|
||||
def setup_case(op="comment.create", payload=None, approval_flags=None):
|
||||
if payload is None:
|
||||
e=expected(); payload={"expected":e,"target":e["target"]}
|
||||
intent=ops.Intent("v1", op, "o/r", 5, HEAD, payload)
|
||||
approval=ops.Approval("v1", intent.digest, "approved", **(approval_flags or {}))
|
||||
declaration={"mode":"none"}
|
||||
calls=[]
|
||||
adapter=ops.Adapter(preflight=lambda i: {"fresh":True,"scope":"exact"}, capability=True,
|
||||
mutate=lambda i: calls.append(copy.deepcopy(i)) or {"acknowledgement":"ok"},
|
||||
readback=lambda i: {"scope":"exact","head":HEAD}, verify=lambda i,p,o: True)
|
||||
return intent,approval,declaration,calls,adapter
|
||||
|
||||
class PublicationTests(unittest.TestCase):
|
||||
def test_entrypoint_is_present_not_import_error(self):
|
||||
self.assertTrue(callable(getattr(pub,"execute_rework_operation",None)))
|
||||
|
||||
def test_invalid_body_target_head_approval_do_not_write(self):
|
||||
cases=[]
|
||||
cases.append(setup_case("pr.patch", {"body":"body", "closing":"#4"}))
|
||||
cases.append(setup_case("comment.create", {"expected":expected(),"target":{"owner":"evil","repository":"r","issue":4,"pr":5}}))
|
||||
p={"head":"f"*40}; cases.append(setup_case("push",p))
|
||||
for intent,approval,decl,calls,adapter in cases:
|
||||
with self.subTest(intent=intent.operation), self.assertRaises(Exception):
|
||||
pub.execute_rework_operation(adapter,intent=intent,approval=approval,declaration=decl,
|
||||
coordinator=ops.Coordinator(),on_attempt=lambda x:None)
|
||||
self.assertEqual(calls,[])
|
||||
|
||||
def test_single_mutation_and_fresh_adoption_at_boundary(self):
|
||||
intent,approval,decl,calls,adapter=setup_case()
|
||||
old=pub.require_adoption
|
||||
try:
|
||||
adopted=Mock(return_value=None); pub.require_adoption=adopted
|
||||
attempts=[]
|
||||
result=pub.execute_rework_operation(adapter,intent=intent,approval=approval,declaration=decl,
|
||||
coordinator=ops.Coordinator(),on_attempt=attempts.append)
|
||||
self.assertEqual(result.status,"verified")
|
||||
self.assertEqual(len(calls),1); self.assertEqual(len(attempts),1)
|
||||
adopted.assert_called_once()
|
||||
finally: pub.require_adoption=old
|
||||
|
||||
def test_adoption_and_preflight_failure_have_zero_mutations(self):
|
||||
intent,approval,decl,calls,adapter=setup_case()
|
||||
old=pub.require_adoption
|
||||
try:
|
||||
pub.require_adoption=Mock(side_effect=ValueError("stale"))
|
||||
r=pub.execute_rework_operation(adapter,intent=intent,approval=approval,declaration=decl,
|
||||
coordinator=ops.Coordinator(),on_attempt=lambda x:None)
|
||||
self.assertEqual(r.status,"partial"); self.assertEqual(calls,[])
|
||||
adapter.preflight=lambda i: {"fresh":False}
|
||||
r=pub.execute_rework_operation(adapter,intent=intent,approval=approval,declaration=decl,
|
||||
coordinator=ops.Coordinator(),on_attempt=lambda x:None)
|
||||
self.assertEqual(r.status,"partial"); self.assertEqual(calls,[])
|
||||
finally: pub.require_adoption=old
|
||||
|
||||
def test_uncertain_ack_readback_once_literal_true_required(self):
|
||||
intent,approval,decl,calls,adapter=setup_case()
|
||||
old=pub.require_adoption
|
||||
try:
|
||||
pub.require_adoption=Mock(return_value=None)
|
||||
mutations=[]; reads=[]
|
||||
adapter.mutate=lambda i: mutations.append(i) or (_ for _ in ()).throw(ops.UncertainAcknowledgement())
|
||||
adapter.readback=lambda i: reads.append(i) or {"head":HEAD}
|
||||
adapter.verify=lambda i,p,o: 1
|
||||
result=pub.execute_rework_operation(adapter,intent=intent,approval=approval,declaration=decl,
|
||||
coordinator=ops.Coordinator(),on_attempt=lambda x:None)
|
||||
self.assertEqual(result.status,"partial")
|
||||
self.assertEqual((len(mutations),len(reads)),(1,1))
|
||||
finally: pub.require_adoption=old
|
||||
|
||||
def test_reuse_collects_fresh_state_without_any_mutation(self):
|
||||
intent, approval, declaration, calls, adapter = setup_case()
|
||||
reads = []
|
||||
adapter.preflight = lambda value: reads.append("preflight") or {"fresh":True}
|
||||
adapter.readback = lambda value: reads.append("readback") or {"exact":True}
|
||||
adapter.verify_reuse = lambda value, before, after: after.get("exact") is True
|
||||
result = pub.verify_rework_reuse(adapter,intent=intent,approval=approval,declaration=declaration)
|
||||
self.assertEqual(result['action'],'reuse')
|
||||
self.assertEqual(reads,['preflight','readback'])
|
||||
self.assertEqual(calls,[])
|
||||
|
||||
def test_reuse_stale_preflight_blocks_even_when_callback_would_accept(self):
|
||||
intent, approval, declaration, calls, adapter = setup_case()
|
||||
reads=[]
|
||||
adapter.preflight=lambda value:{"fresh":False}
|
||||
adapter.readback=lambda value:reads.append(True)
|
||||
adapter.verify_reuse=lambda *args:True
|
||||
with self.assertRaises(ValueError):
|
||||
pub.verify_rework_reuse(adapter,intent=intent,approval=approval,declaration=declaration)
|
||||
self.assertEqual(reads,[])
|
||||
self.assertEqual(calls,[])
|
||||
|
||||
def test_canonical_comment_cannot_publish_to_different_intent_scope(self):
|
||||
intent, approval, declaration, calls, adapter = setup_case()
|
||||
for target, target_id in [('evil/r', 5), ('o/r', 999)]:
|
||||
changed = ops.Intent('v1', intent.operation, target, target_id, HEAD, intent.payload)
|
||||
approved = ops.Approval('v1', changed.digest, 'approved')
|
||||
with self.subTest(target=target, target_id=target_id), self.assertRaises(ValueError):
|
||||
pub.execute_rework_operation(adapter,intent=changed,approval=approved,declaration=declaration,
|
||||
coordinator=ops.Coordinator(),on_attempt=lambda record:None)
|
||||
self.assertEqual(calls, [])
|
||||
|
||||
def test_unimplemented_client_cas_correction_blocks_before_write(self):
|
||||
import rework_comment as rc
|
||||
new = expected()
|
||||
old = copy.deepcopy(new)
|
||||
body = new['marker_free_body']
|
||||
for label in ('Source Issue','Pull Request','Source Review'):
|
||||
body = body.replace('- '+label+': ','- '+label+': #')
|
||||
digest = hashlib.sha256(body.encode()).hexdigest()
|
||||
marker = new['marker'].replace(new['result_sha256'],digest)
|
||||
old.update(body=body+marker,marker=marker,marker_free_body=body,result_sha256=digest)
|
||||
payload = {'old_expected':old,'new_expected':new,'comment_id':7,'actor_id':42}
|
||||
intent = ops.Intent('v1','correction','o/r',7,HEAD,payload)
|
||||
approval = ops.Approval('v1',intent.digest,'approved',correction=True)
|
||||
calls = []
|
||||
adapter = ops.Adapter(lambda value:{'fresh':True},True,
|
||||
lambda value:calls.append('write'),lambda value:{'exact':True},lambda *args:True)
|
||||
with self.assertRaises(ValueError):
|
||||
pub.execute_rework_operation(adapter,intent=intent,approval=approval,declaration={'mode':'none'},
|
||||
coordinator=ops.Coordinator(),on_attempt=lambda record:None)
|
||||
self.assertEqual(calls,[])
|
||||
|
||||
def test_generic_comment_patch_rejected_and_correction_requires_explicit_approval(self):
|
||||
intent,approval,decl,calls,adapter=setup_case("comment.patch",{"body":"arbitrary"})
|
||||
with self.assertRaises(ValueError): pub.execute_rework_operation(adapter,intent=intent,approval=approval,declaration=decl,coordinator=ops.Coordinator(),on_attempt=lambda x:None)
|
||||
self.assertEqual(calls,[])
|
||||
|
||||
if __name__ == "__main__": unittest.main()
|
||||
Reference in New Issue
Block a user