mchung@2538: /* mchung@2538: * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. mchung@2538: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. mchung@2538: * mchung@2538: * This code is free software; you can redistribute it and/or modify it mchung@2538: * under the terms of the GNU General Public License version 2 only, as mchung@2538: * published by the Free Software Foundation. mchung@2538: * mchung@2538: * This code is distributed in the hope that it will be useful, but WITHOUT mchung@2538: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or mchung@2538: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License mchung@2538: * version 2 for more details (a copy is included in the LICENSE file that mchung@2538: * accompanied this code). mchung@2538: * mchung@2538: * You should have received a copy of the GNU General Public License version mchung@2538: * 2 along with this work; if not, write to the Free Software Foundation, mchung@2538: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. mchung@2538: * mchung@2538: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA mchung@2538: * or visit www.oracle.com if you need additional information or have any mchung@2538: * questions. mchung@2538: */ mchung@2538: mchung@2538: /* mchung@2538: * @test mchung@2538: * @bug 8003562 mchung@2538: * @summary Basic tests for jdeps -dotoutput option mchung@2538: * @build Test p.Foo p.Bar javax.activity.NotCompactProfile mchung@2538: * @run main DotFileTest mchung@2538: */ mchung@2538: mchung@2538: import java.io.File; mchung@2538: import java.io.IOException; mchung@2538: import java.io.PrintWriter; mchung@2538: import java.io.StringWriter; mchung@2538: import java.nio.file.DirectoryStream; mchung@2538: import java.nio.file.Files; mchung@2538: import java.nio.file.Path; mchung@2538: import java.nio.file.Paths; mchung@2538: import java.util.*; mchung@2538: import java.util.regex.*; mchung@2538: mchung@2538: public class DotFileTest { mchung@2538: private static boolean symbolFileExist = initProfiles(); mchung@2538: private static boolean initProfiles() { mchung@2538: // check if ct.sym exists; if not use the profiles.properties file mchung@2538: Path home = Paths.get(System.getProperty("java.home")); mchung@2538: if (home.endsWith("jre")) { mchung@2538: home = home.getParent(); mchung@2538: } mchung@2538: Path ctsym = home.resolve("lib").resolve("ct.sym"); mchung@2538: boolean symbolExists = ctsym.toFile().exists(); mchung@2538: if (!symbolExists) { mchung@2538: Path testSrcProfiles = mchung@2538: Paths.get(System.getProperty("test.src", "."), "profiles.properties"); mchung@2538: if (!testSrcProfiles.toFile().exists()) mchung@2538: throw new Error(testSrcProfiles + " does not exist"); mchung@2538: System.out.format("%s doesn't exist.%nUse %s to initialize profiles info%n", mchung@2538: ctsym, testSrcProfiles); mchung@2538: System.setProperty("jdeps.profiles", testSrcProfiles.toString()); mchung@2538: } mchung@2538: return symbolExists; mchung@2538: } mchung@2538: mchung@2538: public static void main(String... args) throws Exception { mchung@2538: int errors = 0; mchung@2538: errors += new DotFileTest().run(); mchung@2538: if (errors > 0) mchung@2538: throw new Exception(errors + " errors found"); mchung@2538: } mchung@2538: mchung@2538: final Path dir; mchung@2538: final Path dotoutput; mchung@2538: DotFileTest() { mchung@2538: this.dir = Paths.get(System.getProperty("test.classes", ".")); mchung@2538: this.dotoutput = dir.resolve("dots"); mchung@2538: } mchung@2538: mchung@2538: int run() throws IOException { mchung@2538: File testDir = dir.toFile(); mchung@2538: // test a .class file mchung@2538: test(new File(testDir, "Test.class"), mchung@2538: new String[] {"java.lang", "p"}, mchung@2538: new String[] {"compact1", "not found"}); mchung@2538: // test a directory mchung@2538: // also test non-SE javax.activity class dependency mchung@2538: test(new File(testDir, "p"), mchung@2538: new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto"}, mchung@2538: new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"}, mchung@2538: new String[] {"-classpath", testDir.getPath()}); mchung@2538: // test class-level dependency output mchung@2538: test(new File(testDir, "Test.class"), mchung@2538: new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"}, mchung@2538: new String[] {"compact1", "compact1", "not found", "not found"}, mchung@2538: new String[] {"-verbose:class"}); mchung@2538: // test -filter:none option mchung@2538: test(new File(testDir, "p"), mchung@2538: new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto", "p"}, mchung@2538: new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1", "p"}, mchung@2538: new String[] {"-classpath", testDir.getPath(), "-verbose:package", "-filter:none"}); mchung@2538: // test -filter:archive option mchung@2538: test(new File(testDir, "p"), mchung@2538: new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto"}, mchung@2538: new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"}, mchung@2538: new String[] {"-classpath", testDir.getPath(), "-verbose:package", "-filter:archive"}); mchung@2538: // test -p option mchung@2538: test(new File(testDir, "Test.class"), mchung@2538: new String[] {"p.Foo", "p.Bar"}, mchung@2538: new String[] {"not found", "not found"}, mchung@2538: new String[] {"-verbose:class", "-p", "p"}); mchung@2538: // test -e option mchung@2538: test(new File(testDir, "Test.class"), mchung@2538: new String[] {"p.Foo", "p.Bar"}, mchung@2538: new String[] {"not found", "not found"}, mchung@2538: new String[] {"-verbose:class", "-e", "p\\..*"}); mchung@2538: test(new File(testDir, "Test.class"), mchung@2538: new String[] {"java.lang"}, mchung@2538: new String[] {"compact1"}, mchung@2538: new String[] {"-verbose:package", "-e", "java\\.lang\\..*"}); mchung@2538: // test -classpath options mchung@2538: test(new File(testDir, "Test.class"), mchung@2538: new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"}, mchung@2538: new String[] {"compact1", "compact1", testDir.getName(), testDir.getName()}, mchung@2538: new String[] {"-v", "-classpath", testDir.getPath()}); mchung@2538: mchung@2538: testSummary(new File(testDir, "Test.class"), mchung@2538: new String[] {"rt.jar", testDir.getName()}, mchung@2538: new String[] {"compact1", ""}, mchung@2538: new String[] {"-classpath", testDir.getPath()}); mchung@2538: testSummary(new File(testDir, "Test.class"), mchung@2538: new String[] {"java.lang", "p"}, mchung@2538: new String[] {"compact1", testDir.getName()}, mchung@2538: new String[] {"-v", "-classpath", testDir.getPath()}); mchung@2538: return errors; mchung@2538: } mchung@2538: mchung@2538: void test(File file, String[] expect, String[] profiles) throws IOException { mchung@2538: test(file, expect, profiles, new String[0]); mchung@2538: } mchung@2538: mchung@2538: void test(File file, String[] expect, String[] profiles, String[] options) mchung@2538: throws IOException mchung@2538: { mchung@2538: Path dotfile = dotoutput.resolve(file.toPath().getFileName().toString() + ".dot"); mchung@2538: mchung@2538: List args = new ArrayList<>(Arrays.asList(options)); mchung@2538: args.add("-dotoutput"); mchung@2538: args.add(dotoutput.toString()); mchung@2538: if (file != null) { mchung@2538: args.add(file.getPath()); mchung@2538: } mchung@2538: mchung@2538: Map result = jdeps(args, dotfile); mchung@2538: checkResult("dependencies", expect, result.keySet()); mchung@2538: mchung@2538: // with -P option mchung@2538: List argsWithDashP = new ArrayList<>(); mchung@2538: argsWithDashP.add("-dotoutput"); mchung@2538: argsWithDashP.add(dotoutput.toString()); mchung@2538: argsWithDashP.add("-P"); mchung@2538: argsWithDashP.addAll(args); mchung@2538: mchung@2538: result = jdeps(argsWithDashP, dotfile); mchung@2538: checkResult("profiles", expect, profiles, result); mchung@2538: } mchung@2538: mchung@2538: void testSummary(File file, String[] expect, String[] profiles, String[] options) mchung@2538: throws IOException mchung@2538: { mchung@2538: Path dotfile = dotoutput.resolve("summary.dot"); mchung@2538: mchung@2538: List args = new ArrayList<>(Arrays.asList(options)); mchung@2538: args.add("-dotoutput"); mchung@2538: args.add(dotoutput.toString()); mchung@2538: if (file != null) { mchung@2538: args.add(file.getPath()); mchung@2538: } mchung@2538: mchung@2538: Map result = jdeps(args, dotfile); mchung@2538: checkResult("dependencies", expect, result.keySet()); mchung@2538: mchung@2538: // with -P option mchung@2538: List argsWithDashP = new ArrayList<>(); mchung@2538: argsWithDashP.add("-dotoutput"); mchung@2538: argsWithDashP.add(dotoutput.toString()); mchung@2538: argsWithDashP.add("-P"); mchung@2538: argsWithDashP.addAll(args); mchung@2538: mchung@2538: result = jdeps(argsWithDashP, dotfile); mchung@2538: checkResult("profiles", expect, profiles, result); mchung@2538: } mchung@2538: mchung@2538: Map jdeps(List args, Path dotfile) throws IOException { mchung@2538: if (Files.exists(dotoutput)) { mchung@2538: try (DirectoryStream stream = Files.newDirectoryStream(dotoutput)) { mchung@2538: for (Path p : stream) { mchung@2538: Files.delete(p); mchung@2538: } mchung@2538: } mchung@2538: Files.delete(dotoutput); mchung@2538: } mchung@2538: // invoke jdeps mchung@2538: StringWriter sw = new StringWriter(); mchung@2538: PrintWriter pw = new PrintWriter(sw); mchung@2538: System.err.println("jdeps " + args); mchung@2538: int rc = com.sun.tools.jdeps.Main.run(args.toArray(new String[0]), pw); mchung@2538: pw.close(); mchung@2538: String out = sw.toString(); mchung@2538: if (!out.isEmpty()) mchung@2538: System.err.println(out); mchung@2538: if (rc != 0) mchung@2538: throw new Error("jdeps failed: rc=" + rc); mchung@2538: mchung@2538: // check output files mchung@2538: if (Files.notExists(dotfile)) { mchung@2538: throw new RuntimeException(dotfile + " doesn't exist"); mchung@2538: } mchung@2538: return parse(dotfile); mchung@2538: } mchung@2538: private static Pattern pattern = Pattern.compile("(.*) -> +([^ ]*) (.*)"); mchung@2538: private Map parse(Path outfile) throws IOException { mchung@2538: Map result = new LinkedHashMap<>(); mchung@2538: for (String line : Files.readAllLines(outfile)) { mchung@2538: line = line.replace('"', ' ').replace(';', ' '); mchung@2538: Matcher pm = pattern.matcher(line); mchung@2538: if (pm.find()) { mchung@2538: String origin = pm.group(1).trim(); mchung@2538: String target = pm.group(2).trim(); mchung@2538: String module = pm.group(3).replace('(', ' ').replace(')', ' ').trim(); mchung@2538: result.put(target, module); mchung@2538: } mchung@2538: } mchung@2538: return result; mchung@2538: } mchung@2538: mchung@2538: void checkResult(String label, String[] expect, Collection found) { mchung@2538: List list = Arrays.asList(expect); mchung@2538: if (!isEqual(list, found)) mchung@2538: error("Unexpected " + label + " found: '" + found + "', expected: '" + list + "'"); mchung@2538: } mchung@2538: mchung@2538: void checkResult(String label, String[] expect, String[] profiles, Map result) { mchung@2538: if (expect.length != profiles.length) mchung@2538: error("Invalid expected names and profiles"); mchung@2538: mchung@2538: // check the dependencies mchung@2538: checkResult(label, expect, result.keySet()); mchung@2538: // check profile information mchung@2538: checkResult(label, profiles, result.values()); mchung@2538: for (int i=0; i < expect.length; i++) { mchung@2538: String profile = result.get(expect[i]); mchung@2538: if (!profile.equals(profiles[i])) mchung@2538: error("Unexpected profile: '" + profile + "', expected: '" + profiles[i] + "'"); mchung@2538: } mchung@2538: } mchung@2538: mchung@2538: boolean isEqual(List expected, Collection found) { mchung@2538: if (expected.size() != found.size()) mchung@2538: return false; mchung@2538: mchung@2538: List list = new ArrayList<>(found); mchung@2538: list.removeAll(expected); mchung@2538: return list.isEmpty(); mchung@2538: } mchung@2538: mchung@2538: void error(String msg) { mchung@2538: System.err.println("Error: " + msg); mchung@2538: errors++; mchung@2538: } mchung@2538: mchung@2538: int errors; mchung@2538: }