134 lines
5.7 KiB
Python
134 lines
5.7 KiB
Python
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()
|