1 /* 2 * Copyright (c) 2016, 2018, 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.File; 25 import java.io.IOException; 26 import java.nio.file.Files; 27 import java.nio.file.Path; 28 import java.nio.file.Paths; 29 import java.util.Arrays; 30 import java.util.Set; 31 import java.util.spi.ToolProvider; 32 import java.util.stream.Collectors; 33 import java.util.stream.Stream; 34 35 import jdk.test.lib.compiler.CompilerUtils; 36 import jdk.test.lib.util.FileUtils; 37 38 import static jdk.test.lib.process.ProcessTools.*; 39 40 import org.testng.annotations.BeforeTest; 41 import org.testng.annotations.Test; 42 import static org.testng.Assert.*; 43 44 /** 45 * @test 46 * @bug 8142968 8173381 8174740 47 * @library /test/lib 48 * @modules jdk.compiler jdk.jlink 49 * @modules java.base/jdk.internal.module 50 * @modules java.base/jdk.internal.org.objectweb.asm 51 * @build jdk.test.lib.compiler.CompilerUtils 52 * jdk.test.lib.util.FileUtils 53 * jdk.test.lib.Platform 54 * ModuleTargetHelper UserModuleTest jdk.test.lib.process.ProcessTools 55 * @run testng UserModuleTest 56 */ 57 58 public class UserModuleTest { 59 private static final String JAVA_HOME = System.getProperty("java.home"); 60 private static final String TEST_SRC = System.getProperty("test.src"); 61 62 private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); 63 private static final Path MODS_DIR = Paths.get("mods"); 64 private static final Path JMODS_DIR = Paths.get("jmods"); 65 66 private static final Path IMAGE = Paths.get("image"); 67 private static final String MAIN_MID = "m1/p1.Main"; 68 69 // the names of the modules in this test 70 private static String[] modules = new String[] {"m1", "m2", "m3", "m4", "m5"}; 71 72 hasJmods()73 private static boolean hasJmods() { 74 if (!Files.exists(Paths.get(JAVA_HOME, "jmods"))) { 75 System.err.println("Test skipped. NO jmods directory"); 76 return false; 77 } 78 return true; 79 } 80 81 /* 82 * Compiles all modules used by the test 83 */ 84 @BeforeTest compileAll()85 public void compileAll() throws Throwable { 86 if (!hasJmods()) return; 87 88 for (String mn : modules) { 89 Path msrc = SRC_DIR.resolve(mn); 90 assertTrue(CompilerUtils.compile(msrc, MODS_DIR, 91 "--module-source-path", SRC_DIR.toString(), 92 "--add-exports", "java.base/jdk.internal.module=" + mn, 93 "--add-exports", "java.base/jdk.internal.org.objectweb.asm=" + mn)); 94 } 95 96 if (Files.exists(IMAGE)) { 97 FileUtils.deleteFileTreeUnchecked(IMAGE); 98 } 99 100 createImage(IMAGE, "m1", "m3"); 101 102 createJmods("m1", "m4"); 103 } 104 105 /* 106 * Test the image created when linking with a module with 107 * no Packages attribute 108 */ 109 @Test testPackagesAttribute()110 public void testPackagesAttribute() throws Throwable { 111 if (!hasJmods()) return; 112 113 Path java = IMAGE.resolve("bin").resolve("java"); 114 assertTrue(executeProcess(java.toString(), 115 "--add-exports", "java.base/jdk.internal.module=m1,m4", 116 "--add-exports", "java.base/jdk.internal.org.objectweb.asm=m1,m4", 117 "-m", MAIN_MID) 118 .outputTo(System.out) 119 .errorTo(System.out) 120 .getExitValue() == 0); 121 } 122 123 /* 124 * Test the image created when linking with an open module 125 */ 126 @Test testOpenModule()127 public void testOpenModule() throws Throwable { 128 if (!hasJmods()) return; 129 130 Path java = IMAGE.resolve("bin").resolve("java"); 131 assertTrue(executeProcess(java.toString(), "-m", "m3/p3.Main") 132 .outputTo(System.out) 133 .errorTo(System.out) 134 .getExitValue() == 0); 135 } 136 137 /* 138 * Disable the fast loading of system modules. 139 * Parsing module-info.class 140 */ 141 @Test disableSystemModules()142 public void disableSystemModules() throws Throwable { 143 if (!hasJmods()) return; 144 145 Path java = IMAGE.resolve("bin").resolve("java"); 146 assertTrue(executeProcess(java.toString(), 147 "--add-exports", "java.base/jdk.internal.module=m1,m4", 148 "--add-exports", "java.base/jdk.internal.org.objectweb.asm=m1,m4", 149 "-Djdk.system.module.finder.disabledFastPath", 150 "-m", MAIN_MID) 151 .outputTo(System.out) 152 .errorTo(System.out) 153 .getExitValue() == 0); 154 } 155 156 /* 157 * Test the optimization that deduplicates Set<String> on targets of exports, 158 * uses, provides. 159 */ 160 @Test testDedupSet()161 public void testDedupSet() throws Throwable { 162 if (!hasJmods()) return; 163 164 Path dir = Paths.get("dedupSetTest"); 165 createImage(dir, "m1", "m2", "m3", "m4"); 166 Path java = dir.resolve("bin").resolve("java"); 167 assertTrue(executeProcess(java.toString(), 168 "--add-exports", "java.base/jdk.internal.module=m1,m4", 169 "--add-exports", "java.base/jdk.internal.org.objectweb.asm=m1,m4", 170 "-m", MAIN_MID) 171 .outputTo(System.out) 172 .errorTo(System.out) 173 .getExitValue() == 0); 174 } 175 176 @Test testRequiresStatic()177 public void testRequiresStatic() throws Throwable { 178 if (!hasJmods()) return; 179 180 Path dir = Paths.get("requiresStatic"); 181 createImage(dir, "m5"); 182 Path java = dir.resolve("bin").resolve("java"); 183 assertTrue(executeProcess(java.toString(), "-m", "m5/p5.Main") 184 .outputTo(System.out) 185 .errorTo(System.out) 186 .getExitValue() == 0); 187 188 // run with m3 present 189 assertTrue(executeProcess(java.toString(), 190 "--module-path", MODS_DIR.toString(), 191 "--add-modules", "m3", 192 "-m", "m5/p5.Main") 193 .outputTo(System.out) 194 .errorTo(System.out) 195 .getExitValue() == 0); 196 } 197 198 @Test testRequiresStatic2()199 public void testRequiresStatic2() throws Throwable { 200 if (!hasJmods()) return; 201 202 Path dir = Paths.get("requiresStatic2"); 203 createImage(dir, "m3", "m5"); 204 205 Path java = dir.resolve("bin").resolve("java"); 206 assertTrue(executeProcess(java.toString(), "-m", "m5/p5.Main") 207 .outputTo(System.out) 208 .errorTo(System.out) 209 .getExitValue() == 0); 210 211 // boot layer with m3 and m5 212 assertTrue(executeProcess(java.toString(), 213 "--add-modules", "m3", 214 "-m", "m5/p5.Main") 215 .outputTo(System.out) 216 .errorTo(System.out) 217 .getExitValue() == 0); 218 } 219 createJmods(String... modules)220 private void createJmods(String... modules) throws IOException { 221 ModuleTargetHelper.ModuleTarget mt = ModuleTargetHelper.getJavaBaseTarget(); 222 if (mt == null) { 223 throw new RuntimeException("ModuleTarget is missing for java.base"); 224 } 225 226 String[] values = mt.targetPlatform().split("-"); 227 String osName = values[0]; 228 String osArch = values[1]; 229 230 // create JMOD files 231 Files.createDirectories(JMODS_DIR); 232 Stream.of(modules).forEach(mn -> 233 assertTrue(jmod("create", 234 "--class-path", MODS_DIR.resolve(mn).toString(), 235 "--target-platform", mt.targetPlatform(), 236 "--main-class", mn.replace('m', 'p') + ".Main", 237 JMODS_DIR.resolve(mn + ".jmod").toString()) == 0) 238 ); 239 } 240 241 242 /** 243 * Verify the module descriptor if package p4.dummy is excluded at link time. 244 */ 245 @Test testModulePackagesAttribute()246 public void testModulePackagesAttribute() throws Throwable { 247 if (!hasJmods()) return; 248 249 // create an image using JMOD files 250 Path dir = Paths.get("packagesTest"); 251 String mp = Paths.get(JAVA_HOME, "jmods").toString() + 252 File.pathSeparator + JMODS_DIR.toString(); 253 254 Set<String> modules = Set.of("m1", "m4"); 255 assertTrue(JLINK_TOOL.run(System.out, System.out, 256 "--output", dir.toString(), 257 "--exclude-resources", "m4/p4/dummy/*", 258 "--add-modules", modules.stream().collect(Collectors.joining(",")), 259 "--module-path", mp) == 0); 260 261 // verify ModuleDescriptor 262 Path java = dir.resolve("bin").resolve("java"); 263 assertTrue(executeProcess(java.toString(), 264 "--add-exports", "java.base/jdk.internal.module=m1,m4", 265 "--add-exports", "java.base/jdk.internal.org.objectweb.asm=m1,m4", 266 "--add-modules=m1", "-m", "m4") 267 .outputTo(System.out) 268 .errorTo(System.out) 269 .getExitValue() == 0); 270 } 271 272 /** 273 * Verify the plugin to retain ModuleTarget attribute 274 */ 275 @Test testRetainModuleTarget()276 public void testRetainModuleTarget() throws Throwable { 277 if (!hasJmods()) return; 278 279 // create an image using JMOD files 280 Path dir = Paths.get("retainModuleTargetTest"); 281 String mp = Paths.get(JAVA_HOME, "jmods").toString() + 282 File.pathSeparator + JMODS_DIR.toString(); 283 284 Set<String> modules = Set.of("m1", "m4"); 285 assertTrue(JLINK_TOOL.run(System.out, System.out, 286 "--output", dir.toString(), 287 "--exclude-resources", "m4/p4/dummy/*", 288 "--add-modules", modules.stream().collect(Collectors.joining(",")), 289 "--module-path", mp) == 0); 290 291 // verify ModuleDescriptor 292 Path java = dir.resolve("bin").resolve("java"); 293 assertTrue(executeProcess(java.toString(), 294 "--add-exports", "java.base/jdk.internal.module=m1,m4", 295 "--add-exports", "java.base/jdk.internal.org.objectweb.asm=m1,m4", 296 "--add-modules=m1", "-m", "m4", "retainModuleTarget") 297 .outputTo(System.out) 298 .errorTo(System.out) 299 .getExitValue() == 0); 300 } 301 302 static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink") 303 .orElseThrow(() -> 304 new RuntimeException("jlink tool not found") 305 ); 306 307 static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod") 308 .orElseThrow(() -> 309 new RuntimeException("jmod tool not found") 310 ); 311 312 static final String MODULE_PATH = Paths.get(JAVA_HOME, "jmods").toString() 313 + File.pathSeparator + MODS_DIR.toString(); 314 createImage(Path outputDir, String... modules)315 private void createImage(Path outputDir, String... modules) throws Throwable { 316 assertTrue(JLINK_TOOL.run(System.out, System.out, 317 "--output", outputDir.toString(), 318 "--add-modules", Arrays.stream(modules).collect(Collectors.joining(",")), 319 "--module-path", MODULE_PATH) == 0); 320 } 321 jmod(String... options)322 private static int jmod(String... options) { 323 System.out.println("jmod " + Arrays.asList(options)); 324 return JMOD_TOOL.run(System.out, System.out, options); 325 } 326 } 327