Skip to content

Commit 45bbc37

Browse files
committed
8343875: Minor improvements of jpackage test library
Reviewed-by: mbaesken Backport-of: 2cdc9ed6d687cee343a5792a066a24839c6baccf
1 parent f7bad98 commit 45bbc37

File tree

9 files changed

+524
-51
lines changed

9 files changed

+524
-51
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
package jdk.jpackage.test;
24+
25+
import java.nio.file.Path;
26+
import java.util.List;
27+
import java.util.function.UnaryOperator;
28+
import jdk.jpackage.test.Annotations.Parameter;
29+
import jdk.jpackage.test.Annotations.Test;
30+
import jdk.jpackage.test.Annotations.Parameters;
31+
32+
public class JavaAppDescTest {
33+
34+
public JavaAppDescTest(JavaAppDesc expectedAppDesc, JavaAppDesc actualAppDesc) {
35+
this.expectedAppDesc = expectedAppDesc;
36+
this.actualAppDesc = actualAppDesc;
37+
}
38+
39+
@Test
40+
public void test() {
41+
TKit.assertEquals(expectedAppDesc.toString(), actualAppDesc.toString(), null);
42+
TKit.assertTrue(expectedAppDesc.equals(actualAppDesc), null);
43+
}
44+
45+
@Test
46+
@Parameter({"Foo", "Foo.class"})
47+
@Parameter({"com.bar.A", "com/bar/A.class"})
48+
@Parameter({"module/com.bar.A", "com/bar/A.class"})
49+
public static void testClassFilePath(String... args) {
50+
var appDesc = args[0];
51+
var expectedClassFilePath = Path.of(args[1]);
52+
TKit.assertEquals(expectedClassFilePath.toString(), JavaAppDesc.parse(
53+
appDesc).classFilePath().toString(), null);
54+
}
55+
56+
@Parameters
57+
public static List<Object[]> input() {
58+
return List.of(new Object[][] {
59+
createTestCase("", "hello.jar:Hello"),
60+
createTestCase("foo.jar*", "foo.jar*hello.jar:Hello"),
61+
createTestCase("Bye", "hello.jar:Bye"),
62+
createTestCase("bye.jar:", "bye.jar:Hello"),
63+
createTestCase("duke.jar:com.other/com.other.foo.bar.Buz!@3.7", appDesc -> {
64+
return appDesc
65+
.setBundleFileName("duke.jar")
66+
.setModuleName("com.other")
67+
.setClassName("com.other.foo.bar.Buz")
68+
.setWithMainClass(true)
69+
.setModuleVersion("3.7");
70+
}),
71+
});
72+
}
73+
74+
private static JavaAppDesc[] createTestCase(String inputAppDesc, String expectedAppDescStr) {
75+
return createTestCase(inputAppDesc, appDesc -> {
76+
return stripDefaultSrcJavaPath(JavaAppDesc.parse(expectedAppDescStr));
77+
});
78+
}
79+
80+
private static JavaAppDesc stripDefaultSrcJavaPath(JavaAppDesc appDesc) {
81+
var defaultAppDesc = HelloApp.createDefaltAppDesc();
82+
if (appDesc.srcJavaPath().equals(defaultAppDesc.srcJavaPath())) {
83+
appDesc.setSrcJavaPath(null);
84+
}
85+
return appDesc;
86+
}
87+
88+
private static JavaAppDesc[] createTestCase(String appDesc, UnaryOperator<JavaAppDesc> config) {
89+
var actualAppDesc = stripDefaultSrcJavaPath(JavaAppDesc.parse(appDesc));
90+
91+
var expectedAppDesc = config.apply(stripDefaultSrcJavaPath(HelloApp.createDefaltAppDesc()));
92+
93+
return new JavaAppDesc[] {expectedAppDesc, actualAppDesc};
94+
}
95+
96+
private final JavaAppDesc expectedAppDesc;
97+
private final JavaAppDesc actualAppDesc;
98+
}
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
package jdk.jpackage.test;
24+
25+
import java.io.BufferedReader;
26+
import java.io.ByteArrayInputStream;
27+
import java.io.ByteArrayOutputStream;
28+
import java.io.InputStreamReader;
29+
import java.io.PrintStream;
30+
import java.lang.reflect.Method;
31+
import java.nio.charset.StandardCharsets;
32+
import java.util.ArrayList;
33+
import java.util.Arrays;
34+
import java.util.Collection;
35+
import java.util.List;
36+
import java.util.Objects;
37+
import java.util.stream.Stream;
38+
import jdk.jpackage.test.Annotations.Parameters;
39+
import jdk.jpackage.test.Annotations.Test;
40+
import jdk.jpackage.test.Functional.ThrowingRunnable;
41+
import static jdk.jpackage.test.Functional.ThrowingRunnable.toRunnable;
42+
import static jdk.jpackage.test.Functional.ThrowingSupplier.toSupplier;
43+
44+
public class TKitTest {
45+
46+
@Parameters
47+
public static Collection<Object[]> assertTestsData() {
48+
List<MethodCallConfig> data = new ArrayList<>();
49+
50+
var assertFunc = MethodCallConfig.build("assertTrue", boolean.class, String.class);
51+
data.addAll(List.of(assertFunc.args(true).pass().expectLog("assertTrue()").createForMessage("Catbird")));
52+
data.addAll(List.of(assertFunc.args(false).fail().expectLog("Failed").createForMessage("Catbird")));
53+
54+
assertFunc = MethodCallConfig.build("assertFalse", boolean.class, String.class);
55+
data.addAll(List.of(assertFunc.args(false).pass().expectLog("assertFalse()").createForMessage("Stork")));
56+
data.addAll(List.of(assertFunc.args(true).fail().expectLog("Failed").createForMessage("Stork")));
57+
58+
assertFunc = MethodCallConfig.build("assertEquals", String.class, String.class, String.class);
59+
data.addAll(List.of(assertFunc.args("a", "a").pass().expectLog("assertEquals(a)").createForMessage("Crow")));
60+
data.addAll(List.of(assertFunc.args("a", "b").fail().expectLog("Expected [a]. Actual [b]").createForMessage("Crow")));
61+
62+
assertFunc = MethodCallConfig.build("assertEquals", long.class, long.class, String.class);
63+
data.addAll(List.of(assertFunc.args(7, 7).pass().expectLog("assertEquals(7)").createForMessage("Owl")));
64+
data.addAll(List.of(assertFunc.args(7, 10).fail().expectLog("Expected [7]. Actual [10]").createForMessage("Owl")));
65+
66+
assertFunc = MethodCallConfig.build("assertNotEquals", String.class, String.class, String.class);
67+
data.addAll(List.of(assertFunc.args("a", "b").pass().expectLog("assertNotEquals(a, b)").createForMessage("Tit")));
68+
data.addAll(List.of(assertFunc.args("a", "a").fail().expectLog("Unexpected [a] value").createForMessage("Tit")));
69+
70+
assertFunc = MethodCallConfig.build("assertNotEquals", long.class, long.class, String.class);
71+
data.addAll(List.of(assertFunc.args(7, 10).pass().expectLog("assertNotEquals(7, 10)").createForMessage("Duck")));
72+
data.addAll(List.of(assertFunc.args(7, 7).fail().expectLog("Unexpected [7] value").createForMessage("Duck")));
73+
74+
assertFunc = MethodCallConfig.build("assertNull", Object.class, String.class);
75+
data.addAll(List.of(assertFunc.args((Object) null).pass().expectLog("assertNull()").createForMessage("Ibis")));
76+
data.addAll(List.of(assertFunc.args("v").fail().expectLog("Unexpected not null value [v]").createForMessage("Ibis")));
77+
78+
assertFunc = MethodCallConfig.build("assertNotNull", Object.class, String.class);
79+
data.addAll(List.of(assertFunc.args("v").pass().expectLog("assertNotNull(v)").createForMessage("Pigeon")));
80+
data.addAll(List.of(assertFunc.args((Object) null).fail().expectLog("Unexpected null value").createForMessage("Pigeon")));
81+
82+
assertFunc = MethodCallConfig.build("assertStringListEquals", List.class, List.class, String.class);
83+
data.addAll(List.of(assertFunc.args(List.of(), List.of()).pass().expectLog(
84+
"assertStringListEquals()").createForMessage("Gull")));
85+
86+
data.addAll(List.of(assertFunc.args(List.of("a", "b"), List.of("a", "b")).pass().expectLog(
87+
"assertStringListEquals()",
88+
"assertStringListEquals(1, a)",
89+
"assertStringListEquals(2, b)").createForMessage("Pelican")));
90+
91+
assertFunc.fail().withAutoExpectLogPrefix(false);
92+
for (var msg : new String[] { "Raven", null }) {
93+
data.addAll(List.of(assertFunc.args(List.of("a"), List.of("a", "b"), msg).expectLog(
94+
concatMessages("TRACE: assertStringListEquals()", msg),
95+
"TRACE: assertStringListEquals(1, a)",
96+
concatMessages("ERROR: Actual list is longer than expected by 1 elements", msg)
97+
).create()));
98+
99+
data.addAll(List.of(assertFunc.args(List.of("n", "m"), List.of("n"), msg).expectLog(
100+
concatMessages("TRACE: assertStringListEquals()", msg),
101+
"TRACE: assertStringListEquals(1, n)",
102+
concatMessages("ERROR: Actual list is shorter than expected by 1 elements", msg)
103+
).create()));
104+
105+
data.addAll(List.of(assertFunc.args(List.of("a", "b"), List.of("n", "m"), msg).expectLog(
106+
concatMessages("TRACE: assertStringListEquals()", msg),
107+
concatMessages("ERROR: (1) Expected [a]. Actual [n]", msg)
108+
).create()));
109+
}
110+
111+
return data.stream().map(v -> {
112+
return new Object[]{v};
113+
}).toList();
114+
}
115+
116+
public record MethodCallConfig(Method method, Object[] args, boolean expectFail, String[] expectLog) {
117+
@Override
118+
public String toString() {
119+
return String.format("%s%s%s", method.getName(), Arrays.toString(args), expectFail ? "!" : "");
120+
}
121+
122+
static Builder build(String name, Class<?> ... parameterTypes) {
123+
return new Builder(name, parameterTypes);
124+
}
125+
126+
private static class Builder {
127+
Builder(Method method) {
128+
Objects.requireNonNull(method);
129+
this.method = method;
130+
}
131+
132+
Builder(String name, Class<?> ... parameterTypes) {
133+
method = toSupplier(() -> TKit.class.getMethod(name, parameterTypes)).get();
134+
}
135+
136+
MethodCallConfig create() {
137+
String[] effectiveExpectLog;
138+
if (!withAutoExpectLogPrefix) {
139+
effectiveExpectLog = expectLog;
140+
} else {
141+
var prefix = expectFail ? "ERROR: " : "TRACE: ";
142+
effectiveExpectLog = Stream.of(expectLog).map(line -> {
143+
return prefix + line;
144+
}).toArray(String[]::new);
145+
}
146+
return new MethodCallConfig(method, args, expectFail, effectiveExpectLog);
147+
}
148+
149+
MethodCallConfig[] createForMessage(String msg) {
150+
return Arrays.asList(msg, null).stream().map(curMsg -> {
151+
var builder = new Builder(method);
152+
builder.expectFail = expectFail;
153+
builder.withAutoExpectLogPrefix = withAutoExpectLogPrefix;
154+
builder.args = Stream.concat(Stream.of(args), Stream.of(curMsg)).toArray();
155+
builder.expectLog = Arrays.copyOf(expectLog, expectLog.length);
156+
builder.expectLog[0] = concatMessages(builder.expectLog[0], curMsg);
157+
return builder.create();
158+
}).toArray(MethodCallConfig[]::new);
159+
}
160+
161+
Builder fail() {
162+
expectFail = true;
163+
return this;
164+
}
165+
166+
Builder pass() {
167+
expectFail = false;
168+
return this;
169+
}
170+
171+
Builder args(Object ... v) {
172+
args = v;
173+
return this;
174+
}
175+
176+
Builder expectLog(String expectLogFirstStr, String ... extra) {
177+
expectLog = Stream.concat(Stream.of(expectLogFirstStr), Stream.of(extra)).toArray(String[]::new);
178+
return this;
179+
}
180+
181+
Builder withAutoExpectLogPrefix(boolean v) {
182+
withAutoExpectLogPrefix = v;
183+
return this;
184+
}
185+
186+
private final Method method;
187+
private Object[] args = new Object[0];
188+
private boolean expectFail;
189+
private String[] expectLog;
190+
private boolean withAutoExpectLogPrefix = true;
191+
}
192+
}
193+
194+
public TKitTest(MethodCallConfig methodCall) {
195+
this.methodCall = methodCall;
196+
}
197+
198+
@Test
199+
public void test() {
200+
runAssertWithExpectedLogOutput(() -> {
201+
methodCall.method.invoke(null, methodCall.args);
202+
}, methodCall.expectFail, methodCall.expectLog);
203+
}
204+
205+
private static void runAssertWithExpectedLogOutput(ThrowingRunnable action,
206+
boolean expectFail, String... expectLogStrings) {
207+
runWithExpectedLogOutput(() -> {
208+
TKit.assertAssert(!expectFail, toRunnable(action));
209+
}, expectLogStrings);
210+
}
211+
212+
private static void runWithExpectedLogOutput(ThrowingRunnable action,
213+
String... expectLogStrings) {
214+
final var buf = new ByteArrayOutputStream();
215+
try (PrintStream ps = new PrintStream(buf, true, StandardCharsets.UTF_8)) {
216+
TKit.withExtraLogStream(action, ps);
217+
} finally {
218+
toRunnable(() -> {
219+
var output = new BufferedReader(new InputStreamReader(
220+
new ByteArrayInputStream(buf.toByteArray()),
221+
StandardCharsets.UTF_8)).lines().map(line -> {
222+
// Skip timestamp
223+
return line.substring(LOG_MSG_TIMESTAMP_LENGTH);
224+
}).toList();
225+
if (output.size() == 1 && expectLogStrings.length == 1) {
226+
TKit.assertEquals(expectLogStrings[0], output.get(0), null);
227+
} else {
228+
TKit.assertStringListEquals(List.of(expectLogStrings), output, null);
229+
}
230+
}).run();
231+
}
232+
}
233+
234+
private static String concatMessages(String msg, String msg2) {
235+
if (msg2 != null && !msg2.isBlank()) {
236+
return msg + ": " + msg2;
237+
}
238+
return msg;
239+
}
240+
241+
private final MethodCallConfig methodCall;
242+
243+
private static final int LOG_MSG_TIMESTAMP_LENGTH = "[HH:mm:ss.SSS] ".length();
244+
}

0 commit comments

Comments
 (0)