Mon, 20 Apr 2015 13:41:05 -0700
Merge
mchung@1472 | 1 | /* |
mchung@2538 | 2 | * Copyright (c) 2012, 2014, 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@2538 | 26 | * @bug 8003562 8005428 8015912 8027481 8048063 |
mchung@1472 | 27 | * @summary Basic tests for jdeps tool |
mchung@2172 | 28 | * @build Test p.Foo p.Bar javax.activity.NotCompactProfile |
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@2172 | 36 | import java.nio.file.Files; |
mchung@1638 | 37 | import java.nio.file.Path; |
mchung@1638 | 38 | import java.nio.file.Paths; |
mchung@1472 | 39 | import java.util.*; |
mchung@1472 | 40 | import java.util.regex.*; |
mchung@2172 | 41 | import static java.nio.file.StandardCopyOption.*; |
mchung@1472 | 42 | |
mchung@1472 | 43 | public class Basic { |
mchung@1638 | 44 | private static boolean symbolFileExist = initProfiles(); |
mchung@1638 | 45 | private static boolean initProfiles() { |
mchung@1638 | 46 | // check if ct.sym exists; if not use the profiles.properties file |
mchung@1638 | 47 | Path home = Paths.get(System.getProperty("java.home")); |
mchung@1638 | 48 | if (home.endsWith("jre")) { |
mchung@1638 | 49 | home = home.getParent(); |
mchung@1638 | 50 | } |
mchung@1638 | 51 | Path ctsym = home.resolve("lib").resolve("ct.sym"); |
mchung@1638 | 52 | boolean symbolExists = ctsym.toFile().exists(); |
mchung@1638 | 53 | if (!symbolExists) { |
mchung@1638 | 54 | Path testSrcProfiles = |
mchung@1638 | 55 | Paths.get(System.getProperty("test.src", "."), "profiles.properties"); |
mchung@1638 | 56 | if (!testSrcProfiles.toFile().exists()) |
mchung@1638 | 57 | throw new Error(testSrcProfiles + " does not exist"); |
mchung@1638 | 58 | System.out.format("%s doesn't exist.%nUse %s to initialize profiles info%n", |
mchung@1638 | 59 | ctsym, testSrcProfiles); |
mchung@1638 | 60 | System.setProperty("jdeps.profiles", testSrcProfiles.toString()); |
mchung@1638 | 61 | } |
mchung@1638 | 62 | return symbolExists; |
mchung@1638 | 63 | } |
mchung@1638 | 64 | |
mchung@1472 | 65 | public static void main(String... args) throws Exception { |
mchung@1472 | 66 | int errors = 0; |
mchung@1472 | 67 | errors += new Basic().run(); |
mchung@1472 | 68 | if (errors > 0) |
mchung@1472 | 69 | throw new Exception(errors + " errors found"); |
mchung@1472 | 70 | } |
mchung@1472 | 71 | |
mchung@1472 | 72 | int run() throws IOException { |
mchung@1472 | 73 | File testDir = new File(System.getProperty("test.classes", ".")); |
mchung@1472 | 74 | // test a .class file |
mchung@1472 | 75 | test(new File(testDir, "Test.class"), |
mchung@1638 | 76 | new String[] {"java.lang", "p"}, |
mchung@1638 | 77 | new String[] {"compact1", "not found"}); |
mchung@1472 | 78 | // test a directory |
mchung@2172 | 79 | // also test non-SE javax.activity class dependency |
mchung@1472 | 80 | test(new File(testDir, "p"), |
mchung@2172 | 81 | new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto"}, |
mchung@2172 | 82 | new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"}, |
mchung@2172 | 83 | new String[] {"-classpath", testDir.getPath()}); |
mchung@1472 | 84 | // test class-level dependency output |
mchung@1472 | 85 | test(new File(testDir, "Test.class"), |
mchung@2172 | 86 | new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"}, |
mchung@2172 | 87 | new String[] {"compact1", "compact1", "not found", "not found"}, |
mchung@2139 | 88 | new String[] {"-verbose:class"}); |
mchung@2538 | 89 | // test -filter:none option |
mchung@2538 | 90 | test(new File(testDir, "p"), |
mchung@2538 | 91 | new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto", "p"}, |
mchung@2538 | 92 | new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1", "p"}, |
mchung@2538 | 93 | new String[] {"-classpath", testDir.getPath(), "-verbose:package", "-filter:none"}); |
mchung@2538 | 94 | // test -filter:archive option |
mchung@2538 | 95 | test(new File(testDir, "p"), |
mchung@2538 | 96 | new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto"}, |
mchung@2538 | 97 | new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"}, |
mchung@2538 | 98 | new String[] {"-classpath", testDir.getPath(), "-verbose:package", "-filter:archive"}); |
mchung@1472 | 99 | // test -p option |
mchung@1472 | 100 | test(new File(testDir, "Test.class"), |
mchung@2172 | 101 | new String[] {"p.Foo", "p.Bar"}, |
mchung@2172 | 102 | new String[] {"not found", "not found"}, |
mchung@2139 | 103 | new String[] {"-verbose:class", "-p", "p"}); |
mchung@1472 | 104 | // test -e option |
mchung@1472 | 105 | test(new File(testDir, "Test.class"), |
mchung@2172 | 106 | new String[] {"p.Foo", "p.Bar"}, |
mchung@2172 | 107 | new String[] {"not found", "not found"}, |
mchung@2139 | 108 | new String[] {"-verbose:class", "-e", "p\\..*"}); |
mchung@1472 | 109 | test(new File(testDir, "Test.class"), |
mchung@1472 | 110 | new String[] {"java.lang"}, |
mchung@1638 | 111 | new String[] {"compact1"}, |
mchung@2139 | 112 | new String[] {"-verbose:package", "-e", "java\\.lang\\..*"}); |
mchung@2538 | 113 | |
mchung@2139 | 114 | // test -classpath and -include options |
mchung@1472 | 115 | test(null, |
mchung@2538 | 116 | new String[] {"java.lang", "java.util", "java.lang.management", |
mchung@2538 | 117 | "javax.activity", "javax.crypto"}, |
mchung@2538 | 118 | new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"}, |
mchung@2139 | 119 | new String[] {"-classpath", testDir.getPath(), "-include", "p.+|Test.class"}); |
mchung@2139 | 120 | test(new File(testDir, "Test.class"), |
mchung@2172 | 121 | new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"}, |
mchung@2172 | 122 | new String[] {"compact1", "compact1", testDir.getName(), testDir.getName()}, |
mchung@2139 | 123 | new String[] {"-v", "-classpath", testDir.getPath(), "Test.class"}); |
mchung@2172 | 124 | |
mchung@2172 | 125 | // split package p - move p/Foo.class to dir1 and p/Bar.class to dir2 |
mchung@2172 | 126 | Path testClassPath = testDir.toPath(); |
mchung@2172 | 127 | Path dirP = testClassPath.resolve("p"); |
mchung@2172 | 128 | Path dir1 = testClassPath.resolve("dir1"); |
mchung@2172 | 129 | Path subdir1P = dir1.resolve("p"); |
mchung@2172 | 130 | Path dir2 = testClassPath.resolve("dir2"); |
mchung@2172 | 131 | Path subdir2P = dir2.resolve("p"); |
mchung@2172 | 132 | if (!Files.exists(subdir1P)) |
mchung@2172 | 133 | Files.createDirectories(subdir1P); |
mchung@2172 | 134 | if (!Files.exists(subdir2P)) |
mchung@2172 | 135 | Files.createDirectories(subdir2P); |
mchung@2172 | 136 | Files.move(dirP.resolve("Foo.class"), subdir1P.resolve("Foo.class"), REPLACE_EXISTING); |
mchung@2172 | 137 | Files.move(dirP.resolve("Bar.class"), subdir2P.resolve("Bar.class"), REPLACE_EXISTING); |
mchung@2172 | 138 | StringBuilder cpath = new StringBuilder(testDir.toString()); |
mchung@2172 | 139 | cpath.append(File.pathSeparator).append(dir1.toString()); |
mchung@2172 | 140 | cpath.append(File.pathSeparator).append(dir2.toString()); |
mchung@2172 | 141 | test(new File(testDir, "Test.class"), |
mchung@2172 | 142 | new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"}, |
mchung@2172 | 143 | new String[] {"compact1", "compact1", dir1.toFile().getName(), dir2.toFile().getName()}, |
mchung@2172 | 144 | new String[] {"-v", "-classpath", cpath.toString(), "Test.class"}); |
mchung@1472 | 145 | return errors; |
mchung@1472 | 146 | } |
mchung@1472 | 147 | |
mchung@1638 | 148 | void test(File file, String[] expect, String[] profiles) { |
mchung@1638 | 149 | test(file, expect, profiles, new String[0]); |
mchung@1472 | 150 | } |
mchung@1472 | 151 | |
mchung@1638 | 152 | void test(File file, String[] expect, String[] profiles, String[] options) { |
mchung@1638 | 153 | List<String> args = new ArrayList<>(Arrays.asList(options)); |
mchung@1472 | 154 | if (file != null) { |
mchung@1638 | 155 | args.add(file.getPath()); |
mchung@1472 | 156 | } |
mchung@1638 | 157 | List<String> argsWithDashP = new ArrayList<>(); |
mchung@1638 | 158 | argsWithDashP.add("-P"); |
mchung@1638 | 159 | argsWithDashP.addAll(args); |
mchung@1638 | 160 | // test without -P |
mchung@1638 | 161 | checkResult("dependencies", expect, jdeps(args.toArray(new String[0])).keySet()); |
mchung@1638 | 162 | // test with -P |
mchung@1638 | 163 | checkResult("profiles", expect, profiles, jdeps(argsWithDashP.toArray(new String[0]))); |
mchung@1472 | 164 | } |
mchung@1472 | 165 | |
mchung@1638 | 166 | Map<String,String> jdeps(String... args) { |
mchung@1472 | 167 | StringWriter sw = new StringWriter(); |
mchung@1472 | 168 | PrintWriter pw = new PrintWriter(sw); |
mchung@1472 | 169 | System.err.println("jdeps " + Arrays.toString(args)); |
mchung@1472 | 170 | int rc = com.sun.tools.jdeps.Main.run(args, pw); |
mchung@1472 | 171 | pw.close(); |
mchung@1472 | 172 | String out = sw.toString(); |
mchung@1472 | 173 | if (!out.isEmpty()) |
mchung@1472 | 174 | System.err.println(out); |
mchung@1472 | 175 | if (rc != 0) |
mchung@1472 | 176 | throw new Error("jdeps failed: rc=" + rc); |
mchung@1472 | 177 | return findDeps(out); |
mchung@1472 | 178 | } |
mchung@1472 | 179 | |
mchung@1472 | 180 | // Pattern used to parse lines |
mchung@1472 | 181 | private static Pattern linePattern = Pattern.compile(".*\r?\n"); |
mchung@1638 | 182 | private static Pattern pattern = Pattern.compile("\\s+ -> (\\S+) +(.*)"); |
mchung@1472 | 183 | |
mchung@1472 | 184 | // Use the linePattern to break the given String into lines, applying |
mchung@1472 | 185 | // the pattern to each line to see if we have a match |
mchung@1638 | 186 | private static Map<String,String> findDeps(String out) { |
mchung@2172 | 187 | Map<String,String> result = new LinkedHashMap<>(); |
mchung@1472 | 188 | Matcher lm = linePattern.matcher(out); // Line matcher |
mchung@1472 | 189 | Matcher pm = null; // Pattern matcher |
mchung@1472 | 190 | int lines = 0; |
mchung@1472 | 191 | while (lm.find()) { |
mchung@1472 | 192 | lines++; |
mchung@1472 | 193 | CharSequence cs = lm.group(); // The current line |
mchung@1472 | 194 | if (pm == null) |
mchung@1472 | 195 | pm = pattern.matcher(cs); |
mchung@1472 | 196 | else |
mchung@1472 | 197 | pm.reset(cs); |
mchung@1472 | 198 | if (pm.find()) |
mchung@1638 | 199 | result.put(pm.group(1), pm.group(2).trim()); |
mchung@1472 | 200 | if (lm.end() == out.length()) |
mchung@1472 | 201 | break; |
mchung@1472 | 202 | } |
mchung@1638 | 203 | return result; |
mchung@1472 | 204 | } |
mchung@1472 | 205 | |
mchung@1638 | 206 | void checkResult(String label, String[] expect, Collection<String> found) { |
mchung@1638 | 207 | List<String> list = Arrays.asList(expect); |
mchung@1638 | 208 | if (!isEqual(list, found)) |
mchung@1638 | 209 | error("Unexpected " + label + " found: '" + found + "', expected: '" + list + "'"); |
mchung@1638 | 210 | } |
mchung@1472 | 211 | |
mchung@1638 | 212 | void checkResult(String label, String[] expect, String[] profiles, Map<String,String> result) { |
mchung@1638 | 213 | if (expect.length != profiles.length) |
mchung@1638 | 214 | error("Invalid expected names and profiles"); |
mchung@1638 | 215 | |
mchung@1638 | 216 | // check the dependencies |
mchung@1638 | 217 | checkResult(label, expect, result.keySet()); |
mchung@1638 | 218 | // check profile information |
mchung@1638 | 219 | checkResult(label, profiles, result.values()); |
mchung@1638 | 220 | for (int i=0; i < expect.length; i++) { |
mchung@1638 | 221 | String profile = result.get(expect[i]); |
mchung@1638 | 222 | if (!profile.equals(profiles[i])) |
mchung@1638 | 223 | error("Unexpected profile: '" + profile + "', expected: '" + profiles[i] + "'"); |
mchung@1638 | 224 | } |
mchung@1638 | 225 | } |
mchung@1638 | 226 | |
mchung@1638 | 227 | boolean isEqual(List<String> expected, Collection<String> found) { |
mchung@1638 | 228 | if (expected.size() != found.size()) |
mchung@1638 | 229 | return false; |
mchung@1638 | 230 | |
mchung@1638 | 231 | List<String> list = new ArrayList<>(found); |
mchung@1638 | 232 | list.removeAll(expected); |
mchung@1638 | 233 | return list.isEmpty(); |
mchung@1472 | 234 | } |
mchung@1472 | 235 | |
mchung@1472 | 236 | void error(String msg) { |
mchung@1472 | 237 | System.err.println("Error: " + msg); |
mchung@1472 | 238 | errors++; |
mchung@1472 | 239 | } |
mchung@1472 | 240 | |
mchung@1472 | 241 | int errors; |
mchung@1472 | 242 | } |