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
  30  * @run main/othervm JImageExtractTest
  31  */
  32 
  33 import java.io.IOException;
  34 import java.nio.file.Files;
  35 import java.nio.file.Path;
  36 import java.nio.file.Paths;
  37 import java.nio.file.attribute.FileAttribute;
  38 import java.nio.file.attribute.PosixFilePermission;
  39 import java.nio.file.attribute.PosixFilePermissions;
  40 import java.util.Arrays;
  41 import java.util.HashSet;
  42 import java.util.Set;
  43 import java.util.stream.Collectors;
  44 
  45 import static jdk.test.lib.Asserts.assertEquals;
  46 import static jdk.test.lib.Asserts.assertTrue;
  47 
  48 public class JImageExtractTest extends JImageCliTest {
  49     public void testExtract() throws IOException {
  50         jimage("extract", getImagePath())
  51                 .assertSuccess()
  52                 .resultChecker(r -> {
  53                     assertTrue(r.output.isEmpty(), "Output is not expected");
  54                 });
  55         verifyExplodedImage(Paths.get("."));
  56     }
  57 
  58     public void testExtractHelp() {
  59         for (String opt : Arrays.asList("-h", "--help")) {
  60             jimage("extract", "--help")
  61                     .assertSuccess()
  62                     .resultChecker(r -> {
  63                         // extract  -  descriptive text
  64                         assertMatches("\\s+extract\\s+-\\s+.*", r.output);
  65                     });
  66         }
  67     }
  68 
  69     public void testExtractToDir() throws IOException {
  70         Path tmp = Files.createTempDirectory(Paths.get("."), getClass().getName());
  71         jimage("extract", "--dir", tmp.toString(), getImagePath())
  72                 .assertSuccess()
  73                 .resultChecker(r -> {
  74                     assertTrue(r.output.isEmpty(), "Output is not expected");
  75                 });
  76         verifyExplodedImage(tmp);
  77     }
  78 
  79     public void testExtractNoImageSpecified() {
  80         jimage("extract", "")
  81                 .assertFailure()
  82                 .assertShowsError();
  83     }
  84 
  85     public void testExtractNotAnImage() throws IOException {
  86         Path tmp = Files.createTempFile(Paths.get("."), getClass().getName(), "not_an_image");
  87         jimage("extract", tmp.toString())
  88                 .assertFailure()
  89                 .assertShowsError();
  90     }
  91 
  92     public void testExtractNotExistingImage() throws IOException {
  93         Path tmp = Paths.get(".", "not_existing_image");
  94         Files.deleteIfExists(tmp);
  95         jimage("extract", tmp.toString())
  96                 .assertFailure()
  97                 .assertShowsError();
  98     }
  99 
 100     public void testExtractToUnspecifiedDir() {
 101         jimage("extract", "--dir", "--", getImagePath())
 102                 .assertFailure()
 103                 .assertShowsError();
 104     }
 105 
 106     public void testExtractToNotExistingDir() throws IOException {
 107         Path tmp = Files.createTempDirectory(Paths.get("."), getClass().getName());
 108         Files.delete(tmp);
 109         jimage("extract", "--dir", tmp.toString(), getImagePath())
 110                 .assertSuccess()
 111                 .resultChecker(r -> {
 112                     assertTrue(r.output.isEmpty(), "Output is not expected");
 113                 });
 114         verifyExplodedImage(tmp);
 115     }
 116 
 117     public void testExtractFromDir() {
 118         Path imagePath = Paths.get(getImagePath());
 119         Path imageDirPath = imagePath.subpath(0, imagePath.getNameCount() - 1);
 120         jimage("extract", imageDirPath.toString())
 121                 .assertFailure()
 122                 .assertShowsError();
 123     }
 124 
 125     public void testExtractToDirBySymlink() throws IOException {
 126         Path tmp = Files.createTempDirectory(Paths.get("."), getClass().getName());
 127         try {
 128             Path symlink = Files.createSymbolicLink(Paths.get(".", "symlink"), tmp);
 129             jimage("extract", "--dir", symlink.toString(), getImagePath())
 130                     .assertSuccess()
 131                     .resultChecker(r -> {
 132                         assertTrue(r.output.isEmpty(), "Output is not expected");
 133                     });
 134             verifyExplodedImage(tmp);
 135         } catch (UnsupportedOperationException e) {
 136             // symlinks are not supported
 137             // nothing to test
 138         }
 139     }
 140 
 141     public void testExtractToReadOnlyDir() throws IOException {
 142         Set<PosixFilePermission> perms = PosixFilePermissions.fromString("r-xr--r--");
 143         FileAttribute<Set<PosixFilePermission>> atts = PosixFilePermissions.asFileAttribute(perms);
 144         Path tmp = Files.createTempDirectory(Paths.get("."), getClass().getName(), atts);
 145         jimage("extract", "--dir", tmp.toString(), getImagePath())
 146                 .assertFailure()
 147                 .assertShowsError();
 148     }
 149 
 150     public void testExtractToNotEmptyDir() throws IOException {
 151         Path tmp = Files.createTempDirectory(Paths.get("."), getClass().getName());
 152         Files.createFile(Paths.get(tmp.toString(), ".not_empty"));
 153         jimage("extract", "--dir", tmp.toString(), getImagePath())
 154                 .assertFailure()
 155                 .assertShowsError();
 156     }
 157 
 158     public void testExtractToFile() throws IOException {
 159         Path tmp = Files.createTempFile(Paths.get("."), getClass().getName(), "not_a_dir");
 160         jimage("extract", "--dir", tmp.toString(), getImagePath())
 161                 .assertFailure()
 162                 .assertShowsError();
 163     }
 164 
 165     private void verifyExplodedImage(Path imagePath) throws IOException {
 166         Set<Path> allModules = Files.walk(imagePath, 1).collect(Collectors.toSet());
 167         assertTrue(allModules.stream().anyMatch(p -> "java.base".equals(p.getFileName().toString())),
 168                 "Exploded image contains java.base module.");
 169 
 170         Set<Path> badModules = allModules.stream()
 171                 .filter(p -> !Files.exists(p.resolve("module-info.class")))
 172                 .collect(Collectors.toSet());
 173         assertEquals(badModules, new HashSet<Path>() {{ add(imagePath); }},
 174                 "There are no exploded modules with missing 'module-info.class'");
 175     }
 176 
 177     public static void main(String[] args) throws Throwable {
 178         new JImageExtractTest().runTests();
 179     }
 180 }
 181