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.io.File; 39 import java.nio.file.Path; 40 import java.nio.file.Paths; 41 import java.util.Arrays; 42 import java.util.List; 43 import java.util.stream.Collectors; 44 45 import org.testng.annotations.BeforeTest; 46 import org.testng.annotations.DataProvider; 47 import org.testng.annotations.Test; 48 49 import static org.testng.Assert.assertEquals; 50 import static org.testng.Assert.assertTrue; 51 52 public class ListModuleDeps { 53 private static final String TEST_SRC = System.getProperty("test.src"); 54 55 private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); 56 private static final Path CLASSES_DIR = Paths.get("classes"); 57 private static final Path LIB_DIR = Paths.get("lib"); 58 private static final Path LIB2_DIR = Paths.get("lib2"); 59 60 private static final Path HI_CLASS = 61 CLASSES_DIR.resolve("hi").resolve("Hi.class"); 62 private static final Path FOO_CLASS = 63 CLASSES_DIR.resolve("z").resolve("Foo.class"); 64 private static final Path BAR_CLASS = 65 CLASSES_DIR.resolve("z").resolve("Bar.class"); 66 private static final Path UNSAFE_CLASS = 67 CLASSES_DIR.resolve("z").resolve("UseUnsafe.class"); 68 69 /** 70 * Compiles classes used by the test 71 */ 72 @BeforeTest 73 public void compileAll() throws Exception { 74 // compile library 75 assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "lib2"), LIB2_DIR)); 76 assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "lib"), LIB_DIR, "-cp", LIB2_DIR.toString())); 77 78 // simple program depends only on java.base 79 assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "hi"), CLASSES_DIR)); 80 81 // compile classes in unnamed module 82 assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "z"), 83 CLASSES_DIR, 84 "-cp", LIB_DIR.toString(), 85 "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", 86 "--add-exports=java.base/sun.security.util=ALL-UNNAMED", 87 "--add-exports=java.xml/jdk.xml.internal=ALL-UNNAMED" 88 )); 89 } 90 91 @DataProvider(name = "jdkModules") 92 public Object[][] jdkModules() { 93 return new Object[][]{ 94 {"jdk.compiler", new String[]{ 95 "java.base/jdk.internal.jmod", 96 "java.base/jdk.internal.misc", 97 "java.base/sun.reflect.annotation", 98 "java.compiler", 99 } 100 }, 101 }; 102 } 103 104 @Test(dataProvider = "jdkModules") 105 public void testJDKModule(String moduleName, String[] expected) { 106 JdepsRunner jdeps = JdepsRunner.run( 107 "--list-deps", "-m", moduleName 108 ); 109 String[] output = Arrays.stream(jdeps.output()) 110 .map(s -> s.trim()) 111 .toArray(String[]::new); 112 assertEquals(output, expected); 113 } 114 115 @Test(dataProvider = "listdeps") 116 public void testListDeps(Path classes, String[] expected) { 117 JdepsRunner jdeps = JdepsRunner.run( 118 "--class-path", LIB_DIR.toString() + File.pathSeparator + LIB2_DIR.toString(), 119 "--list-deps", classes.toString() 120 ); 121 String[] output = Arrays.stream(jdeps.output()) 122 .map(s -> s.trim()) 123 .toArray(String[]::new); 124 assertEquals(output, expected); 125 } 126 127 @Test(dataProvider = "reduceddeps") 128 public void testListReducedDeps(Path classes, String[] expected) { 129 JdepsRunner jdeps = JdepsRunner.run( 130 "--class-path", LIB_DIR.toString() + File.pathSeparator + LIB2_DIR.toString(), 131 "--list-reduced-deps", classes.toString() 132 ); 133 String[] output = Arrays.stream(jdeps.output()) 134 .map(s -> s.trim()) 135 .toArray(String[]::new); 136 assertEquals(output, expected); 137 } 138 139 140 @DataProvider(name = "listdeps") 141 public Object[][] listdeps() { 142 return new Object[][] { 143 { CLASSES_DIR, new String[] { 144 "java.base/jdk.internal.misc", 145 "java.base/sun.security.util", 146 "java.logging", 147 "java.management", 148 "java.sql", 149 "java.xml/jdk.xml.internal", 150 "jdk.unsupported" 151 } 152 }, 153 154 { HI_CLASS, new String[] { 155 "java.base" 156 } 157 }, 158 159 { FOO_CLASS, new String[] { 160 "java.base", 161 "java.logging", 162 "java.management", 163 "java.sql", 164 "java.xml" 165 } 166 }, 167 168 { BAR_CLASS, new String[] { 169 "java.base/sun.security.util", 170 "java.xml/jdk.xml.internal", 171 } 172 }, 173 174 { UNSAFE_CLASS, new String[] { 175 "java.base/jdk.internal.misc", 176 "jdk.unsupported" 177 } 178 }, 179 }; 180 } 181 182 @DataProvider(name = "reduceddeps") 183 public Object[][] reduceddeps() { 184 Path barClass = CLASSES_DIR.resolve("z").resolve("Bar.class"); 185 186 return new Object[][] { 187 { CLASSES_DIR, new String[] { 188 "java.base/jdk.internal.misc", 189 "java.base/sun.security.util", 190 "java.management", 191 "java.sql", 192 "java.xml/jdk.xml.internal", 193 "jdk.unsupported" 194 } 195 }, 196 197 { HI_CLASS, new String[] { 198 "java.base" 199 } 200 }, 201 202 { FOO_CLASS, new String[] { 203 "java.base", 204 "java.management", 205 "java.sql" 206 } 207 }, 208 209 { BAR_CLASS, new String[] { 210 "java.base/sun.security.util", 211 "java.xml/jdk.xml.internal", 212 } 213 }, 214 215 { UNSAFE_CLASS, new String[] { 216 "java.base/jdk.internal.misc", 217 "jdk.unsupported" 218 } 219 }, 220 }; 221 } 222 223 @Test(dataProvider = "moduledeps") 224 public void testPrintModuleDeps(Path classes, String expected) { 225 JdepsRunner jdeps = JdepsRunner.run( 226 "--class-path", LIB_DIR.toString() + File.pathSeparator + LIB2_DIR.toString(), 227 "--print-module-deps", classes.toString() 228 ); 229 String output = Arrays.stream(jdeps.output()) 230 .map(s -> s.trim()) 231 .collect(Collectors.joining(",")); 232 assertEquals(output, expected); 233 } 234 235 236 @DataProvider(name = "moduledeps") 237 public Object[][] moduledeps() { 238 Path barClass = CLASSES_DIR.resolve("z").resolve("Bar.class"); 239 240 return new Object[][] { 241 // java.xml is an implied reads edge from java.sql 242 { CLASSES_DIR, "java.base,java.management,java.sql,jdk.unsupported"}, 243 { HI_CLASS, "java.base"}, 244 { FOO_CLASS, "java.base,java.management,java.sql"}, 245 { BAR_CLASS, "java.base,java.xml"}, 246 { UNSAFE_CLASS, "java.base,jdk.unsupported"}, 247 }; 248 } 249 250 @Test(dataProvider = "noRecursiveModuledeps") 251 public void testNoRecursiveModuleDeps(Path classes, String expected) { 252 JdepsRunner jdeps = JdepsRunner.run( 253 "--class-path", LIB_DIR.toString() + File.pathSeparator + LIB2_DIR.toString(), 254 "--print-module-deps", "--no-recursive", classes.toString() 255 ); 256 String output = Arrays.stream(jdeps.output()) 257 .map(s -> s.trim()) 258 .collect(Collectors.joining(",")); 259 assertEquals(output, expected); 260 } 261 262 @DataProvider(name = "noRecursiveModuledeps") 263 public Object[][] noRecursiveModuledeps() { 264 Path barClass = CLASSES_DIR.resolve("z").resolve("Bar.class"); 265 266 return new Object[][] { 267 // java.xml is an implied reads edge from java.sql 268 { CLASSES_DIR, "java.base,java.sql,jdk.unsupported"}, 269 { HI_CLASS, "java.base"}, 270 { FOO_CLASS, "java.base,java.sql"}, 271 { BAR_CLASS, "java.base,java.xml"}, 272 { UNSAFE_CLASS, "java.base,jdk.unsupported"}, 273 }; 274 } 275 276 @DataProvider(name = "recursiveDeps") 277 public Object[][] recursiveDeps() { 278 return new Object[][] { 279 { // lib2 is classpath but not analyzed because lib.Lib is not present 280 // but it is the only class depending on lib2.Lib2 281 List.of("--list-deps", "--class-path", LIB2_DIR.toString(), 282 "--ignore-missing-deps", CLASSES_DIR.toString()), 283 new String[] { 284 "java.base/jdk.internal.misc", 285 "java.base/sun.security.util", 286 "java.logging", 287 "java.sql", 288 "java.xml/jdk.xml.internal", 289 "jdk.unsupported" 290 } 291 }, 292 { // lib2 is classpath but not analyzed because lib.Lib is not present 293 // but it is the only class depending on lib2.Lib2 294 List.of("--print-module-deps", "--class-path", LIB2_DIR.toString(), 295 "--ignore-missing-deps", CLASSES_DIR.toString()), 296 new String[] { 297 "java.base,java.sql,jdk.unsupported" 298 } 299 }, 300 { // Foo depends on lib.Lib which depends on lib2.Libs 301 List.of("--print-module-deps", 302 "--ignore-missing-deps", FOO_CLASS.toString()), 303 new String[] { 304 "java.base,java.sql" 305 } 306 }, 307 }; 308 } 309 310 @Test(dataProvider = "recursiveDeps") 311 public void testRecursiveDeps(List<String> options, String[] expected) { 312 JdepsRunner jdeps = JdepsRunner.run(options.toArray(new String[0])); 313 String[] output = Arrays.stream(jdeps.output()) 314 .map(s -> s.trim()) 315 .toArray(String[]::new); 316 assertEquals(output, expected); 317 } 318 }