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