Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/tools/jar/mmrjar/Basic.java
41149 views
1
/*
2
* Copyright (c) 2016, 2017, 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 8146486 8172432
27
* @summary Fail to create a MR modular JAR with a versioned entry in
28
* base-versioned empty package
29
* @modules java.base/jdk.internal.module
30
* jdk.compiler
31
* jdk.jartool
32
* @library /test/lib
33
* @build jdk.test.lib.Platform
34
* jdk.test.lib.util.FileUtils
35
* @run testng Basic
36
*/
37
38
import org.testng.Assert;
39
import org.testng.annotations.AfterClass;
40
import org.testng.annotations.Test;
41
42
import java.io.ByteArrayInputStream;
43
import java.io.ByteArrayOutputStream;
44
import java.io.IOException;
45
import java.io.PrintStream;
46
import java.io.UncheckedIOException;
47
import java.lang.module.ModuleDescriptor;
48
import java.lang.module.ModuleDescriptor.Version;
49
import java.nio.file.Files;
50
import java.nio.file.Path;
51
import java.nio.file.Paths;
52
import java.util.Arrays;
53
import java.util.Optional;
54
import java.util.Set;
55
import java.util.spi.ToolProvider;
56
import java.util.stream.Collectors;
57
import java.util.stream.Stream;
58
import java.util.zip.ZipFile;
59
60
import jdk.internal.module.ModuleInfoExtender;
61
import jdk.test.lib.util.FileUtils;
62
63
public class Basic {
64
private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
65
.orElseThrow(() -> new RuntimeException("jar tool not found"));
66
private static final ToolProvider JAVAC_TOOL = ToolProvider.findFirst("javac")
67
.orElseThrow(() -> new RuntimeException("javac tool not found"));
68
private final String linesep = System.lineSeparator();
69
private final Path testsrc;
70
private final Path userdir;
71
private final ByteArrayOutputStream outbytes = new ByteArrayOutputStream();
72
private final PrintStream out = new PrintStream(outbytes, true);
73
private final ByteArrayOutputStream errbytes = new ByteArrayOutputStream();
74
private final PrintStream err = new PrintStream(errbytes, true);
75
76
public Basic() throws IOException {
77
testsrc = Paths.get(System.getProperty("test.src"));
78
userdir = Paths.get(System.getProperty("user.dir", "."));
79
80
// compile the classes directory
81
Path source = testsrc.resolve("src").resolve("classes");
82
Path destination = Paths.get("classes");
83
javac(source, destination);
84
85
// compile the mr9 directory including module-info.java
86
source = testsrc.resolve("src").resolve("mr9");
87
destination = Paths.get("mr9");
88
javac(source, destination);
89
90
// move module-info.class for later use
91
Files.move(destination.resolve("module-info.class"),
92
Paths.get("module-info.class"));
93
}
94
95
private void javac(Path source, Path destination) throws IOException {
96
String[] args = Stream.concat(
97
Stream.of("-d", destination.toString()),
98
Files.walk(source)
99
.map(Path::toString)
100
.filter(s -> s.endsWith(".java"))
101
).toArray(String[]::new);
102
JAVAC_TOOL.run(System.out, System.err, args);
103
}
104
105
private int jar(String cmd) {
106
outbytes.reset();
107
errbytes.reset();
108
return JAR_TOOL.run(out, err, cmd.split(" +"));
109
}
110
111
@AfterClass
112
public void cleanup() throws IOException {
113
Files.walk(userdir, 1)
114
.filter(p -> !p.equals(userdir))
115
.forEach(p -> {
116
try {
117
if (Files.isDirectory(p)) {
118
FileUtils.deleteFileTreeWithRetry(p);
119
} else {
120
FileUtils.deleteFileIfExistsWithRetry(p);
121
}
122
} catch (IOException x) {
123
throw new UncheckedIOException(x);
124
}
125
});
126
}
127
128
// updates a valid multi-release jar with a new public class in
129
// versioned section and fails
130
@Test
131
public void test1() {
132
// successful build of multi-release jar
133
int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 p/Hi.class");
134
Assert.assertEquals(rc, 0);
135
136
jar("-tf mmr.jar");
137
138
Set<String> actual = lines(outbytes);
139
Set<String> expected = Set.of(
140
"META-INF/",
141
"META-INF/MANIFEST.MF",
142
"p/",
143
"p/Hi.class",
144
"META-INF/versions/9/p/Hi.class"
145
);
146
Assert.assertEquals(actual, expected);
147
148
// failed build because of new public class
149
rc = jar("-uf mmr.jar --release 9 -C mr9 p/internal/Bar.class");
150
Assert.assertEquals(rc, 1);
151
152
String s = new String(errbytes.toByteArray());
153
Assert.assertTrue(Message.NOT_FOUND_IN_BASE_ENTRY.match(s, "p/internal/Bar.class"));
154
}
155
156
// updates a valid multi-release jar with a module-info class and new
157
// concealed public class in versioned section and succeeds
158
@Test
159
public void test2() {
160
// successful build of multi-release jar
161
int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 p/Hi.class");
162
Assert.assertEquals(rc, 0);
163
164
// successful build because of module-info and new public class
165
rc = jar("-uf mmr.jar module-info.class --release 9 -C mr9 p/internal/Bar.class");
166
Assert.assertEquals(rc, 0);
167
168
String s = new String(errbytes.toByteArray());
169
Assert.assertTrue(Message.NEW_CONCEALED_PACKAGE_WARNING.match(s, "p/internal/Bar.class"));
170
171
jar("-tf mmr.jar");
172
173
Set<String> actual = lines(outbytes);
174
Set<String> expected = Set.of(
175
"META-INF/",
176
"META-INF/MANIFEST.MF",
177
"p/",
178
"p/Hi.class",
179
"META-INF/versions/9/p/Hi.class",
180
"META-INF/versions/9/p/internal/Bar.class",
181
"module-info.class"
182
);
183
Assert.assertEquals(actual, expected);
184
}
185
186
// jar tool fails building mmr.jar because of new public class
187
@Test
188
public void test3() {
189
int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 .");
190
Assert.assertEquals(rc, 1);
191
192
String s = new String(errbytes.toByteArray());
193
Assert.assertTrue(Message.NOT_FOUND_IN_BASE_ENTRY.match(s, "p/internal/Bar.class"));
194
}
195
196
// jar tool succeeds building mmr.jar because of concealed package
197
@Test
198
public void test4() {
199
int rc = jar("-cf mmr.jar module-info.class -C classes . " +
200
"--release 9 module-info.class -C mr9 .");
201
Assert.assertEquals(rc, 0);
202
203
String s = new String(errbytes.toByteArray());
204
Assert.assertTrue(Message.NEW_CONCEALED_PACKAGE_WARNING.match(s, "p/internal/Bar.class"));
205
206
jar("-tf mmr.jar");
207
208
Set<String> actual = lines(outbytes);
209
Set<String> expected = Set.of(
210
"META-INF/",
211
"META-INF/MANIFEST.MF",
212
"module-info.class",
213
"META-INF/versions/9/module-info.class",
214
"p/",
215
"p/Hi.class",
216
"META-INF/versions/9/",
217
"META-INF/versions/9/p/",
218
"META-INF/versions/9/p/Hi.class",
219
"META-INF/versions/9/p/internal/",
220
"META-INF/versions/9/p/internal/Bar.class"
221
);
222
Assert.assertEquals(actual, expected);
223
}
224
225
// jar tool does two updates, no exported packages, all concealed.
226
// Along with various --describe-module variants
227
@Test
228
public void test5() throws IOException {
229
// compile the mr10 directory
230
Path source = testsrc.resolve("src").resolve("mr10");
231
Path destination = Paths.get("mr10");
232
javac(source, destination);
233
234
// create a directory for this tests special files
235
Files.createDirectory(Paths.get("test5"));
236
237
// create an empty module-info.java
238
String hi = "module hi {" + linesep + "}" + linesep;
239
Path modinfo = Paths.get("test5", "module-info.java");
240
Files.write(modinfo, hi.getBytes());
241
242
// and compile it
243
javac(modinfo, Paths.get("test5"));
244
245
int rc = jar("--create --file mr.jar -C classes .");
246
Assert.assertEquals(rc, 0);
247
248
rc = jar("--update --file mr.jar -C test5 module-info.class"
249
+ " --release 9 -C mr9 .");
250
Assert.assertEquals(rc, 0);
251
252
jar("tf mr.jar");
253
254
Set<String> actual = lines(outbytes);
255
Set<String> expected = Set.of(
256
"META-INF/",
257
"META-INF/MANIFEST.MF",
258
"p/",
259
"p/Hi.class",
260
"META-INF/versions/9/",
261
"META-INF/versions/9/p/",
262
"META-INF/versions/9/p/Hi.class",
263
"META-INF/versions/9/p/internal/",
264
"META-INF/versions/9/p/internal/Bar.class",
265
"module-info.class"
266
);
267
Assert.assertEquals(actual, expected);
268
269
jar("-d --file mr.jar");
270
271
String uri = (Paths.get("mr.jar")).toUri().toString();
272
uri = "jar:" + uri + "!/module-info.class";
273
274
actual = lines(outbytes);
275
expected = Set.of(
276
"hi " + uri,
277
"requires java.base mandated",
278
"contains p",
279
"contains p.internal"
280
);
281
Assert.assertEquals(actual, expected);
282
283
rc = jar("--update --file mr.jar --release 10 -C mr10 .");
284
Assert.assertEquals(rc, 0);
285
286
jar("tf mr.jar");
287
288
actual = lines(outbytes);
289
expected = Set.of(
290
"META-INF/",
291
"META-INF/MANIFEST.MF",
292
"p/",
293
"p/Hi.class",
294
"META-INF/versions/9/",
295
"META-INF/versions/9/p/",
296
"META-INF/versions/9/p/Hi.class",
297
"META-INF/versions/9/p/internal/",
298
"META-INF/versions/9/p/internal/Bar.class",
299
"META-INF/versions/10/",
300
"META-INF/versions/10/p/",
301
"META-INF/versions/10/p/internal/",
302
"META-INF/versions/10/p/internal/bar/",
303
"META-INF/versions/10/p/internal/bar/Gee.class",
304
"module-info.class"
305
);
306
Assert.assertEquals(actual, expected);
307
308
jar("-d --file mr.jar");
309
310
actual = lines(outbytes);
311
expected = Set.of(
312
"hi " + uri,
313
"requires java.base mandated",
314
"contains p",
315
"contains p.internal",
316
"contains p.internal.bar"
317
);
318
Assert.assertEquals(actual, expected);
319
320
for (String release : new String[] {"9" , "10", "100", "1000"}) {
321
jar("-d --file mr.jar --release " + release);
322
actual = lines(outbytes);
323
Assert.assertEquals(actual, expected);
324
}
325
}
326
327
// root and versioned module-info entries have different main-class, version
328
// attributes
329
@Test
330
public void test6() throws IOException {
331
// create a directory for this tests special files
332
Files.createDirectory(Paths.get("test6"));
333
Files.createDirectory(Paths.get("test6-v9"));
334
335
// compile the classes directory
336
Path src = testsrc.resolve("src").resolve("classes");
337
Path dst = Paths.get("test6");
338
javac(src, dst);
339
340
byte[] mdBytes = Files.readAllBytes(Paths.get("module-info.class"));
341
342
ModuleInfoExtender mie = ModuleInfoExtender.newExtender(
343
new ByteArrayInputStream(mdBytes));
344
345
mie.mainClass("p.Main");
346
mie.version(Version.parse("1.0"));
347
348
ByteArrayOutputStream baos = new ByteArrayOutputStream();
349
mie.write(baos);
350
Files.write(Paths.get("test6", "module-info.class"), baos.toByteArray());
351
Files.write(Paths.get("test6-v9", "module-info.class"), baos.toByteArray());
352
353
int rc = jar("--create --file mmr.jar -C test6 . --release 9 -C test6-v9 .");
354
Assert.assertEquals(rc, 0);
355
356
357
// different main-class
358
mie = ModuleInfoExtender.newExtender(new ByteArrayInputStream(mdBytes));
359
mie.mainClass("p.Main2");
360
mie.version(Version.parse("1.0"));
361
baos.reset();
362
mie.write(baos);
363
Files.write(Paths.get("test6-v9", "module-info.class"), baos.toByteArray());
364
365
rc = jar("--create --file mmr.jar -C test6 . --release 9 -C test6-v9 .");
366
Assert.assertEquals(rc, 1);
367
368
Assert.assertTrue(Message.CONTAINS_DIFFERENT_MAINCLASS.match(
369
new String(errbytes.toByteArray()),
370
"META-INF/versions/9/module-info.class"));
371
372
// different version
373
mie = ModuleInfoExtender.newExtender(new ByteArrayInputStream(mdBytes));
374
mie.mainClass("p.Main");
375
mie.version(Version.parse("2.0"));
376
baos.reset();
377
mie.write(baos);
378
Files.write(Paths.get("test6-v9", "module-info.class"), baos.toByteArray());
379
380
rc = jar("--create --file mmr.jar -C test6 . --release 9 -C test6-v9 .");
381
Assert.assertEquals(rc, 1);
382
383
Assert.assertTrue(Message.CONTAINS_DIFFERENT_VERSION.match(
384
new String(errbytes.toByteArray()),
385
"META-INF/versions/9/module-info.class"));
386
387
}
388
389
// versioned mmr without root module-info.class
390
@Test
391
public void test7() throws IOException {
392
// create a directory for this tests special files
393
Files.createDirectory(Paths.get("test7"));
394
Files.createDirectory(Paths.get("test7-v9"));
395
Files.createDirectory(Paths.get("test7-v10"));
396
397
// compile the classes directory
398
Path src = testsrc.resolve("src").resolve("classes");
399
Path dst = Paths.get("test7");
400
javac(src, dst);
401
402
// move module-info.class to v9 later use
403
Files.copy(Paths.get("module-info.class"),
404
Paths.get("test7-v9", "module-info.class"));
405
406
Files.copy(Paths.get("test7-v9", "module-info.class"),
407
Paths.get("test7-v10", "module-info.class"));
408
409
int rc = jar("--create --file mmr.jar --main-class=p.Main -C test7 . --release 9 -C test7-v9 . --release 10 -C test7-v10 .");
410
Assert.assertEquals(rc, 0);
411
412
jar("-d --file=mmr.jar");
413
Set<String> actual = lines(outbytes);
414
Set<String> expected = Set.of(
415
"releases: 9 10",
416
"No root module descriptor, specify --release"
417
);
418
Assert.assertEquals(actual, expected);
419
420
String uriPrefix = "jar:" + (Paths.get("mmr.jar")).toUri().toString();
421
422
jar("-d --file=mmr.jar --release 9");
423
actual = lines(outbytes);
424
expected = Set.of(
425
"releases: 9 10",
426
"m1 " + uriPrefix + "!/META-INF/versions/9/module-info.class",
427
"requires java.base mandated",
428
"exports p",
429
"main-class p.Main"
430
);
431
Assert.assertEquals(actual, expected);
432
433
jar("-d --file=mmr.jar --release 10");
434
actual = lines(outbytes);
435
expected = Set.of(
436
"releases: 9 10",
437
"m1 " + uriPrefix + "!/META-INF/versions/10/module-info.class",
438
"requires java.base mandated",
439
"exports p",
440
"main-class p.Main"
441
);
442
Assert.assertEquals(actual, expected);
443
444
for (String release : new String[] {"11", "12", "15", "100"}) {
445
jar("-d --file mmr.jar --release " + release);
446
actual = lines(outbytes);
447
Assert.assertEquals(actual, expected);
448
}
449
450
Optional<String> exp = Optional.of("p.Main");
451
try (ZipFile zf = new ZipFile("mmr.jar")) {
452
Assert.assertTrue(zf.getEntry("module-info.class") == null);
453
454
ModuleDescriptor md = ModuleDescriptor.read(
455
zf.getInputStream(zf.getEntry("META-INF/versions/9/module-info.class")));
456
Assert.assertEquals(md.mainClass(), exp);
457
458
md = ModuleDescriptor.read(
459
zf.getInputStream(zf.getEntry("META-INF/versions/10/module-info.class")));
460
Assert.assertEquals(md.mainClass(), exp);
461
}
462
}
463
464
private static Set<String> lines(ByteArrayOutputStream baos) {
465
String s = new String(baos.toByteArray());
466
return Arrays.stream(s.split("\\R"))
467
.map(l -> l.trim())
468
.filter(l -> l.length() > 0)
469
.collect(Collectors.toSet());
470
}
471
472
static enum Message {
473
CONTAINS_DIFFERENT_MAINCLASS(
474
": module-info.class in a versioned directory contains different \"main-class\""
475
),
476
CONTAINS_DIFFERENT_VERSION(
477
": module-info.class in a versioned directory contains different \"version\""
478
),
479
NOT_FOUND_IN_BASE_ENTRY(
480
", contains a new public class not found in base entries"
481
),
482
NEW_CONCEALED_PACKAGE_WARNING(
483
" is a public class" +
484
" in a concealed package, placing this jar on the class path will result" +
485
" in incompatible public interfaces"
486
);
487
488
final String msg;
489
Message(String msg) {
490
this.msg = msg;
491
}
492
493
/*
494
* Test if the given output contains this message ignoring the line break.
495
*/
496
boolean match(String output, String entry) {
497
System.out.println("Expected: " + entry + msg);
498
System.out.println("Found: " + output);
499
return Arrays.stream(output.split("\\R"))
500
.collect(Collectors.joining(" "))
501
.contains(entry + msg);
502
}
503
}
504
}
505
506