From adfbe354c383cb75c6ca98635b5f308bb740bd02 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 9 Nov 2026 06:22:16 +0000 Subject: [PATCH] Add Java 22 multi-file source launcher test (JEP 458) --- .../main/java/pl/mperor/lab/java/Greeter.java | 5 ++ .../java/pl/mperor/lab/java/GreetingMain.java | 3 + .../test/java/pl/mperor/lab/java/Java22.java | 58 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 JavaReleases/src/main/java/pl/mperor/lab/java/Greeter.java create mode 100644 JavaReleases/src/main/java/pl/mperor/lab/java/GreetingMain.java diff --git a/JavaReleases/src/main/java/pl/mperor/lab/java/Greeter.java b/JavaReleases/src/main/java/pl/mperor/lab/java/Greeter.java new file mode 100644 index 0000000..2531788 --- /dev/null +++ b/JavaReleases/src/main/java/pl/mperor/lab/java/Greeter.java @@ -0,0 +1,5 @@ +class Greeter { + static String greet(String name) { + return "Hello, " + name + "!"; + } +} diff --git a/JavaReleases/src/main/java/pl/mperor/lab/java/GreetingMain.java b/JavaReleases/src/main/java/pl/mperor/lab/java/GreetingMain.java new file mode 100644 index 0000000..b835140 --- /dev/null +++ b/JavaReleases/src/main/java/pl/mperor/lab/java/GreetingMain.java @@ -0,0 +1,3 @@ +void main() { + IO.println(Greeter.greet("World")); +} diff --git a/JavaReleases/src/test/java/pl/mperor/lab/java/Java22.java b/JavaReleases/src/test/java/pl/mperor/lab/java/Java22.java index b410559..bdfc8a6 100644 --- a/JavaReleases/src/test/java/pl/mperor/lab/java/Java22.java +++ b/JavaReleases/src/test/java/pl/mperor/lab/java/Java22.java @@ -2,9 +2,13 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import java.io.IOException; import java.lang.foreign.*; import java.lang.invoke.MethodHandle; +import java.nio.file.Files; +import java.nio.file.Path; import java.text.ListFormat; import java.util.Comparator; import java.util.List; @@ -141,4 +145,58 @@ public void testListFormat() { .format(List.of("One", "Two", "Three")); Assertions.assertEquals("One, Two and Three", formatted); } + + /// GreetingMain.java has no package declaration and sits next to Greeter.java: JEP 458 lets + /// `java GreetingMain.java` find and compile that sibling file automatically, with no explicit + /// `javac` step and no build file - unlike the single-file-only launcher from Java 11 (JEP 330), + /// which could not resolve a dependency living in another source file. + @Test + public void testMultiFileSourceLauncherCompilesSiblingClassAutomatically() throws IOException, InterruptedException { + var javaLauncher = Path.of(System.getProperty("java.home"), "bin", "java"); + var mainFile = Path.of("src", "main", "java", "pl", "mperor", "lab", "java", "GreetingMain.java"); + + var process = new ProcessBuilder(javaLauncher.toString(), mainFile.toString()) + .redirectErrorStream(true) + .start(); + String output = new String(process.getInputStream().readAllBytes()); + int exitCode = process.waitFor(); + + Assertions.assertEquals(0, exitCode, output); + Assertions.assertEquals("Hello, World!" + System.lineSeparator(), output); + } + + /// The launcher only compiles source files it actually needs: BrokenSibling.java below has a + /// syntax error but is never referenced by OnDemandMain, so `java OnDemandMain.java` still + /// succeeds - proof that compilation happens on demand, file by file, not for the whole directory. + @Test + public void testMultiFileSourceLauncherCompilesOnlyReferencedFiles(@TempDir Path dir) throws IOException, InterruptedException { + Files.writeString(dir.resolve("OnDemandMain.java"), """ + void main() { + IO.println(Dependency.value()); + } + """); + Files.writeString(dir.resolve("Dependency.java"), """ + class Dependency { + static String value() { + return "used"; + } + } + """); + Files.writeString(dir.resolve("BrokenSibling.java"), """ + class BrokenSibling { + this does not compile + } + """); + + var javaLauncher = Path.of(System.getProperty("java.home"), "bin", "java"); + var process = new ProcessBuilder(javaLauncher.toString(), "OnDemandMain.java") + .directory(dir.toFile()) + .redirectErrorStream(true) + .start(); + String output = new String(process.getInputStream().readAllBytes()); + int exitCode = process.waitFor(); + + Assertions.assertEquals(0, exitCode, output); + Assertions.assertEquals("used" + System.lineSeparator(), output); + } } \ No newline at end of file