1 /* 2 * Copyright (c) 2015, 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.IOException; 25 import java.io.PrintWriter; 26 import java.io.StringWriter; 27 import java.lang.module.ModuleDescriptor; 28 import java.nio.file.Files; 29 import java.nio.file.Path; 30 import java.nio.file.Paths; 31 import java.util.ArrayList; 32 import java.util.Collections; 33 import java.util.List; 34 import java.util.spi.ToolProvider; 35 import java.util.stream.Stream; 36 37 import jdk.tools.jlink.plugin.Plugin; 38 import jdk.tools.jlink.internal.PluginRepository; 39 import tests.Helper; 40 import tests.JImageGenerator; 41 42 /* 43 * @test 44 * @summary Test image creation 45 * @bug 8189777 46 * @bug 8194922 47 * @bug 8206962 48 * @author Jean-Francois Denise 49 * @requires (vm.compMode != "Xcomp" & os.maxMemory >= 2g) 50 * @library ../lib 51 * @modules java.base/jdk.internal.jimage 52 * jdk.jdeps/com.sun.tools.classfile 53 * jdk.jlink/jdk.tools.jlink.internal 54 * jdk.jlink/jdk.tools.jlink.plugin 55 * jdk.jlink/jdk.tools.jimage 56 * jdk.compiler 57 * @build tests.* 58 * @run main/othervm -Xmx1g JLinkTest 59 */ 60 public class JLinkTest { 61 static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink") 62 .orElseThrow(() -> 63 new RuntimeException("jlink tool not found") 64 ); 65 66 // number of built-in plugins from jdk.jlink module 67 private static int getNumJlinkPlugins() { 68 ModuleDescriptor desc = Plugin.class.getModule().getDescriptor(); 69 return desc.provides().stream() 70 .filter(p -> p.service().equals(Plugin.class.getName())) 71 .map(p -> p.providers().size()) 72 .findAny() 73 .orElse(0); 74 } 75 76 private static boolean isOfJLinkModule(Plugin p) { 77 return p.getClass().getModule() == Plugin.class.getModule(); 78 } 79 80 public static void main(String[] args) throws Exception { 81 82 Helper helper = Helper.newHelper(); 83 if (helper == null) { 84 System.err.println("Test not run"); 85 return; 86 } 87 helper.generateDefaultModules(); 88 // expected num. of plugins from jdk.jlink module 89 int expectedJLinkPlugins = getNumJlinkPlugins(); 90 int totalPlugins = 0; 91 { 92 // number of built-in plugins 93 List<Plugin> builtInPlugins = new ArrayList<>(); 94 builtInPlugins.addAll(PluginRepository.getPlugins(ModuleLayer.boot())); 95 totalPlugins = builtInPlugins.size(); 96 // actual num. of plugins loaded from jdk.jlink module 97 int actualJLinkPlugins = 0; 98 for (Plugin p : builtInPlugins) { 99 p.getState(); 100 p.getType(); 101 if (isOfJLinkModule(p)) { 102 actualJLinkPlugins++; 103 } 104 } 105 if (expectedJLinkPlugins != actualJLinkPlugins) { 106 throw new AssertionError("Actual plugins loaded from jdk.jlink: " + 107 actualJLinkPlugins + " which doesn't match expected number : " + 108 expectedJLinkPlugins); 109 } 110 } 111 112 { 113 // No --module-path specified. --add-modules ALL-MODULE-PATH specified. 114 String imageDir = "bug8189777-all-module-path"; 115 JImageGenerator.getJLinkTask() 116 .output(helper.createNewImageDir(imageDir)) 117 .addMods("ALL-MODULE-PATH") 118 .call().assertSuccess(); 119 } 120 121 { 122 String moduleName = "bug8134651"; 123 JImageGenerator.getJLinkTask() 124 .modulePath(helper.defaultModulePath()) 125 .output(helper.createNewImageDir(moduleName)) 126 .addMods("leaf1") 127 .call().assertSuccess(); 128 JImageGenerator.getJLinkTask() 129 .modulePath(helper.defaultModulePath()) 130 .addMods("leaf1") 131 .option("--output") 132 .call().assertFailure("Error: no value given for --output"); 133 JImageGenerator.getJLinkTask() 134 .modulePath("") 135 .output(helper.createNewImageDir(moduleName)) 136 .addMods("leaf1") 137 .call().assertFailure("Error: no value given for --module-path"); 138 // do not include standard module path - should be added automatically 139 JImageGenerator.getJLinkTask() 140 .modulePath(helper.defaultModulePath(false)) 141 .output(helper.createNewImageDir(moduleName)) 142 .addMods("leaf1") 143 .call().assertSuccess(); 144 // no --module-path. default sys mod path is assumed - but that won't contain 'leaf1' module 145 JImageGenerator.getJLinkTask() 146 .output(helper.createNewImageDir(moduleName)) 147 .addMods("leaf1") 148 .call().assertFailure("Error: Module leaf1 not found"); 149 } 150 151 { 152 String moduleName = "m"; // 8163382 153 Path jmod = helper.generateDefaultJModule(moduleName).assertSuccess(); 154 JImageGenerator.getJLinkTask() 155 .modulePath(helper.defaultModulePath()) 156 .output(helper.createNewImageDir(moduleName)) 157 .addMods("m") 158 .call().assertSuccess(); 159 moduleName = "mod"; 160 jmod = helper.generateDefaultJModule(moduleName).assertSuccess(); 161 JImageGenerator.getJLinkTask() 162 .modulePath(helper.defaultModulePath()) 163 .output(helper.createNewImageDir(moduleName)) 164 .addMods("m") 165 .call().assertSuccess(); 166 } 167 168 { 169 String moduleName = "m_8165735"; // JDK-8165735 170 helper.generateDefaultJModule(moduleName+"dependency").assertSuccess(); 171 Path jmod = helper.generateDefaultJModule(moduleName, moduleName+"dependency").assertSuccess(); 172 JImageGenerator.getJLinkTask() 173 .modulePath(helper.defaultModulePath()) 174 .repeatedModulePath(".") // second --module-path overrides the first one 175 .output(helper.createNewImageDir(moduleName)) 176 .addMods(moduleName) 177 // second --module-path does not have that module 178 .call().assertFailure("Error: Module m_8165735 not found"); 179 180 JImageGenerator.getJLinkTask() 181 .modulePath(".") // first --module-path overridden later 182 .repeatedModulePath(helper.defaultModulePath()) 183 .output(helper.createNewImageDir(moduleName)) 184 .addMods(moduleName) 185 // second --module-path has that module 186 .call().assertSuccess(); 187 188 JImageGenerator.getJLinkTask() 189 .modulePath(helper.defaultModulePath()) 190 .output(helper.createNewImageDir(moduleName)) 191 .limitMods(moduleName) 192 .repeatedLimitMods("java.base") // second --limit-modules overrides first 193 .addMods(moduleName) 194 .call().assertFailure("Error: Module m_8165735dependency not found, required by m_8165735"); 195 196 JImageGenerator.getJLinkTask() 197 .modulePath(helper.defaultModulePath()) 198 .output(helper.createNewImageDir(moduleName)) 199 .limitMods("java.base") 200 .repeatedLimitMods(moduleName) // second --limit-modules overrides first 201 .addMods(moduleName) 202 .call().assertSuccess(); 203 } 204 205 { 206 // Help 207 StringWriter writer = new StringWriter(); 208 PrintWriter pw = new PrintWriter(writer); 209 JLINK_TOOL.run(pw, pw, "--help"); 210 String output = writer.toString(); 211 if (output.split("\n").length < 10) { 212 System.err.println(output); 213 throw new AssertionError("Help"); 214 } 215 } 216 217 { 218 // List plugins 219 StringWriter writer = new StringWriter(); 220 PrintWriter pw = new PrintWriter(writer); 221 222 JLINK_TOOL.run(pw, pw, "--list-plugins"); 223 String output = writer.toString(); 224 long number = Stream.of(output.split("\\R")) 225 .filter((s) -> s.matches("Plugin Name:.*")) 226 .count(); 227 if (number != totalPlugins) { 228 System.err.println(output); 229 throw new AssertionError("Found: " + number + " expected " + totalPlugins); 230 } 231 } 232 233 // filter out files and resources + Skip debug + compress 234 { 235 String[] userOptions = {"--compress", "2", "--strip-debug", 236 "--exclude-resources", "*.jcov, */META-INF/*", "--exclude-files", 237 "*" + Helper.getDebugSymbolsExtension()}; 238 String moduleName = "excludezipskipdebugcomposite2"; 239 helper.generateDefaultJModule(moduleName, "composite2"); 240 String[] res = {".jcov", "/META-INF/"}; 241 String[] files = {Helper.getDebugSymbolsExtension()}; 242 Path imageDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess(); 243 helper.checkImage(imageDir, moduleName, res, files); 244 } 245 246 // filter out + Skip debug + compress with filter + sort resources 247 { 248 String[] userOptions2 = {"--compress=2:compress-filter=^/java.base/*", 249 "--strip-debug", "--exclude-resources", 250 "*.jcov, */META-INF/*", "--order-resources", 251 "*/module-info.class,/sortcomposite2/*,*/javax/management/*"}; 252 String moduleName = "excludezipfilterskipdebugcomposite2"; 253 helper.generateDefaultJModule(moduleName, "composite2"); 254 String[] res = {".jcov", "/META-INF/"}; 255 Path imageDir = helper.generateDefaultImage(userOptions2, moduleName).assertSuccess(); 256 helper.checkImage(imageDir, moduleName, res, null); 257 } 258 259 // module-info.class should not be excluded 260 { 261 String[] userOptions = { "--exclude-resources", "/jdk_8194922/module-info.class" }; 262 String moduleName = "jdk_8194922"; 263 helper.generateDefaultJModule(moduleName); 264 helper.generateDefaultImage(userOptions, moduleName). 265 assertFailure("Cannot exclude /jdk_8194922/module-info.class"); 266 } 267 268 // default compress 269 { 270 testCompress(helper, "compresscmdcomposite2", "--compress", "2"); 271 } 272 273 { 274 testCompress(helper, "compressfiltercmdcomposite2", 275 "--compress=2:filter=^/java.base/java/lang/*"); 276 } 277 278 // compress 0 279 { 280 testCompress(helper, "compress0filtercmdcomposite2", 281 "--compress=0:filter=^/java.base/java/lang/*"); 282 } 283 284 // compress 1 285 { 286 testCompress(helper, "compress1filtercmdcomposite2", 287 "--compress=1:filter=^/java.base/java/lang/*"); 288 } 289 290 // compress 2 291 { 292 testCompress(helper, "compress2filtercmdcomposite2", 293 "--compress=2:filter=^/java.base/java/lang/*"); 294 } 295 296 // invalid compress level 297 { 298 String[] userOptions = {"--compress", "invalid"}; 299 String moduleName = "invalidCompressLevel"; 300 helper.generateDefaultJModule(moduleName, "composite2"); 301 helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: Invalid compression level invalid"); 302 } 303 304 // orphan argument - JDK-8166810 305 { 306 String[] userOptions = {"--compress", "2", "foo" }; 307 String moduleName = "orphanarg1"; 308 helper.generateDefaultJModule(moduleName, "composite2"); 309 helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: invalid argument: foo"); 310 } 311 312 // orphan argument - JDK-8166810 313 { 314 String[] userOptions = {"--output", "foo", "bar" }; 315 String moduleName = "orphanarg2"; 316 helper.generateDefaultJModule(moduleName, "composite2"); 317 helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: invalid argument: bar"); 318 } 319 320 // basic check for --help - JDK-8173717 321 { 322 JImageGenerator.getJLinkTask() 323 .option("--help") 324 .call().assertSuccess(); 325 } 326 327 { 328 String imageDir = "bug8206962"; 329 JImageGenerator.getJLinkTask() 330 .modulePath(helper.defaultModulePath()) 331 .output(helper.createNewImageDir(imageDir)) 332 .addMods("java.base") 333 .option("--release-info=del") 334 .call().assertFailure("Error: No key specified for delete"); 335 } 336 } 337 338 private static void testCompress(Helper helper, String moduleName, String... userOptions) throws IOException { 339 helper.generateDefaultJModule(moduleName, "composite2"); 340 Path imageDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess(); 341 helper.checkImage(imageDir, moduleName, null, null); 342 } 343 }