|
15 | 15 | import java.io.FilenameFilter; |
16 | 16 | import java.lang.reflect.Constructor; |
17 | 17 | import java.lang.reflect.Field; |
| 18 | +import java.lang.reflect.Method; |
18 | 19 | import java.nio.charset.StandardCharsets; |
19 | 20 | import java.nio.file.Files; |
20 | 21 | import java.nio.file.Path; |
@@ -624,4 +625,173 @@ private String nativeReportSource() { |
624 | 625 | " printf(\"RESULT=%d\\n\", value);\n" + |
625 | 626 | "}\n"; |
626 | 627 | } |
| 628 | + |
| 629 | + @Test |
| 630 | + void handleDefaultOutputWritesOutput() throws Exception { |
| 631 | + Parser.cleanup(); |
| 632 | + resetByteCodeClass(); |
| 633 | + Path sourceDir = Files.createTempDirectory("default-output-source"); |
| 634 | + Path outputDir = Files.createTempDirectory("default-output-dest"); |
| 635 | + |
| 636 | + Files.write(sourceDir.resolve("resource.txt"), "data".getBytes(StandardCharsets.UTF_8)); |
| 637 | + compileDummyMainClass(sourceDir, "com.example", "MyAppDefault"); |
| 638 | + |
| 639 | + String[] args = new String[] { |
| 640 | + "csharp", |
| 641 | + sourceDir.toAbsolutePath().toString(), |
| 642 | + outputDir.toAbsolutePath().toString(), |
| 643 | + "MyAppDefault", "com.example", "My App", "1.0", "ios", "none" |
| 644 | + }; |
| 645 | + |
| 646 | + ByteCodeTranslator.OutputType originalOutput = ByteCodeTranslator.output; |
| 647 | + try { |
| 648 | + ByteCodeTranslator.main(args); |
| 649 | + |
| 650 | + assertTrue(Files.exists(outputDir.resolve("resource.txt")), "Default output handler should copy resources"); |
| 651 | + } finally { |
| 652 | + ByteCodeTranslator.output = originalOutput; |
| 653 | + Parser.cleanup(); |
| 654 | + resetByteCodeClass(); |
| 655 | + } |
| 656 | + } |
| 657 | + |
| 658 | + @Test |
| 659 | + void readFileAsStringBuilderReadsContent() throws Exception { |
| 660 | + File temp = File.createTempFile("readfile", ".txt"); |
| 661 | + Files.write(temp.toPath(), "Hello World".getBytes(StandardCharsets.UTF_8)); |
| 662 | + |
| 663 | + Method m = ByteCodeTranslator.class.getDeclaredMethod("readFileAsStringBuilder", File.class); |
| 664 | + m.setAccessible(true); |
| 665 | + StringBuilder sb = (StringBuilder) m.invoke(null, temp); |
| 666 | + |
| 667 | + assertEquals("Hello World", sb.toString()); |
| 668 | + temp.delete(); |
| 669 | + } |
| 670 | + |
| 671 | + @Test |
| 672 | + void replaceInFileModifiesContent() throws Exception { |
| 673 | + File temp = File.createTempFile("replace", ".txt"); |
| 674 | + Files.write(temp.toPath(), "Hello World".getBytes(StandardCharsets.UTF_8)); |
| 675 | + |
| 676 | + Method m = ByteCodeTranslator.class.getDeclaredMethod("replaceInFile", File.class, String[].class); |
| 677 | + m.setAccessible(true); |
| 678 | + m.invoke(null, temp, new String[]{"World", "Universe"}); |
| 679 | + |
| 680 | + String content = new String(Files.readAllBytes(temp.toPath()), StandardCharsets.UTF_8); |
| 681 | + assertEquals("Hello Universe", content); |
| 682 | + temp.delete(); |
| 683 | + } |
| 684 | + |
| 685 | + @Test |
| 686 | + void getFileTypeReturnsCorrectTypes() throws Exception { |
| 687 | + Method m = ByteCodeTranslator.class.getDeclaredMethod("getFileType", String.class); |
| 688 | + m.setAccessible(true); |
| 689 | + |
| 690 | + assertEquals("wrapper.framework", m.invoke(null, "foo.framework")); |
| 691 | + assertEquals("sourcecode.c.objc", m.invoke(null, "foo.m")); |
| 692 | + assertEquals("file", m.invoke(null, "foo.txt")); |
| 693 | + assertEquals("wrapper.plug-in", m.invoke(null, "foo.bundle")); |
| 694 | + } |
| 695 | + |
| 696 | + @Test |
| 697 | + void copyDirRecursivelyCopies() throws Exception { |
| 698 | + Path src = Files.createTempDirectory("copydir-src"); |
| 699 | + Path dest = Files.createTempDirectory("copydir-dest"); |
| 700 | + |
| 701 | + Files.createDirectories(src.resolve("subdir")); |
| 702 | + Files.write(src.resolve("file1.txt"), "content1".getBytes()); |
| 703 | + Files.write(src.resolve("subdir/file2.txt"), "content2".getBytes()); |
| 704 | + |
| 705 | + Method m = ByteCodeTranslator.class.getDeclaredMethod("copyDir", File.class, File.class); |
| 706 | + m.setAccessible(true); |
| 707 | + ByteCodeTranslator instance = new ByteCodeTranslator(); |
| 708 | + m.invoke(instance, src.toFile(), dest.toFile()); |
| 709 | + |
| 710 | + Path copiedRoot = dest.resolve(src.getFileName()); |
| 711 | + assertTrue(Files.exists(copiedRoot)); |
| 712 | + assertTrue(Files.exists(copiedRoot.resolve("file1.txt"))); |
| 713 | + assertTrue(Files.exists(copiedRoot.resolve("subdir/file2.txt"))); |
| 714 | + } |
| 715 | + |
| 716 | + @Test |
| 717 | + void handleIosOutputGeneratesProjectStructure() throws Exception { |
| 718 | + Parser.cleanup(); |
| 719 | + resetByteCodeClass(); |
| 720 | + Path sourceDir = Files.createTempDirectory("ios-output-source"); |
| 721 | + Path outputDir = Files.createTempDirectory("ios-output-dest"); |
| 722 | + |
| 723 | + Files.write(sourceDir.resolve("resource.txt"), "data".getBytes(StandardCharsets.UTF_8)); |
| 724 | + compileDummyMainClass(sourceDir, "com.example", "MyAppIOS"); |
| 725 | + |
| 726 | + // Add a bundle to test copyDir invocation in execute loop |
| 727 | + Path bundleDir = sourceDir.resolve("test.bundle"); |
| 728 | + Files.createDirectories(bundleDir); |
| 729 | + Files.write(bundleDir.resolve("info.txt"), "bundle info".getBytes(StandardCharsets.UTF_8)); |
| 730 | + |
| 731 | + String[] args = new String[] { |
| 732 | + "ios", |
| 733 | + sourceDir.toAbsolutePath().toString(), |
| 734 | + outputDir.toAbsolutePath().toString(), |
| 735 | + "MyAppIOS", "com.example", "My App", "1.0", "ios", "none" |
| 736 | + }; |
| 737 | + |
| 738 | + ByteCodeTranslator.OutputType originalOutput = ByteCodeTranslator.output; |
| 739 | + try { |
| 740 | + ByteCodeTranslator.main(args); |
| 741 | + |
| 742 | + Path dist = outputDir.resolve("dist"); |
| 743 | + assertTrue(Files.exists(dist)); |
| 744 | + Path srcRoot = dist.resolve("MyAppIOS-src"); |
| 745 | + assertTrue(Files.exists(srcRoot)); |
| 746 | + assertTrue(Files.exists(srcRoot.resolve("resource.txt"))); |
| 747 | + assertTrue(Files.exists(srcRoot.resolve("Images.xcassets"))); |
| 748 | + assertTrue(Files.exists(dist.resolve("MyAppIOS.xcodeproj"))); |
| 749 | + assertTrue(Files.exists(srcRoot.resolve("MyAppIOS-Info.plist"))); |
| 750 | + |
| 751 | + // Verify bundle copied |
| 752 | + assertTrue(Files.exists(srcRoot.resolve("test.bundle"))); |
| 753 | + assertTrue(Files.exists(srcRoot.resolve("test.bundle/info.txt"))); |
| 754 | + |
| 755 | + } finally { |
| 756 | + ByteCodeTranslator.output = originalOutput; |
| 757 | + Parser.cleanup(); |
| 758 | + resetByteCodeClass(); |
| 759 | + } |
| 760 | + } |
| 761 | + |
| 762 | + private void resetByteCodeClass() throws Exception { |
| 763 | + Field mainClassField = ByteCodeClass.class.getDeclaredField("mainClass"); |
| 764 | + mainClassField.setAccessible(true); |
| 765 | + mainClassField.set(null, null); |
| 766 | + |
| 767 | + Field arrayTypesField = ByteCodeClass.class.getDeclaredField("arrayTypes"); |
| 768 | + arrayTypesField.setAccessible(true); |
| 769 | + ((Set<?>) arrayTypesField.get(null)).clear(); |
| 770 | + |
| 771 | + Field writableFieldsField = ByteCodeClass.class.getDeclaredField("writableFields"); |
| 772 | + writableFieldsField.setAccessible(true); |
| 773 | + ((Set<?>) writableFieldsField.get(null)).clear(); |
| 774 | + } |
| 775 | + |
| 776 | + private void compileDummyMainClass(Path sourceDir, String packageName, String className) throws Exception { |
| 777 | + Path packageDir = sourceDir; |
| 778 | + for (String part : packageName.split("\\.")) { |
| 779 | + packageDir = packageDir.resolve(part); |
| 780 | + } |
| 781 | + Files.createDirectories(packageDir); |
| 782 | + Path javaFile = packageDir.resolve(className + ".java"); |
| 783 | + String content = "package " + packageName + ";\n" + |
| 784 | + "public class " + className + " {\n" + |
| 785 | + " public static void main(String[] args) {}\n" + |
| 786 | + "}\n"; |
| 787 | + Files.write(javaFile, content.getBytes(StandardCharsets.UTF_8)); |
| 788 | + |
| 789 | + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); |
| 790 | + int result = compiler.run(null, null, null, |
| 791 | + "-source", "1.8", |
| 792 | + "-target", "1.8", |
| 793 | + "-d", sourceDir.toString(), |
| 794 | + javaFile.toString()); |
| 795 | + assertEquals(0, result, "Compilation failed"); |
| 796 | + } |
627 | 797 | } |
0 commit comments