8350011: Convert jpackage test lib tests in JUnit format

Reviewed-by: almatvee
This commit is contained in:
Alexey Semenyuk 2025-02-14 13:12:30 +00:00
parent 19c0ce43e2
commit db42a48dc5
10 changed files with 199 additions and 185 deletions

View File

@ -0,0 +1,9 @@
JUnit.dirs = .
lib.dirs = /test/jdk/tools/jpackage/helpers /test/jdk/tools/jpackage/helpers-test
modules=jdk.jpackage/jdk.jpackage.internal:+open \
jdk.jpackage/jdk.jpackage.internal.util:+open \
jdk.jpackage/jdk.jpackage.internal.util.function:+open \
java.base/jdk.internal.util \
jdk.jlink/jdk.tools.jlink.internal

View File

@ -23,6 +23,9 @@
package jdk.jpackage.test;
import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE;
import static java.util.stream.Collectors.toMap;
import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.time.LocalDate;
@ -32,34 +35,34 @@ import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import static java.util.stream.Collectors.toMap;
import java.util.stream.Stream;
import jdk.internal.util.OperatingSystem;
import jdk.jpackage.test.Annotations.Parameter;
import jdk.jpackage.test.Annotations.ParameterSupplier;
import jdk.jpackage.test.Annotations.Parameters;
import jdk.jpackage.test.Annotations.Test;
import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.jupiter.params.provider.ValueSource;
/*
* @test
* @summary Test jpackage test library's annotation processor
* @library /test/jdk/tools/jpackage/helpers
* @build jdk.jpackage.test.*
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.AnnotationsTest
*/
public class AnnotationsTest {
public class AnnotationsTest extends JUnitAdapter {
public static void main(String... args) {
runTests(List.of(BasicTest.class, ParameterizedInstanceTest.class));
for (var os : OperatingSystem.values()) {
try {
TestBuilderConfig.setOperatingSystem(os);
TKit.log("Current operating system: " + os);
runTests(List.of(IfOSTest.class));
} finally {
TestBuilderConfig.setDefaults();
}
@ParameterizedTest
@ValueSource(classes = {BasicTest.class, ParameterizedInstanceTest.class})
public void test(Class<? extends TestExecutionRecorder> clazz, @TempDir Path workDir) {
runTest(clazz, workDir);
}
@ParameterizedTest
@EnumSource(OperatingSystem.class)
public void testIfOSTest(OperatingSystem os, @TempDir Path workDir) {
try {
TestBuilderConfig.setOperatingSystem(os);
TKit.log("Current operating system: " + os);
runTest(IfOSTest.class, workDir);
} finally {
TestBuilderConfig.setDefaults();
}
}
@ -300,22 +303,18 @@ public class AnnotationsTest {
});
}
private static void runTests(List<Class<? extends TestExecutionRecorder>> tests) {
private static void runTest(Class<? extends TestExecutionRecorder> test, Path workDir) {
ACTUAL_TEST_DESCS.get().clear();
var expectedTestDescs = tests.stream()
.map(AnnotationsTest::getExpectedTestDescs)
.flatMap(x -> x)
var expectedTestDescs = getExpectedTestDescs(test)
// Collect in the map to check for collisions for free
.collect(toMap(x -> x, x -> ""))
.keySet();
var args = tests.stream().map(test -> {
return String.format("--jpt-run=%s", test.getName());
}).toArray(String[]::new);
var args = new String[] { String.format("--jpt-run=%s", test.getName()) };
try {
Main.main(args);
Main.main(TestBuilder.build().workDirRoot(workDir), args);
assertRecordedTestDescs(expectedTestDescs);
} catch (Throwable t) {
t.printStackTrace(System.err);

View File

@ -22,7 +22,11 @@
*/
package jdk.jpackage.test;
import java.io.IOException;
import static java.util.stream.Collectors.toSet;
import static jdk.jpackage.test.DirectoryContentVerifierTest.AssertType.CONTAINS;
import static jdk.jpackage.test.DirectoryContentVerifierTest.AssertType.MATCH;
import static jdk.jpackage.test.TKit.assertAssert;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
@ -30,16 +34,12 @@ import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
import static java.util.stream.Collectors.toSet;
import java.util.stream.Stream;
import jdk.jpackage.test.Annotations.Parameters;
import jdk.jpackage.test.Annotations.ParameterSupplier;
import jdk.jpackage.test.Annotations.Test;
import static jdk.jpackage.test.DirectoryContentVerifierTest.AssertType.CONTAINS;
import static jdk.jpackage.test.DirectoryContentVerifierTest.AssertType.MATCH;
import jdk.jpackage.test.TKit.DirectoryContentVerifier;
import static jdk.jpackage.test.TKit.assertAssert;
public class DirectoryContentVerifierTest {
public class DirectoryContentVerifierTest extends JUnitAdapter {
enum AssertType {
MATCH(DirectoryContentVerifier::match),
@ -105,7 +105,6 @@ public class DirectoryContentVerifierTest {
private boolean success = true;
}
@Parameters
public static Collection<?> input() {
List<Object[]> data = new ArrayList<>();
buildArgs().applyVariantsTo(data);
@ -127,35 +126,23 @@ public class DirectoryContentVerifierTest {
return data;
}
public DirectoryContentVerifierTest(String[] expectedPaths, String[] actualPaths,
AssertType assertOp, Boolean success) {
this.expectedPaths = conv(expectedPaths);
this.actualPaths = conv(actualPaths);
this.assertOp = assertOp;
this.success = success;
}
@Test
public void test() {
TKit.withTempDirectory("basedir", this::test);
}
@ParameterSupplier("input")
public void test(String[] expectedPaths, String[] actualPaths, AssertType assertOp, Boolean success) {
final var expectedPathsAsSet = conv(expectedPaths);
final var actualPathsAsSet = conv(actualPaths);
TKit.withTempDirectory("basedir", basedir -> {
for (var path : actualPathsAsSet) {
Files.createFile(basedir.resolve(path));
}
private void test(Path basedir) throws IOException {
for (var path : actualPaths) {
Files.createFile(basedir.resolve(path));
}
var testee = TKit.assertDirectoryContent(basedir);
var testee = TKit.assertDirectoryContent(basedir);
assertAssert(success, () -> assertOp.assertFunc.accept(testee, expectedPaths));
assertAssert(success, () -> assertOp.assertFunc.accept(testee, expectedPathsAsSet));
});
}
private static Set<Path> conv(String... paths) {
return Stream.of(paths).map(Path::of).collect(toSet());
}
private final Set<Path> expectedPaths;
private final Set<Path> actualPaths;
private final AssertType assertOp;
private final boolean success;
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2025, 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.
*/
package jdk.jpackage.test;
import static jdk.jpackage.internal.util.function.ThrowingRunnable.toRunnable;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.List;
import jdk.jpackage.internal.util.function.ThrowingRunnable;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
public class JUnitAdapter {
JUnitAdapter() {
if (System.getProperty("test.src") == null) {
// Was called by somebody else but not by jtreg
System.setProperty("test.src", Path.of("@@openJdkDir@@/test/jdk/tools/jpackage").toString());
}
}
@Test
void runJPackageTests(@TempDir Path workDir) throws Throwable {
if (!getClass().equals(JUnitAdapter.class)) {
Main.main(TestBuilder.build().workDirRoot(workDir), new String [] {
"--jpt-before-run=jdk.jpackage.test.JPackageCommand.useToolProviderByDefault",
"--jpt-run=" + getClass().getName()
});
}
}
static List<String> captureJPackageTestLog(ThrowingRunnable runnable) {
final var buf = new ByteArrayOutputStream();
try (PrintStream ps = new PrintStream(buf, true, StandardCharsets.UTF_8)) {
TKit.withExtraLogStream(runnable, ps);
}
try (final var in = new ByteArrayInputStream(buf.toByteArray());
final var reader = new InputStreamReader(in, StandardCharsets.UTF_8);
final var bufReader = new BufferedReader(reader)) {
return bufReader.lines().map(line -> {
// Skip timestamp
return line.substring(LOG_MSG_TIMESTAMP_LENGTH);
}).toList();
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
private static final int LOG_MSG_TIMESTAMP_LENGTH = "[HH:mm:ss.SSS] ".length();
}

View File

@ -26,18 +26,14 @@ import java.nio.file.Path;
import java.util.List;
import java.util.function.UnaryOperator;
import jdk.jpackage.test.Annotations.Parameter;
import jdk.jpackage.test.Annotations.ParameterSupplier;
import jdk.jpackage.test.Annotations.Test;
import jdk.jpackage.test.Annotations.Parameters;
public class JavaAppDescTest {
public JavaAppDescTest(JavaAppDesc expectedAppDesc, JavaAppDesc actualAppDesc) {
this.expectedAppDesc = expectedAppDesc;
this.actualAppDesc = actualAppDesc;
}
public class JavaAppDescTest extends JUnitAdapter {
@Test
public void test() {
@ParameterSupplier("input")
public void test(JavaAppDesc expectedAppDesc, JavaAppDesc actualAppDesc) {
TKit.assertEquals(expectedAppDesc.toString(), actualAppDesc.toString(), null);
TKit.assertTrue(expectedAppDesc.equals(actualAppDesc), null);
}
@ -53,7 +49,6 @@ public class JavaAppDescTest {
appDesc).classFilePath().toString(), null);
}
@Parameters
public static List<Object[]> input() {
return List.of(new Object[][] {
createTestCase("", "hello.jar:Hello"),
@ -93,6 +88,4 @@ public class JavaAppDescTest {
return new JavaAppDesc[] {expectedAppDesc, actualAppDesc};
}
private final JavaAppDesc expectedAppDesc;
private final JavaAppDesc actualAppDesc;
}

View File

@ -22,28 +22,22 @@
*/
package jdk.jpackage.test;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import static jdk.jpackage.internal.util.function.ThrowingRunnable.toRunnable;
import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
import jdk.jpackage.test.Annotations.Parameters;
import jdk.jpackage.test.Annotations.Test;
import jdk.jpackage.internal.util.function.ThrowingRunnable;
import static jdk.jpackage.internal.util.function.ThrowingRunnable.toRunnable;
import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier;
import jdk.jpackage.test.Annotations.ParameterSupplier;
import jdk.jpackage.test.Annotations.Test;
public class TKitTest {
public class TKitTest extends JUnitAdapter {
@Parameters
public static Collection<Object[]> assertTestsData() {
List<MethodCallConfig> data = new ArrayList<>();
@ -191,12 +185,9 @@ public class TKitTest {
}
}
public TKitTest(MethodCallConfig methodCall) {
this.methodCall = methodCall;
}
@Test
public void test() {
@ParameterSupplier("assertTestsData")
public void test(MethodCallConfig methodCall) {
runAssertWithExpectedLogOutput(() -> {
methodCall.method.invoke(null, methodCall.args);
}, methodCall.expectFail, methodCall.expectLog);
@ -211,23 +202,11 @@ public class TKitTest {
private static void runWithExpectedLogOutput(ThrowingRunnable action,
String... expectLogStrings) {
final var buf = new ByteArrayOutputStream();
try (PrintStream ps = new PrintStream(buf, true, StandardCharsets.UTF_8)) {
TKit.withExtraLogStream(action, ps);
} finally {
toRunnable(() -> {
var output = new BufferedReader(new InputStreamReader(
new ByteArrayInputStream(buf.toByteArray()),
StandardCharsets.UTF_8)).lines().map(line -> {
// Skip timestamp
return line.substring(LOG_MSG_TIMESTAMP_LENGTH);
}).toList();
if (output.size() == 1 && expectLogStrings.length == 1) {
TKit.assertEquals(expectLogStrings[0], output.get(0), null);
} else {
TKit.assertStringListEquals(List.of(expectLogStrings), output, null);
}
}).run();
final var output = JUnitAdapter.captureJPackageTestLog(action);
if (output.size() == 1 && expectLogStrings.length == 1) {
TKit.assertEquals(expectLogStrings[0], output.get(0), null);
} else {
TKit.assertStringListEquals(List.of(expectLogStrings), output, null);
}
}
@ -237,8 +216,4 @@ public class TKitTest {
}
return msg;
}
private final MethodCallConfig methodCall;
private static final int LOG_MSG_TIMESTAMP_LENGTH = "[HH:mm:ss.SSS] ".length();
}

View File

@ -1,63 +0,0 @@
/*
* Copyright (c) 2024, 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.
*/
package jdk.jpackage.test;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
/*
* @test
* @summary Unit tests for jpackage test library
* @library /test/jdk/tools/jpackage/helpers
* @library /test/jdk/tools/jpackage/helpers-test
* @build jdk.jpackage.test.*
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.TestSuite
*/
public final class TestSuite {
public static void main(String args[]) throws Throwable {
final var pkgName = TestSuite.class.getPackageName();
final var javaSuffix = ".java";
final var testSrcNameSuffix = "Test" + javaSuffix;
final var unitTestDir = TKit.TEST_SRC_ROOT.resolve(Path.of("helpers-test", pkgName.split("\\.")));
final List<String> runTestArgs = new ArrayList<>();
runTestArgs.addAll(List.of(args));
try (var javaSources = Files.list(unitTestDir)) {
runTestArgs.addAll(javaSources.filter(path -> {
return path.getFileName().toString().endsWith(testSrcNameSuffix);
}).map(path -> {
var filename = path.getFileName().toString();
return String.join(".", pkgName, filename.substring(0, filename.length() - javaSuffix.length()));
}).map(testClassName -> {
return "--jpt-run=" + testClassName;
}).toList());
}
Main.main(runTestArgs.toArray(String[]::new));
}
}

View File

@ -38,10 +38,15 @@ import static jdk.jpackage.test.TestBuilder.CMDLINE_ARG_PREFIX;
public final class Main {
public static void main(String args[]) throws Throwable {
main(TestBuilder.build(), args);
}
public static void main(TestBuilder.Builder builder, String args[]) throws Throwable {
boolean listTests = false;
List<TestInstance> tests = new ArrayList<>();
try (TestBuilder testBuilder = new TestBuilder(tests::add)) {
try (TestBuilder testBuilder = builder.testConsumer(tests::add).create()) {
Deque<String> argsAsList = new ArrayDeque<>(List.of(args));
while (!argsAsList.isEmpty()) {
var arg = argsAsList.pop();

View File

@ -23,9 +23,13 @@
package jdk.jpackage.test;
import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer;
import static jdk.jpackage.test.TestMethodSupplier.MethodQuery.fromQualifiedMethodName;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
@ -38,14 +42,12 @@ import java.util.function.Consumer;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import jdk.jpackage.internal.util.function.ThrowingConsumer;
import jdk.jpackage.internal.util.function.ThrowingFunction;
import jdk.jpackage.test.Annotations.AfterEach;
import jdk.jpackage.test.Annotations.BeforeEach;
import jdk.jpackage.test.Annotations.Test;
import jdk.jpackage.internal.util.function.ThrowingConsumer;
import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer;
import jdk.jpackage.internal.util.function.ThrowingFunction;
import jdk.jpackage.test.TestMethodSupplier.InvalidAnnotationException;
import static jdk.jpackage.test.TestMethodSupplier.MethodQuery.fromQualifiedMethodName;
final class TestBuilder implements AutoCloseable {
@ -54,8 +56,35 @@ final class TestBuilder implements AutoCloseable {
flushTestGroup();
}
TestBuilder(Consumer<TestInstance> testConsumer) {
static Builder build() {
return new Builder();
}
final static class Builder {
private Builder() {
}
Builder testConsumer(Consumer<TestInstance> v) {
testConsumer = v;
return this;
}
Builder workDirRoot(Path v) {
workDirRoot = v;
return this;
}
TestBuilder create() {
return new TestBuilder(testConsumer, workDirRoot);
}
private Consumer<TestInstance> testConsumer;
private Path workDirRoot = Path.of("");
}
private TestBuilder(Consumer<TestInstance> testConsumer, Path workDirRoot) {
this.testMethodSupplier = TestBuilderConfig.getDefault().createTestMethodSupplier();
this.workDirRoot = Objects.requireNonNull(workDirRoot);
argProcessors = Map.of(
CMDLINE_ARG_PREFIX + "after-run",
arg -> getJavaMethodsFromArg(arg).map(
@ -88,7 +117,7 @@ final class TestBuilder implements AutoCloseable {
CMDLINE_ARG_PREFIX + "dry-run",
arg -> dryRun = true
);
this.testConsumer = testConsumer;
this.testConsumer = Objects.requireNonNull(testConsumer);
clear();
}
@ -188,7 +217,7 @@ final class TestBuilder implements AutoCloseable {
}
TestInstance test = new TestInstance(testBody, curBeforeActions,
curAfterActions, dryRun);
curAfterActions, dryRun, workDirRoot);
if (includedTests == null) {
trace(String.format("Create: %s", test.fullName()));
}
@ -348,6 +377,7 @@ final class TestBuilder implements AutoCloseable {
private final TestMethodSupplier testMethodSupplier;
private final Map<String, ThrowingConsumer<String>> argProcessors;
private final Consumer<TestInstance> testConsumer;
private final Path workDirRoot;
private List<MethodCall> testGroup;
private List<ThrowingConsumer<Object>> beforeActions;
private List<ThrowingConsumer<Object>> afterActions;

View File

@ -150,7 +150,7 @@ final class TestInstance implements ThrowingRunnable {
private String instanceArgs;
}
TestInstance(ThrowingRunnable testBody) {
TestInstance(ThrowingRunnable testBody, Path workDirRoot) {
assertCount = 0;
this.testConstructor = (unused) -> null;
this.testBody = (unused) -> testBody.run();
@ -158,11 +158,11 @@ final class TestInstance implements ThrowingRunnable {
this.afterActions = Collections.emptyList();
this.testDesc = TestDesc.createBuilder().get();
this.dryRun = false;
this.workDir = createWorkDirName(testDesc);
this.workDir = workDirRoot.resolve(createWorkDirPath(testDesc));
}
TestInstance(MethodCall testBody, List<ThrowingConsumer<Object>> beforeActions,
List<ThrowingConsumer<Object>> afterActions, boolean dryRun) {
List<ThrowingConsumer<Object>> afterActions, boolean dryRun, Path workDirRoot) {
assertCount = 0;
this.testConstructor = v -> ((MethodCall)v).newInstance();
this.testBody = testBody;
@ -170,7 +170,7 @@ final class TestInstance implements ThrowingRunnable {
this.afterActions = afterActions;
this.testDesc = testBody.createDescription();
this.dryRun = dryRun;
this.workDir = createWorkDirName(testDesc);
this.workDir = workDirRoot.resolve(createWorkDirPath(testDesc));
}
void notifyAssert() {
@ -276,8 +276,8 @@ final class TestInstance implements ThrowingRunnable {
return false;
}
private static Path createWorkDirName(TestDesc testDesc) {
Path result = Path.of(".");
private static Path createWorkDirPath(TestDesc testDesc) {
Path result = Path.of("");
if (!isCalledByJavatest()) {
result = result.resolve(testDesc.clazz.getSimpleName());
}