import json import tempfile import unittest from pathlib import Path from unittest.mock import patch from generate_surface import ( check_test_parity, extract_tests, generate_tests, mask_csharp_comments, reviewed_tests, ) class ParityGenerationTests(unittest.TestCase): def test_reviewed_tests_include_owning_crate_unit_tests(self) -> None: with tempfile.TemporaryDirectory() as temporary: root = Path(temporary) rust_file = root / "crates" / "example" / "src" / "internal_semantics.rs" rust_file.parent.mkdir(parents=True) case_id = "Example.Tests.cs::ExampleTests.InternalMember::test" rust_file.write_text( f"// parity-case: {case_id} {'a' * 64} translated\n" "#[test]\nfn internal_member() {\n" " let fixture: &'static str = r#\"{ fixture }\"#;\n" " assert_eq!(fixture, \"{ fixture }\");\n" " Example::internal_member().expect(\"internal member\");\n" "}\n" ) review = reviewed_tests(root)[case_id] self.assertEqual(review["rust_file"], "crates/example/src/internal_semantics.rs") self.assertEqual(review["rust_test"], "internal_member") self.assertRegex(str(review["rust_body_sha256"]), r"^[0-9a-f]{64}$") def test_comment_masking_preserves_offsets_and_ignores_fake_tests(self) -> None: source = '''var url = "https://example.com/[Test]"; // [Test]\n/* [TestCase(1)] */\n[Test]\n''' masked = mask_csharp_comments(source) self.assertEqual(len(masked), len(source)) self.assertEqual(masked.count("\n"), source.count("\n")) self.assertIn('"https://example.com/[Test]"', masked) self.assertEqual(masked.count("[Test]"), 2) with tempfile.TemporaryDirectory() as temporary: upstream = Path(temporary) tests = upstream / "LibreMetaverse.Tests" tests.mkdir() (upstream / "LibreMetaverse.Rendering.Tests").mkdir() (tests / "Comments.cs").write_text( """public class Comments { // [Test] // public void CommentedOut() {} [Test] [TestCase(1)] [TestCase(2)] public void Cases(int value) {} } """ ) self.assertEqual([case["parameter_case"] for case in extract_tests(upstream)], ["1", "2"]) def test_reviewed_rust_test_is_preserved_and_pending_cases_are_not_fake_tests(self) -> None: with tempfile.TemporaryDirectory() as temporary: root = Path(temporary) upstream = root / "upstream" source = upstream / "LibreMetaverse.Tests" / "ExampleTests.cs" source.parent.mkdir(parents=True) (upstream / "LibreMetaverse.Rendering.Tests").mkdir() source.write_text( """namespace LibreMetaverse.Tests; [Category("Example")] public class ExampleTests { [TestCase(1, Description = "one")] public void KeepsIdentity(int value) { Assert.That(value, Is.EqualTo(1)); } [Test] public void RemainsPending() { Assert.Pass(); } } """ ) reviewed, _pending = extract_tests(upstream) output = root / "output" rust_file = output / "tests" / "compat" / "tests" / "example.rs" rust_file.parent.mkdir(parents=True) rust_file.write_text( f"// parity-case: {reviewed['id']} {reviewed['body_sha256']} translated\n" "#[test]\nfn translated_case() {\n" " let actual = Example::keeps_identity(1).expect(\"KeepsIdentity\");\n" " assert_eq!(actual, 1);\n" "}\n" ) original = rust_file.read_bytes() with patch("generate_surface.EXPECTED_TESTS", 2): self.assertEqual(generate_tests(upstream, output), 2) self.assertEqual(rust_file.read_bytes(), original) generated = output / "tests/compat/tests/generated_parity.rs" self.assertNotIn(reviewed["id"], generated.read_text()) self.assertNotIn("#[test]", generated.read_text()) self.assertNotIn("pending(", generated.read_text()) catalog = json.loads((output / "tests/upstream-tests.json").read_text()) self.assertEqual(catalog["tests"][0]["status"], "translated") self.assertEqual(catalog["tests"][0]["rust_test"], "translated_case") self.assertEqual(check_test_parity(output)["unreviewed"], 1) rust_file.unlink() with self.assertRaisesRegex(RuntimeError, "Missing Rust parity cases"): check_test_parity(output) def test_placeholder_and_dispatcher_bodies_cannot_count_as_reviewed(self) -> None: bodies = [ "", ' pending("case");\n', ' assert_reviewed_case("Source.cs", "Method");\n', ' libremetaverse_types::unimplemented_api!("member");\n', ] for body in bodies: with self.subTest(body=body), tempfile.TemporaryDirectory() as temporary: root = Path(temporary) rust_file = root / "tests" / "compat" / "tests" / "invalid.rs" rust_file.parent.mkdir(parents=True) rust_file.write_text( f"// parity-case: Example.cs::Example.Invalid::test {'a' * 64} translated\n" f"#[test]\nfn invalid() {{\n{body}}}\n" ) with self.assertRaisesRegex(RuntimeError, "empty body|forbidden placeholder/dispatcher"): reviewed_tests(root) if __name__ == "__main__": unittest.main()