[verified] Separate rework intake from publication counter checks
This commit is contained in:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user