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