Tue, 08 May 2018 12:00:20 -0700
Merge
mchung@2538 | 1 | /* |
mchung@2538 | 2 | * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. |
mchung@2538 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
mchung@2538 | 4 | * |
mchung@2538 | 5 | * This code is free software; you can redistribute it and/or modify it |
mchung@2538 | 6 | * under the terms of the GNU General Public License version 2 only, as |
mchung@2538 | 7 | * published by the Free Software Foundation. |
mchung@2538 | 8 | * |
mchung@2538 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
mchung@2538 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
mchung@2538 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
mchung@2538 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
mchung@2538 | 13 | * accompanied this code). |
mchung@2538 | 14 | * |
mchung@2538 | 15 | * You should have received a copy of the GNU General Public License version |
mchung@2538 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
mchung@2538 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
mchung@2538 | 18 | * |
mchung@2538 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
mchung@2538 | 20 | * or visit www.oracle.com if you need additional information or have any |
mchung@2538 | 21 | * questions. |
mchung@2538 | 22 | */ |
mchung@2538 | 23 | |
mchung@2538 | 24 | /* |
mchung@2538 | 25 | * @test |
mchung@2538 | 26 | * @bug 8003562 |
mchung@2538 | 27 | * @summary Basic tests for jdeps -dotoutput option |
mchung@2538 | 28 | * @build Test p.Foo p.Bar javax.activity.NotCompactProfile |
mchung@2538 | 29 | * @run main DotFileTest |
mchung@2538 | 30 | */ |
mchung@2538 | 31 | |
mchung@2538 | 32 | import java.io.File; |
mchung@2538 | 33 | import java.io.IOException; |
mchung@2538 | 34 | import java.io.PrintWriter; |
mchung@2538 | 35 | import java.io.StringWriter; |
mchung@2538 | 36 | import java.nio.file.DirectoryStream; |
mchung@2538 | 37 | import java.nio.file.Files; |
mchung@2538 | 38 | import java.nio.file.Path; |
mchung@2538 | 39 | import java.nio.file.Paths; |
mchung@2538 | 40 | import java.util.*; |
mchung@2538 | 41 | import java.util.regex.*; |
mchung@2538 | 42 | |
mchung@2538 | 43 | public class DotFileTest { |
mchung@2538 | 44 | private static boolean symbolFileExist = initProfiles(); |
mchung@2538 | 45 | private static boolean initProfiles() { |
mchung@2538 | 46 | // check if ct.sym exists; if not use the profiles.properties file |
mchung@2538 | 47 | Path home = Paths.get(System.getProperty("java.home")); |
mchung@2538 | 48 | if (home.endsWith("jre")) { |
mchung@2538 | 49 | home = home.getParent(); |
mchung@2538 | 50 | } |
mchung@2538 | 51 | Path ctsym = home.resolve("lib").resolve("ct.sym"); |
mchung@2538 | 52 | boolean symbolExists = ctsym.toFile().exists(); |
mchung@2538 | 53 | if (!symbolExists) { |
mchung@2538 | 54 | Path testSrcProfiles = |
mchung@2538 | 55 | Paths.get(System.getProperty("test.src", "."), "profiles.properties"); |
mchung@2538 | 56 | if (!testSrcProfiles.toFile().exists()) |
mchung@2538 | 57 | throw new Error(testSrcProfiles + " does not exist"); |
mchung@2538 | 58 | System.out.format("%s doesn't exist.%nUse %s to initialize profiles info%n", |
mchung@2538 | 59 | ctsym, testSrcProfiles); |
mchung@2538 | 60 | System.setProperty("jdeps.profiles", testSrcProfiles.toString()); |
mchung@2538 | 61 | } |
mchung@2538 | 62 | return symbolExists; |
mchung@2538 | 63 | } |
mchung@2538 | 64 | |
mchung@2538 | 65 | public static void main(String... args) throws Exception { |
mchung@2538 | 66 | int errors = 0; |
mchung@2538 | 67 | errors += new DotFileTest().run(); |
mchung@2538 | 68 | if (errors > 0) |
mchung@2538 | 69 | throw new Exception(errors + " errors found"); |
mchung@2538 | 70 | } |
mchung@2538 | 71 | |
mchung@2538 | 72 | final Path dir; |
mchung@2538 | 73 | final Path dotoutput; |
mchung@2538 | 74 | DotFileTest() { |
mchung@2538 | 75 | this.dir = Paths.get(System.getProperty("test.classes", ".")); |
mchung@2538 | 76 | this.dotoutput = dir.resolve("dots"); |
mchung@2538 | 77 | } |
mchung@2538 | 78 | |
mchung@2538 | 79 | int run() throws IOException { |
mchung@2538 | 80 | File testDir = dir.toFile(); |
mchung@2538 | 81 | // test a .class file |
mchung@2538 | 82 | test(new File(testDir, "Test.class"), |
mchung@2538 | 83 | new String[] {"java.lang", "p"}, |
mchung@2538 | 84 | new String[] {"compact1", "not found"}); |
mchung@2538 | 85 | // test a directory |
mchung@2538 | 86 | // also test non-SE javax.activity class dependency |
mchung@2538 | 87 | test(new File(testDir, "p"), |
mchung@2538 | 88 | new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto"}, |
mchung@2538 | 89 | new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"}, |
mchung@2538 | 90 | new String[] {"-classpath", testDir.getPath()}); |
mchung@2538 | 91 | // test class-level dependency output |
mchung@2538 | 92 | test(new File(testDir, "Test.class"), |
mchung@2538 | 93 | new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"}, |
mchung@2538 | 94 | new String[] {"compact1", "compact1", "not found", "not found"}, |
mchung@2538 | 95 | new String[] {"-verbose:class"}); |
mchung@2538 | 96 | // test -filter:none option |
mchung@2538 | 97 | test(new File(testDir, "p"), |
mchung@2538 | 98 | new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto", "p"}, |
mchung@2538 | 99 | new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1", "p"}, |
mchung@2538 | 100 | new String[] {"-classpath", testDir.getPath(), "-verbose:package", "-filter:none"}); |
mchung@2538 | 101 | // test -filter:archive option |
mchung@2538 | 102 | test(new File(testDir, "p"), |
mchung@2538 | 103 | new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto"}, |
mchung@2538 | 104 | new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"}, |
mchung@2538 | 105 | new String[] {"-classpath", testDir.getPath(), "-verbose:package", "-filter:archive"}); |
mchung@2538 | 106 | // test -p option |
mchung@2538 | 107 | test(new File(testDir, "Test.class"), |
mchung@2538 | 108 | new String[] {"p.Foo", "p.Bar"}, |
mchung@2538 | 109 | new String[] {"not found", "not found"}, |
mchung@2538 | 110 | new String[] {"-verbose:class", "-p", "p"}); |
mchung@2538 | 111 | // test -e option |
mchung@2538 | 112 | test(new File(testDir, "Test.class"), |
mchung@2538 | 113 | new String[] {"p.Foo", "p.Bar"}, |
mchung@2538 | 114 | new String[] {"not found", "not found"}, |
mchung@2538 | 115 | new String[] {"-verbose:class", "-e", "p\\..*"}); |
mchung@2538 | 116 | test(new File(testDir, "Test.class"), |
mchung@2538 | 117 | new String[] {"java.lang"}, |
mchung@2538 | 118 | new String[] {"compact1"}, |
mchung@2538 | 119 | new String[] {"-verbose:package", "-e", "java\\.lang\\..*"}); |
mchung@2538 | 120 | // test -classpath options |
mchung@2538 | 121 | test(new File(testDir, "Test.class"), |
mchung@2538 | 122 | new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"}, |
mchung@2538 | 123 | new String[] {"compact1", "compact1", testDir.getName(), testDir.getName()}, |
mchung@2538 | 124 | new String[] {"-v", "-classpath", testDir.getPath()}); |
mchung@2538 | 125 | |
mchung@2538 | 126 | testSummary(new File(testDir, "Test.class"), |
mchung@2538 | 127 | new String[] {"rt.jar", testDir.getName()}, |
mchung@2538 | 128 | new String[] {"compact1", ""}, |
mchung@2538 | 129 | new String[] {"-classpath", testDir.getPath()}); |
mchung@2538 | 130 | testSummary(new File(testDir, "Test.class"), |
mchung@2538 | 131 | new String[] {"java.lang", "p"}, |
mchung@2538 | 132 | new String[] {"compact1", testDir.getName()}, |
mchung@2538 | 133 | new String[] {"-v", "-classpath", testDir.getPath()}); |
mchung@2538 | 134 | return errors; |
mchung@2538 | 135 | } |
mchung@2538 | 136 | |
mchung@2538 | 137 | void test(File file, String[] expect, String[] profiles) throws IOException { |
mchung@2538 | 138 | test(file, expect, profiles, new String[0]); |
mchung@2538 | 139 | } |
mchung@2538 | 140 | |
mchung@2538 | 141 | void test(File file, String[] expect, String[] profiles, String[] options) |
mchung@2538 | 142 | throws IOException |
mchung@2538 | 143 | { |
mchung@2538 | 144 | Path dotfile = dotoutput.resolve(file.toPath().getFileName().toString() + ".dot"); |
mchung@2538 | 145 | |
mchung@2538 | 146 | List<String> args = new ArrayList<>(Arrays.asList(options)); |
mchung@2538 | 147 | args.add("-dotoutput"); |
mchung@2538 | 148 | args.add(dotoutput.toString()); |
mchung@2538 | 149 | if (file != null) { |
mchung@2538 | 150 | args.add(file.getPath()); |
mchung@2538 | 151 | } |
mchung@2538 | 152 | |
mchung@2538 | 153 | Map<String,String> result = jdeps(args, dotfile); |
mchung@2538 | 154 | checkResult("dependencies", expect, result.keySet()); |
mchung@2538 | 155 | |
mchung@2538 | 156 | // with -P option |
mchung@2538 | 157 | List<String> argsWithDashP = new ArrayList<>(); |
mchung@2538 | 158 | argsWithDashP.add("-dotoutput"); |
mchung@2538 | 159 | argsWithDashP.add(dotoutput.toString()); |
mchung@2538 | 160 | argsWithDashP.add("-P"); |
mchung@2538 | 161 | argsWithDashP.addAll(args); |
mchung@2538 | 162 | |
mchung@2538 | 163 | result = jdeps(argsWithDashP, dotfile); |
mchung@2538 | 164 | checkResult("profiles", expect, profiles, result); |
mchung@2538 | 165 | } |
mchung@2538 | 166 | |
mchung@2538 | 167 | void testSummary(File file, String[] expect, String[] profiles, String[] options) |
mchung@2538 | 168 | throws IOException |
mchung@2538 | 169 | { |
mchung@2538 | 170 | Path dotfile = dotoutput.resolve("summary.dot"); |
mchung@2538 | 171 | |
mchung@2538 | 172 | List<String> args = new ArrayList<>(Arrays.asList(options)); |
mchung@2538 | 173 | args.add("-dotoutput"); |
mchung@2538 | 174 | args.add(dotoutput.toString()); |
mchung@2538 | 175 | if (file != null) { |
mchung@2538 | 176 | args.add(file.getPath()); |
mchung@2538 | 177 | } |
mchung@2538 | 178 | |
mchung@2538 | 179 | Map<String,String> result = jdeps(args, dotfile); |
mchung@2538 | 180 | checkResult("dependencies", expect, result.keySet()); |
mchung@2538 | 181 | |
mchung@2538 | 182 | // with -P option |
mchung@2538 | 183 | List<String> argsWithDashP = new ArrayList<>(); |
mchung@2538 | 184 | argsWithDashP.add("-dotoutput"); |
mchung@2538 | 185 | argsWithDashP.add(dotoutput.toString()); |
mchung@2538 | 186 | argsWithDashP.add("-P"); |
mchung@2538 | 187 | argsWithDashP.addAll(args); |
mchung@2538 | 188 | |
mchung@2538 | 189 | result = jdeps(argsWithDashP, dotfile); |
mchung@2538 | 190 | checkResult("profiles", expect, profiles, result); |
mchung@2538 | 191 | } |
mchung@2538 | 192 | |
mchung@2538 | 193 | Map<String,String> jdeps(List<String> args, Path dotfile) throws IOException { |
mchung@2538 | 194 | if (Files.exists(dotoutput)) { |
mchung@2538 | 195 | try (DirectoryStream<Path> stream = Files.newDirectoryStream(dotoutput)) { |
mchung@2538 | 196 | for (Path p : stream) { |
mchung@2538 | 197 | Files.delete(p); |
mchung@2538 | 198 | } |
mchung@2538 | 199 | } |
mchung@2538 | 200 | Files.delete(dotoutput); |
mchung@2538 | 201 | } |
mchung@2538 | 202 | // invoke jdeps |
mchung@2538 | 203 | StringWriter sw = new StringWriter(); |
mchung@2538 | 204 | PrintWriter pw = new PrintWriter(sw); |
mchung@2538 | 205 | System.err.println("jdeps " + args); |
mchung@2538 | 206 | int rc = com.sun.tools.jdeps.Main.run(args.toArray(new String[0]), pw); |
mchung@2538 | 207 | pw.close(); |
mchung@2538 | 208 | String out = sw.toString(); |
mchung@2538 | 209 | if (!out.isEmpty()) |
mchung@2538 | 210 | System.err.println(out); |
mchung@2538 | 211 | if (rc != 0) |
mchung@2538 | 212 | throw new Error("jdeps failed: rc=" + rc); |
mchung@2538 | 213 | |
mchung@2538 | 214 | // check output files |
mchung@2538 | 215 | if (Files.notExists(dotfile)) { |
mchung@2538 | 216 | throw new RuntimeException(dotfile + " doesn't exist"); |
mchung@2538 | 217 | } |
mchung@2538 | 218 | return parse(dotfile); |
mchung@2538 | 219 | } |
mchung@2538 | 220 | private static Pattern pattern = Pattern.compile("(.*) -> +([^ ]*) (.*)"); |
mchung@2538 | 221 | private Map<String,String> parse(Path outfile) throws IOException { |
mchung@2538 | 222 | Map<String,String> result = new LinkedHashMap<>(); |
mchung@2538 | 223 | for (String line : Files.readAllLines(outfile)) { |
mchung@2538 | 224 | line = line.replace('"', ' ').replace(';', ' '); |
mchung@2538 | 225 | Matcher pm = pattern.matcher(line); |
mchung@2538 | 226 | if (pm.find()) { |
mchung@2538 | 227 | String origin = pm.group(1).trim(); |
mchung@2538 | 228 | String target = pm.group(2).trim(); |
mchung@2538 | 229 | String module = pm.group(3).replace('(', ' ').replace(')', ' ').trim(); |
mchung@2538 | 230 | result.put(target, module); |
mchung@2538 | 231 | } |
mchung@2538 | 232 | } |
mchung@2538 | 233 | return result; |
mchung@2538 | 234 | } |
mchung@2538 | 235 | |
mchung@2538 | 236 | void checkResult(String label, String[] expect, Collection<String> found) { |
mchung@2538 | 237 | List<String> list = Arrays.asList(expect); |
mchung@2538 | 238 | if (!isEqual(list, found)) |
mchung@2538 | 239 | error("Unexpected " + label + " found: '" + found + "', expected: '" + list + "'"); |
mchung@2538 | 240 | } |
mchung@2538 | 241 | |
mchung@2538 | 242 | void checkResult(String label, String[] expect, String[] profiles, Map<String,String> result) { |
mchung@2538 | 243 | if (expect.length != profiles.length) |
mchung@2538 | 244 | error("Invalid expected names and profiles"); |
mchung@2538 | 245 | |
mchung@2538 | 246 | // check the dependencies |
mchung@2538 | 247 | checkResult(label, expect, result.keySet()); |
mchung@2538 | 248 | // check profile information |
mchung@2538 | 249 | checkResult(label, profiles, result.values()); |
mchung@2538 | 250 | for (int i=0; i < expect.length; i++) { |
mchung@2538 | 251 | String profile = result.get(expect[i]); |
mchung@2538 | 252 | if (!profile.equals(profiles[i])) |
mchung@2538 | 253 | error("Unexpected profile: '" + profile + "', expected: '" + profiles[i] + "'"); |
mchung@2538 | 254 | } |
mchung@2538 | 255 | } |
mchung@2538 | 256 | |
mchung@2538 | 257 | boolean isEqual(List<String> expected, Collection<String> found) { |
mchung@2538 | 258 | if (expected.size() != found.size()) |
mchung@2538 | 259 | return false; |
mchung@2538 | 260 | |
mchung@2538 | 261 | List<String> list = new ArrayList<>(found); |
mchung@2538 | 262 | list.removeAll(expected); |
mchung@2538 | 263 | return list.isEmpty(); |
mchung@2538 | 264 | } |
mchung@2538 | 265 | |
mchung@2538 | 266 | void error(String msg) { |
mchung@2538 | 267 | System.err.println("Error: " + msg); |
mchung@2538 | 268 | errors++; |
mchung@2538 | 269 | } |
mchung@2538 | 270 | |
mchung@2538 | 271 | int errors; |
mchung@2538 | 272 | } |