4a78906db1
Reviewed-by: jpai
337 lines
12 KiB
Java
337 lines
12 KiB
Java
/*
|
|
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/*
|
|
* @test
|
|
* @bug 8304400
|
|
* @summary Test source launcher running Java programs spanning multiple files
|
|
* @modules jdk.compiler/com.sun.tools.javac.launcher
|
|
* @run junit MultiFileSourceLauncherTests
|
|
*/
|
|
|
|
import static org.junit.jupiter.api.Assertions.*;
|
|
|
|
import com.sun.tools.javac.launcher.Fault;
|
|
import java.nio.file.*;
|
|
import org.junit.jupiter.api.*;
|
|
import org.junit.jupiter.api.io.*;
|
|
|
|
class MultiFileSourceLauncherTests {
|
|
@Test
|
|
void testHelloWorldInTwoCompilationUnits(@TempDir Path base) throws Exception {
|
|
var hello = Files.writeString(base.resolve("Hello.java"),
|
|
"""
|
|
public class Hello {
|
|
public static void main(String... args) {
|
|
System.out.println("Hello " + new World("Terra"));
|
|
System.out.println(Hello.class.getResource("Hello.java"));
|
|
System.out.println(Hello.class.getResource("World.java"));
|
|
}
|
|
}
|
|
""");
|
|
Files.writeString(base.resolve("World.java"),
|
|
"""
|
|
record World(String name) {}
|
|
""");
|
|
|
|
var run = Run.of(hello);
|
|
assertLinesMatch(
|
|
"""
|
|
Hello World[name=Terra]
|
|
\\Qfile:\\E.+\\QHello.java\\E
|
|
\\Qfile:\\E.+\\QWorld.java\\E
|
|
""".lines(),
|
|
run.stdOut().lines());
|
|
assertTrue(run.stdErr().isEmpty(), run.toString());
|
|
assertNull(run.exception(), run.toString());
|
|
}
|
|
|
|
@Test
|
|
void testLoadingOfEnclosedTypes(@TempDir Path base) throws Exception {
|
|
var hello = Files.writeString(base.resolve("Hello.java"),
|
|
"""
|
|
public class Hello {
|
|
public static void main(String... args) throws Exception {
|
|
System.out.println(Class.forName("World$Core"));
|
|
System.out.println(Class.forName("p.q.Unit$Fir$t"));
|
|
System.out.println(Class.forName("p.q.Unit$123$Fir$t$$econd"));
|
|
System.out.println(Class.forName("$.$.$"));
|
|
}
|
|
}
|
|
""");
|
|
Files.writeString(base.resolve("World.java"),
|
|
"""
|
|
record World(String name) {
|
|
record Core() {}
|
|
}
|
|
""");
|
|
var pq = Files.createDirectories(base.resolve("p/q"));
|
|
Files.writeString(pq.resolve("Unit.java"),
|
|
"""
|
|
package p.q;
|
|
record Unit() {
|
|
record Fir$t() {
|
|
record $econd() {}
|
|
}
|
|
}
|
|
""");
|
|
Files.writeString(pq.resolve("Unit$123.java"),
|
|
"""
|
|
package p.q;
|
|
record Unit$123() {
|
|
record Fir$t() {
|
|
record $econd() {}
|
|
}
|
|
}
|
|
""");
|
|
var $$ = Files.createDirectories(base.resolve("$/$"));
|
|
Files.writeString($$.resolve("$.java"),
|
|
"""
|
|
package $.$;
|
|
record $($ $) {}
|
|
""");
|
|
|
|
var run = Run.of(hello);
|
|
assertAll("Run -> " + run,
|
|
() -> assertLinesMatch(
|
|
"""
|
|
class World$Core
|
|
class p.q.Unit$Fir$t
|
|
class p.q.Unit$123$Fir$t$$econd
|
|
class $.$.$
|
|
""".lines(),
|
|
run.stdOut().lines()),
|
|
() -> assertTrue(run.stdErr().isEmpty()),
|
|
() -> assertNull(run.exception())
|
|
);
|
|
}
|
|
|
|
@Test
|
|
void testMultiplePackages(@TempDir Path base) throws Exception {
|
|
var packageA = Files.createDirectories(base.resolve("a"));
|
|
var hello = Files.writeString(packageA.resolve("Hello.java"),
|
|
"""
|
|
package a;
|
|
import b.World;
|
|
public class Hello {
|
|
public static void main(String... args) {
|
|
System.out.println("Hello " + new World("in package b"));
|
|
}
|
|
}
|
|
""");
|
|
var packageB = Files.createDirectories(base.resolve("b"));
|
|
Files.writeString(packageB.resolve("World.java"),
|
|
"""
|
|
package b;
|
|
public record World(String name) {}
|
|
""");
|
|
|
|
var run = Run.of(hello);
|
|
assertLinesMatch(
|
|
"""
|
|
Hello World[name=in package b]
|
|
""".lines(),
|
|
run.stdOut().lines());
|
|
assertTrue(run.stdErr().isEmpty(), run.toString());
|
|
assertNull(run.exception(), run.toString());
|
|
}
|
|
|
|
@Test
|
|
void testMissingSecondUnit(@TempDir Path base) throws Exception {
|
|
var program = Files.writeString(base.resolve("Program.java"),
|
|
"""
|
|
public class Program {
|
|
public static void main(String... args) {
|
|
System.out.println("Hello " + new MissingSecondUnit());
|
|
}
|
|
}
|
|
""");
|
|
|
|
var run = Run.of(program);
|
|
assertTrue(run.stdOut().isEmpty(), run.toString());
|
|
assertLinesMatch(
|
|
"""
|
|
%s:3: error: cannot find symbol
|
|
System.out.println("Hello " + new MissingSecondUnit());
|
|
^
|
|
symbol: class MissingSecondUnit
|
|
location: class Program
|
|
1 error
|
|
""".formatted(program.toString())
|
|
.lines(),
|
|
run.stdErr().lines(),
|
|
run.toString());
|
|
assertTrue(run.exception() instanceof Fault);
|
|
}
|
|
|
|
@Test
|
|
void testSecondUnitWithSyntaxError(@TempDir Path base) throws Exception {
|
|
var program = Files.writeString(base.resolve("Program.java"),
|
|
"""
|
|
public class Program {
|
|
public static void main(String... args) {
|
|
System.out.println("Hello " + new BrokenSecondUnit());
|
|
}
|
|
}
|
|
""");
|
|
var broken = Files.writeString(base.resolve("BrokenSecondUnit.java"),
|
|
"""
|
|
record BrokenSecondUnit {}
|
|
""");
|
|
|
|
var run = Run.of(program);
|
|
assertTrue(run.stdOut().isEmpty(), run.toString());
|
|
assertLinesMatch(
|
|
"""
|
|
%s:1: error: '(' expected
|
|
>> MORE LINES >>
|
|
""".formatted(broken.toString())
|
|
.lines(),
|
|
run.stdErr().lines(),
|
|
run.toString());
|
|
assertTrue(run.exception() instanceof Fault);
|
|
}
|
|
|
|
@Test
|
|
void onlyJavaFilesReferencedByTheProgramAreCompiled(@TempDir Path base) throws Exception {
|
|
var prog = Files.writeString(base.resolve("Prog.java"),
|
|
"""
|
|
class Prog {
|
|
public static void main(String... args) {
|
|
Helper.run();
|
|
}
|
|
}
|
|
""");
|
|
Files.writeString(base.resolve("Helper.java"),
|
|
"""
|
|
class Helper {
|
|
static void run() {
|
|
System.out.println("Hello!");
|
|
}
|
|
}
|
|
""");
|
|
|
|
var old = Files.writeString(base.resolve("OldProg.java"),
|
|
"""
|
|
class OldProg {
|
|
public static void main(String... args) {
|
|
Helper.run()
|
|
}
|
|
}
|
|
""");
|
|
|
|
var run = Run.of(prog);
|
|
assertAll("Run := " + run,
|
|
() -> assertLinesMatch(
|
|
"""
|
|
Hello!
|
|
""".lines(), run.stdOut().lines()),
|
|
() -> assertTrue(run.stdErr().isEmpty()),
|
|
() -> assertNull(run.exception()));
|
|
|
|
var fail = Run.of(old);
|
|
assertAll("Run := " + fail,
|
|
() -> assertTrue(fail.stdOut().isEmpty()),
|
|
() -> assertLinesMatch(
|
|
"""
|
|
%s:3: error: ';' expected
|
|
Helper.run()
|
|
^
|
|
1 error
|
|
""".formatted(old).lines(), fail.stdErr().lines()),
|
|
() -> assertNotNull(fail.exception()));
|
|
}
|
|
|
|
@Test
|
|
void classesDeclaredInSameFileArePreferredToClassesInOtherFiles(@TempDir Path base) throws Exception {
|
|
var prog = Files.writeString(base.resolve("Prog.java"),
|
|
"""
|
|
class Helper {
|
|
static void run() {
|
|
System.out.println("Same file.");
|
|
}
|
|
}
|
|
public class Prog {
|
|
public static void main(String... args) {
|
|
Helper.run();
|
|
}
|
|
}
|
|
""");
|
|
Files.writeString(base.resolve("Helper.java"),
|
|
"""
|
|
class Helper {
|
|
static void run() {
|
|
System.out.println("Other file.");
|
|
}
|
|
}
|
|
""");
|
|
|
|
var run = Run.of(prog);
|
|
assertAll("Run := " + run,
|
|
() -> assertLinesMatch(
|
|
"""
|
|
Same file.
|
|
""".lines(), run.stdOut().lines()),
|
|
() -> assertTrue(run.stdErr().isEmpty()),
|
|
() -> assertNull(run.exception()));
|
|
}
|
|
|
|
@Test
|
|
void duplicateDeclarationOfClassFails(@TempDir Path base) throws Exception {
|
|
var prog = Files.writeString(base.resolve("Prog.java"),
|
|
"""
|
|
class Prog {
|
|
public static void main(String... args) {
|
|
Helper.run();
|
|
Aux.cleanup();
|
|
}
|
|
}
|
|
class Aux {
|
|
static void cleanup() {}
|
|
}
|
|
""");
|
|
var helper = Files.writeString(base.resolve("Helper.java"),
|
|
"""
|
|
class Helper {
|
|
static void run() {}
|
|
}
|
|
class Aux {
|
|
static void cleanup() {}
|
|
}
|
|
""");
|
|
|
|
|
|
var fail = Run.of(prog);
|
|
assertAll("Run := " + fail,
|
|
() -> assertTrue(fail.stdOut().isEmpty()),
|
|
() -> assertLinesMatch(
|
|
"""
|
|
%s:4: error: duplicate class: Aux
|
|
class Aux {
|
|
^
|
|
1 error
|
|
""".formatted(helper).lines(), fail.stdErr().lines()),
|
|
() -> assertNotNull(fail.exception()));
|
|
}
|
|
}
|