Thu, 17 Oct 2013 13:19:48 -0700
8015912: jdeps support to output in dot file format
8026255: Switch jdeps to follow traditional Java option style
Reviewed-by: alanb
mchung@1472 | 1 | /* |
mchung@1472 | 2 | * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. |
mchung@1472 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
mchung@1472 | 4 | * |
mchung@1472 | 5 | * This code is free software; you can redistribute it and/or modify it |
mchung@1472 | 6 | * under the terms of the GNU General Public License version 2 only, as |
mchung@1472 | 7 | * published by the Free Software Foundation. |
mchung@1472 | 8 | * |
mchung@1472 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
mchung@1472 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
mchung@1472 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
mchung@1472 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
mchung@1472 | 13 | * accompanied this code). |
mchung@1472 | 14 | * |
mchung@1472 | 15 | * You should have received a copy of the GNU General Public License version |
mchung@1472 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
mchung@1472 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
mchung@1472 | 18 | * |
mchung@1472 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
mchung@1472 | 20 | * or visit www.oracle.com if you need additional information or have any |
mchung@1472 | 21 | * questions. |
mchung@1472 | 22 | */ |
mchung@1472 | 23 | |
mchung@1472 | 24 | /* |
mchung@1472 | 25 | * @test |
mchung@2139 | 26 | * @bug 8003562 8005428 8015912 |
mchung@1472 | 27 | * @summary Basic tests for jdeps tool |
mchung@1472 | 28 | * @build Test p.Foo |
mchung@1472 | 29 | * @run main Basic |
mchung@1472 | 30 | */ |
mchung@1472 | 31 | |
mchung@1472 | 32 | import java.io.File; |
mchung@1472 | 33 | import java.io.IOException; |
mchung@1472 | 34 | import java.io.PrintWriter; |
mchung@1472 | 35 | import java.io.StringWriter; |
mchung@1638 | 36 | import java.nio.file.Path; |
mchung@1638 | 37 | import java.nio.file.Paths; |
mchung@1472 | 38 | import java.util.*; |
mchung@1472 | 39 | import java.util.regex.*; |
mchung@1472 | 40 | |
mchung@1472 | 41 | public class Basic { |
mchung@1638 | 42 | private static boolean symbolFileExist = initProfiles(); |
mchung@1638 | 43 | private static boolean initProfiles() { |
mchung@1638 | 44 | // check if ct.sym exists; if not use the profiles.properties file |
mchung@1638 | 45 | Path home = Paths.get(System.getProperty("java.home")); |
mchung@1638 | 46 | if (home.endsWith("jre")) { |
mchung@1638 | 47 | home = home.getParent(); |
mchung@1638 | 48 | } |
mchung@1638 | 49 | Path ctsym = home.resolve("lib").resolve("ct.sym"); |
mchung@1638 | 50 | boolean symbolExists = ctsym.toFile().exists(); |
mchung@1638 | 51 | if (!symbolExists) { |
mchung@1638 | 52 | Path testSrcProfiles = |
mchung@1638 | 53 | Paths.get(System.getProperty("test.src", "."), "profiles.properties"); |
mchung@1638 | 54 | if (!testSrcProfiles.toFile().exists()) |
mchung@1638 | 55 | throw new Error(testSrcProfiles + " does not exist"); |
mchung@1638 | 56 | System.out.format("%s doesn't exist.%nUse %s to initialize profiles info%n", |
mchung@1638 | 57 | ctsym, testSrcProfiles); |
mchung@1638 | 58 | System.setProperty("jdeps.profiles", testSrcProfiles.toString()); |
mchung@1638 | 59 | } |
mchung@1638 | 60 | return symbolExists; |
mchung@1638 | 61 | } |
mchung@1638 | 62 | |
mchung@1472 | 63 | public static void main(String... args) throws Exception { |
mchung@1472 | 64 | int errors = 0; |
mchung@1472 | 65 | errors += new Basic().run(); |
mchung@1472 | 66 | if (errors > 0) |
mchung@1472 | 67 | throw new Exception(errors + " errors found"); |
mchung@1472 | 68 | } |
mchung@1472 | 69 | |
mchung@1472 | 70 | int run() throws IOException { |
mchung@1472 | 71 | File testDir = new File(System.getProperty("test.classes", ".")); |
mchung@1472 | 72 | // test a .class file |
mchung@1472 | 73 | test(new File(testDir, "Test.class"), |
mchung@1638 | 74 | new String[] {"java.lang", "p"}, |
mchung@1638 | 75 | new String[] {"compact1", "not found"}); |
mchung@1472 | 76 | // test a directory |
mchung@1472 | 77 | test(new File(testDir, "p"), |
mchung@1638 | 78 | new String[] {"java.lang", "java.util", "java.lang.management"}, |
mchung@1638 | 79 | new String[] {"compact1", "compact1", "compact3"}); |
mchung@1472 | 80 | // test class-level dependency output |
mchung@1472 | 81 | test(new File(testDir, "Test.class"), |
mchung@2139 | 82 | new String[] {"java.lang.Object", "java.lang.String", "p.Foo"}, |
mchung@2139 | 83 | new String[] {"compact1", "compact1", "not found"}, |
mchung@2139 | 84 | new String[] {"-verbose:class"}); |
mchung@1472 | 85 | // test -p option |
mchung@1472 | 86 | test(new File(testDir, "Test.class"), |
mchung@1472 | 87 | new String[] {"p.Foo"}, |
mchung@1638 | 88 | new String[] {"not found"}, |
mchung@2139 | 89 | new String[] {"-verbose:class", "-p", "p"}); |
mchung@1472 | 90 | // test -e option |
mchung@1472 | 91 | test(new File(testDir, "Test.class"), |
mchung@1472 | 92 | new String[] {"p.Foo"}, |
mchung@1638 | 93 | new String[] {"not found"}, |
mchung@2139 | 94 | new String[] {"-verbose:class", "-e", "p\\..*"}); |
mchung@1472 | 95 | test(new File(testDir, "Test.class"), |
mchung@1472 | 96 | new String[] {"java.lang"}, |
mchung@1638 | 97 | new String[] {"compact1"}, |
mchung@2139 | 98 | new String[] {"-verbose:package", "-e", "java\\.lang\\..*"}); |
mchung@2139 | 99 | // test -classpath and -include options |
mchung@1472 | 100 | test(null, |
mchung@2139 | 101 | new String[] {"java.lang", "java.util", |
mchung@1638 | 102 | "java.lang.management"}, |
mchung@2139 | 103 | new String[] {"compact1", "compact1", "compact3"}, |
mchung@2139 | 104 | new String[] {"-classpath", testDir.getPath(), "-include", "p.+|Test.class"}); |
mchung@2139 | 105 | test(new File(testDir, "Test.class"), |
mchung@2139 | 106 | new String[] {"java.lang.Object", "java.lang.String", "p.Foo"}, |
mchung@2139 | 107 | new String[] {"compact1", "compact1", testDir.getName()}, |
mchung@2139 | 108 | new String[] {"-v", "-classpath", testDir.getPath(), "Test.class"}); |
mchung@1472 | 109 | return errors; |
mchung@1472 | 110 | } |
mchung@1472 | 111 | |
mchung@1638 | 112 | void test(File file, String[] expect, String[] profiles) { |
mchung@1638 | 113 | test(file, expect, profiles, new String[0]); |
mchung@1472 | 114 | } |
mchung@1472 | 115 | |
mchung@1638 | 116 | void test(File file, String[] expect, String[] profiles, String[] options) { |
mchung@1638 | 117 | List<String> args = new ArrayList<>(Arrays.asList(options)); |
mchung@1472 | 118 | if (file != null) { |
mchung@1638 | 119 | args.add(file.getPath()); |
mchung@1472 | 120 | } |
mchung@1638 | 121 | List<String> argsWithDashP = new ArrayList<>(); |
mchung@1638 | 122 | argsWithDashP.add("-P"); |
mchung@1638 | 123 | argsWithDashP.addAll(args); |
mchung@1638 | 124 | // test without -P |
mchung@1638 | 125 | checkResult("dependencies", expect, jdeps(args.toArray(new String[0])).keySet()); |
mchung@1638 | 126 | // test with -P |
mchung@1638 | 127 | checkResult("profiles", expect, profiles, jdeps(argsWithDashP.toArray(new String[0]))); |
mchung@1472 | 128 | } |
mchung@1472 | 129 | |
mchung@1638 | 130 | Map<String,String> jdeps(String... args) { |
mchung@1472 | 131 | StringWriter sw = new StringWriter(); |
mchung@1472 | 132 | PrintWriter pw = new PrintWriter(sw); |
mchung@1472 | 133 | System.err.println("jdeps " + Arrays.toString(args)); |
mchung@1472 | 134 | int rc = com.sun.tools.jdeps.Main.run(args, pw); |
mchung@1472 | 135 | pw.close(); |
mchung@1472 | 136 | String out = sw.toString(); |
mchung@1472 | 137 | if (!out.isEmpty()) |
mchung@1472 | 138 | System.err.println(out); |
mchung@1472 | 139 | if (rc != 0) |
mchung@1472 | 140 | throw new Error("jdeps failed: rc=" + rc); |
mchung@1472 | 141 | return findDeps(out); |
mchung@1472 | 142 | } |
mchung@1472 | 143 | |
mchung@1472 | 144 | // Pattern used to parse lines |
mchung@1472 | 145 | private static Pattern linePattern = Pattern.compile(".*\r?\n"); |
mchung@1638 | 146 | private static Pattern pattern = Pattern.compile("\\s+ -> (\\S+) +(.*)"); |
mchung@1472 | 147 | |
mchung@1472 | 148 | // Use the linePattern to break the given String into lines, applying |
mchung@1472 | 149 | // the pattern to each line to see if we have a match |
mchung@1638 | 150 | private static Map<String,String> findDeps(String out) { |
mchung@1638 | 151 | Map<String,String> result = new HashMap<>(); |
mchung@1472 | 152 | Matcher lm = linePattern.matcher(out); // Line matcher |
mchung@1472 | 153 | Matcher pm = null; // Pattern matcher |
mchung@1472 | 154 | int lines = 0; |
mchung@1472 | 155 | while (lm.find()) { |
mchung@1472 | 156 | lines++; |
mchung@1472 | 157 | CharSequence cs = lm.group(); // The current line |
mchung@1472 | 158 | if (pm == null) |
mchung@1472 | 159 | pm = pattern.matcher(cs); |
mchung@1472 | 160 | else |
mchung@1472 | 161 | pm.reset(cs); |
mchung@1472 | 162 | if (pm.find()) |
mchung@1638 | 163 | result.put(pm.group(1), pm.group(2).trim()); |
mchung@1472 | 164 | if (lm.end() == out.length()) |
mchung@1472 | 165 | break; |
mchung@1472 | 166 | } |
mchung@1638 | 167 | return result; |
mchung@1472 | 168 | } |
mchung@1472 | 169 | |
mchung@1638 | 170 | void checkResult(String label, String[] expect, Collection<String> found) { |
mchung@1638 | 171 | List<String> list = Arrays.asList(expect); |
mchung@1638 | 172 | if (!isEqual(list, found)) |
mchung@1638 | 173 | error("Unexpected " + label + " found: '" + found + "', expected: '" + list + "'"); |
mchung@1638 | 174 | } |
mchung@1472 | 175 | |
mchung@1638 | 176 | void checkResult(String label, String[] expect, String[] profiles, Map<String,String> result) { |
mchung@1638 | 177 | if (expect.length != profiles.length) |
mchung@1638 | 178 | error("Invalid expected names and profiles"); |
mchung@1638 | 179 | |
mchung@1638 | 180 | // check the dependencies |
mchung@1638 | 181 | checkResult(label, expect, result.keySet()); |
mchung@1638 | 182 | // check profile information |
mchung@1638 | 183 | checkResult(label, profiles, result.values()); |
mchung@1638 | 184 | for (int i=0; i < expect.length; i++) { |
mchung@1638 | 185 | String profile = result.get(expect[i]); |
mchung@1638 | 186 | if (!profile.equals(profiles[i])) |
mchung@1638 | 187 | error("Unexpected profile: '" + profile + "', expected: '" + profiles[i] + "'"); |
mchung@1638 | 188 | } |
mchung@1638 | 189 | } |
mchung@1638 | 190 | |
mchung@1638 | 191 | boolean isEqual(List<String> expected, Collection<String> found) { |
mchung@1638 | 192 | if (expected.size() != found.size()) |
mchung@1638 | 193 | return false; |
mchung@1638 | 194 | |
mchung@1638 | 195 | List<String> list = new ArrayList<>(found); |
mchung@1638 | 196 | list.removeAll(expected); |
mchung@1638 | 197 | return list.isEmpty(); |
mchung@1472 | 198 | } |
mchung@1472 | 199 | |
mchung@1472 | 200 | void error(String msg) { |
mchung@1472 | 201 | System.err.println("Error: " + msg); |
mchung@1472 | 202 | errors++; |
mchung@1472 | 203 | } |
mchung@1472 | 204 | |
mchung@1472 | 205 | int errors; |
mchung@1472 | 206 | } |