Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/tools/jmod/JmodTest.java
41144 views
1
/*
2
* Copyright (c) 2015, 2020, 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
/*
25
* @test
26
* @bug 8142968 8166568 8166286 8170618 8168149 8240910
27
* @summary Basic test for jmod
28
* @library /test/lib
29
* @modules jdk.compiler
30
* jdk.jlink
31
* @build jdk.test.lib.compiler.CompilerUtils
32
* jdk.test.lib.util.FileUtils
33
* jdk.test.lib.Platform
34
* @run testng/othervm -Djava.io.tmpdir=. JmodTest
35
*/
36
37
import java.io.*;
38
import java.lang.module.ModuleDescriptor;
39
import java.lang.reflect.Method;
40
import java.nio.file.*;
41
import java.util.*;
42
import java.util.function.Consumer;
43
import java.util.regex.Pattern;
44
import java.util.spi.ToolProvider;
45
import java.util.stream.Stream;
46
import jdk.test.lib.compiler.CompilerUtils;
47
import jdk.test.lib.util.FileUtils;
48
import org.testng.annotations.BeforeTest;
49
import org.testng.annotations.Test;
50
51
import static java.io.File.pathSeparator;
52
import static java.lang.module.ModuleDescriptor.Version;
53
import static java.nio.charset.StandardCharsets.UTF_8;
54
import static java.util.stream.Collectors.toSet;
55
import static org.testng.Assert.*;
56
57
public class JmodTest {
58
59
static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod")
60
.orElseThrow(() ->
61
new RuntimeException("jmod tool not found")
62
);
63
static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
64
.orElseThrow(() ->
65
new RuntimeException("jar tool not found")
66
);
67
68
static final String TEST_SRC = System.getProperty("test.src", ".");
69
static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
70
static final Path EXPLODED_DIR = Paths.get("build");
71
static final Path MODS_DIR = Paths.get("jmods");
72
73
static final String CLASSES_PREFIX = "classes/";
74
static final String CMDS_PREFIX = "bin/";
75
static final String LIBS_PREFIX = "lib/";
76
static final String CONFIGS_PREFIX = "conf/";
77
78
@BeforeTest
79
public void buildExplodedModules() throws IOException {
80
if (Files.exists(EXPLODED_DIR))
81
FileUtils.deleteFileTreeWithRetry(EXPLODED_DIR);
82
83
for (String name : new String[] { "foo"/*, "bar", "baz"*/ } ) {
84
Path dir = EXPLODED_DIR.resolve(name);
85
assertTrue(compileModule(name, dir.resolve("classes")));
86
copyResource(SRC_DIR.resolve("foo"),
87
dir.resolve("classes"),
88
"jdk/test/foo/resources/foo.properties");
89
createCmds(dir.resolve("bin"));
90
createLibs(dir.resolve("lib"));
91
createConfigs(dir.resolve("conf"));
92
}
93
94
if (Files.exists(MODS_DIR))
95
FileUtils.deleteFileTreeWithRetry(MODS_DIR);
96
Files.createDirectories(MODS_DIR);
97
}
98
99
// JDK-8166286 - jmod fails on symlink to directory
100
@Test
101
public void testDirSymlinks() throws IOException {
102
Path apaDir = EXPLODED_DIR.resolve("apa");
103
Path classesDir = EXPLODED_DIR.resolve("apa").resolve("classes");
104
assertTrue(compileModule("apa", classesDir));
105
Path libDir = apaDir.resolve("lib");
106
createFiles(libDir, List.of("foo/bar/libfoo.so"));
107
try {
108
Path link = Files.createSymbolicLink(
109
libDir.resolve("baz"), libDir.resolve("foo").toAbsolutePath());
110
assertTrue(Files.exists(link));
111
} catch (IOException|UnsupportedOperationException uoe) {
112
// OS does not support symlinks. Nothing to test!
113
System.out.println("Creating symlink failed. Test passes vacuously.");
114
uoe.printStackTrace();
115
return;
116
}
117
118
Path jmod = MODS_DIR.resolve("apa.jmod");
119
jmod("create",
120
"--libs=" + libDir.toString(),
121
"--class-path", classesDir.toString(),
122
jmod.toString())
123
.assertSuccess();
124
Files.delete(jmod);
125
}
126
127
// JDK-8267583 - jmod fails on symlink to class file
128
@Test
129
public void testFileSymlinks() throws IOException {
130
Path apaDir = EXPLODED_DIR.resolve("apa");
131
Path classesDir = EXPLODED_DIR.resolve("apa").resolve("classes");
132
assertTrue(compileModule("apa", classesDir));
133
134
Files.move(classesDir.resolve("module-info.class"),
135
classesDir.resolve("module-info.class1"));
136
Files.move(classesDir.resolve(Paths.get("jdk", "test", "apa", "Apa.class")),
137
classesDir.resolve("Apa.class1"));
138
try {
139
Path link = Files.createSymbolicLink(
140
classesDir.resolve("module-info.class"),
141
classesDir.resolve("module-info.class1").toAbsolutePath());
142
assertTrue(Files.exists(link));
143
link = Files.createSymbolicLink(
144
classesDir.resolve(Paths.get("jdk", "test", "apa", "Apa.class")),
145
classesDir.resolve("Apa.class1").toAbsolutePath());
146
assertTrue(Files.exists(link));
147
} catch (IOException|UnsupportedOperationException uoe) {
148
// OS does not support symlinks. Nothing to test!
149
System.out.println("Creating symlinks failed. Test passes vacuously.");
150
uoe.printStackTrace();
151
return;
152
}
153
154
Path jmod = MODS_DIR.resolve("apa.jmod");
155
jmod("create",
156
"--class-path", classesDir.toString(),
157
jmod.toString())
158
.assertSuccess();
159
Files.delete(jmod);
160
}
161
162
// JDK-8170618 - jmod should validate if any exported or open package is missing
163
@Test
164
public void testMissingPackages() throws IOException {
165
Path apaDir = EXPLODED_DIR.resolve("apa");
166
Path classesDir = EXPLODED_DIR.resolve("apa").resolve("classes");
167
if (Files.exists(classesDir))
168
FileUtils.deleteFileTreeWithRetry(classesDir);
169
assertTrue(compileModule("apa", classesDir));
170
FileUtils.deleteFileTreeWithRetry(classesDir.resolve("jdk"));
171
Path jmod = MODS_DIR.resolve("apa.jmod");
172
jmod("create",
173
"--class-path", classesDir.toString(),
174
jmod.toString())
175
.assertFailure()
176
.resultChecker(r -> {
177
assertContains(r.output, "Packages that are exported or open in apa are not present: [jdk.test.apa]");
178
});
179
if (Files.exists(classesDir))
180
FileUtils.deleteFileTreeWithRetry(classesDir);
181
}
182
183
@Test
184
public void testList() throws IOException {
185
String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
186
jmod("create",
187
"--class-path", cp,
188
MODS_DIR.resolve("foo.jmod").toString())
189
.assertSuccess();
190
191
jmod("list",
192
MODS_DIR.resolve("foo.jmod").toString())
193
.assertSuccess()
194
.resultChecker(r -> {
195
// asserts dependent on the exact contents of foo
196
assertContains(r.output, CLASSES_PREFIX + "module-info.class");
197
assertContains(r.output, CLASSES_PREFIX + "jdk/test/foo/Foo.class");
198
assertContains(r.output, CLASSES_PREFIX + "jdk/test/foo/internal/Message.class");
199
assertContains(r.output, CLASSES_PREFIX + "jdk/test/foo/resources/foo.properties");
200
});
201
}
202
203
@Test
204
public void testExtractCWD() throws IOException {
205
Path cp = EXPLODED_DIR.resolve("foo").resolve("classes");
206
jmod("create",
207
"--class-path", cp.toString(),
208
MODS_DIR.resolve("fooExtractCWD.jmod").toString())
209
.assertSuccess();
210
211
jmod("extract",
212
MODS_DIR.resolve("fooExtractCWD.jmod").toString())
213
.assertSuccess()
214
.resultChecker(r -> {
215
// module-info should exist, but jmod will have added its Packages attr.
216
assertTrue(Files.exists(Paths.get("classes/module-info.class")));
217
assertSameContent(cp.resolve("jdk/test/foo/Foo.class"),
218
Paths.get("classes/jdk/test/foo/Foo.class"));
219
assertSameContent(cp.resolve("jdk/test/foo/internal/Message.class"),
220
Paths.get("classes/jdk/test/foo/internal/Message.class"));
221
assertSameContent(cp.resolve("jdk/test/foo/resources/foo.properties"),
222
Paths.get("classes/jdk/test/foo/resources/foo.properties"));
223
});
224
}
225
226
@Test
227
public void testExtractDir() throws IOException {
228
if (Files.exists(Paths.get("extractTestDir")))
229
FileUtils.deleteFileTreeWithRetry(Paths.get("extractTestDir"));
230
Path cp = EXPLODED_DIR.resolve("foo").resolve("classes");
231
Path bp = EXPLODED_DIR.resolve("foo").resolve("bin");
232
Path lp = EXPLODED_DIR.resolve("foo").resolve("lib");
233
Path cf = EXPLODED_DIR.resolve("foo").resolve("conf");
234
235
jmod("create",
236
"--conf", cf.toString(),
237
"--cmds", bp.toString(),
238
"--libs", lp.toString(),
239
"--class-path", cp.toString(),
240
MODS_DIR.resolve("fooExtractDir.jmod").toString())
241
.assertSuccess();
242
243
jmod("extract",
244
"--dir", "extractTestDir",
245
MODS_DIR.resolve("fooExtractDir.jmod").toString())
246
.assertSuccess();
247
248
jmod("extract",
249
"--dir", "extractTestDir",
250
MODS_DIR.resolve("fooExtractDir.jmod").toString())
251
.assertSuccess()
252
.resultChecker(r -> {
253
// check a sample of the extracted files
254
Path p = Paths.get("extractTestDir");
255
assertTrue(Files.exists(p.resolve("classes/module-info.class")));
256
assertSameContent(cp.resolve("jdk/test/foo/Foo.class"),
257
p.resolve("classes/jdk/test/foo/Foo.class"));
258
assertSameContent(bp.resolve("first"),
259
p.resolve(CMDS_PREFIX).resolve("first"));
260
assertSameContent(lp.resolve("first.so"),
261
p.resolve(LIBS_PREFIX).resolve("second.so"));
262
assertSameContent(cf.resolve("second.cfg"),
263
p.resolve(CONFIGS_PREFIX).resolve("second.cfg"));
264
});
265
}
266
267
@Test
268
public void testMainClass() throws IOException {
269
Path jmod = MODS_DIR.resolve("fooMainClass.jmod");
270
FileUtils.deleteFileIfExistsWithRetry(jmod);
271
String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
272
273
jmod("create",
274
"--class-path", cp,
275
"--main-class", "jdk.test.foo.Foo",
276
jmod.toString())
277
.assertSuccess()
278
.resultChecker(r -> {
279
Optional<String> omc = getModuleDescriptor(jmod).mainClass();
280
assertTrue(omc.isPresent());
281
assertEquals(omc.get(), "jdk.test.foo.Foo");
282
});
283
}
284
285
@Test
286
public void testModuleVersion() throws IOException {
287
Path jmod = MODS_DIR.resolve("fooVersion.jmod");
288
FileUtils.deleteFileIfExistsWithRetry(jmod);
289
String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
290
291
jmod("create",
292
"--class-path", cp,
293
"--module-version", "5.4.3",
294
jmod.toString())
295
.assertSuccess()
296
.resultChecker(r -> {
297
Optional<Version> ov = getModuleDescriptor(jmod).version();
298
assertTrue(ov.isPresent());
299
assertEquals(ov.get().toString(), "5.4.3");
300
});
301
}
302
303
@Test
304
public void testConfig() throws IOException {
305
Path jmod = MODS_DIR.resolve("fooConfig.jmod");
306
FileUtils.deleteFileIfExistsWithRetry(jmod);
307
Path cp = EXPLODED_DIR.resolve("foo").resolve("classes");
308
Path cf = EXPLODED_DIR.resolve("foo").resolve("conf");
309
310
jmod("create",
311
"--class-path", cp.toString(),
312
"--config", cf.toString(),
313
jmod.toString())
314
.assertSuccess()
315
.resultChecker(r -> {
316
try (Stream<String> s1 = findFiles(cf).map(p -> CONFIGS_PREFIX + p);
317
Stream<String> s2 = findFiles(cp).map(p -> CLASSES_PREFIX + p)) {
318
Set<String> expectedFilenames = Stream.concat(s1, s2)
319
.collect(toSet());
320
assertJmodContent(jmod, expectedFilenames);
321
}
322
});
323
}
324
325
@Test
326
public void testCmds() throws IOException {
327
Path jmod = MODS_DIR.resolve("fooCmds.jmod");
328
FileUtils.deleteFileIfExistsWithRetry(jmod);
329
Path cp = EXPLODED_DIR.resolve("foo").resolve("classes");
330
Path bp = EXPLODED_DIR.resolve("foo").resolve("bin");
331
332
jmod("create",
333
"--cmds", bp.toString(),
334
"--class-path", cp.toString(),
335
jmod.toString())
336
.assertSuccess()
337
.resultChecker(r -> {
338
try (Stream<String> s1 = findFiles(bp).map(p -> CMDS_PREFIX + p);
339
Stream<String> s2 = findFiles(cp).map(p -> CLASSES_PREFIX + p)) {
340
Set<String> expectedFilenames = Stream.concat(s1,s2)
341
.collect(toSet());
342
assertJmodContent(jmod, expectedFilenames);
343
}
344
});
345
}
346
347
@Test
348
public void testLibs() throws IOException {
349
Path jmod = MODS_DIR.resolve("fooLibs.jmod");
350
FileUtils.deleteFileIfExistsWithRetry(jmod);
351
Path cp = EXPLODED_DIR.resolve("foo").resolve("classes");
352
Path lp = EXPLODED_DIR.resolve("foo").resolve("lib");
353
354
jmod("create",
355
"--libs=" + lp.toString(),
356
"--class-path", cp.toString(),
357
jmod.toString())
358
.assertSuccess()
359
.resultChecker(r -> {
360
try (Stream<String> s1 = findFiles(lp).map(p -> LIBS_PREFIX + p);
361
Stream<String> s2 = findFiles(cp).map(p -> CLASSES_PREFIX + p)) {
362
Set<String> expectedFilenames = Stream.concat(s1,s2)
363
.collect(toSet());
364
assertJmodContent(jmod, expectedFilenames);
365
}
366
});
367
}
368
369
@Test
370
public void testAll() throws IOException {
371
Path jmod = MODS_DIR.resolve("fooAll.jmod");
372
FileUtils.deleteFileIfExistsWithRetry(jmod);
373
Path cp = EXPLODED_DIR.resolve("foo").resolve("classes");
374
Path bp = EXPLODED_DIR.resolve("foo").resolve("bin");
375
Path lp = EXPLODED_DIR.resolve("foo").resolve("lib");
376
Path cf = EXPLODED_DIR.resolve("foo").resolve("conf");
377
378
jmod("create",
379
"--conf", cf.toString(),
380
"--cmds=" + bp.toString(),
381
"--libs=" + lp.toString(),
382
"--class-path", cp.toString(),
383
jmod.toString())
384
.assertSuccess()
385
.resultChecker(r -> {
386
try (Stream<String> s1 = findFiles(lp).map(p -> LIBS_PREFIX + p);
387
Stream<String> s2 = findFiles(cp).map(p -> CLASSES_PREFIX + p);
388
Stream<String> s3 = findFiles(bp).map(p -> CMDS_PREFIX + p);
389
Stream<String> s4 = findFiles(cf).map(p -> CONFIGS_PREFIX + p)) {
390
Set<String> expectedFilenames = Stream.concat(Stream.concat(s1,s2),
391
Stream.concat(s3, s4))
392
.collect(toSet());
393
assertJmodContent(jmod, expectedFilenames);
394
}
395
});
396
}
397
398
@Test
399
public void testExcludes() throws IOException {
400
Path jmod = MODS_DIR.resolve("fooLibs.jmod");
401
FileUtils.deleteFileIfExistsWithRetry(jmod);
402
Path cp = EXPLODED_DIR.resolve("foo").resolve("classes");
403
Path lp = EXPLODED_DIR.resolve("foo").resolve("lib");
404
405
jmod("create",
406
"--libs=" + lp.toString(),
407
"--class-path", cp.toString(),
408
"--exclude", "**internal**",
409
"--exclude", "first.so",
410
jmod.toString())
411
.assertSuccess()
412
.resultChecker(r -> {
413
Set<String> expectedFilenames = new HashSet<>();
414
expectedFilenames.add(CLASSES_PREFIX + "module-info.class");
415
expectedFilenames.add(CLASSES_PREFIX + "jdk/test/foo/Foo.class");
416
expectedFilenames.add(CLASSES_PREFIX + "jdk/test/foo/resources/foo.properties");
417
expectedFilenames.add(LIBS_PREFIX + "second.so");
418
expectedFilenames.add(LIBS_PREFIX + "third/third.so");
419
assertJmodContent(jmod, expectedFilenames);
420
421
Set<String> unexpectedFilenames = new HashSet<>();
422
unexpectedFilenames.add(CLASSES_PREFIX + "jdk/test/foo/internal/Message.class");
423
unexpectedFilenames.add(LIBS_PREFIX + "first.so");
424
assertJmodDoesNotContain(jmod, unexpectedFilenames);
425
});
426
}
427
428
@Test
429
public void describe() throws IOException {
430
String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
431
jmod("create",
432
"--class-path", cp,
433
MODS_DIR.resolve("describeFoo.jmod").toString())
434
.assertSuccess();
435
436
jmod("describe",
437
MODS_DIR.resolve("describeFoo.jmod").toString())
438
.assertSuccess()
439
.resultChecker(r -> {
440
// Expect similar output: "foo... exports jdk.test.foo ...
441
// ... requires java.base mandated... contains jdk.test.foo.internal"
442
Pattern p = Pattern.compile("foo\\s+exports\\s+jdk.test.foo");
443
assertTrue(p.matcher(r.output).find(),
444
"Expecting to find \"foo... exports jdk.test.foo\"" +
445
"in output, but did not: [" + r.output + "]");
446
p = Pattern.compile(
447
"requires\\s+java.base\\s+mandated\\s+contains\\s+jdk.test.foo.internal");
448
assertTrue(p.matcher(r.output).find(),
449
"Expecting to find \"requires java.base mandated..., " +
450
"contains jdk.test.foo.internal ...\"" +
451
"in output, but did not: [" + r.output + "]");
452
});
453
}
454
455
@Test
456
public void testDuplicateEntries() throws IOException {
457
Path jmod = MODS_DIR.resolve("testDuplicates.jmod");
458
FileUtils.deleteFileIfExistsWithRetry(jmod);
459
String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
460
Path lp = EXPLODED_DIR.resolve("foo").resolve("lib");
461
462
jmod("create",
463
"--class-path", cp + pathSeparator + cp,
464
jmod.toString())
465
.assertSuccess()
466
.resultChecker(r ->
467
assertContains(r.output, "Warning: ignoring duplicate entry")
468
);
469
470
FileUtils.deleteFileIfExistsWithRetry(jmod);
471
jmod("create",
472
"--class-path", cp,
473
"--libs", lp.toString() + pathSeparator + lp.toString(),
474
jmod.toString())
475
.assertSuccess()
476
.resultChecker(r ->
477
assertContains(r.output, "Warning: ignoring duplicate entry")
478
);
479
}
480
481
@Test
482
public void testDuplicateEntriesFromJarFile() throws IOException {
483
String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
484
Path jar = Paths.get("foo.jar");
485
Path jmod = MODS_DIR.resolve("testDuplicates.jmod");
486
FileUtils.deleteFileIfExistsWithRetry(jar);
487
FileUtils.deleteFileIfExistsWithRetry(jmod);
488
// create JAR file
489
assertTrue(JAR_TOOL.run(System.out, System.err, "cf", jar.toString(), "-C", cp, ".") == 0);
490
491
jmod("create",
492
"--class-path", jar.toString() + pathSeparator + jar.toString(),
493
jmod.toString())
494
.assertSuccess()
495
.resultChecker(r ->
496
assertContains(r.output, "Warning: ignoring duplicate entry")
497
);
498
}
499
500
@Test
501
public void testIgnoreModuleInfoInOtherSections() throws IOException {
502
Path jmod = MODS_DIR.resolve("testIgnoreModuleInfoInOtherSections.jmod");
503
FileUtils.deleteFileIfExistsWithRetry(jmod);
504
String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
505
506
jmod("create",
507
"--class-path", cp,
508
"--libs", cp,
509
jmod.toString())
510
.assertSuccess()
511
.resultChecker(r ->
512
assertContains(r.output, "Warning: ignoring entry")
513
);
514
515
FileUtils.deleteFileIfExistsWithRetry(jmod);
516
jmod("create",
517
"--class-path", cp,
518
"--cmds", cp,
519
jmod.toString())
520
.assertSuccess()
521
.resultChecker(r ->
522
assertContains(r.output, "Warning: ignoring entry")
523
);
524
}
525
526
@Test
527
public void testLastOneWins() throws IOException {
528
Path workDir = Paths.get("lastOneWins");
529
if (Files.exists(workDir))
530
FileUtils.deleteFileTreeWithRetry(workDir);
531
Files.createDirectory(workDir);
532
Path jmod = MODS_DIR.resolve("lastOneWins.jmod");
533
FileUtils.deleteFileIfExistsWithRetry(jmod);
534
Path cp = EXPLODED_DIR.resolve("foo").resolve("classes");
535
Path bp = EXPLODED_DIR.resolve("foo").resolve("bin");
536
Path lp = EXPLODED_DIR.resolve("foo").resolve("lib");
537
Path cf = EXPLODED_DIR.resolve("foo").resolve("conf");
538
539
Path shouldNotBeAdded = workDir.resolve("shouldNotBeAdded");
540
Files.createDirectory(shouldNotBeAdded);
541
Files.write(shouldNotBeAdded.resolve("aFile"), "hello".getBytes(UTF_8));
542
543
// Pairs of options. For options with required arguments the last one
544
// should win ( first should be effectively ignored, but may still be
545
// validated ).
546
jmod("create",
547
"--conf", shouldNotBeAdded.toString(),
548
"--conf", cf.toString(),
549
"--cmds", shouldNotBeAdded.toString(),
550
"--cmds", bp.toString(),
551
"--libs", shouldNotBeAdded.toString(),
552
"--libs", lp.toString(),
553
"--class-path", shouldNotBeAdded.toString(),
554
"--class-path", cp.toString(),
555
"--main-class", "does.NotExist",
556
"--main-class", "jdk.test.foo.Foo",
557
"--module-version", "00001",
558
"--module-version", "5.4.3",
559
"--do-not-resolve-by-default",
560
"--do-not-resolve-by-default",
561
"--warn-if-resolved=incubating",
562
"--warn-if-resolved=deprecated",
563
MODS_DIR.resolve("lastOneWins.jmod").toString())
564
.assertSuccess()
565
.resultChecker(r -> {
566
ModuleDescriptor md = getModuleDescriptor(jmod);
567
Optional<String> omc = md.mainClass();
568
assertTrue(omc.isPresent());
569
assertEquals(omc.get(), "jdk.test.foo.Foo");
570
Optional<Version> ov = md.version();
571
assertTrue(ov.isPresent());
572
assertEquals(ov.get().toString(), "5.4.3");
573
574
try (Stream<String> s1 = findFiles(lp).map(p -> LIBS_PREFIX + p);
575
Stream<String> s2 = findFiles(cp).map(p -> CLASSES_PREFIX + p);
576
Stream<String> s3 = findFiles(bp).map(p -> CMDS_PREFIX + p);
577
Stream<String> s4 = findFiles(cf).map(p -> CONFIGS_PREFIX + p)) {
578
Set<String> expectedFilenames = Stream.concat(Stream.concat(s1,s2),
579
Stream.concat(s3, s4))
580
.collect(toSet());
581
assertJmodContent(jmod, expectedFilenames);
582
}
583
});
584
585
jmod("extract",
586
"--dir", "blah",
587
"--dir", "lastOneWinsExtractDir",
588
jmod.toString())
589
.assertSuccess()
590
.resultChecker(r -> {
591
assertTrue(Files.exists(Paths.get("lastOneWinsExtractDir")));
592
assertTrue(Files.notExists(Paths.get("blah")));
593
});
594
}
595
596
@Test
597
public void testPackagesAttribute() throws IOException {
598
Path jmod = MODS_DIR.resolve("foo.jmod");
599
FileUtils.deleteFileIfExistsWithRetry(jmod);
600
String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
601
602
Set<String> expectedPackages = Set.of("jdk.test.foo",
603
"jdk.test.foo.internal",
604
"jdk.test.foo.resources");
605
606
jmod("create",
607
"--class-path", cp,
608
jmod.toString())
609
.assertSuccess()
610
.resultChecker(r -> {
611
Set<String> pkgs = getModuleDescriptor(jmod).packages();
612
assertEquals(pkgs, expectedPackages);
613
});
614
}
615
616
@Test
617
public void testVersion() {
618
jmod("--version")
619
.assertSuccess()
620
.resultChecker(r -> {
621
assertContains(r.output, System.getProperty("java.version"));
622
});
623
}
624
625
@Test
626
public void testHelp() {
627
jmod("--help")
628
.assertSuccess()
629
.resultChecker(r -> {
630
assertTrue(r.output.startsWith("Usage: jmod"), "Help not printed");
631
assertFalse(r.output.contains("--do-not-resolve-by-default"));
632
assertFalse(r.output.contains("--warn-if-resolved"));
633
});
634
}
635
636
@Test
637
public void testHelpExtra() {
638
jmod("--help-extra")
639
.assertSuccess()
640
.resultChecker(r -> {
641
assertTrue(r.output.startsWith("Usage: jmod"), "Extra help not printed");
642
assertContains(r.output, "--do-not-resolve-by-default");
643
assertContains(r.output, "--warn-if-resolved");
644
});
645
}
646
647
@Test
648
public void testTmpFileRemoved() throws IOException {
649
// Implementation detail: jmod tool creates <jmod-file>.tmp
650
// Ensure that it is removed in the event of a failure.
651
// The failure in this case is a class in the unnamed package.
652
653
Path jmod = MODS_DIR.resolve("testTmpFileRemoved.jmod");
654
Path tmp = MODS_DIR.resolve(".testTmpFileRemoved.jmod.tmp");
655
FileUtils.deleteFileIfExistsWithRetry(jmod);
656
FileUtils.deleteFileIfExistsWithRetry(tmp);
657
String cp = EXPLODED_DIR.resolve("foo").resolve("classes") + File.pathSeparator +
658
EXPLODED_DIR.resolve("foo").resolve("classes")
659
.resolve("jdk").resolve("test").resolve("foo").toString();
660
661
jmod("create",
662
"--class-path", cp,
663
jmod.toString())
664
.assertFailure()
665
.resultChecker(r -> {
666
assertContains(r.output, "unnamed package");
667
assertTrue(Files.notExists(tmp), "Unexpected tmp file:" + tmp);
668
});
669
}
670
671
// ---
672
673
static boolean compileModule(String name, Path dest) throws IOException {
674
return CompilerUtils.compile(SRC_DIR.resolve(name), dest);
675
}
676
677
static void assertContains(String output, String subString) {
678
if (output.contains(subString))
679
assertTrue(true);
680
else
681
assertTrue(false,"Expected to find [" + subString + "], in output ["
682
+ output + "]" + "\n");
683
}
684
685
static ModuleDescriptor getModuleDescriptor(Path jmod) {
686
ClassLoader cl = ClassLoader.getSystemClassLoader();
687
try (FileSystem fs = FileSystems.newFileSystem(jmod, cl)) {
688
String p = "/classes/module-info.class";
689
try (InputStream is = Files.newInputStream(fs.getPath(p))) {
690
return ModuleDescriptor.read(is);
691
}
692
} catch (IOException ioe) {
693
throw new UncheckedIOException(ioe);
694
}
695
}
696
697
static Stream<String> findFiles(Path dir) {
698
try {
699
return Files.find(dir, Integer.MAX_VALUE, (p, a) -> a.isRegularFile())
700
.map(dir::relativize)
701
.map(Path::toString)
702
.map(p -> p.replace(File.separator, "/"));
703
} catch (IOException x) {
704
throw new UncheckedIOException(x);
705
}
706
}
707
708
static Set<String> getJmodContent(Path jmod) {
709
JmodResult r = jmod("list", jmod.toString()).assertSuccess();
710
return Stream.of(r.output.split("\r?\n")).collect(toSet());
711
}
712
713
static void assertJmodContent(Path jmod, Set<String> expected) {
714
Set<String> actual = getJmodContent(jmod);
715
if (!Objects.equals(actual, expected)) {
716
Set<String> unexpected = new HashSet<>(actual);
717
unexpected.removeAll(expected);
718
Set<String> notFound = new HashSet<>(expected);
719
notFound.removeAll(actual);
720
StringBuilder sb = new StringBuilder();
721
sb.append("Unexpected but found:\n");
722
unexpected.forEach(s -> sb.append("\t" + s + "\n"));
723
sb.append("Expected but not found:\n");
724
notFound.forEach(s -> sb.append("\t" + s + "\n"));
725
assertTrue(false, "Jmod content check failed.\n" + sb.toString());
726
}
727
}
728
729
static void assertJmodDoesNotContain(Path jmod, Set<String> unexpectedNames) {
730
Set<String> actual = getJmodContent(jmod);
731
Set<String> unexpected = new HashSet<>();
732
for (String name : unexpectedNames) {
733
if (actual.contains(name))
734
unexpected.add(name);
735
}
736
if (!unexpected.isEmpty()) {
737
StringBuilder sb = new StringBuilder();
738
for (String s : unexpected)
739
sb.append("Unexpected but found: " + s + "\n");
740
sb.append("In :");
741
for (String s : actual)
742
sb.append("\t" + s + "\n");
743
assertTrue(false, "Jmod content check failed.\n" + sb.toString());
744
}
745
}
746
747
static void assertSameContent(Path p1, Path p2) {
748
try {
749
byte[] ba1 = Files.readAllBytes(p1);
750
byte[] ba2 = Files.readAllBytes(p2);
751
assertEquals(ba1, ba2);
752
} catch (IOException x) {
753
throw new UncheckedIOException(x);
754
}
755
}
756
757
static JmodResult jmod(String... args) {
758
ByteArrayOutputStream baos = new ByteArrayOutputStream();
759
PrintStream ps = new PrintStream(baos);
760
System.out.println("jmod " + Arrays.asList(args));
761
int ec = JMOD_TOOL.run(ps, ps, args);
762
return new JmodResult(ec, new String(baos.toByteArray(), UTF_8));
763
}
764
765
static class JmodResult {
766
final int exitCode;
767
final String output;
768
769
JmodResult(int exitValue, String output) {
770
this.exitCode = exitValue;
771
this.output = output;
772
}
773
JmodResult assertSuccess() { assertTrue(exitCode == 0, output); return this; }
774
JmodResult assertFailure() { assertTrue(exitCode != 0, output); return this; }
775
JmodResult resultChecker(Consumer<JmodResult> r) { r.accept(this); return this; }
776
}
777
778
static void createCmds(Path dir) throws IOException {
779
List<String> files = Arrays.asList(
780
"first", "second", "third" + File.separator + "third");
781
createFiles(dir, files);
782
}
783
784
static void createLibs(Path dir) throws IOException {
785
List<String> files = Arrays.asList(
786
"first.so", "second.so", "third" + File.separator + "third.so");
787
createFiles(dir, files);
788
}
789
790
static void createConfigs(Path dir) throws IOException {
791
List<String> files = Arrays.asList(
792
"first.cfg", "second.cfg", "third" + File.separator + "third.cfg");
793
createFiles(dir, files);
794
}
795
796
static void createFiles(Path dir, List<String> filenames) throws IOException {
797
for (String name : filenames) {
798
Path file = dir.resolve(name);
799
Files.createDirectories(file.getParent());
800
Files.createFile(file);
801
try (OutputStream os = Files.newOutputStream(file)) {
802
os.write("blahblahblah".getBytes(UTF_8));
803
}
804
}
805
}
806
807
static void copyResource(Path srcDir, Path dir, String resource) throws IOException {
808
Path dest = dir.resolve(resource);
809
Files.deleteIfExists(dest);
810
811
Files.createDirectories(dest.getParent());
812
Files.copy(srcDir.resolve(resource), dest);
813
}
814
815
// Standalone entry point.
816
public static void main(String[] args) throws Throwable {
817
JmodTest test = new JmodTest();
818
test.buildExplodedModules();
819
for (Method m : JmodTest.class.getDeclaredMethods()) {
820
if (m.getAnnotation(Test.class) != null) {
821
System.out.println("Invoking " + m.getName());
822
m.invoke(test);
823
}
824
}
825
}
826
}
827
828