[verified] Separate rework intake from publication counter checks

This commit is contained in:
2026-10-13 08:27:25 +00:00
parent e1be0dd526
commit 31ac634585
5 changed files with 194 additions and 23 deletions
@@ -317,5 +317,130 @@ class OrderedDecisionTests(unittest.TestCase):
self.assertEqual(cmd.main(),2)
self.assertGreater(len(requests),1);self.assertEqual(output.read_bytes(),b'created concurrently');self.assertEqual(output.stat().st_mode&0o777,0o600)
def test_pr_comment_counter_mismatch_preserves_no_op_and_diagnostics(self):
self.assertEqual(self.snapshot()['status'], 'no_op')
self.rb.pr['comments'] += 4
receipt = self.snapshot()
self.assertEqual(receipt['status'], 'no_op')
diagnostics = receipt['counter_diagnostics']
self.assertEqual(set(diagnostics), {'inline', 'pr', 'pr_issue'})
self.assertEqual(diagnostics['pr']['status'], 'mismatch')
def test_review_counter_mismatch_preserves_rework(self):
import copy
rows = copy.deepcopy(self.rows)
rows[1].update(state='REQUEST_CHANGES', body=self.code_body('request_changes'))
self.set_rows(rows)
self.rb.pr['review_comments'] += 3
receipt = self.snapshot()
self.assertEqual(receipt['status'], 'rework')
self.assertEqual(receipt['counter_diagnostics']['inline']['status'], 'mismatch')
self.assertEqual(receipt['decision']['rework_review_ids'], [302])
def test_malformed_pr_counters_are_unverified_diagnostics(self):
self.rb.pr['comments'] = 'not-a-count'
receipt = self.snapshot()
self.assertEqual(receipt['status'], 'no_op')
self.assertEqual(receipt['counter_diagnostics']['pr']['status'], 'unverified')
self.assertIn('field', receipt['counter_diagnostics']['pr'])
def test_unavailable_inline_endpoint_is_rejected_even_with_pr_count_fallback(self):
from urllib.parse import urlsplit
original = self.rb.request
def unavailable(path):
if '/pulls/9/reviews/' in urlsplit(path).path and urlsplit(path).path.endswith('/comments'):
self.rb.calls.append(path)
return {'message': 'not available'}, {}, 404
return original(path)
self.rb.request = unavailable
self.rb.contract['inline']['mode'] = 'per_review_or_pr_count'
with self.assertRaisesRegex(ValueError, 'inline collection unavailable'):
self.snapshot()
def test_inline_endpoint_405_is_rejected_even_with_pr_count_fallback(self):
from urllib.parse import urlsplit
original = self.rb.request
def unavailable(path):
if '/pulls/9/reviews/' in urlsplit(path).path and urlsplit(path).path.endswith('/comments'):
self.rb.calls.append(path)
return {'message': 'method not allowed'}, {}, 405
return original(path)
self.rb.request = unavailable
self.rb.contract['inline']['mode'] = 'per_review_or_pr_count'
with self.assertRaisesRegex(ValueError, 'inline collection unavailable'):
self.snapshot()
def test_publication_snapshot_remains_strict_on_pr_counter_mismatch(self):
from harness.tests.impl.test_rework_readback import ReworkReadbackTests
publication = ReworkReadbackTests()
publication.setUp()
self.addCleanup(publication.doCleanups)
publication.adapter().snapshot(publication.expected)
publication.pr['comments'] += 1
with self.assertRaisesRegex(ValueError, 'provider aggregate count mismatch'):
publication.adapter().snapshot(publication.expected)
def test_complete_lists_with_zero_pr_issue_counter_preserve_no_op(self):
self.rb.pr['comments'] = self.rb.underlying['comments'] = 0
receipt = self.snapshot()
self.assertEqual(receipt['status'], 'no_op')
for scope in ('pr', 'pr_issue'):
diagnostic = receipt['counter_diagnostics'][scope]
self.assertEqual(diagnostic, {'field':'comments',
'components':['top_level','reviews','inline'], 'observed':0,
'expected':2, 'status':'mismatch'})
self.assertEqual(receipt['raw_input_snapshot'][scope]['comments'], 0)
def test_missing_and_invalid_counters_do_not_replace_record_validation(self):
import copy
saved_pr, saved_issue = copy.deepcopy(self.rb.pr), copy.deepcopy(self.rb.underlying)
for scope, field in (('inline','review_comments'), ('pr','comments'), ('pr_issue','comments')):
for value in (None, True, -1, '0', 0.5, 'missing'):
with self.subTest(scope=scope, value=value):
self.rb.pr, self.rb.underlying = copy.deepcopy(saved_pr), copy.deepcopy(saved_issue)
record = self.rb.underlying if scope == 'pr_issue' else self.rb.pr
if value == 'missing': record.pop(field)
else: record[field] = value
receipt = self.snapshot()
self.assertEqual(receipt['status'], 'no_op')
self.assertEqual(receipt['counter_diagnostics'][scope]['status'], 'unverified')
raw_record = receipt['raw_input_snapshot']['pr_issue' if scope == 'pr_issue' else 'pr']
if value == 'missing': self.assertNotIn(field, raw_record)
else: self.assertEqual(raw_record[field], value)
def test_counter_mismatch_does_not_unblock_missing_code_review(self):
self.set_rows(self.rows[:1])
self.rb.pr['comments'] = self.rb.underlying['comments'] = 0
receipt = self.snapshot()
self.assertEqual(receipt['status'], 'blocked')
self.assertEqual(receipt['counter_diagnostics']['pr']['status'], 'mismatch')
self.assertEqual(receipt['decision']['rework_review_ids'], [])
def test_counter_mismatch_does_not_hide_per_review_inline_count_mismatch(self):
self.rb.reviews[0]['comments_count'] = 1
self.rb.pr['comments'] = self.rb.underlying['comments'] = 0
with self.assertRaisesRegex(ValueError, 'per-review inline count mismatch'):
self.snapshot()
def test_counter_mismatch_does_not_hide_duplicate_review_records(self):
import copy
self.rb.reviews.append(copy.deepcopy(self.rb.reviews[0]))
self.rb.pr['comments'] = self.rb.underlying['comments'] = 0
with self.assertRaisesRegex(ValueError, 'duplicate'):
self.snapshot()
def test_counter_mismatch_does_not_hide_incomplete_review_pagination(self):
original = self.rb.request
def truncated(path):
if '/pulls/9/reviews?' in path:
payload, headers, status = original(path)
return payload, dict(headers, **{'X-Total-Count':'3'}), status
return original(path)
self.rb.request = truncated
self.rb.pr['comments'] = self.rb.underlying['comments'] = 0
with self.assertRaisesRegex(ValueError, 'truncated collection'):
self.snapshot()
if __name__ == '__main__':
unittest.main()