1 /*
   2  * Copyright (c) 2015, 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  * @library /lib/testlibrary /test/lib
  27  * @modules jdk.compiler
  28  * @build AddReadsTest JarUtils jdk.testlibrary.*
  29  *        jdk.test.lib.compiler.CompilerUtils
  30  * @run testng AddReadsTest
  31  * @summary Basic tests for java --add-reads
  32  */
  33 
  34 import java.nio.file.Path;
  35 import java.nio.file.Paths;
  36 
  37 import jdk.test.lib.compiler.CompilerUtils;
  38 import jdk.testlibrary.OutputAnalyzer;
  39 import static jdk.testlibrary.ProcessTools.*;
  40 
  41 import org.testng.annotations.BeforeTest;
  42 import org.testng.annotations.DataProvider;
  43 import org.testng.annotations.Test;
  44 import static org.testng.Assert.*;
  45 
  46 /**
  47  * The tests consists of two modules: m1 and junit.
  48  * Code in module m1 calls into code in module junit but the module-info.java
  49  * does not have a 'requires'. Instead a read edge is added via the command
  50  * line option --add-reads.
  51  */
  52 
  53 @Test
  54 public class AddReadsTest {
  55 
  56     private static final String TEST_SRC = System.getProperty("test.src");
  57 
  58     private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
  59     private static final Path CLASSES_DIR = Paths.get("classes");
  60     private static final Path MODS_DIR = Paths.get("mods");
  61 
  62     private static final String MAIN = "m1/p.Main";
  63 
  64 
  65     @BeforeTest
  66     public void setup() throws Exception {
  67 
  68         // javac -d classes src/junit/**
  69         assertTrue(CompilerUtils
  70             .compile(SRC_DIR.resolve("junit"), CLASSES_DIR));
  71 
  72         // javac -d mods/m1 -cp classes/ src/m1/**
  73         assertTrue(CompilerUtils
  74             .compile(SRC_DIR.resolve("m1"),
  75                     MODS_DIR.resolve("m1"),
  76                     "-cp", CLASSES_DIR.toString(),
  77                     "--add-reads", "m1=ALL-UNNAMED"));
  78 
  79         // jar cf mods/junit.jar -C classes .
  80         JarUtils.createJarFile(MODS_DIR.resolve("junit.jar"), CLASSES_DIR);
  81 
  82     }
  83 
  84     private OutputAnalyzer run(String... options) throws Exception {
  85         return executeTestJava(options)
  86             .outputTo(System.out)
  87             .errorTo(System.out);
  88     }
  89 
  90 
  91     /**
  92      * Run with junit as a module on the module path.
  93      */
  94     public void testJUnitOnModulePath() throws Exception {
  95 
  96         // java --module-path mods --add-modules junit --add-reads m1=junit -m ..
  97         int exitValue
  98             = run("--module-path", MODS_DIR.toString(),
  99                   "--add-modules", "junit",
 100                   "--add-reads", "m1=junit",
 101                   "-m", MAIN)
 102                 .getExitValue();
 103 
 104         assertTrue(exitValue == 0);
 105     }
 106 
 107 
 108     /**
 109      * Exercise --add-reads m1=ALL-UNNAMED by running with junit on the
 110      * class path.
 111      */
 112     public void testJUnitOnClassPath() throws Exception {
 113 
 114         // java --module-path mods -cp mods/junit.jar --add-reads m1=ALL-UNNAMED -m ..
 115         String cp = MODS_DIR.resolve("junit.jar").toString();
 116         int exitValue
 117             = run("--module-path", MODS_DIR.toString(),
 118                   "-cp", cp,
 119                   "--add-reads", "m1=ALL-UNNAMED",
 120                   "-m", MAIN)
 121                 .getExitValue();
 122 
 123         assertTrue(exitValue == 0);
 124     }
 125 
 126 
 127     /**
 128      * Run with junit as a module on the module path but without --add-reads.
 129      */
 130     public void testJUnitOnModulePathMissingAddReads() throws Exception {
 131         // java --module-path mods --add-modules junit --module ..
 132         int exitValue
 133             = run("--module-path", MODS_DIR.toString(),
 134                   "--add-modules", "junit",
 135                   "--module", MAIN)
 136                 .shouldContain("IllegalAccessError")
 137                 .getExitValue();
 138 
 139         assertTrue(exitValue != 0);
 140     }
 141 
 142 
 143     /**
 144      * Run with junit on the class path but without --add-reads.
 145      */
 146     public void testJUnitOnClassPathMissingAddReads() throws Exception {
 147         // java --module-path mods -cp mods/junit.jar -m ..
 148         String cp = MODS_DIR.resolve("junit.jar").toString();
 149         int exitValue
 150             = run("--module-path", MODS_DIR.toString(),
 151                   "-cp", cp,
 152                   "-m", MAIN)
 153                 .shouldContain("IllegalAccessError")
 154                 .getExitValue();
 155 
 156         assertTrue(exitValue != 0);
 157     }
 158 
 159 
 160     /**
 161      * Exercise --add-reads with a more than one source module.
 162      */
 163     public void testJUnitWithMultiValueOption() throws Exception {
 164 
 165         int exitValue
 166             = run("--module-path", MODS_DIR.toString(),
 167                   "--add-modules", "java.xml,junit",
 168                   "--add-reads", "m1=java.xml,junit",
 169                   "--module", MAIN)
 170                 .getExitValue();
 171 
 172         assertTrue(exitValue == 0);
 173     }
 174 
 175 
 176     /**
 177      * Exercise --add-reads where the target module is specified more than once
 178      */
 179     public void testWithTargetSpecifiedManyTimes() throws Exception {
 180 
 181         int exitValue
 182             = run("--module-path", MODS_DIR.toString(),
 183                   "--add-modules", "java.xml,junit",
 184                   "--add-reads", "m1=java.xml",
 185                   "--add-reads", "m1=junit",
 186                   "-m", MAIN)
 187                  .getExitValue();
 188 
 189         assertTrue(exitValue == 0);
 190     }
 191 
 192 
 193     /**
 194      * Exercise --add-reads with missing source
 195      */
 196     public void testWithMissingSource() throws Exception {
 197 
 198         //  --add-exports $VALUE -version
 199         assertTrue(run("--add-reads", "java.base", "-version").getExitValue() != 0);
 200     }
 201 
 202 
 203     /**
 204      * Exercise --add-reads with unknown source/target module.
 205      * Warning is emitted.
 206      */
 207     @Test(dataProvider = "badvalues")
 208     public void testWithBadValue(String value, String ignore) throws Exception {
 209 
 210         //  --add-exports $VALUE -version
 211         int exitValue = run("--add-reads", value, "-version")
 212                             .stderrShouldMatch("WARNING: Unknown module: .*.monkey")
 213                             .outputTo(System.out)
 214                             .errorTo(System.out)
 215                             .getExitValue();
 216 
 217         assertTrue(exitValue == 0);
 218     }
 219 
 220     @DataProvider(name = "badvalues")
 221     public Object[][] badValues() {
 222         return new Object[][]{
 223 
 224             { "java.monkey=java.base",      null }, // unknown module
 225             { "java.base=sun.monkey",       null }, // unknown source
 226 
 227         };
 228     }
 229 }