1 /*
2 * Copyright (c) 2016, 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 /*
25 * @test
26 * @summary Tests to verify jimage 'extract' action
27 * @library /test/lib
28 * @modules jdk.jlink/jdk.tools.jimage
29 * @build jdk.test.lib.Asserts JImageCliTest
30 * @run main/othervm JImageExtractTest
31 */
32
33 import java.io.File;
34 import java.io.IOException;
35 import java.nio.file.Files;
36 import java.nio.file.Path;
37 import java.nio.file.Paths;
38 import java.nio.file.attribute.FileAttribute;
39 import java.nio.file.attribute.PosixFilePermission;
40 import java.nio.file.attribute.PosixFilePermissions;
41 import java.util.Arrays;
42 import java.util.HashSet;
43 import java.util.Set;
44 import java.util.stream.Collectors;
45
46 import static jdk.test.lib.Asserts.assertEquals;
47 import static jdk.test.lib.Asserts.assertTrue;
48
49 public class JImageExtractTest extends JImageCliTest {
50 public void beforeTest() throws IOException {
51 Path cwd = new File(".").toPath();
52 System.out.printf("cleaning working dir [%s]... \n", cwd.toAbsolutePath());
53 for (File f : new File(".").listFiles()) {
54 if (f.isDirectory()) {
55 jdk.test.lib.util.FileUtils.deleteFileTreeWithRetry(f.toPath());
56 } else {
57 f.delete();
58 }
59 }
60 }
61
62 public void testExtract() throws IOException {
63 jimage("extract", getImagePath())
64 .assertSuccess()
65 .resultChecker(r -> {
66 assertTrue(r.output.isEmpty(), "Output is not expected");
67 });
68 verifyExplodedImage(Paths.get("."));
69 }
70
71 // do a second round to check that workspace initialization works ok
72 public void testExtractSecondRound() throws IOException {
73 jimage("extract", getImagePath())
74 .assertSuccess()
75 .resultChecker(r -> {
76 assertTrue(r.output.isEmpty(), "Output is not expected");
77 });
78 verifyExplodedImage(Paths.get("."));
79 }
80
81 public void testExtractHelp() {
82 for (String opt : Arrays.asList("-h", "--help")) {
83 jimage("extract", "--help")
84 .assertSuccess()
85 .resultChecker(r -> {
86 // extract - descriptive text
87 assertMatches("\\s+extract\\s+-\\s+.*", r.output);
88 });
89 }
90 }
91
92 public void testExtractToDir() throws IOException {
93 Path tmp = Files.createTempDirectory(Paths.get("."), getClass().getName());
94 jimage("extract", "--dir", tmp.toString(), getImagePath())
95 .assertSuccess()
96 .resultChecker(r -> {
97 assertTrue(r.output.isEmpty(), "Output is not expected");
98 });
99 verifyExplodedImage(tmp);
100 }
101
102 public void testExtractNoImageSpecified() {
103 jimage("extract", "")
104 .assertFailure()
105 .assertShowsError();
106 }
107
108 public void testExtractEmptyFile() throws IOException {
109 Path tmp = Files.createTempFile(Paths.get("."), getClass().getName(), "empty_file");
110 jimage("extract", "--dir", "some_directory", tmp.toString())
111 .assertFailure()
112 .assertShowsError();
113 }
114
115 public void testExtractNotAnImage() throws IOException {
116 Path tmp = Files.createTempFile(Paths.get("."), getClass().getName(), "not_an_image");
117 Files.write(tmp, "This is not an image".getBytes());
118 jimage("extract", "--dir", "some_directory", tmp.toString())
119 .assertFailure()
120 .assertShowsError();
121 }
122
123 public void testExtractNotExistingImage() throws IOException {
124 Path tmp = Paths.get(".", "not_existing_image");
125 Files.deleteIfExists(tmp);
126 jimage("extract", tmp.toString())
127 .assertFailure()
128 .assertShowsError();
129 }
130
131 public void testExtractToUnspecifiedDir() {
132 jimage("extract", "--dir", "--", getImagePath())
133 .assertFailure()
134 .assertShowsError();
135 }
136
137 public void testExtractToNotExistingDir() throws IOException {
138 Path tmp = Files.createTempDirectory(Paths.get("."), getClass().getName());
139 Files.delete(tmp);
140 jimage("extract", "--dir", tmp.toString(), getImagePath())
141 .assertSuccess()
142 .resultChecker(r -> {
143 assertTrue(r.output.isEmpty(), "Output is not expected");
144 });
145 verifyExplodedImage(tmp);
146 }
147
148 public void testExtractFromDir() {
149 Path imagePath = Paths.get(getImagePath());
150 Path imageDirPath = imagePath.subpath(0, imagePath.getNameCount() - 1);
151 jimage("extract", imageDirPath.toString())
152 .assertFailure()
153 .assertShowsError();
154 }
155
156 public void testExtractToDirBySymlink() throws IOException {
157 Path tmp = Files.createTempDirectory(Paths.get("."), getClass().getName());
158 Path symlink;
159 try {
160 symlink = Files.createSymbolicLink(Paths.get(".", "symlink"), tmp);
161 } catch (IOException|UnsupportedOperationException e) {
162 // symlinks are not supported
163 // nothing to test
164 return;
165 }
166
167 jimage("extract", "--dir", symlink.toString(), getImagePath())
168 .assertSuccess()
169 .resultChecker(r -> {
170 assertTrue(r.output.isEmpty(), "Output is not expected");
171 });
172 verifyExplodedImage(tmp);
173 }
174
175 public void testExtractToReadOnlyDir() throws IOException {
176 Set<PosixFilePermission> perms = PosixFilePermissions.fromString("r-xr--r--");
177 FileAttribute<Set<PosixFilePermission>> atts = PosixFilePermissions.asFileAttribute(perms);
178 Path tmp = Files.createTempDirectory(Paths.get("."), getClass().getName(), atts);
179 jimage("extract", "--dir", tmp.toString(), getImagePath())
180 .assertFailure()
181 .assertShowsError();
182 }
183
184 public void testExtractToNotEmptyDir() throws IOException {
185 Path tmp = Files.createTempDirectory(Paths.get("."), getClass().getName());
186 Files.createFile(Paths.get(tmp.toString(), ".not_empty"));
187 jimage("extract", "--dir", tmp.toString(), getImagePath())
188 .assertFailure()
189 .assertShowsError();
190 }
191
192 public void testExtractToFile() throws IOException {
193 Path tmp = Files.createTempFile(Paths.get("."), getClass().getName(), "not_a_dir");
194 jimage("extract", "--dir", tmp.toString(), getImagePath())
195 .assertFailure()
196 .assertShowsError();
197 }
198
199 private void verifyExplodedImage(Path imagePath) throws IOException {
200 Set<Path> allModules = Files.walk(imagePath, 1).collect(Collectors.toSet());
201 assertTrue(allModules.stream().anyMatch(p -> "java.base".equals(p.getFileName().toString())),
202 "Exploded image contains java.base module.");
203
204 Set<Path> badModules = allModules.stream()
205 .filter(p -> !Files.exists(p.resolve("module-info.class")))
206 .collect(Collectors.toSet());
207 assertEquals(badModules, new HashSet<Path>() {{ add(imagePath); }},
208 "There are no exploded modules with missing 'module-info.class'");
209 }
210
211 public static void main(String[] args) throws Throwable {
212 new JImageExtractTest().runTests();
213 }
214 }
215