1 /** 2 * Copyright (c) 2015, 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 * @summary Negative tests for jlink 27 * @bug 8130861 28 * @author Andrei Eremeev 29 * @library ../lib 30 * @modules java.base/jdk.internal.jimage 31 * java.base/jdk.internal.module 32 * jdk.jdeps/com.sun.tools.classfile 33 * jdk.jlink/jdk.tools.jlink 34 * jdk.jlink/jdk.tools.jlink.internal 35 * jdk.jlink/jdk.tools.jmod 36 * jdk.jlink/jdk.tools.jimage 37 * @build tests.* 38 * @run testng JLinkNegativeTest 39 */ 40 41 import java.io.IOException; 42 import java.io.OutputStream; 43 import java.lang.module.ModuleDescriptor; 44 import java.nio.file.FileVisitResult; 45 import java.nio.file.Files; 46 import java.nio.file.Path; 47 import java.nio.file.Paths; 48 import java.nio.file.SimpleFileVisitor; 49 import java.nio.file.attribute.BasicFileAttributes; 50 import java.util.Arrays; 51 import java.util.Collections; 52 import java.util.List; 53 54 import jdk.internal.module.ModuleInfoWriter; 55 import org.testng.SkipException; 56 import org.testng.annotations.BeforeClass; 57 import org.testng.annotations.Test; 58 import tests.Helper; 59 import tests.JImageGenerator; 60 import tests.JImageGenerator.InMemoryFile; 61 import tests.Result; 62 63 @Test 64 public class JLinkNegativeTest { 65 66 private Helper helper; 67 68 @BeforeClass 69 public void setUp() throws IOException { 70 helper = Helper.newHelper(); 71 if (helper == null) { 72 throw new SkipException("Not run"); 73 } 74 helper.generateDefaultModules(); 75 } 76 77 private void deleteDirectory(Path dir) throws IOException { 78 Files.walkFileTree(dir, new SimpleFileVisitor<Path>() { 79 @Override 80 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { 81 Files.delete(file); 82 return FileVisitResult.CONTINUE; 83 } 84 85 @Override 86 public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { 87 Files.delete(dir); 88 return FileVisitResult.CONTINUE; 89 } 90 }); 91 } 92 93 public void testModuleNotExist() { 94 helper.generateDefaultImage("failure1").assertFailure("Error: Module failure1 not found"); 95 } 96 97 public void testNotExistInAddMods() { 98 // cannot find jmod from --addmods 99 JImageGenerator.getJLinkTask() 100 .modulePath(".") 101 .addMods("not_exist") 102 .output(helper.getImageDir().resolve("failure2")) 103 .call().assertFailure("Error: Module not_exist not found"); 104 } 105 106 public void test() throws IOException { 107 helper.generateDefaultJModule("failure3"); 108 Path image = helper.generateDefaultImage("failure3").assertSuccess(); 109 JImageGenerator.getJLinkTask() 110 .modulePath(helper.defaultModulePath()) 111 .output(image) 112 .addMods("leaf1") 113 .limitMods("leaf1") 114 .call().assertFailure("Error: not empty: .*failure3.image(\n|\r|.)*"); 115 } 116 117 public void testOutputIsFile() throws IOException { 118 // output == file 119 Path image = helper.createNewImageDir("failure4"); 120 Files.createFile(image); 121 JImageGenerator.getJLinkTask() 122 .modulePath(helper.defaultModulePath()) 123 .output(image) 124 .call().assertFailure("Error: file already exists: .*failure4.image(\n|\r|.)*"); 125 } 126 127 public void testModuleNotFound() { 128 // limit module is not found 129 Path imageFile = helper.createNewImageDir("test"); 130 JImageGenerator.getJLinkTask() 131 .output(imageFile) 132 .addMods("leaf1") 133 .limitMods("leaf1") 134 .limitMods("failure5") 135 .modulePath(helper.defaultModulePath()) 136 .call().assertFailure("Error: Module failure5 not found"); 137 } 138 139 public void testAddedModuleIsFiltered() { 140 // added module is filtered out 141 Path imageFile = helper.createNewImageDir("test"); 142 JImageGenerator.getJLinkTask() 143 .output(imageFile) 144 .addMods("leaf1") 145 .limitMods("leaf2") 146 .modulePath(helper.defaultModulePath()) 147 .call().assertFailure("Error: Module leaf1 not found"); 148 } 149 150 public void testJmodIsDir() throws IOException { 151 Path imageFile = helper.createNewImageDir("test"); 152 Path dirJmod = helper.createNewJmodFile("dir"); 153 Files.createDirectory(dirJmod); 154 try { 155 JImageGenerator.getJLinkTask() 156 .output(imageFile) 157 .addMods("dir") 158 .modulePath(helper.defaultModulePath()) 159 .call().assertFailure("Error: Module dir not found"); 160 } finally { 161 deleteDirectory(dirJmod); 162 } 163 } 164 165 public void testJarIsDir() throws IOException { 166 Path imageFile = helper.createNewImageDir("test"); 167 Path dirJar = helper.createNewJarFile("dir"); 168 Files.createDirectory(dirJar); 169 try { 170 JImageGenerator.getJLinkTask() 171 .output(imageFile) 172 .addMods("dir") 173 .modulePath(helper.defaultModulePath()) 174 .call().assertFailure("Error: Module dir not found"); 175 } finally { 176 deleteDirectory(dirJar); 177 } 178 } 179 180 public void testMalformedJar() throws IOException { 181 Path imageFile = helper.createNewImageDir("test"); 182 Path jar = helper.createNewJarFile("not_zip"); 183 Files.createFile(jar); 184 try { 185 JImageGenerator.getJLinkTask() 186 .output(imageFile) 187 .addMods("not_zip") 188 .modulePath(helper.defaultModulePath()) 189 .call().assertFailure("Error: java.util.zip.ZipException: zip file is empty"); 190 } finally { 191 deleteDirectory(jar); 192 } 193 } 194 195 public void testMalformedJmod() throws IOException { 196 Path imageFile = helper.createNewImageDir("test"); 197 Path jmod = helper.createNewJmodFile("not_zip"); 198 Files.createFile(jmod); 199 try { 200 JImageGenerator.getJLinkTask() 201 .output(imageFile) 202 .addMods("not_zip") 203 .modulePath(helper.defaultModulePath()) 204 .call().assertFailure("Error: java.util.zip.ZipException: zip file is empty"); 205 } finally { 206 deleteDirectory(jmod); 207 } 208 } 209 210 public void testAddDefaultPackage() throws IOException { 211 String moduleName = "hacked1"; 212 Path module = helper.generateModuleCompiledClasses(helper.getJmodSrcDir(), helper.getJmodClassesDir(), 213 moduleName, Arrays.asList("hacked1.Main", "A", "B"), "leaf1"); 214 JImageGenerator 215 .getJModTask() 216 .addClassPath(module) 217 .jmod(helper.getJmodDir().resolve(moduleName + ".jmod")) 218 .create().assertSuccess(); 219 Path image = helper.generateDefaultImage(moduleName).assertSuccess(); 220 helper.checkImage(image, moduleName, null, null); 221 } 222 223 public void testAddSomeTopLevelFiles() throws IOException { 224 String moduleName = "hacked2"; 225 Path module = helper.generateModuleCompiledClasses(helper.getJmodSrcDir(), helper.getJmodClassesDir(), 226 moduleName); 227 Files.createFile(module.resolve("top-level-file")); 228 Path jmod = JImageGenerator 229 .getJModTask() 230 .addClassPath(module) 231 .jmod(helper.getJmodDir().resolve(moduleName + ".jmod")) 232 .create().assertSuccess(); 233 try { 234 Path image = helper.generateDefaultImage(moduleName).assertSuccess(); 235 helper.checkImage(image, moduleName, null, null); 236 } finally { 237 deleteDirectory(jmod); 238 } 239 } 240 241 public void testAddNonStandardSection() throws IOException { 242 String moduleName = "hacked3"; 243 Path module = helper.generateDefaultJModule(moduleName).assertSuccess(); 244 JImageGenerator.addFiles(module, new InMemoryFile("unknown/A.class", new byte[0])); 245 try { 246 Result result = helper.generateDefaultImage(moduleName); 247 if (result.getExitCode() != 4) { 248 throw new AssertionError("Crash expected"); 249 } 250 if (!result.getMessage().contains("java.lang.InternalError: unexpected entry: unknown")) { 251 System.err.println(result.getMessage()); 252 throw new AssertionError("InternalError expected"); 253 } 254 } finally { 255 deleteDirectory(module); 256 } 257 } 258 259 @Test(enabled = false) 260 public void testSectionsAreFiles() throws IOException { 261 String moduleName = "module"; 262 Path jmod = helper.generateDefaultJModule(moduleName).assertSuccess(); 263 JImageGenerator.addFiles(jmod, 264 new InMemoryFile("/native", new byte[0]), 265 new InMemoryFile("/conf", new byte[0]), 266 new InMemoryFile("/bin", new byte[0])); 267 Path image = helper.generateDefaultImage(moduleName).assertSuccess(); 268 helper.checkImage(image, moduleName, null, null); 269 } 270 271 public void testDuplicateModule1() throws IOException { 272 String moduleName1 = "dupRes1Jmod1"; 273 String moduleName2 = "dupRes1Jmod2"; 274 List<String> classNames = Arrays.asList("java.A", "javax.B"); 275 Path module1 = helper.generateModuleCompiledClasses( 276 helper.getJmodSrcDir(), helper.getJmodClassesDir(), moduleName1, classNames); 277 Path module2 = helper.generateModuleCompiledClasses( 278 helper.getJmodSrcDir(), helper.getJmodClassesDir(), moduleName2, classNames); 279 280 try (OutputStream out = Files.newOutputStream(module2.resolve("module-info.class"))) { 281 ModuleInfoWriter.write(new ModuleDescriptor.Builder(moduleName1) 282 .requires("java.base").build(), out); 283 } 284 285 Path jmod1 = JImageGenerator.getJModTask() 286 .addClassPath(module1) 287 .jmod(helper.createNewJmodFile(moduleName1)) 288 .create() 289 .assertSuccess(); 290 Path jmod2 = JImageGenerator.getJModTask() 291 .addClassPath(module2) 292 .jmod(helper.createNewJmodFile(moduleName2)) 293 .create() 294 .assertSuccess(); 295 try { 296 helper.generateDefaultImage(moduleName1) 297 .assertFailure("Error: Two versions of module dupRes1Jmod1 found in"); 298 } finally { 299 deleteDirectory(jmod1); 300 deleteDirectory(jmod2); 301 } 302 } 303 304 public void testDuplicateModule2() throws IOException { 305 String moduleName = "dupRes2Jmod"; 306 List<String> classNames = Arrays.asList("java.A", "javax.B"); 307 Path module1 = helper.generateModuleCompiledClasses( 308 helper.getJmodSrcDir(), helper.getJmodClassesDir(), moduleName, classNames); 309 Path module2 = helper.generateModuleCompiledClasses( 310 helper.getJarSrcDir(), helper.getJarClassesDir(), moduleName, classNames); 311 312 Path jmod = JImageGenerator.getJModTask() 313 .addClassPath(module1) 314 .jmod(helper.createNewJmodFile(moduleName)) 315 .create() 316 .assertSuccess(); 317 Path jar = JImageGenerator.createJarFile(helper.getJarDir().resolve(moduleName + ".jar"), module2); 318 Path newJar = helper.getJmodDir().resolve(jar.getFileName()); 319 Files.move(jar, newJar); 320 try { 321 helper.generateDefaultImage(moduleName) 322 .assertFailure("Error: Two versions of module dupRes2Jmod found in"); 323 } finally { 324 deleteDirectory(jmod); 325 deleteDirectory(newJar); 326 } 327 } 328 329 public void testDuplicateModule3() throws IOException { 330 String moduleName1 = "dupRes3Jar1"; 331 String moduleName2 = "dupRes3Jar2"; 332 List<String> classNames = Arrays.asList("java.A", "javax.B"); 333 Path module1 = helper.generateModuleCompiledClasses( 334 helper.getJarSrcDir(), helper.getJarClassesDir(), moduleName1, classNames); 335 Path module2 = helper.generateModuleCompiledClasses( 336 helper.getJarSrcDir(), helper.getJarClassesDir(), moduleName2, classNames); 337 338 try (OutputStream out = Files.newOutputStream(module2.resolve("module-info.class"))) { 339 ModuleInfoWriter.write(new ModuleDescriptor.Builder(moduleName1) 340 .requires("java.base").build(), out); 341 } 342 343 Path jar1 = JImageGenerator.createJarFile(helper.getJarDir().resolve(moduleName1 + ".jar"), module1); 344 Path jar2 = JImageGenerator.createJarFile(helper.getJarDir().resolve(moduleName2 + ".jar"), module2); 345 try { 346 helper.generateDefaultImage(moduleName1) 347 .assertFailure("Error: Two versions of module dupRes3Jar1 found in"); 348 } finally { 349 deleteDirectory(jar1); 350 deleteDirectory(jar2); 351 } 352 } 353 354 public void testCustomImageBuilderNotFound() throws IOException { 355 String builderName = "not-found-image-builder"; 356 JImageGenerator.getJLinkTask() 357 .option("--image-builder") 358 .option("not-found-image-builder") 359 .modulePath(helper.defaultModulePath()) 360 .output(helper.createNewImageDir("leaf1")) 361 .addMods("leaf1") 362 .call().assertFailure("Error: Image builder not found for " + builderName); 363 } 364 }