Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/tools/jar/modularJar/Basic.java
41149 views
1
/*
2
* Copyright (c) 2015, 2019, 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
24
import java.io.*;
25
import java.lang.module.ModuleDescriptor;
26
import java.lang.reflect.Method;
27
import java.nio.file.Files;
28
import java.nio.file.Path;
29
import java.nio.file.Paths;
30
import java.util.*;
31
import java.util.function.Consumer;
32
import java.util.jar.JarEntry;
33
import java.util.jar.JarFile;
34
import java.util.jar.JarInputStream;
35
import java.util.jar.Manifest;
36
import java.util.regex.Pattern;
37
import java.util.spi.ToolProvider;
38
import java.util.stream.Collectors;
39
import java.util.stream.Stream;
40
41
import jdk.test.lib.util.FileUtils;
42
import jdk.test.lib.JDKToolFinder;
43
import org.testng.annotations.BeforeTest;
44
import org.testng.annotations.DataProvider;
45
import org.testng.annotations.Test;
46
47
import static java.lang.String.format;
48
import static java.lang.System.out;
49
50
/*
51
* @test
52
* @bug 8167328 8171830 8165640 8174248 8176772 8196748 8191533 8210454
53
* @library /test/lib
54
* @modules jdk.compiler
55
* jdk.jartool
56
* @build jdk.test.lib.Platform
57
* jdk.test.lib.util.FileUtils
58
* jdk.test.lib.JDKToolFinder
59
* @compile Basic.java
60
* @run testng Basic
61
* @summary Tests for plain Modular jars & Multi-Release Modular jars
62
*/
63
64
public class Basic {
65
66
private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
67
.orElseThrow(()
68
-> new RuntimeException("jar tool not found")
69
);
70
private static final ToolProvider JAVAC_TOOL = ToolProvider.findFirst("javac")
71
.orElseThrow(()
72
-> new RuntimeException("javac tool not found")
73
);
74
75
static final Path TEST_SRC = Paths.get(System.getProperty("test.src", "."));
76
static final Path TEST_CLASSES = Paths.get(System.getProperty("test.classes", "."));
77
static final Path MODULE_CLASSES = TEST_CLASSES.resolve("build");
78
static final Path MRJAR_DIR = MODULE_CLASSES.resolve("mrjar");
79
80
static final String VM_OPTIONS = System.getProperty("test.vm.opts", "");
81
static final String TOOL_VM_OPTIONS = System.getProperty("test.tool.vm.opts", "");
82
static final String JAVA_OPTIONS = System.getProperty("test.java.opts", "");
83
84
// Details based on the checked in module source
85
static TestModuleData FOO = new TestModuleData("foo",
86
"1.123",
87
"jdk.test.foo.Foo",
88
"Hello World!!!",
89
null, // no hashes
90
Set.of("java.base"),
91
Set.of("jdk.test.foo"),
92
null, // no uses
93
null, // no provides
94
Set.of("jdk.test.foo.internal",
95
"jdk.test.foo.resources"));
96
static TestModuleData BAR = new TestModuleData("bar",
97
"4.5.6.7",
98
"jdk.test.bar.Bar",
99
"Hello from Bar!",
100
null, // no hashes
101
Set.of("java.base", "foo"),
102
null, // no exports
103
null, // no uses
104
null, // no provides
105
Set.of("jdk.test.bar",
106
"jdk.test.bar.internal"));
107
108
static class TestModuleData {
109
final String moduleName;
110
final Set<String> requires;
111
final Set<String> exports;
112
final Set<String> uses;
113
final Set<String> provides;
114
final String mainClass;
115
final String version;
116
final String message;
117
final String hashes;
118
final Set<String> packages;
119
120
TestModuleData(String mn, String v, String mc, String m, String h,
121
Set<String> requires, Set<String> exports, Set<String> uses,
122
Set<String> provides, Set<String> contains) {
123
moduleName = mn; mainClass = mc; version = v; message = m; hashes = h;
124
this.requires = requires != null ? requires : Collections.emptySet();
125
this.exports = exports != null ? exports : Collections.emptySet();
126
this.uses = uses != null ? uses : Collections.emptySet();;
127
this.provides = provides != null ? provides : Collections.emptySet();
128
this.packages = Stream.concat(this.exports.stream(), contains.stream())
129
.collect(Collectors.toSet());
130
}
131
static TestModuleData from(String s) {
132
try {
133
BufferedReader reader = new BufferedReader(new StringReader(s));
134
String line;
135
String message = null;
136
String name = null, version = null, mainClass = null;
137
String hashes = null;
138
Set<String> requires, exports, uses, provides, conceals;
139
requires = exports = uses = provides = conceals = null;
140
while ((line = reader.readLine()) != null) {
141
if (line.startsWith("message:")) {
142
message = line.substring("message:".length());
143
} else if (line.startsWith("nameAndVersion:")) {
144
line = line.substring("nameAndVersion:".length());
145
int i = line.indexOf('@');
146
if (i != -1) {
147
name = line.substring(0, i);
148
version = line.substring(i + 1, line.length());
149
} else {
150
name = line;
151
}
152
} else if (line.startsWith("mainClass:")) {
153
mainClass = line.substring("mainClass:".length());
154
} else if (line.startsWith("requires:")) {
155
line = line.substring("requires:".length());
156
requires = stringToSet(line);
157
} else if (line.startsWith("exports:")) {
158
line = line.substring("exports:".length());
159
exports = stringToSet(line);
160
} else if (line.startsWith("uses:")) {
161
line = line.substring("uses:".length());
162
uses = stringToSet(line);
163
} else if (line.startsWith("provides:")) {
164
line = line.substring("provides:".length());
165
provides = stringToSet(line);
166
} else if (line.startsWith("hashes:")) {
167
hashes = line.substring("hashes:".length());
168
} else if (line.startsWith("contains:")) {
169
line = line.substring("contains:".length());
170
conceals = stringToSet(line);
171
} else if (line.contains("VM warning:")) {
172
continue; // ignore server vm warning see#8196748
173
} else if (line.contains("WARNING: JNI access from module not specified in --enable-native-access:")) {
174
continue;
175
} else {
176
throw new AssertionError("Unknown value " + line);
177
}
178
}
179
180
return new TestModuleData(name, version, mainClass, message,
181
hashes, requires, exports, uses,
182
provides, conceals);
183
} catch (IOException x) {
184
throw new UncheckedIOException(x);
185
}
186
}
187
static Set<String> stringToSet(String commaList) {
188
Set<String> s = new HashSet<>();
189
int i = commaList.indexOf(',');
190
if (i != -1) {
191
String[] p = commaList.split(",");
192
Stream.of(p).forEach(s::add);
193
} else {
194
s.add(commaList);
195
}
196
return s;
197
}
198
}
199
200
static void assertModuleData(Result r, TestModuleData expected) {
201
//out.printf("%s%n", r.output);
202
TestModuleData received = TestModuleData.from(r.output);
203
if (expected.message != null)
204
assertTrue(expected.message.equals(received.message),
205
"Expected message:", expected.message, ", got:", received.message);
206
assertTrue(expected.moduleName.equals(received.moduleName),
207
"Expected moduleName: ", expected.moduleName, ", got:", received.moduleName);
208
assertTrue(expected.version.equals(received.version),
209
"Expected version: ", expected.version, ", got:", received.version);
210
assertTrue(expected.mainClass.equals(received.mainClass),
211
"Expected mainClass: ", expected.mainClass, ", got:", received.mainClass);
212
assertSetsEqual(expected.requires, received.requires);
213
assertSetsEqual(expected.exports, received.exports);
214
assertSetsEqual(expected.uses, received.uses);
215
assertSetsEqual(expected.provides, received.provides);
216
assertSetsEqual(expected.packages, received.packages);
217
}
218
219
static void assertSetsEqual(Set<String> s1, Set<String> s2) {
220
if (!s1.equals(s2)) {
221
org.testng.Assert.assertTrue(false, s1 + " vs " + s2);
222
}
223
}
224
225
@BeforeTest
226
public void compileModules() throws Exception {
227
compileModule(FOO.moduleName);
228
compileModule(BAR.moduleName, MODULE_CLASSES);
229
compileModule("baz"); // for service provider consistency checking
230
231
// copy resources
232
copyResource(TEST_SRC.resolve("src").resolve(FOO.moduleName),
233
MODULE_CLASSES.resolve(FOO.moduleName),
234
"jdk/test/foo/resources/foo.properties");
235
236
setupMRJARModuleInfo(FOO.moduleName);
237
setupMRJARModuleInfo(BAR.moduleName);
238
setupMRJARModuleInfo("baz");
239
}
240
241
@Test
242
public void createFoo() throws IOException {
243
Path mp = Paths.get("createFoo");
244
createTestDir(mp);
245
Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
246
Path modularJar = mp.resolve(FOO.moduleName + ".jar");
247
248
jar("--create",
249
"--file=" + modularJar.toString(),
250
"--main-class=" + FOO.mainClass,
251
"--module-version=" + FOO.version,
252
"--no-manifest",
253
"-C", modClasses.toString(), ".")
254
.assertSuccess();
255
256
assertSetsEqual(readPackagesAttribute(modularJar),
257
Set.of("jdk.test.foo",
258
"jdk.test.foo.resources",
259
"jdk.test.foo.internal"));
260
261
java(mp, FOO.moduleName + "/" + FOO.mainClass)
262
.assertSuccess()
263
.resultChecker(r -> assertModuleData(r, FOO));
264
try (InputStream fis = Files.newInputStream(modularJar);
265
JarInputStream jis = new JarInputStream(fis)) {
266
assertTrue(!jarContains(jis, "./"),
267
"Unexpected ./ found in ", modularJar.toString());
268
}
269
}
270
271
/** Similar to createFoo, but with a Multi-Release Modular jar. */
272
@Test
273
public void createMRMJarFoo() throws IOException {
274
Path mp = Paths.get("createMRMJarFoo");
275
createTestDir(mp);
276
Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
277
Path mrjarDir = MRJAR_DIR.resolve(FOO.moduleName);
278
Path modularJar = mp.resolve(FOO.moduleName + ".jar");
279
280
// Positive test, create
281
jar("--create",
282
"--file=" + modularJar.toString(),
283
"--main-class=" + FOO.mainClass,
284
"--module-version=" + FOO.version,
285
"-m", mrjarDir.resolve("META-INF/MANIFEST.MF").toRealPath().toString(),
286
"-C", mrjarDir.toString(), "META-INF/versions/9/module-info.class",
287
"-C", modClasses.toString(), ".")
288
.assertSuccess();
289
java(mp, FOO.moduleName + "/" + FOO.mainClass)
290
.assertSuccess()
291
.resultChecker(r -> assertModuleData(r, FOO));
292
}
293
294
295
@Test
296
public void updateFoo() throws IOException {
297
Path mp = Paths.get("updateFoo");
298
createTestDir(mp);
299
Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
300
Path modularJar = mp.resolve(FOO.moduleName + ".jar");
301
302
jar("--create",
303
"--file=" + modularJar.toString(),
304
"--no-manifest",
305
"-C", modClasses.toString(), "jdk")
306
.assertSuccess();
307
jar("--update",
308
"--file=" + modularJar.toString(),
309
"--main-class=" + FOO.mainClass,
310
"--module-version=" + FOO.version,
311
"--no-manifest",
312
"-C", modClasses.toString(), "module-info.class")
313
.assertSuccess();
314
java(mp, FOO.moduleName + "/" + FOO.mainClass)
315
.assertSuccess()
316
.resultChecker(r -> assertModuleData(r, FOO));
317
}
318
319
@Test
320
public void updateMRMJarFoo() throws IOException {
321
Path mp = Paths.get("updateMRMJarFoo");
322
createTestDir(mp);
323
Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
324
Path mrjarDir = MRJAR_DIR.resolve(FOO.moduleName);
325
Path modularJar = mp.resolve(FOO.moduleName + ".jar");
326
327
jar("--create",
328
"--file=" + modularJar.toString(),
329
"--no-manifest",
330
"-C", modClasses.toString(), "jdk")
331
.assertSuccess();
332
jar("--update",
333
"--file=" + modularJar.toString(),
334
"--main-class=" + FOO.mainClass,
335
"--module-version=" + FOO.version,
336
"-m", mrjarDir.resolve("META-INF/MANIFEST.MF").toRealPath().toString(),
337
"-C", mrjarDir.toString(), "META-INF/versions/9/module-info.class",
338
"-C", modClasses.toString(), "module-info.class")
339
.assertSuccess();
340
java(mp, FOO.moduleName + "/" + FOO.mainClass)
341
.assertSuccess()
342
.resultChecker(r -> assertModuleData(r, FOO));
343
}
344
345
@Test
346
public void partialUpdateFooMainClass() throws IOException {
347
Path mp = Paths.get("partialUpdateFooMainClass");
348
createTestDir(mp);
349
Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
350
Path modularJar = mp.resolve(FOO.moduleName + ".jar");
351
352
// A "bad" main class in first create ( and no version )
353
jar("--create",
354
"--file=" + modularJar.toString(),
355
"--main-class=" + "jdk.test.foo.IAmNotTheEntryPoint",
356
"--no-manifest",
357
"-C", modClasses.toString(), ".") // includes module-info.class
358
.assertSuccess();
359
jar("--update",
360
"--file=" + modularJar.toString(),
361
"--main-class=" + FOO.mainClass,
362
"--module-version=" + FOO.version,
363
"--no-manifest")
364
.assertSuccess();
365
java(mp, FOO.moduleName + "/" + FOO.mainClass)
366
.assertSuccess()
367
.resultChecker(r -> assertModuleData(r, FOO));
368
}
369
370
@Test
371
public void partialUpdateFooVersion() throws IOException {
372
Path mp = Paths.get("partialUpdateFooVersion");
373
createTestDir(mp);
374
Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
375
Path modularJar = mp.resolve(FOO.moduleName + ".jar");
376
377
// A "bad" version in first create ( and no main class )
378
jar("--create",
379
"--file=" + modularJar.toString(),
380
"--module-version=" + "100000000",
381
"--no-manifest",
382
"-C", modClasses.toString(), ".") // includes module-info.class
383
.assertSuccess();
384
jar("--update",
385
"--file=" + modularJar.toString(),
386
"--main-class=" + FOO.mainClass,
387
"--module-version=" + FOO.version,
388
"--no-manifest")
389
.assertSuccess();
390
java(mp, FOO.moduleName + "/" + FOO.mainClass)
391
.assertSuccess()
392
.resultChecker(r -> assertModuleData(r, FOO));
393
}
394
395
@Test
396
public void partialUpdateFooNotAllFiles() throws IOException {
397
Path mp = Paths.get("partialUpdateFooNotAllFiles");
398
createTestDir(mp);
399
Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
400
Path modularJar = mp.resolve(FOO.moduleName + ".jar");
401
402
// Not all files, and none from non-exported packages,
403
// i.e. no concealed list in first create
404
jar("--create",
405
"--file=" + modularJar.toString(),
406
"--no-manifest",
407
"-C", modClasses.toString(), "module-info.class",
408
"-C", modClasses.toString(), "jdk/test/foo/Foo.class",
409
"-C", modClasses.toString(), "jdk/test/foo/resources/foo.properties")
410
.assertSuccess();
411
jar("--update",
412
"--file=" + modularJar.toString(),
413
"--main-class=" + FOO.mainClass,
414
"--module-version=" + FOO.version,
415
"--no-manifest",
416
"-C", modClasses.toString(), "jdk/test/foo/internal/Message.class")
417
.assertSuccess();
418
java(mp, FOO.moduleName + "/" + FOO.mainClass)
419
.assertSuccess()
420
.resultChecker(r -> assertModuleData(r, FOO));
421
}
422
423
@Test
424
public void partialUpdateMRMJarFooNotAllFiles() throws IOException {
425
Path mp = Paths.get("partialUpdateMRMJarFooNotAllFiles");
426
createTestDir(mp);
427
Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
428
Path mrjarDir = MRJAR_DIR.resolve(FOO.moduleName);
429
Path modularJar = mp.resolve(FOO.moduleName + ".jar");
430
431
jar("--create",
432
"--file=" + modularJar.toString(),
433
"--module-version=" + FOO.version,
434
"-C", modClasses.toString(), ".")
435
.assertSuccess();
436
jar("--update",
437
"--file=" + modularJar.toString(),
438
"--main-class=" + FOO.mainClass,
439
"--module-version=" + FOO.version,
440
"-m", mrjarDir.resolve("META-INF/MANIFEST.MF").toRealPath().toString(),
441
"-C", mrjarDir.toString(), "META-INF/versions/9/module-info.class")
442
.assertSuccess();
443
java(mp, FOO.moduleName + "/" + FOO.mainClass)
444
.assertSuccess()
445
.resultChecker(r -> assertModuleData(r, FOO));
446
}
447
448
@Test
449
public void partialUpdateFooAllFilesAndAttributes() throws IOException {
450
Path mp = Paths.get("partialUpdateFooAllFilesAndAttributes");
451
createTestDir(mp);
452
Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
453
Path modularJar = mp.resolve(FOO.moduleName + ".jar");
454
455
// all attributes and files
456
jar("--create",
457
"--file=" + modularJar.toString(),
458
"--main-class=" + FOO.mainClass,
459
"--module-version=" + FOO.version,
460
"--no-manifest",
461
"-C", modClasses.toString(), ".")
462
.assertSuccess();
463
jar("--update",
464
"--file=" + modularJar.toString(),
465
"--main-class=" + FOO.mainClass,
466
"--module-version=" + FOO.version,
467
"--no-manifest",
468
"-C", modClasses.toString(), ".")
469
.assertSuccess();
470
java(mp, FOO.moduleName + "/" + FOO.mainClass)
471
.assertSuccess()
472
.resultChecker(r -> assertModuleData(r, FOO));
473
}
474
475
@Test
476
public void partialUpdateFooModuleInfo() throws IOException {
477
Path mp = Paths.get("partialUpdateFooModuleInfo");
478
createTestDir(mp);
479
Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
480
Path modularJar = mp.resolve(FOO.moduleName + ".jar");
481
Path barModInfo = MODULE_CLASSES.resolve(BAR.moduleName);
482
483
jar("--create",
484
"--file=" + modularJar.toString(),
485
"--main-class=" + FOO.mainClass,
486
"--module-version=" + FOO.version,
487
"--no-manifest",
488
"-C", modClasses.toString(), ".")
489
.assertSuccess();
490
jar("--update",
491
"--file=" + modularJar.toString(),
492
"--no-manifest",
493
"-C", barModInfo.toString(), "module-info.class") // stuff in bar's info
494
.assertSuccess();
495
jar("-d",
496
"--file=" + modularJar.toString())
497
.assertSuccess()
498
.resultChecker(r -> {
499
// Expect "bar jar:file:/...!/module-info.class"
500
// conceals jdk.test.foo, conceals jdk.test.foo.internal"
501
String uri = "jar:" + modularJar.toUri().toString() + "!/module-info.class";
502
assertTrue(r.output.contains("bar " + uri),
503
"Expecting to find \"bar " + uri + "\"",
504
"in output, but did not: [" + r.output + "]");
505
Pattern p = Pattern.compile(
506
"contains\\s+jdk.test.foo\\s+contains\\s+jdk.test.foo.internal");
507
assertTrue(p.matcher(r.output).find(),
508
"Expecting to find \"contains jdk.test.foo,...\"",
509
"in output, but did not: [" + r.output + "]");
510
});
511
}
512
513
514
@Test
515
public void partialUpdateFooPackagesAttribute() throws IOException {
516
Path mp = Paths.get("partialUpdateFooPackagesAttribute");
517
createTestDir(mp);
518
Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
519
Path modularJar = mp.resolve(FOO.moduleName + ".jar");
520
521
// Not all files, and none from non-exported packages,
522
// i.e. no concealed list in first create
523
jar("--create",
524
"--file=" + modularJar.toString(),
525
"--no-manifest",
526
"-C", modClasses.toString(), "module-info.class",
527
"-C", modClasses.toString(), "jdk/test/foo/Foo.class")
528
.assertSuccess();
529
530
assertSetsEqual(readPackagesAttribute(modularJar),
531
Set.of("jdk.test.foo"));
532
533
jar("--update",
534
"--file=" + modularJar.toString(),
535
"-C", modClasses.toString(), "jdk/test/foo/resources/foo.properties")
536
.assertSuccess();
537
538
assertSetsEqual(readPackagesAttribute(modularJar),
539
Set.of("jdk.test.foo", "jdk.test.foo.resources"));
540
541
jar("--update",
542
"--file=" + modularJar.toString(),
543
"--main-class=" + FOO.mainClass,
544
"--module-version=" + FOO.version,
545
"--no-manifest",
546
"-C", modClasses.toString(), "jdk/test/foo/internal/Message.class")
547
.assertSuccess();
548
549
assertSetsEqual(readPackagesAttribute(modularJar),
550
Set.of("jdk.test.foo",
551
"jdk.test.foo.resources",
552
"jdk.test.foo.internal"));
553
554
java(mp, FOO.moduleName + "/" + FOO.mainClass)
555
.assertSuccess()
556
.resultChecker(r -> assertModuleData(r, FOO));
557
}
558
559
private Set<String> readPackagesAttribute(Path jar) {
560
return getModuleDescriptor(jar).packages();
561
}
562
563
@Test
564
public void hashBarInFooModule() throws IOException {
565
Path mp = Paths.get("dependencesFooBar");
566
createTestDir(mp);
567
568
Path modClasses = MODULE_CLASSES.resolve(BAR.moduleName);
569
Path modularJar = mp.resolve(BAR.moduleName + ".jar");
570
jar("--create",
571
"--file=" + modularJar.toString(),
572
"--main-class=" + BAR.mainClass,
573
"--module-version=" + BAR.version,
574
"--no-manifest",
575
"-C", modClasses.toString(), ".")
576
.assertSuccess();
577
578
modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
579
modularJar = mp.resolve(FOO.moduleName + ".jar");
580
jar("--create",
581
"--file=" + modularJar.toString(),
582
"--main-class=" + FOO.mainClass,
583
"--module-version=" + FOO.version,
584
"--module-path=" + mp.toString(),
585
"--hash-modules=" + "bar",
586
"--no-manifest",
587
"-C", modClasses.toString(), ".")
588
.assertSuccess();
589
590
java(mp, BAR.moduleName + "/" + BAR.mainClass,
591
"--add-exports", "java.base/jdk.internal.misc=bar",
592
"--add-exports", "java.base/jdk.internal.module=bar")
593
.assertSuccess()
594
.resultChecker(r -> {
595
assertModuleData(r, BAR);
596
TestModuleData received = TestModuleData.from(r.output);
597
assertTrue(received.hashes != null, "Expected non-null hashes value.");
598
});
599
}
600
601
@Test
602
public void invalidHashInFooModule() throws IOException {
603
Path mp = Paths.get("badDependencyFooBar");
604
createTestDir(mp);
605
606
Path barClasses = MODULE_CLASSES.resolve(BAR.moduleName);
607
Path barJar = mp.resolve(BAR.moduleName + ".jar");
608
jar("--create",
609
"--file=" + barJar.toString(),
610
"--main-class=" + BAR.mainClass,
611
"--module-version=" + BAR.version,
612
"--no-manifest",
613
"-C", barClasses.toString(), ".").assertSuccess();
614
615
Path fooClasses = MODULE_CLASSES.resolve(FOO.moduleName);
616
Path fooJar = mp.resolve(FOO.moduleName + ".jar");
617
jar("--create",
618
"--file=" + fooJar.toString(),
619
"--main-class=" + FOO.mainClass,
620
"--module-version=" + FOO.version,
621
"-p", mp.toString(), // test short-form
622
"--hash-modules=" + "bar",
623
"--no-manifest",
624
"-C", fooClasses.toString(), ".").assertSuccess();
625
626
// Rebuild bar.jar with a change that will cause its hash to be different
627
FileUtils.deleteFileWithRetry(barJar);
628
jar("--create",
629
"--file=" + barJar.toString(),
630
"--main-class=" + BAR.mainClass,
631
"--module-version=" + BAR.version + ".1", // a newer version
632
"--no-manifest",
633
"-C", barClasses.toString(), ".").assertSuccess();
634
635
java(mp, BAR.moduleName + "/" + BAR.mainClass,
636
"--add-exports", "java.base/jdk.internal.misc=bar",
637
"--add-exports", "java.base/jdk.internal.module=bar")
638
.assertFailure()
639
.resultChecker(r -> {
640
// Expect similar output: "java.lang.module.ResolutionException: Hash
641
// of bar (WdktSIQSkd4+CEacpOZoeDrCosMATNrIuNub9b5yBeo=) differs to
642
// expected hash (iepvdv8xTeVrFgMtUhcFnmetSub6qQHCHc92lSaSEg0=)"
643
Pattern p = Pattern.compile(".*Hash of bar.*differs to expected hash.*");
644
assertTrue(p.matcher(r.output).find(),
645
"Expecting error message containing \"Hash of bar ... differs to"
646
+ " expected hash...\" but got: [", r.output + "]");
647
});
648
}
649
650
@Test
651
public void badOptionsFoo() throws IOException {
652
Path mp = Paths.get("badOptionsFoo");
653
createTestDir(mp);
654
Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
655
Path modularJar = mp.resolve(FOO.moduleName + ".jar");
656
657
jar("--create",
658
"--file=" + modularJar.toString(),
659
"--module-version=" + 1.1, // no module-info.class
660
"-C", modClasses.toString(), "jdk")
661
.assertFailure(); // TODO: expected failure message
662
663
jar("--create",
664
"--file=" + modularJar.toString(),
665
"--hash-modules=" + ".*", // no module-info.class
666
"-C", modClasses.toString(), "jdk")
667
.assertFailure(); // TODO: expected failure message
668
}
669
670
@Test
671
public void servicesCreateWithoutFailure() throws IOException {
672
Path mp = Paths.get("servicesCreateWithoutFailure");
673
createTestDir(mp);
674
Path modClasses = MODULE_CLASSES.resolve("baz");
675
Path modularJar = mp.resolve("baz" + ".jar");
676
677
// Positive test, create
678
jar("--create",
679
"--file=" + modularJar.toString(),
680
"-C", modClasses.toString(), "module-info.class",
681
"-C", modClasses.toString(), "jdk/test/baz/BazService.class",
682
"-C", modClasses.toString(), "jdk/test/baz/internal/BazServiceImpl.class")
683
.assertSuccess();
684
685
for (String option : new String[] {"--describe-module", "-d" }) {
686
jar(option,
687
"--file=" + modularJar.toString())
688
.assertSuccess()
689
.resultChecker(r ->
690
assertTrue(r.output.contains("provides jdk.test.baz.BazService with jdk.test.baz.internal.BazServiceImpl"),
691
"Expected to find ", "provides jdk.test.baz.BazService with jdk.test.baz.internal.BazServiceImpl",
692
" in [", r.output, "]")
693
);
694
}
695
}
696
697
@Test
698
public void servicesCreateWithoutServiceImpl() throws IOException {
699
Path mp = Paths.get("servicesWithoutServiceImpl");
700
createTestDir(mp);
701
Path modClasses = MODULE_CLASSES.resolve("baz");
702
Path modularJar = mp.resolve("baz" + ".jar");
703
704
// Omit service impl
705
jar("--create",
706
"--file=" + modularJar.toString(),
707
"-C", modClasses.toString(), "module-info.class",
708
"-C", modClasses.toString(), "jdk/test/baz/BazService.class")
709
.assertFailure();
710
}
711
712
@Test
713
public void servicesUpdateWithoutFailure() throws IOException {
714
Path mp = Paths.get("servicesUpdateWithoutFailure");
715
createTestDir(mp);
716
Path modClasses = MODULE_CLASSES.resolve("baz");
717
Path modularJar = mp.resolve("baz" + ".jar");
718
719
// Positive test, update
720
jar("--create",
721
"--file=" + modularJar.toString(),
722
"-C", modClasses.toString(), "jdk/test/baz/BazService.class",
723
"-C", modClasses.toString(), "jdk/test/baz/internal/BazServiceImpl.class")
724
.assertSuccess();
725
jar("--update",
726
"--file=" + modularJar.toString(),
727
"-C", modClasses.toString(), "module-info.class")
728
.assertSuccess();
729
}
730
731
@Test
732
public void servicesUpdateWithoutServiceImpl() throws IOException {
733
Path mp = Paths.get("servicesUpdateWithoutServiceImpl");
734
createTestDir(mp);
735
Path modClasses = MODULE_CLASSES.resolve("baz");
736
Path modularJar = mp.resolve("baz" + ".jar");
737
738
// Omit service impl
739
jar("--create",
740
"--file=" + modularJar.toString(),
741
"-C", modClasses.toString(), "jdk/test/baz/BazService.class")
742
.assertSuccess();
743
jar("--update",
744
"--file=" + modularJar.toString(),
745
"-C", modClasses.toString(), "module-info.class")
746
.assertFailure();
747
}
748
749
@Test
750
public void servicesCreateWithoutFailureMRMJAR() throws IOException {
751
Path mp = Paths.get("servicesCreateWithoutFailureMRMJAR");
752
createTestDir(mp);
753
Path modClasses = MODULE_CLASSES.resolve("baz");
754
Path mrjarDir = MRJAR_DIR.resolve("baz");
755
Path modularJar = mp.resolve("baz" + ".jar");
756
757
jar("--create",
758
"--file=" + modularJar.toString(),
759
"-m", mrjarDir.resolve("META-INF/MANIFEST.MF").toRealPath().toString(),
760
"-C", modClasses.toString(), "module-info.class",
761
"-C", mrjarDir.toString(), "META-INF/versions/9/module-info.class",
762
"-C", modClasses.toString(), "jdk/test/baz/BazService.class",
763
"-C", modClasses.toString(), "jdk/test/baz/internal/BazServiceImpl.class")
764
.assertSuccess();
765
}
766
767
@Test
768
public void servicesCreateWithoutFailureNonRootMRMJAR() throws IOException {
769
// without a root module-info.class
770
Path mp = Paths.get("servicesCreateWithoutFailureNonRootMRMJAR");
771
createTestDir(mp);
772
Path modClasses = MODULE_CLASSES.resolve("baz");
773
Path mrjarDir = MRJAR_DIR.resolve("baz");
774
Path modularJar = mp.resolve("baz.jar");
775
776
jar("--create",
777
"--file=" + modularJar.toString(),
778
"--main-class=" + "jdk.test.baz.Baz",
779
"-m", mrjarDir.resolve("META-INF/MANIFEST.MF").toRealPath().toString(),
780
"-C", mrjarDir.toString(), "META-INF/versions/9/module-info.class",
781
"-C", modClasses.toString(), "jdk/test/baz/BazService.class",
782
"-C", modClasses.toString(), "jdk/test/baz/Baz.class",
783
"-C", modClasses.toString(), "jdk/test/baz/internal/BazServiceImpl.class")
784
.assertSuccess();
785
786
787
for (String option : new String[] {"--describe-module", "-d" }) {
788
789
jar(option,
790
"--file=" + modularJar.toString(),
791
"--release", "9")
792
.assertSuccess()
793
.resultChecker(r ->
794
assertTrue(r.output.contains("main-class jdk.test.baz.Baz"),
795
"Expected to find ", "main-class jdk.test.baz.Baz",
796
" in [", r.output, "]"));
797
798
jarWithStdin(modularJar.toFile(), option, "--release", "9")
799
.assertSuccess()
800
.resultChecker(r ->
801
assertTrue(r.output.contains("main-class jdk.test.baz.Baz"),
802
"Expected to find ", "main-class jdk.test.baz.Baz",
803
" in [", r.output, "]"));
804
805
}
806
// run module main class
807
java(mp, "baz/jdk.test.baz.Baz")
808
.assertSuccess()
809
.resultChecker(r ->
810
assertTrue(r.output.contains("mainClass:jdk.test.baz.Baz"),
811
"Expected to find ", "mainClass:jdk.test.baz.Baz",
812
" in [", r.output, "]"));
813
}
814
815
@Test
816
public void exportCreateWithMissingPkg() throws IOException {
817
818
Path foobar = TEST_SRC.resolve("src").resolve("foobar");
819
Path dst = Files.createDirectories(MODULE_CLASSES.resolve("foobar"));
820
javac(dst, null, sourceList(foobar));
821
822
Path mp = Paths.get("exportWithMissingPkg");
823
createTestDir(mp);
824
Path modClasses = dst;
825
Path modularJar = mp.resolve("foofoo.jar");
826
827
jar("--create",
828
"--file=" + modularJar.toString(),
829
"-C", modClasses.toString(), "module-info.class",
830
"-C", modClasses.toString(), "jdk/test/foo/Foo.class")
831
.assertFailure();
832
}
833
834
@Test
835
public void describeModuleFoo() throws IOException {
836
Path mp = Paths.get("describeModuleFoo");
837
createTestDir(mp);
838
Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
839
Path modularJar = mp.resolve(FOO.moduleName + ".jar");
840
841
jar("--create",
842
"--file=" + modularJar.toString(),
843
"--main-class=" + FOO.mainClass,
844
"--module-version=" + FOO.version,
845
"--no-manifest",
846
"-C", modClasses.toString(), ".")
847
.assertSuccess();
848
849
for (String option : new String[] {"--describe-module", "-d" }) {
850
jar(option,
851
"--file=" + modularJar.toString())
852
.assertSuccess()
853
.resultChecker(r -> {
854
assertTrue(r.output.contains(FOO.moduleName + "@" + FOO.version),
855
"Expected to find ", FOO.moduleName + "@" + FOO.version,
856
" in [", r.output, "]");
857
assertTrue(r.output.contains(modularJar.toUri().toString()),
858
"Expected to find ", modularJar.toUri().toString(),
859
" in [", r.output, "]");
860
}
861
);
862
863
jar(option,
864
"--file=" + modularJar.toString(),
865
modularJar.toString())
866
.assertFailure();
867
868
jar(option, modularJar.toString())
869
.assertFailure();
870
}
871
}
872
873
@Test
874
public void describeModuleFooFromStdin() throws IOException {
875
Path mp = Paths.get("describeModuleFooFromStdin");
876
createTestDir(mp);
877
Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
878
Path modularJar = mp.resolve(FOO.moduleName + ".jar");
879
880
jar("--create",
881
"--file=" + modularJar.toString(),
882
"--main-class=" + FOO.mainClass,
883
"--module-version=" + FOO.version,
884
"--no-manifest",
885
"-C", modClasses.toString(), ".")
886
.assertSuccess();
887
888
for (String option : new String[] {"--describe-module", "-d" }) {
889
jarWithStdin(modularJar.toFile(),
890
option)
891
.assertSuccess()
892
.resultChecker(r ->
893
assertTrue(r.output.contains(FOO.moduleName + "@" + FOO.version),
894
"Expected to find ", FOO.moduleName + "@" + FOO.version,
895
" in [", r.output, "]")
896
);
897
}
898
}
899
900
/**
901
* Validate that you can update a jar only specifying --module-version
902
* @throws IOException
903
*/
904
@Test
905
public void updateFooModuleVersion() throws IOException {
906
Path mp = Paths.get("updateFooModuleVersion");
907
createTestDir(mp);
908
Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
909
Path modularJar = mp.resolve(FOO.moduleName + ".jar");
910
String newFooVersion = "87.0";
911
912
jar("--create",
913
"--file=" + modularJar.toString(),
914
"--main-class=" + FOO.mainClass,
915
"--module-version=" + FOO.version,
916
"--no-manifest",
917
"-C", modClasses.toString(), ".")
918
.assertSuccess();
919
920
jarWithStdin(modularJar.toFile(), "--describe-module")
921
.assertSuccess()
922
.resultChecker(r ->
923
assertTrue(r.output.contains(FOO.moduleName + "@" + FOO.version),
924
"Expected to find ", FOO.moduleName + "@" + FOO.version,
925
" in [", r.output, "]")
926
);
927
928
jar("--update",
929
"--file=" + modularJar.toString(),
930
"--module-version=" + newFooVersion)
931
.assertSuccess();
932
933
for (String option : new String[] {"--describe-module", "-d" }) {
934
jarWithStdin(modularJar.toFile(),
935
option)
936
.assertSuccess()
937
.resultChecker(r ->
938
assertTrue(r.output.contains(FOO.moduleName + "@" + newFooVersion),
939
"Expected to find ", FOO.moduleName + "@" + newFooVersion,
940
" in [", r.output, "]")
941
);
942
}
943
}
944
945
@DataProvider(name = "autoNames")
946
public Object[][] autoNames() {
947
return new Object[][] {
948
// JAR file name module-name[@version]
949
{ "foo.jar", "foo" },
950
{ "foo1.jar", "foo1" },
951
{ "foo4j.jar", "foo4j", },
952
{ "foo-1.2.3.4.jar", "[email protected]" },
953
{ "foo-bar.jar", "foo.bar" },
954
{ "foo-1.2-SNAPSHOT.jar", "[email protected]" },
955
};
956
}
957
958
@Test(dataProvider = "autoNames")
959
public void describeAutomaticModule(String jarName, String mid)
960
throws IOException
961
{
962
Path mp = Paths.get("describeAutomaticModule");
963
createTestDir(mp);
964
Path regularJar = mp.resolve(jarName);
965
Path t = Paths.get("t");
966
if (Files.notExists(t))
967
Files.createFile(t);
968
969
jar("--create",
970
"--file=" + regularJar.toString(),
971
t.toString())
972
.assertSuccess();
973
974
for (String option : new String[] {"--describe-module", "-d" }) {
975
jar(option,
976
"--file=" + regularJar.toString())
977
.assertSuccess()
978
.resultChecker(r -> {
979
assertTrue(r.output.contains("No module descriptor found"));
980
assertTrue(r.output.contains("Derived automatic module"));
981
assertTrue(r.output.contains(mid + " automatic"),
982
"Expected [", "module " + mid,"] in [", r.output, "]");
983
}
984
);
985
}
986
}
987
988
// -- Infrastructure
989
990
static Result jarWithStdin(File stdinSource, String... args) {
991
String jar = getJDKTool("jar");
992
List<String> commands = new ArrayList<>();
993
commands.add(jar);
994
if (!TOOL_VM_OPTIONS.isEmpty()) {
995
commands.addAll(Arrays.asList(TOOL_VM_OPTIONS.split("\\s+", -1)));
996
}
997
Stream.of(args).forEach(commands::add);
998
ProcessBuilder p = new ProcessBuilder(commands);
999
if (stdinSource != null) {
1000
p.redirectInput(stdinSource);
1001
}
1002
return run(p);
1003
}
1004
1005
static Result jar(String... args) {
1006
return run(JAR_TOOL, args);
1007
}
1008
1009
static Path compileModule(String mn) throws IOException {
1010
return compileModule(mn, null);
1011
}
1012
1013
static Path compileModule(String mn, Path mp)
1014
throws IOException
1015
{
1016
Path sourcePath = TEST_SRC.resolve("src").resolve(mn);
1017
Path build = Files.createDirectories(MODULE_CLASSES.resolve(mn));
1018
javac(build, mp, sourceList(sourcePath));
1019
return build;
1020
}
1021
1022
static void copyResource(Path srcDir, Path dir, String resource)
1023
throws IOException
1024
{
1025
Path dest = dir.resolve(resource);
1026
Files.deleteIfExists(dest);
1027
1028
Files.createDirectories(dest.getParent());
1029
Files.copy(srcDir.resolve(resource), dest);
1030
}
1031
1032
static void setupMRJARModuleInfo(String moduleName) throws IOException {
1033
Path modClasses = MODULE_CLASSES.resolve(moduleName);
1034
Path metaInfDir = MRJAR_DIR.resolve(moduleName).resolve("META-INF");
1035
Path versionSection = metaInfDir.resolve("versions").resolve("9");
1036
createTestDir(versionSection);
1037
1038
Path versionModuleInfo = versionSection.resolve("module-info.class");
1039
System.out.println("copying " + modClasses.resolve("module-info.class") + " to " + versionModuleInfo);
1040
Files.copy(modClasses.resolve("module-info.class"), versionModuleInfo);
1041
1042
Manifest manifest = new Manifest();
1043
manifest.getMainAttributes().putValue("Manifest-Version", "1.0");
1044
manifest.getMainAttributes().putValue("Multi-Release", "true");
1045
try (OutputStream os = Files.newOutputStream(metaInfDir.resolve("MANIFEST.MF"))) {
1046
manifest.write(os);
1047
}
1048
}
1049
1050
static ModuleDescriptor getModuleDescriptor(Path jar) {
1051
ClassLoader cl = ClassLoader.getSystemClassLoader();
1052
try (JarFile jf = new JarFile(jar.toFile())) {
1053
JarEntry entry = jf.getJarEntry("module-info.class");
1054
try (InputStream in = jf.getInputStream(entry)) {
1055
return ModuleDescriptor.read(in);
1056
}
1057
} catch (IOException ioe) {
1058
throw new UncheckedIOException(ioe);
1059
}
1060
}
1061
1062
// Re-enable when there is support in javax.tools for module path
1063
// static void javac(Path dest, Path... sourceFiles) throws IOException {
1064
// out.printf("Compiling %d source files %s%n", sourceFiles.length,
1065
// Arrays.asList(sourceFiles));
1066
// JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
1067
// try (StandardJavaFileManager fileManager =
1068
// compiler.getStandardFileManager(null, null, null)) {
1069
//
1070
// List<File> files = Stream.of(sourceFiles)
1071
// .map(p -> p.toFile())
1072
// .collect(Collectors.toList());
1073
// List<File> dests = Stream.of(dest)
1074
// .map(p -> p.toFile())
1075
// .collect(Collectors.toList());
1076
// Iterable<? extends JavaFileObject> compilationUnits =
1077
// fileManager.getJavaFileObjectsFromFiles(files);
1078
// fileManager.setLocation(StandardLocation.CLASS_OUTPUT, dests);
1079
// JavaCompiler.CompilationTask task =
1080
// compiler.getTask(null, fileManager, null, null, null, compilationUnits);
1081
// boolean passed = task.call();
1082
// if (!passed)
1083
// throw new RuntimeException("Error compiling " + files);
1084
// }
1085
// }
1086
1087
static void javac(Path dest, Path... sourceFiles) throws IOException {
1088
javac(dest, null, sourceFiles);
1089
}
1090
1091
static void javac(Path dest, Path modulePath, Path... sourceFiles)
1092
throws IOException
1093
{
1094
1095
List<String> commands = new ArrayList<>();
1096
if (!TOOL_VM_OPTIONS.isEmpty()) {
1097
commands.addAll(Arrays.asList(TOOL_VM_OPTIONS.split("\\s+", -1)));
1098
}
1099
commands.add("-d");
1100
commands.add(dest.toString());
1101
if (dest.toString().contains("bar")) {
1102
commands.add("--add-exports");
1103
commands.add("java.base/jdk.internal.misc=bar");
1104
commands.add("--add-exports");
1105
commands.add("java.base/jdk.internal.module=bar");
1106
}
1107
if (modulePath != null) {
1108
commands.add("--module-path");
1109
commands.add(modulePath.toString());
1110
}
1111
Stream.of(sourceFiles).map(Object::toString).forEach(x -> commands.add(x));
1112
1113
StringWriter sw = new StringWriter();
1114
try (PrintWriter pw = new PrintWriter(sw)) {
1115
int rc = JAVAC_TOOL.run(pw, pw, commands.toArray(new String[0]));
1116
if(rc != 0) {
1117
throw new RuntimeException(sw.toString());
1118
}
1119
}
1120
}
1121
1122
static Result java(Path modulePath, String entryPoint, String... args) {
1123
String java = getJDKTool("java");
1124
1125
List<String> commands = new ArrayList<>();
1126
commands.add(java);
1127
if (!VM_OPTIONS.isEmpty()) {
1128
commands.addAll(Arrays.asList(VM_OPTIONS.split("\\s+", -1)));
1129
}
1130
if (!JAVA_OPTIONS.isEmpty()) {
1131
commands.addAll(Arrays.asList(JAVA_OPTIONS.split("\\s+", -1)));
1132
}
1133
Stream.of(args).forEach(x -> commands.add(x));
1134
commands.add("--module-path");
1135
commands.add(modulePath.toString());
1136
commands.add("-m");
1137
commands.add(entryPoint);
1138
1139
return run(new ProcessBuilder(commands));
1140
}
1141
1142
static Path[] sourceList(Path directory) throws IOException {
1143
return Files.find(directory, Integer.MAX_VALUE,
1144
(file, attrs) -> (file.toString().endsWith(".java")))
1145
.toArray(Path[]::new);
1146
}
1147
1148
static void createTestDir(Path p) throws IOException{
1149
if (Files.exists(p))
1150
FileUtils.deleteFileTreeWithRetry(p);
1151
Files.createDirectories(p);
1152
}
1153
1154
static boolean jarContains(JarInputStream jis, String entryName)
1155
throws IOException
1156
{
1157
JarEntry e;
1158
while((e = jis.getNextJarEntry()) != null) {
1159
if (e.getName().equals(entryName))
1160
return true;
1161
}
1162
return false;
1163
}
1164
1165
static Result run(ToolProvider tp, String[] commands) {
1166
int rc = 0;
1167
StringWriter sw = new StringWriter();
1168
try (PrintWriter pw = new PrintWriter(sw)) {
1169
rc = tp.run(pw, pw, commands);
1170
}
1171
return new Result(rc, sw.toString());
1172
}
1173
1174
static Result run(ProcessBuilder pb) {
1175
Process p;
1176
out.printf("Running: %s%n", pb.command());
1177
try {
1178
p = pb.start();
1179
} catch (IOException e) {
1180
throw new RuntimeException(
1181
format("Couldn't start process '%s'", pb.command()), e);
1182
}
1183
1184
String output;
1185
try {
1186
output = toString(p.getInputStream(), p.getErrorStream());
1187
} catch (IOException e) {
1188
throw new RuntimeException(
1189
format("Couldn't read process output '%s'", pb.command()), e);
1190
}
1191
1192
try {
1193
p.waitFor();
1194
} catch (InterruptedException e) {
1195
throw new RuntimeException(
1196
format("Process hasn't finished '%s'", pb.command()), e);
1197
}
1198
return new Result(p.exitValue(), output);
1199
}
1200
1201
static final String DEFAULT_IMAGE_BIN = System.getProperty("java.home")
1202
+ File.separator + "bin" + File.separator;
1203
1204
static String getJDKTool(String name) {
1205
try {
1206
return JDKToolFinder.getJDKTool(name);
1207
} catch (Exception x) {
1208
return DEFAULT_IMAGE_BIN + name;
1209
}
1210
}
1211
1212
static String toString(InputStream in1, InputStream in2) throws IOException {
1213
try (ByteArrayOutputStream dst = new ByteArrayOutputStream();
1214
InputStream concatenated = new SequenceInputStream(in1, in2)) {
1215
concatenated.transferTo(dst);
1216
return new String(dst.toByteArray(), "UTF-8");
1217
}
1218
}
1219
1220
static class Result {
1221
final int ec;
1222
final String output;
1223
1224
private Result(int ec, String output) {
1225
this.ec = ec;
1226
this.output = output;
1227
}
1228
Result assertSuccess() {
1229
assertTrue(ec == 0, "Expected ec 0, got: ", ec, " , output [", output, "]");
1230
return this;
1231
}
1232
Result assertFailure() {
1233
assertTrue(ec != 0, "Expected ec != 0, got:", ec, " , output [", output, "]");
1234
return this;
1235
}
1236
Result resultChecker(Consumer<Result> r) { r.accept(this); return this; }
1237
}
1238
1239
static void assertTrue(boolean cond, Object ... failedArgs) {
1240
if (cond)
1241
return;
1242
StringBuilder sb = new StringBuilder();
1243
for (Object o : failedArgs)
1244
sb.append(o);
1245
org.testng.Assert.assertTrue(false, sb.toString());
1246
}
1247
1248
// Standalone entry point.
1249
public static void main(String[] args) throws Throwable {
1250
Basic test = new Basic();
1251
test.compileModules();
1252
for (Method m : Basic.class.getDeclaredMethods()) {
1253
if (m.getAnnotation(Test.class) != null) {
1254
System.out.println("Invoking " + m.getName());
1255
m.invoke(test);
1256
}
1257
}
1258
}
1259
}
1260
1261