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 'list' action
  27  * @library /test/lib
  28  * @modules jdk.jlink/jdk.tools.jimage
  29  * @build jdk.test.lib.Asserts
  30  * @run main JImageListTest
  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.util.*;
  38 import java.util.stream.Collectors;
  39 import java.util.stream.Stream;
  40 
  41 import static jdk.test.lib.Asserts.assertEquals;
  42 import static jdk.test.lib.Asserts.assertFalse;
  43 import static jdk.test.lib.Asserts.assertTrue;
  44 
  45 public class JImageListTest extends JImageCliTest {
  46     public void testList() {
  47         jimage("list", getImagePath())
  48                 .assertSuccess()
  49                 .resultChecker(r -> {
  50                     String[] lines = r.output.split(System.lineSeparator());
  51                     assertTrue(lines.length > 0, "Option --list has output.");
  52                     assertTrue(lines[0].startsWith("jimage: " + getImagePath()),
  53                             "Output should start with jimage path.");
  54 
  55                     List<String> modules = Stream.of(lines)
  56                             .filter(s -> s.startsWith("Module: "))
  57                             .map(s -> s.substring(s.indexOf(':') + 1).trim())
  58                             .collect(Collectors.toList());
  59                     assertTrue(modules.size() > 0, "Image contains at least one module.");
  60                     assertTrue(modules.indexOf("java.base") > 0, "Module java.base found.");
  61                 });
  62     }
  63 
  64     public void testListHelp() {
  65         for (String opt : Arrays.asList("-h", "--help")) {
  66             jimage("list", opt)
  67                     .assertSuccess()
  68                     .resultChecker(r -> {
  69                         // list  -  descriptive text
  70                         assertMatches("\\s+list\\s+-\\s+.*", r.output);
  71                     });
  72         }
  73     }
  74 
  75     public void testListVerbose() {
  76         jimage("list", "--verbose", getImagePath())
  77                 .assertSuccess()
  78                 .resultChecker(r -> {
  79                     assertMatches("Offset\\s+Size\\s+Compressed\\s+Entry", r.output);
  80 
  81                     String[] lines = r.output.split("[" + System.lineSeparator() + "]+");
  82                     assertTrue(lines.length > 0, "Option --list has output.");
  83                     assertTrue(lines[0].startsWith("jimage: " + getImagePath()),
  84                             "Output should start with jimage path.");
  85 
  86                     List<String> modules = Stream.of(lines)
  87                             .filter(s -> s.startsWith("Module: "))
  88                             .map(s -> s.substring(s.indexOf(':') + 1).trim())
  89                             .collect(Collectors.toList());
  90                     assertTrue(modules.size() > 0, "Image contains at least one module.");
  91                     assertTrue(modules.indexOf("java.base") > 0, "Module java.base found.");
  92 
  93                     Set<String> entries = Stream.of(lines)
  94                             .filter(s -> { return !s.startsWith("Module: ") && !s.startsWith("Offset"); })
  95                             // Offset \d+  Size \d+  Compressed \d+ Entry \.*
  96                             .filter(s -> !s.matches("\\s+\\d+\\s+\\d+\\s+\\d+\\s+.*"))
  97                             .collect(Collectors.toSet());
  98                     assertEquals(entries, new HashSet<>() {{ add("jimage: " + getImagePath()); }},
  99                             "All entries should be in format: Offset Size Compressed Entry");
 100                 });
 101     }
 102 
 103     public void testListIncludeAllWithGlob() {
 104         JImageResult listAll = jimage("list", getImagePath()).assertSuccess();
 105         JImageResult listAllGlob = jimage("list", "--include", "**", getImagePath()).assertSuccess();
 106         assertEquals(listAllGlob.output, listAll.output, "--include ** should produce the same output");
 107     }
 108 
 109     public void testListIncludeWithGlob() {
 110         JImageResult listAll = jimage("list", getImagePath()).assertSuccess();
 111         Set<String> expected = Stream.of(listAll.output.split("[" + System.lineSeparator() + "]+"))
 112                 .map(String::trim)
 113                 .filter(s -> s.startsWith("java/util/zip"))
 114                 .collect(Collectors.toSet());
 115 
 116         JImageResult listJavaUtil = jimage("list", "--include", "/java.base/java/util/zip/**", getImagePath()).assertSuccess();
 117         Set<String> actual = Stream.of(listJavaUtil.output.split("[" + System.lineSeparator() + "]+"))
 118                 .map(String::trim)
 119                 .filter(s -> !s.startsWith("jimage:") && !s.startsWith("Module:"))
 120                 .collect(Collectors.toSet());
 121         assertEquals(actual, expected, "All java.util.zip classes are listed");
 122     }
 123 
 124     public void testListIncludeNoMatchWithGlob() {
 125         JImageResult listNotMatching = jimage("list", "--include", "not_matching", getImagePath()).assertSuccess();
 126         Set<String> entries = Stream.of(listNotMatching.output.split("["+ System.lineSeparator() + "]+"))
 127                 .map(String::trim)
 128                 .filter(s -> !s.startsWith("jimage:") && !s.startsWith("Module:"))
 129                 .collect(Collectors.toSet());
 130         assertEquals(entries, Collections.emptySet(), "No java.util classes are listed");
 131     }
 132 
 133     public void testListIncludeAllWithExplicitGlob() {
 134         JImageResult listAll = jimage("list", getImagePath()).assertSuccess();
 135         JImageResult listAllGlob = jimage("list", "--include", "glob:**", getImagePath()).assertSuccess();
 136         assertEquals(listAllGlob.output, listAll.output, "--include glob:** should produce the same output");
 137     }
 138 
 139     public void testListIncludeAllWithRegex() {
 140         JImageResult listAll = jimage("list", getImagePath()).assertSuccess();
 141         JImageResult listAllRegex = jimage("list", "--include", "regex:.*", getImagePath()).assertSuccess();
 142         assertEquals(listAllRegex.output, listAll.output, "--include regex:.* should produce the same output");
 143     }
 144 
 145     public void testListIncludeWithRegex() {
 146         JImageResult listAll = jimage("list", getImagePath()).assertSuccess();
 147         Set<String> expected = Stream.of(listAll.output.split("[" + System.lineSeparator() + "]+"))
 148                 .map(String::trim)
 149                 .filter(s -> s.startsWith("java/text/"))
 150                 .collect(Collectors.toSet());
 151         assertFalse(expected.isEmpty(), "There should be classes from java.text package");
 152 
 153         JImageResult listJavaText = jimage("list", "--include", "regex:/java.base/java/text/.*", getImagePath()).assertSuccess();
 154         Set<String> actual = Stream.of(listJavaText.output.split("[" + System.lineSeparator() + "]+"))
 155                 .map(String::trim)
 156                 .filter(s -> !s.startsWith("jimage:") && !s.startsWith("Module:"))
 157                 .collect(Collectors.toSet());
 158 
 159         assertEquals(actual, expected, "All java.text classes are listed");
 160     }
 161 
 162     public void testListIncludeNoMatchWithRegex() {
 163         JImageResult listNotMatching = jimage("list", "--include", "regex:not_matching",
 164                 getImagePath()).assertSuccess();
 165         Set<String> entries = Stream.of(listNotMatching.output.split("[" + System.lineSeparator() + "]+"))
 166                 .map(String::trim)
 167                 .filter(s -> !s.startsWith("jimage:") && !s.startsWith("Module:"))
 168                 .collect(Collectors.toSet());
 169         assertEquals(entries, Collections.emptySet(), "No classes are listed");
 170     }
 171 
 172     public void testListIncludeMultiplePatterns() throws IOException {
 173         JImageResult listAll = jimage("list", getImagePath()).assertSuccess();
 174         Set<String> expected = Stream.of(listAll.output.split("[" + System.lineSeparator() + "]+"))
 175                 .map(String::trim)
 176                 .filter(s -> s.startsWith("java/time/") || s.startsWith("java/util/zip"))
 177                 .collect(Collectors.toSet());
 178         assertFalse(expected.isEmpty(), "There should be classes from java.time and java.io packages");
 179 
 180         JImageResult listMatched = jimage("list", "--include", "glob:/java.base/java/time/**,regex:/java.base/java/util/zip/.*",
 181                 getImagePath()).assertSuccess();
 182         Set<String> actual = Stream.of(listMatched.output.split("[" + System.lineSeparator() + "]+"))
 183                 .map(String::trim)
 184                 .filter(s -> !s.startsWith("jimage:") && !s.startsWith("Module:"))
 185                 .collect(Collectors.toSet());
 186 
 187         assertEquals(actual, expected, "All java.time and java.util.zip classes are listed");
 188     }
 189 
 190     public void testListNoImageSpecified() {
 191         jimage("list", "")
 192                 .assertFailure()
 193                 .assertShowsError();
 194     }
 195 
 196     public void testListEmptyFile() throws IOException {
 197         Path tmp = Files.createTempFile(Paths.get("."), getClass().getName(), "empty_file");
 198         jimage("list", tmp.toString())
 199                 .assertFailure()
 200                 .assertShowsError();
 201     }
 202 
 203     public void testListNotAnImage() throws IOException {
 204         Path tmp = Files.createTempFile(Paths.get("."), getClass().getName(), "not_an_image");
 205         Files.write(tmp, "This is not an image".getBytes());
 206         jimage("list", tmp.toString())
 207                 .assertFailure()
 208                 .assertShowsError();
 209     }
 210 
 211     public void testListNotExistingImage() throws IOException {
 212         Path tmp = Paths.get(".", "not_existing_image");
 213         Files.deleteIfExists(tmp);
 214         jimage("list", tmp.toString())
 215                 .assertFailure()
 216                 .assertShowsError();
 217     }
 218 
 219     public void testListWithUnknownOption() {
 220         jimage("list", "--unknown")
 221                 .assertFailure()
 222                 .assertShowsError();
 223     }
 224 
 225     public static void main(String[] args) throws Throwable {
 226         new JImageListTest().runTests();
 227     }
 228 }
 229