blob: 30205067b0ef0cdb52db62ce3e7d90a3d50b8579 [file] [log] [blame]
Alan Batemandb4d3832016-03-17 19:04:16 +00001/**
Igor Ignatyevc85d2732017-05-30 15:05:33 -07002 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
Alan Batemandb4d3832016-03-17 19:04:16 +00003 * 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
Igor Ignatyevff3aa032017-06-06 19:54:08 -070026 * @library /test/lib
Mandy Chung44a7c1b2016-10-12 15:41:00 -070027 * @modules jdk.compiler
28 * jdk.jlink
Igor Ignatyevff3aa032017-06-06 19:54:08 -070029 * @build jdk.test.lib.compiler.CompilerUtils
Igor Ignatyevf84b5212017-06-12 12:43:26 -070030 * jdk.test.lib.util.FileUtils
31 * jdk.test.lib.Platform
Alan Batemandb4d3832016-03-17 19:04:16 +000032 * @run testng JmodNegativeTest
33 * @summary Negative tests for jmod
34 */
35
36import java.io.*;
37import java.nio.file.Files;
38import java.nio.file.Path;
39import java.nio.file.Paths;
40import java.util.Arrays;
41import java.util.List;
42import java.util.function.Consumer;
43import java.util.function.Supplier;
Mandy Chung44a7c1b2016-10-12 15:41:00 -070044import java.util.spi.ToolProvider;
Alan Batemandb4d3832016-03-17 19:04:16 +000045import java.util.zip.ZipOutputStream;
Igor Ignatyevc85d2732017-05-30 15:05:33 -070046import jdk.test.lib.util.FileUtils;
Igor Ignatyevff3aa032017-06-06 19:54:08 -070047import jdk.test.lib.compiler.CompilerUtils;
Alan Batemandb4d3832016-03-17 19:04:16 +000048import org.testng.annotations.BeforeTest;
49import org.testng.annotations.DataProvider;
50import org.testng.annotations.Test;
51
52import static java.io.File.pathSeparator;
53import static java.nio.charset.StandardCharsets.UTF_8;
54import static org.testng.Assert.assertTrue;
55
56public class JmodNegativeTest {
57
Mandy Chung44a7c1b2016-10-12 15:41:00 -070058 static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod")
59 .orElseThrow(() ->
60 new RuntimeException("jmod tool not found")
61 );
62
Alan Batemandb4d3832016-03-17 19:04:16 +000063 static final String TEST_SRC = System.getProperty("test.src", ".");
64 static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
65 static final Path EXPLODED_DIR = Paths.get("build");
66 static final Path MODS_DIR = Paths.get("jmods");
67
68 @BeforeTest
69 public void buildExplodedModules() throws IOException {
70 if (Files.exists(EXPLODED_DIR))
71 FileUtils.deleteFileTreeWithRetry(EXPLODED_DIR);
72
73 for (String name : new String[] { "foo"/*, "bar", "baz"*/ } ) {
74 Path dir = EXPLODED_DIR.resolve(name);
75 assertTrue(compileModule(name, dir.resolve("classes")));
76 }
77
78 if (Files.exists(MODS_DIR))
79 FileUtils.deleteFileTreeWithRetry(MODS_DIR);
80 Files.createDirectories(MODS_DIR);
81 }
82
83 @Test
84 public void testNoArgs() {
85 jmod()
86 .assertFailure()
87 .resultChecker(r ->
Chris Hegarty6d2dd6f2016-12-10 14:19:53 +000088 assertContains(r.output, "Error: one of create, extract, list, describe, or hash must be specified")
Alan Batemandb4d3832016-03-17 19:04:16 +000089 );
90 }
91
92 @Test
93 public void testBadAction() {
94 jmod("badAction")
95 .assertFailure()
96 .resultChecker(r ->
Chris Hegarty6d2dd6f2016-12-10 14:19:53 +000097 assertContains(r.output, "Error: mode must be one of create, extract, list, describe, or hash")
Alan Batemandb4d3832016-03-17 19:04:16 +000098 );
99
100 jmod("--badOption")
101 .assertFailure()
102 .resultChecker(r ->
103 assertContains(r.output, "Error: 'badOption' is not a recognized option")
104 );
105 }
106
107 @Test
108 public void testTooManyArgs() throws IOException {
109 Path jmod = MODS_DIR.resolve("doesNotExist.jmod");
110 FileUtils.deleteFileIfExistsWithRetry(jmod);
111
112 jmod("create",
113 jmod.toString(),
114 "AAA")
115 .assertFailure()
116 .resultChecker(r ->
117 assertContains(r.output, "Error: unknown option(s): [AAA]")
118 );
119 }
120
121 @Test
122 public void testCreateNoArgs() {
123 jmod("create")
124 .assertFailure()
125 .resultChecker(r ->
126 assertContains(r.output, "Error: jmod-file must be specified")
127 );
128 }
129
130 @Test
131 public void testListNoArgs() {
132 jmod("list")
133 .assertFailure()
134 .resultChecker(r ->
135 assertContains(r.output, "Error: jmod-file must be specified")
136 );
137 }
138
139 @Test
140 public void testListFileDoesNotExist() throws IOException {
141 Path jmod = MODS_DIR.resolve("doesNotExist.jmod");
142 FileUtils.deleteFileIfExistsWithRetry(jmod);
143
144 jmod("list",
145 jmod.toString())
146 .assertFailure()
147 .resultChecker(r ->
148 assertContains(r.output, "Error: no jmod file found: "
149 + jmod.toString())
150 );
151 }
152
153 @Test
154 public void testListJmodIsDir() throws IOException {
155 Path jmod = MODS_DIR.resolve("testListJmodIsDir.jmod");
156 if (Files.notExists(jmod))
157 Files.createDirectory(jmod);
158
159 jmod("list",
160 jmod.toString())
161 .assertFailure()
162 .resultChecker(r ->
163 assertContains(r.output, "Error: error opening jmod file")
164 );
165 }
166
167 @Test
168 public void testlistJmodMalformed() throws IOException {
169 Path jmod = MODS_DIR.resolve("testlistJmodMalformed.jmod");
170 if (Files.notExists(jmod))
171 Files.createFile(jmod);
172
173 jmod("list",
174 jmod.toString())
175 .assertFailure()
176 .resultChecker(r ->
177 assertContains(r.output, "Error: error opening jmod file")
178 );
179 }
180
181 @Test
Alan Bateman36e08202016-05-03 09:09:57 +0100182 public void testHashModulesModulePathNotSpecified() {
Alan Batemandb4d3832016-03-17 19:04:16 +0000183 jmod("create",
Alan Bateman36e08202016-05-03 09:09:57 +0100184 "--hash-modules", "anyPattern.*",
Alan Batemandb4d3832016-03-17 19:04:16 +0000185 "output.jmod")
186 .assertFailure()
187 .resultChecker(r ->
188 assertContains(r.output, "Error: --module-path must be "
Alan Bateman36e08202016-05-03 09:09:57 +0100189 +"specified when hashing modules")
Alan Batemandb4d3832016-03-17 19:04:16 +0000190 );
191 }
192
193 @Test
194 public void testCreateJmodAlreadyExists() throws IOException {
195 Path jmod = MODS_DIR.resolve("testCreateJmodAlreadyExists.jmod");
196 if (Files.notExists(jmod))
197 Files.createFile(jmod);
198
199 jmod("create",
200 "--class-path", Paths.get(".").toString(), // anything that exists
201 jmod.toString())
202 .assertFailure()
203 .resultChecker(r ->
204 assertContains(r.output, "Error: file already exists: " + jmod.toString())
205 );
206 }
207
208 @Test
209 public void testCreateJmodIsDir() throws IOException {
210 Path jmod = MODS_DIR.resolve("testCreateJmodAlreadyExists");
211 if (Files.notExists(jmod))
212 Files.createDirectory(jmod);
213
214 jmod("create",
215 "--class-path", Paths.get(".").toString(), // anything that exists
216 jmod.toString())
217 .assertFailure()
218 .resultChecker(r ->
219 assertContains(r.output, "Error: file already exists: " + jmod.toString())
220 );
221 }
222
223 @Test
224 public void testInvalidModuleVersion() throws IOException {
225 Path jmod = MODS_DIR.resolve("testEmptyModuleVersion.jmod");
226 FileUtils.deleteFileIfExistsWithRetry(jmod);
227 String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
228
229 for (String version : new String[] { "", "NOT_A_VALID_VERSION" }) {
230 jmod("create",
231 "--class-path", cp,
232 "--module-version", version,
233 jmod.toString())
234 .assertFailure()
235 .resultChecker(r ->
236 assertContains(r.output, "Error: invalid module version")
237 );
238 }
239 }
240
Alan Batemandb4d3832016-03-17 19:04:16 +0000241 @Test
242 public void testEmptyFileInClasspath() throws IOException {
243 Path jmod = MODS_DIR.resolve("testEmptyFileInClasspath.jmod");
244 FileUtils.deleteFileIfExistsWithRetry(jmod);
245 Path jar = MODS_DIR.resolve("NotARealJar_Empty.jar");
246 FileUtils.deleteFileIfExistsWithRetry(jar);
247 Files.createFile(jar);
248
249 jmod("create",
250 "--class-path", jar.toString(),
251 jmod.toString())
252 .assertFailure()
253 .resultChecker(r ->
254 assertContains(r.output, "Error: module-info.class not found")
255 );
256 }
257
258 @Test
259 public void testEmptyJarInClasspath() throws IOException {
260 Path jmod = MODS_DIR.resolve("testEmptyJarInClasspath.jmod");
261 FileUtils.deleteFileIfExistsWithRetry(jmod);
262 Path jar = MODS_DIR.resolve("empty.jar");
263 FileUtils.deleteFileIfExistsWithRetry(jar);
264 try (FileOutputStream fos = new FileOutputStream(jar.toFile());
265 ZipOutputStream zos = new ZipOutputStream(fos)) {
266 // empty
267 }
268
269 jmod("create",
270 "--class-path", jar.toString(),
271 jmod.toString())
272 .assertFailure()
273 .resultChecker(r ->
274 assertContains(r.output, "Error: module-info.class not found")
275 );
276 }
277
278 @Test
279 public void testModuleInfoNotFound() throws IOException {
280 Path jmod = MODS_DIR.resolve("output.jmod");
281 FileUtils.deleteFileIfExistsWithRetry(jmod);
282 Path jar = MODS_DIR.resolve("empty");
283 FileUtils.deleteFileIfExistsWithRetry(jar);
284 Files.createDirectory(jar);
285
286 jmod("create",
287 "--class-path", jar.toString(),
288 jmod.toString())
289 .assertFailure()
290 .resultChecker(r ->
291 assertContains(r.output, "Error: module-info.class not found")
292 );
293 }
294
295 @Test
296 public void testModuleInfoIsDir() throws IOException {
297 Path jmod = MODS_DIR.resolve("output.jmod");
298 FileUtils.deleteFileIfExistsWithRetry(jmod);
299 Path cp = MODS_DIR.resolve("module-info.class");
300 FileUtils.deleteFileIfExistsWithRetry(cp);
301 Files.createDirectory(cp);
302 Files.createFile(cp.resolve("nada.txt"));
303
304 jmod("create",
305 "--class-path", cp.toString(),
306 jmod.toString())
307 .assertFailure()
308 .resultChecker(r ->
309 assertContains(r.output, "Error: module-info.class not found")
310 );
311 }
312
313 @Test
Alan Bateman36e08202016-05-03 09:09:57 +0100314 public void testNoModuleHash() throws IOException {
Alan Batemandb4d3832016-03-17 19:04:16 +0000315 Path jmod = MODS_DIR.resolve("output.jmod");
316 FileUtils.deleteFileIfExistsWithRetry(jmod);
317 Path emptyDir = Paths.get("empty");
318 if (Files.exists(emptyDir))
319 FileUtils.deleteFileTreeWithRetry(emptyDir);
320 Files.createDirectory(emptyDir);
321 String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
322
323 jmod("create",
324 "--class-path", cp,
Alan Bateman36e08202016-05-03 09:09:57 +0100325 "--hash-modules", ".*",
Mandy Chunge2a0ff32016-08-10 15:51:25 -0700326 "--module-path", emptyDir.toString(),
Alan Batemandb4d3832016-03-17 19:04:16 +0000327 jmod.toString())
Alan Batemandb4d3832016-03-17 19:04:16 +0000328 .resultChecker(r ->
Alan Bateman36e08202016-05-03 09:09:57 +0100329 assertContains(r.output, "No hashes recorded: " +
330 "no module specified for hashing depends on foo")
Alan Batemandb4d3832016-03-17 19:04:16 +0000331 );
332 }
333
334 @Test
335 public void testEmptyFileInModulePath() throws IOException {
336 Path jmod = MODS_DIR.resolve("output.jmod");
337 FileUtils.deleteFileIfExistsWithRetry(jmod);
338 Path empty = MODS_DIR.resolve("emptyFile.jmod");
339 FileUtils.deleteFileIfExistsWithRetry(empty);
340 Files.createFile(empty);
341 try {
342 String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
343
344 jmod("create",
345 "--class-path", cp,
Alan Bateman36e08202016-05-03 09:09:57 +0100346 "--hash-modules", ".*",
Mandy Chunge2a0ff32016-08-10 15:51:25 -0700347 "--module-path", MODS_DIR.toString(),
Alan Batemandb4d3832016-03-17 19:04:16 +0000348 jmod.toString())
Alan Bateman36e08202016-05-03 09:09:57 +0100349 .assertFailure();
Alan Batemandb4d3832016-03-17 19:04:16 +0000350 } finally {
351 FileUtils.deleteFileWithRetry(empty);
352 }
353 }
354
355 @Test
356 public void testFileInModulePath() throws IOException {
357 Path jmod = MODS_DIR.resolve("output.jmod");
358 FileUtils.deleteFileIfExistsWithRetry(jmod);
359 Path file = MODS_DIR.resolve("testFileInModulePath.txt");
360 FileUtils.deleteFileIfExistsWithRetry(file);
361 Files.createFile(file);
362
363 jmod("create",
Alan Bateman36e08202016-05-03 09:09:57 +0100364 "--hash-modules", ".*",
Mandy Chunge2a0ff32016-08-10 15:51:25 -0700365 "--module-path", file.toString(),
Alan Batemandb4d3832016-03-17 19:04:16 +0000366 jmod.toString())
367 .assertFailure()
368 .resultChecker(r ->
369 assertContains(r.output, "Error: path must be a directory")
370 );
371 }
372
373 @DataProvider(name = "pathDoesNotExist")
374 public Object[][] pathDoesNotExist() throws IOException {
375 Path jmod = MODS_DIR.resolve("output.jmod");
376 FileUtils.deleteFileIfExistsWithRetry(jmod);
377 FileUtils.deleteFileIfExistsWithRetry(Paths.get("doesNotExist"));
378
379 List<Supplier<JmodResult>> tasks = Arrays.asList(
380 () -> jmod("create",
Alan Bateman36e08202016-05-03 09:09:57 +0100381 "--hash-modules", "anyPattern",
Mandy Chunge2a0ff32016-08-10 15:51:25 -0700382 "--module-path", "doesNotExist",
Alan Batemandb4d3832016-03-17 19:04:16 +0000383 "output.jmod"),
384 () -> jmod("create",
385 "--class-path", "doesNotExist",
386 "output.jmod"),
387 () -> jmod("create",
388 "--class-path", "doesNotExist.jar",
389 "output.jmod"),
390 () -> jmod("create",
391 "--cmds", "doesNotExist",
392 "output.jmod"),
393 () -> jmod("create",
394 "--config", "doesNotExist",
395 "output.jmod"),
396 () -> jmod("create",
397 "--libs", "doesNotExist",
398 "output.jmod") );
399
400 String errMsg = "Error: path not found: doesNotExist";
401 return tasks.stream().map(t -> new Object[] {t, errMsg} )
402 .toArray(Object[][]::new);
403 }
404
405 @Test(dataProvider = "pathDoesNotExist")
406 public void testPathDoesNotExist(Supplier<JmodResult> supplier,
407 String errMsg)
408 {
409 supplier.get()
410 .assertFailure()
411 .resultChecker(r -> {
412 assertContains(r.output, errMsg);
413 });
414 }
415
416 @DataProvider(name = "partOfPathDoesNotExist")
417 public Object[][] partOfPathDoesNotExist() throws IOException {
418 Path jmod = MODS_DIR.resolve("output.jmod");
419 FileUtils.deleteFileIfExistsWithRetry(jmod);
420 FileUtils.deleteFileIfExistsWithRetry(Paths.get("doesNotExist"));
421
422 Path emptyDir = Paths.get("empty");
423 if (Files.exists(emptyDir))
424 FileUtils.deleteFileTreeWithRetry(emptyDir);
425 Files.createDirectory(emptyDir);
426
427 List<Supplier<JmodResult>> tasks = Arrays.asList(
428 () -> jmod("create",
Alan Bateman36e08202016-05-03 09:09:57 +0100429 "--hash-modules", "anyPattern",
Mandy Chunge2a0ff32016-08-10 15:51:25 -0700430 "--module-path","empty" + pathSeparator + "doesNotExist",
Alan Batemandb4d3832016-03-17 19:04:16 +0000431 "output.jmod"),
432 () -> jmod("create",
433 "--class-path", "empty" + pathSeparator + "doesNotExist",
434 "output.jmod"),
435 () -> jmod("create",
436 "--class-path", "empty" + pathSeparator + "doesNotExist.jar",
437 "output.jmod"),
438 () -> jmod("create",
439 "--cmds", "empty" + pathSeparator + "doesNotExist",
440 "output.jmod"),
441 () -> jmod("create",
442 "--config", "empty" + pathSeparator + "doesNotExist",
443 "output.jmod"),
444 () -> jmod("create",
445 "--libs", "empty" + pathSeparator + "doesNotExist",
446 "output.jmod") );
447
448 String errMsg = "Error: path not found: doesNotExist";
449 return tasks.stream().map(t -> new Object[] {t, errMsg} )
450 .toArray(Object[][]::new);
451 }
452
453 @Test(dataProvider = "partOfPathDoesNotExist")
454 public void testPartOfPathNotExist(Supplier<JmodResult> supplier,
455 String errMsg)
456 {
457 supplier.get()
458 .assertFailure()
459 .resultChecker(r -> {
460 assertContains(r.output, errMsg);
461 });
462 }
463
464 @DataProvider(name = "pathIsFile")
465 public Object[][] pathIsFile() throws IOException {
466 Path jmod = MODS_DIR.resolve("output.jmod");
467 FileUtils.deleteFileIfExistsWithRetry(jmod);
468 Path aFile = Paths.get("aFile.txt");
469 if (Files.exists(aFile) && !Files.isRegularFile(aFile))
470 throw new InternalError("Unexpected file:" + aFile);
471 else
472 Files.createFile(aFile);
473
474 List<Supplier<JmodResult>> tasks = Arrays.asList(
475 () -> jmod("create",
476 "--class-path", "aFile.txt",
477 "output.jmod"),
478 () -> jmod("create",
Mandy Chunge2a0ff32016-08-10 15:51:25 -0700479 "--module-path", "aFile.txt",
Alan Batemandb4d3832016-03-17 19:04:16 +0000480 "output.jmod"),
481 () -> jmod("create",
482 "--cmds", "aFile.txt",
483 "output.jmod"),
484 () -> jmod("create",
485 "--config", "aFile.txt",
486 "output.jmod"),
487 () -> jmod("create",
488 "--libs", "aFile.txt",
489 "output.jmod") );
490
491 String errMsg = "Error: path must be a directory: aFile.txt";
492 Object[][] a = tasks.stream().map(t -> new Object[] {t, errMsg} )
493 .toArray(Object[][]::new);
494 a[0][1] = "invalid class path entry: aFile.txt"; // class path err msg
495 return a;
496 }
497
498 @Test(dataProvider = "pathIsFile")
499 public void testPathIsFile(Supplier<JmodResult> supplier,
500 String errMsg)
501 {
502 supplier.get()
503 .assertFailure()
504 .resultChecker(r -> {
505 assertContains(r.output, errMsg);
506 });
507 }
508
509 // ---
510
511 static boolean compileModule(String name, Path dest) throws IOException {
512 return CompilerUtils.compile(SRC_DIR.resolve(name), dest);
513 }
514
515 static void assertContains(String output, String subString) {
516 if (output.contains(subString))
517 assertTrue(true);
518 else
519 assertTrue(false,"Expected to find [" + subString + "], in output ["
520 + output + "]");
521 }
522
523 static JmodResult jmod(String... args) {
524 ByteArrayOutputStream baos = new ByteArrayOutputStream();
525 PrintStream ps = new PrintStream(baos);
526 System.out.println("jmod " + Arrays.asList(args));
Mandy Chung44a7c1b2016-10-12 15:41:00 -0700527 int ec = JMOD_TOOL.run(ps, ps, args);
Alan Batemandb4d3832016-03-17 19:04:16 +0000528 return new JmodResult(ec, new String(baos.toByteArray(), UTF_8));
529 }
530
531 static class JmodResult {
532 final int exitCode;
533 final String output;
534
535 JmodResult(int exitValue, String output) {
536 this.exitCode = exitValue;
537 this.output = output;
538 }
539 JmodResult assertFailure() { assertTrue(exitCode != 0, output); return this; }
540 JmodResult resultChecker(Consumer<JmodResult> r) { r.accept(this); return this; }
541 }
542}