1 /*
   2  * Copyright (c) 2016, 2017, 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  * @bug 8170859
  27  * @summary Ensure no incubator modules are resolved by default in the image
  28  * @library /lib/testlibrary /test/lib
  29  * @modules jdk.compiler
  30  * @build jdk.test.lib.compiler.CompilerUtils
  31  * @run testng DefaultImage
  32  */
  33 
  34 import java.io.ByteArrayOutputStream;
  35 import java.io.PrintStream;
  36 import java.lang.module.ModuleDescriptor;
  37 import java.lang.module.ModuleFinder;
  38 import java.lang.module.ModuleReference;
  39 import java.nio.file.Files;
  40 import java.nio.file.Path;
  41 import java.nio.file.Paths;
  42 import java.util.function.Consumer;
  43 import java.util.stream.Stream;
  44 import jdk.test.lib.compiler.CompilerUtils;
  45 
  46 import org.testng.annotations.BeforeTest;
  47 import org.testng.annotations.Test;
  48 
  49 import static java.nio.charset.StandardCharsets.UTF_8;
  50 import static jdk.testlibrary.ProcessTools.executeCommand;
  51 import static org.testng.Assert.*;
  52 
  53 @Test
  54 public class DefaultImage {
  55     private static final String JAVA_HOME = System.getProperty("java.home");
  56     private static final Path TEST_SRC = Paths.get(System.getProperty("test.src"));
  57     private static final Path CP_DIR = Paths.get("cp");
  58 
  59     @BeforeTest
  60     private void setup() throws Throwable {
  61         Path src = TEST_SRC.resolve("src").resolve("cp").resolve("listmods");
  62         assertTrue(CompilerUtils.compile(src, CP_DIR));
  63     }
  64 
  65     public void test() throws Throwable {
  66         if (isExplodedBuild()) {
  67             System.out.println("Test cannot run on exploded build");
  68             return;
  69         }
  70 
  71         java("-cp", CP_DIR.toString(),
  72              "listmods.ListModules")
  73             .assertSuccess()
  74             .resultChecker(r -> r.assertOutputContains("java.base"))
  75             .resultChecker(r -> r.assertOutputDoesNotContain("jdk.incubator"));
  76     }
  77 
  78     public void testAllDefault() throws Throwable {
  79         if (isExplodedBuild()) {
  80             System.out.println("Test cannot run on exploded build");
  81             return;
  82         }
  83 
  84         java("--add-modules", "ALL-DEFAULT",
  85              "-cp", CP_DIR.toString(),
  86              "listmods.ListModules")
  87             .assertSuccess()
  88             .resultChecker(r -> r.assertOutputContains("java.base"))
  89             .resultChecker(r -> r.assertOutputDoesNotContain("jdk.incubator"));
  90     }
  91 
  92     public void testAllSystem() throws Throwable {
  93         if (isExplodedBuild()) {
  94             System.out.println("Test cannot run on exploded build");
  95             return;
  96         }
  97 
  98         if (containsAnyIncubatorModules()) {
  99             java("--add-modules", "ALL-SYSTEM",
 100                  "-cp", CP_DIR.toString(),
 101                  "listmods.ListModules")
 102                 .assertSuccess()
 103                 .resultChecker(r -> r.assertOutputContains("java.base"))
 104                 .resultChecker(r -> r.assertOutputContains("jdk.incubator"));
 105         }
 106     }
 107 
 108     static ToolResult java(String... opts) throws Throwable {
 109         ByteArrayOutputStream baos = new ByteArrayOutputStream();
 110         PrintStream ps = new PrintStream(baos);
 111         String[] options = Stream.concat(Stream.of(getJava()), Stream.of(opts))
 112                 .toArray(String[]::new);
 113 
 114         ProcessBuilder pb = new ProcessBuilder(options);
 115         int exitValue = executeCommand(pb).outputTo(ps)
 116                 .errorTo(ps)
 117                 .getExitValue();
 118 
 119         return new ToolResult(exitValue, new String(baos.toByteArray(), UTF_8));
 120     }
 121 
 122     static class ToolResult {
 123         final int exitCode;
 124         final String output;
 125 
 126         ToolResult(int exitValue, String output) {
 127             this.exitCode = exitValue;
 128             this.output = output;
 129         }
 130 
 131         ToolResult assertSuccess() {
 132             assertEquals(exitCode, 0,
 133                     "Expected exit code 0, got " + exitCode
 134                             + ", with output[" + output + "]");
 135             return this;
 136         }
 137 
 138         ToolResult resultChecker(Consumer<ToolResult> r) {
 139             r.accept(this);
 140             return this;
 141         }
 142 
 143         ToolResult assertOutputContains(String subString) {
 144             assertTrue(output.contains(subString),
 145                        "Expected to find [" + subString + "], in output ["
 146                             + output + "]" + "\n");
 147             return this;
 148         }
 149 
 150         ToolResult assertOutputDoesNotContain(String subString) {
 151             assertFalse(output.contains(subString),
 152                         "Expected to NOT find [" + subString + "], in output ["
 153                             + output + "]" + "\n");
 154             return this;
 155         }
 156     }
 157 
 158     static String getJava() {
 159         Path image = Paths.get(JAVA_HOME);
 160         boolean isWindows = System.getProperty("os.name").startsWith("Windows");
 161         Path java = image.resolve("bin").resolve(isWindows ? "java.exe" : "java");
 162         if (Files.notExists(java))
 163             throw new RuntimeException(java + " not found");
 164         return java.toAbsolutePath().toString();
 165     }
 166 
 167     static boolean isExplodedBuild() {
 168         Path modulesPath = Paths.get(JAVA_HOME).resolve("lib").resolve("modules");
 169         return Files.notExists(modulesPath);
 170     }
 171 
 172     static boolean containsAnyIncubatorModules() {
 173         return ModuleFinder.ofSystem().findAll().stream()
 174                 .map(ModuleReference::descriptor)
 175                 .map(ModuleDescriptor::name)
 176                 .filter(mn -> mn.startsWith("jdk.incubator"))
 177                 .map(mn -> true)
 178                 .findAny()
 179                 .orElse(false);
 180     }
 181 }