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