Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
3.7 kB · 92 lines
Python
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293"""The class-file editing behind the patch build, checked against real javac output."""import shutilimport subprocessimport sysimport tempfileimport unittestfrom pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "tools"))from build_patch import TOO_NEW, retarget # noqa: E402from classfile import JAVA_1_4_MAJOR, ClassFile # noqa: E402
SOURCE = """package pkg;public class Thing { public Thing next; public long big = 5000000000L; public double ratio = 2.5; public static Thing make(Thing other) { return new Thing(); } public static Integer boxed(int i) { return i; } public static String joined(String a, int b) { return a + b; }}"""
# Written the way patch/src has to be: nothing newer than Java 1.4.CLEAN_SOURCE = """package pkg;public class Clean { public static String joined(String a, int b) { return new StringBuffer(a).append(b).toString(); }}"""
@unittest.skipUnless(shutil.which("javac"), "needs a JDK on PATH")class ClassFileTests(unittest.TestCase): @classmethod def setUpClass(cls): cls.dir = tempfile.TemporaryDirectory() root = Path(cls.dir.name) (root / "pkg").mkdir() (root / "pkg" / "Thing.java").write_text(SOURCE, encoding="utf-8") (root / "pkg" / "Clean.java").write_text(CLEAN_SOURCE, encoding="utf-8") subprocess.run(["javac", "--release", "8", "-d", str(root), str(root / "pkg" / "Thing.java"), str(root / "pkg" / "Clean.java")], check=True, capture_output=True) cls.data = (root / "pkg" / "Thing.class").read_bytes() cls.clean_data = (root / "pkg" / "Clean.class").read_bytes()
@classmethod def tearDownClass(cls): cls.dir.cleanup()
def test_round_trip_is_byte_identical(self): # Also proves longs and doubles (two pool slots each) are walked correctly. self.assertEqual(ClassFile(self.data).to_bytes(), self.data)
def test_rename_covers_the_name_and_descriptors(self): parsed = ClassFile(self.data) self.assertGreaterEqual(parsed.replace_in_utf8({"pkg/Thing": "pkg/RenamedThing"}), 3) strings = ClassFile(parsed.to_bytes()).utf8_strings() self.assertIn("pkg/RenamedThing", strings) self.assertIn("(Lpkg/RenamedThing;)Lpkg/RenamedThing;", strings) self.assertFalse([s for s in strings if "pkg/Thing" in s])
def test_retarget_changes_only_the_version(self): self.assertEqual(ClassFile(self.data).major, 52) clean = Path(self.dir.name) / "Clean.class" clean.write_bytes(self.clean_data) retarget(clean) out = clean.read_bytes() self.assertEqual((ClassFile(out).major, ClassFile(out).minor), (JAVA_1_4_MAJOR, 0)) self.assertEqual(out[8:], self.clean_data[8:])
def test_retarget_refuses_post_1_4_code(self): modern = Path(self.dir.name) / "Modern.class" modern.write_bytes(self.data) with self.assertRaises(SystemExit): retarget(modern) self.assertEqual(modern.read_bytes(), self.data) # left untouched
def test_build_guard_markers_really_appear_for_post_1_4_code(self): # SOURCE autoboxes and concatenates; the build must be able to see both. pool = "\n".join(ClassFile(self.data).utf8_strings()) found = [marker for marker in TOO_NEW if marker in pool] self.assertIn("(I)Ljava/lang/Integer;", found) self.assertIn("java/lang/StringBuilder", found)
def test_rejects_non_class_data(self): with self.assertRaises(ValueError): ClassFile(b"not a class")
if __name__ == "__main__": unittest.main()