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