"""Tests for non-mergeable skip conflict-proof verifier (#322).""" import sys import unittest from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from reviewer_mergeability_skip import assess_non_mergeable_skip_proof # noqa: E402 HEAD_A = "0fdc8f582026b72a229d59a172c0a63ac4aaeaf9" HEAD_B = "1111111111111111111111111111111111111111" def _good_skip_report(pr_number: int, head: str, files: str = "review_proofs.py") -> str: return "\n".join([ f"Skipped PR #{pr_number} (non-mergeable).", f"- PR number: #{pr_number}", f"- Current head SHA: {head}", "- Mergeability result: false", "- Conflict proof command: git merge-tree $(git merge-base prgs/master prgs/feat) prgs/master prgs/feat", f"- Conflicting files: {files}", "- Head unchanged since prior blocker", "- Blocking category: merge conflict", ]) class TestNonMergeableSkipProof(unittest.TestCase): def test_no_skips_passes(self): report = "Selected PR #203 for review. No earlier PRs skipped." result = assess_non_mergeable_skip_proof(report, skipped_prs=[]) self.assertTrue(result["proven"]) self.assertFalse(result["block"]) def test_documented_non_mergeable_skip_passes(self): report = _good_skip_report(282, HEAD_A) result = assess_non_mergeable_skip_proof( report, skipped_prs=[{ "pr_number": 282, "mergeable": False, "head_sha": HEAD_A, "mergeability_verified": True, "conflicting_files": ["review_proofs.py"], "head_changed_since_prior_blocker": False, }], ) self.assertTrue(result["proven"]) def test_skip_without_conflict_proof_blocks(self): report = "\n".join([ "Skipped PR #284 because it was not mergeable.", f"Head SHA: {HEAD_B}", ]) result = assess_non_mergeable_skip_proof( report, skipped_prs=[{ "pr_number": 284, "mergeable": False, "head_sha": HEAD_B, "mergeability_verified": True, }], ) self.assertFalse(result["proven"]) self.assertTrue(result["block"]) self.assertTrue(any("conflict proof" in r for r in result["reasons"])) def test_missing_head_sha_blocks(self): report = _good_skip_report(282, HEAD_A).replace(HEAD_A, "") result = assess_non_mergeable_skip_proof( report, skipped_prs=[{ "pr_number": 282, "mergeable": False, "head_sha": HEAD_A, "mergeability_verified": True, }], ) self.assertFalse(result["proven"]) def test_mergeability_unverified_classification_passes(self): report = "\n".join([ "Skipped PR #282.", "Classification: MERGEABILITY_UNVERIFIED", "Conflict proof could not be retrieved in this session.", ]) result = assess_non_mergeable_skip_proof( report, skipped_prs=[{ "pr_number": 282, "mergeable": False, "mergeability_verified": False, }], ) self.assertTrue(result["proven"]) def test_unverified_without_classification_blocks(self): report = "Skipped PR #282 due to conflicts." result = assess_non_mergeable_skip_proof( report, skipped_prs=[{ "pr_number": 282, "mergeable": False, "mergeability_verified": False, }], ) self.assertFalse(result["proven"]) self.assertTrue(any("MERGEABILITY_UNVERIFIED" in r for r in result["reasons"])) def test_non_mergeable_without_file_details_still_passes_with_command(self): report = _good_skip_report(284, HEAD_B, files="not available") result = assess_non_mergeable_skip_proof( report, skipped_prs=[{ "pr_number": 284, "mergeable": False, "head_sha": HEAD_B, "mergeability_verified": True, "conflicting_files": [], }], ) self.assertTrue(result["proven"]) def test_stale_head_requires_head_change_field(self): report = _good_skip_report(282, HEAD_A).replace( "- Head unchanged since prior blocker", "", ) result = assess_non_mergeable_skip_proof( report, skipped_prs=[{ "pr_number": 282, "mergeable": False, "head_sha": HEAD_A, "mergeability_verified": True, "head_changed_since_prior_blocker": True, }], ) self.assertFalse(result["proven"]) self.assertTrue(any("head-changed" in r for r in result["reasons"])) class TestExport(unittest.TestCase): def test_review_proofs_reexport(self): from review_proofs import assess_non_mergeable_skip_proof as exported self.assertTrue(callable(exported)) if __name__ == "__main__": unittest.main()