1 /*
   2  * Copyright (c) 2016, 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  * @bug 8167057
  27  * @summary Tests --list-deps, --list-reduced-deps, --print-module-deps options
  28  * @modules java.logging
  29  *          java.xml
  30  *          jdk.compiler
  31  *          jdk.jdeps
  32  *          jdk.unsupported
  33  * @library ../lib
  34  * @build CompilerUtils JdepsRunner
  35  * @run testng ListModuleDeps
  36  */
  37 
  38 import java.nio.file.Path;
  39 import java.nio.file.Paths;
  40 import java.util.Arrays;
  41 import java.util.stream.Collectors;
  42 
  43 import org.testng.annotations.BeforeTest;
  44 import org.testng.annotations.DataProvider;
  45 import org.testng.annotations.Test;
  46 
  47 import static org.testng.Assert.assertEquals;
  48 import static org.testng.Assert.assertTrue;
  49 
  50 public class ListModuleDeps {
  51     private static final String TEST_SRC = System.getProperty("test.src");
  52 
  53     private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
  54     private static final Path CLASSES_DIR = Paths.get("classes");
  55     private static final Path LIB_DIR = Paths.get("lib");
  56 
  57     private static final Path HI_CLASS =
  58         CLASSES_DIR.resolve("hi").resolve("Hi.class");
  59     private static final Path FOO_CLASS =
  60         CLASSES_DIR.resolve("z").resolve("Foo.class");
  61     private static final Path BAR_CLASS =
  62         CLASSES_DIR.resolve("z").resolve("Bar.class");
  63     private static final Path UNSAFE_CLASS =
  64         CLASSES_DIR.resolve("z").resolve("UseUnsafe.class");
  65 
  66     /**
  67      * Compiles classes used by the test
  68      */
  69     @BeforeTest
  70     public void compileAll() throws Exception {
  71         // compile library
  72         assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "lib"), LIB_DIR));
  73 
  74         // simple program depends only on java.base
  75         assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "hi"), CLASSES_DIR));
  76 
  77         // compile classes in unnamed module
  78         assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "z"),
  79             CLASSES_DIR,
  80             "-cp", LIB_DIR.toString(),
  81             "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
  82             "--add-exports=java.base/sun.security.util=ALL-UNNAMED",
  83             "--add-exports=java.xml/jdk.xml.internal=ALL-UNNAMED"
  84         ));
  85     }
  86 
  87     @DataProvider(name = "jdkModules")
  88     public Object[][] jdkModules() {
  89         return new Object[][]{
  90             {"jdk.compiler", new String[]{
  91                                 "java.base/jdk.internal.jmod",
  92                                 "java.base/jdk.internal.misc",
  93                                 "java.base/sun.reflect.annotation",
  94                                 "java.compiler",
  95                              }
  96             },
  97         };
  98     }
  99 
 100     @Test(dataProvider = "jdkModules")
 101     public void testJDKModule(String moduleName, String[] expected) {
 102         JdepsRunner jdeps = JdepsRunner.run(
 103             "--list-deps", "-m", moduleName
 104         );
 105         String[] output = Arrays.stream(jdeps.output())
 106                                 .map(s -> s.trim())
 107                                 .toArray(String[]::new);
 108         assertEquals(output, expected);
 109     }
 110 
 111     @Test(dataProvider = "listdeps")
 112     public void testListDeps(Path classes, String[] expected) {
 113         JdepsRunner jdeps = JdepsRunner.run(
 114             "--class-path", LIB_DIR.toString(),
 115             "--list-deps", classes.toString()
 116         );
 117         String[] output = Arrays.stream(jdeps.output())
 118                                 .map(s -> s.trim())
 119                                 .toArray(String[]::new);
 120         assertEquals(output, expected);
 121     }
 122 
 123     @Test(dataProvider = "reduceddeps")
 124     public void testListReducedDeps(Path classes, String[]  expected) {
 125         JdepsRunner jdeps = JdepsRunner.run(
 126             "--class-path", LIB_DIR.toString(),
 127             "--list-reduced-deps", classes.toString()
 128         );
 129         String[] output = Arrays.stream(jdeps.output())
 130                                 .map(s -> s.trim())
 131                                 .toArray(String[]::new);
 132         assertEquals(output, expected);
 133     }
 134 
 135 
 136     @DataProvider(name = "listdeps")
 137     public Object[][] listdeps() {
 138         return new Object[][] {
 139             { CLASSES_DIR,  new String[] {
 140                                 "java.base/jdk.internal.misc",
 141                                 "java.base/sun.security.util",
 142                                 "java.logging",
 143                                 "java.sql",
 144                                 "java.xml/jdk.xml.internal",
 145                                 "jdk.unsupported"
 146                             }
 147             },
 148 
 149             { HI_CLASS,     new String[] {
 150                                 "java.base"
 151                             }
 152             },
 153 
 154             { FOO_CLASS,    new String[] {
 155                                 "java.base",
 156                                 "java.logging",
 157                                 "java.sql",
 158                                 "java.xml"
 159                             }
 160             },
 161 
 162             { BAR_CLASS,    new String[] {
 163                                 "java.base/sun.security.util",
 164                                 "java.xml/jdk.xml.internal",
 165                             }
 166             },
 167 
 168             { UNSAFE_CLASS, new String[] {
 169                                 "java.base/jdk.internal.misc",
 170                                 "jdk.unsupported"
 171                             }
 172             },
 173         };
 174     }
 175 
 176     @DataProvider(name = "reduceddeps")
 177     public Object[][] reduceddeps() {
 178         Path barClass = CLASSES_DIR.resolve("z").resolve("Bar.class");
 179 
 180         return new Object[][] {
 181             { CLASSES_DIR,  new String[] {
 182                                 "java.base/jdk.internal.misc",
 183                                 "java.base/sun.security.util",
 184                                 "java.sql",
 185                                 "java.xml/jdk.xml.internal",
 186                                 "jdk.unsupported"
 187                             }
 188             },
 189 
 190             { HI_CLASS,     new String[] {
 191                                 "java.base"
 192                             }
 193             },
 194 
 195             { FOO_CLASS,    new String[] {
 196                                 "java.base",
 197                                 "java.sql"
 198                             }
 199             },
 200 
 201             { BAR_CLASS,    new String[] {
 202                                 "java.base/sun.security.util",
 203                                 "java.xml/jdk.xml.internal",
 204                             }
 205             },
 206 
 207             { UNSAFE_CLASS, new String[] {
 208                                 "java.base/jdk.internal.misc",
 209                                 "jdk.unsupported"
 210                             }
 211             },
 212         };
 213     }
 214 
 215     @Test(dataProvider = "moduledeps")
 216     public void testPrintModuleDeps(Path classes, String expected) {
 217         JdepsRunner jdeps = JdepsRunner.run(
 218             "--class-path", LIB_DIR.toString(),
 219             "--print-module-deps", classes.toString()
 220         );
 221         String output = Arrays.stream(jdeps.output())
 222             .map(s -> s.trim())
 223             .collect(Collectors.joining(","));
 224         assertEquals(output, expected);
 225     }
 226 
 227 
 228     @DataProvider(name = "moduledeps")
 229     public Object[][] moduledeps() {
 230         Path barClass = CLASSES_DIR.resolve("z").resolve("Bar.class");
 231 
 232         return new Object[][] {
 233             // java.xml is an implied reads edge from java.sql
 234             { CLASSES_DIR,  "java.base,java.sql,jdk.unsupported"},
 235             { HI_CLASS,     "java.base"},
 236             { FOO_CLASS,    "java.base,java.sql"},
 237             { BAR_CLASS,    "java.base,java.xml"},
 238             { UNSAFE_CLASS, "java.base,jdk.unsupported"},
 239         };
 240     }
 241 }