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