Path: blob/master/test/langtools/tools/jdeps/APIDeps.java
41144 views
/*1* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 8015912 8029216 8048063 805080426* @summary Test -apionly and -jdkinternals options27* @library lib28* @modules java.base/sun.security.x50929* java.management30* jdk.jdeps/com.sun.tools.classfile31* jdk.jdeps/com.sun.tools.jdeps32* @run main APIDeps33*/3435import java.io.File;36import java.io.IOException;37import java.io.PrintWriter;38import java.io.StringWriter;39import java.nio.file.*;40import java.util.*;41import java.util.regex.*;42import java.util.stream.Collectors;4344public class APIDeps {45public static void main(String... args) throws Exception {46int errors = 0;47errors += new APIDeps().run();48if (errors > 0)49throw new Exception(errors + " errors found");50}5152private static final Path dest = Paths.get(System.getProperty("test.classes", "."), "tmp");53private static final String[] srcDirs = new String[] {54"m", "b", "c", "d", "e", "f", "g"55};56void setup(Path dest) throws IOException {57CompilerUtils.cleanDir(dest);58Files.createDirectories(dest);59Path testsrc = Paths.get(System.getProperty("test.src"));60List<String> options = new ArrayList<>();6162// jdk.jdeps is a service provider module so needs to be explicitly included63options.add("--add-modules=jdk.jdeps");6465// add --add-exports66String testModules = System.getProperty("test.modules", "");67List<String> addExports = new ArrayList<>();68for (String s : testModules.split("\\s+")) {69if (s.isEmpty()) continue;70if (s.indexOf('/') != -1)71addExports.add("--add-exports=" + s.trim() + "=ALL-UNNAMED");72}73options.addAll(addExports);7475for (String dir : srcDirs) {76Path source = testsrc.resolve(dir);77boolean ok = CompilerUtils.compile(source, dest, options.toArray(new String[0]));78if (!ok) {79throw new RuntimeException("compilation fails");80}81}82}8384int run() throws IOException {85// compile classes in a separate directory for analysis86setup(dest);8788File testDir = dest.toFile();89String testDirBasename = testDir.toPath().getFileName().toString();90File mDir = new File(testDir, "m");91// all dependencies92test(new File(mDir, "Bar.class"),93new String[] {"java.lang.Object", "java.lang.String",94"java.util.Set", "java.util.HashSet",95"java.lang.management.ManagementFactory",96"java.lang.management.RuntimeMXBean",97"b.B", "c.C", "d.D", "f.F", "g.G"},98new String[] {"compact1", "compact3", testDirBasename},99new String[] {"-classpath", testDir.getPath(), "-verbose", "-P"});100test(new File(mDir, "Foo.class"),101new String[] {"c.I", "e.E", "f.F"},102new String[] {testDirBasename},103new String[] {"-classpath", testDir.getPath(), "-verbose:class", "-P"});104test(new File(mDir, "Foo.class"),105new String[] {"c.I", "e.E", "f.F", "m.Bar"},106new String[] {testDirBasename},107new String[] {"-classpath", testDir.getPath(), "-verbose:class", "-filter:none", "-P"});108test(new File(mDir, "Gee.class"),109new String[] {"g.G", "sun.security.x509.X509CertInfo", "com.sun.tools.classfile.ClassFile",110"com.sun.management.ThreadMXBean", "com.sun.source.tree.BinaryTree"},111new String[] {testDirBasename, "JDK internal API", "compact3", ""},112new String[] {"-classpath", testDir.getPath(), "-verbose", "-P"});113114// -jdkinternals115test(new File(mDir, "Gee.class"),116new String[] {"sun.security.x509.X509CertInfo", "com.sun.tools.classfile.ClassFile"},117new String[] {"JDK internal API"},118new String[] {"-jdkinternals", "-quiet"});119// -jdkinternals parses all classes on -classpath and the input arguments120test(new File(mDir, "Gee.class"),121new String[] {"com.sun.tools.classfile.ClassFile",122"sun.security.x509.X509CertInfo"},123new String[] {"JDK internal API"},124// use -classpath tmp/a with no use of JDK internal API125new String[] {"-classpath", dest.resolve("a").toString(), "-jdkinternals", "-quiet"});126127// parse only APIs128test(mDir,129new String[] {"java.lang.Object", "java.lang.String",130"java.util.Set",131"c.C", "d.D", "c.I", "e.E"},132new String[] {"compact1", testDirBasename},133new String[] {"-classpath", testDir.getPath(), "-verbose:class", "-P", "-apionly"});134135test(mDir,136new String[] {"java.lang.Object", "java.lang.String",137"java.util.Set",138"c.C", "d.D", "c.I", "e.E", "m.Bar"},139new String[] {"compact1", testDirBasename, mDir.getName()},140new String[] {"-classpath", testDir.getPath(), "-verbose", "-P", "--api-only"});141return errors;142}143144void test(File file, String[] expect, String[] profiles) {145test(file, expect, profiles, new String[0]);146}147148void test(File file, String[] expect, String[] profiles, String[] options) {149List<String> args = new ArrayList<>(Arrays.asList(options));150if (file != null) {151args.add(file.getPath());152}153checkResult("api-dependencies", expect, profiles,154jdeps(args.toArray(new String[0])));155}156157Map<String,String> jdeps(String... args) {158StringWriter sw = new StringWriter();159PrintWriter pw = new PrintWriter(sw);160System.err.println("jdeps " + Arrays.stream(args)161.collect(Collectors.joining(" ")));162int rc = com.sun.tools.jdeps.Main.run(args, pw);163pw.close();164String out = sw.toString();165if (!out.isEmpty())166System.err.println(out);167if (rc != 0)168throw new Error("jdeps failed: rc=" + rc);169return findDeps(out);170}171172// Pattern used to parse lines173private static Pattern linePattern = Pattern.compile(".*\r?\n");174private static Pattern pattern = Pattern.compile("\\s+ -> (\\S+) +(.*)");175176// Use the linePattern to break the given String into lines, applying177// the pattern to each line to see if we have a match178private static Map<String,String> findDeps(String out) {179Map<String,String> result = new HashMap<>();180Matcher lm = linePattern.matcher(out); // Line matcher181Matcher pm = null; // Pattern matcher182int lines = 0;183while (lm.find()) {184lines++;185CharSequence cs = lm.group(); // The current line186if (pm == null)187pm = pattern.matcher(cs);188else189pm.reset(cs);190if (pm.find())191result.put(pm.group(1), pm.group(2).trim());192if (lm.end() == out.length())193break;194}195return result;196}197198void checkResult(String label, String[] expect, Collection<String> found) {199List<String> list = Arrays.asList(expect);200if (!isEqual(list, found))201error("Unexpected " + label + " found: '" + found + "', expected: '" + list + "'");202}203204void checkResult(String label, String[] expect, String[] profiles, Map<String,String> result) {205// check the dependencies206checkResult(label, expect, result.keySet());207// check profile information208Set<String> values = new TreeSet<>();209String internal = "JDK internal API";210for (String s: result.values()) {211if (s.startsWith(internal)){212values.add(internal);213} else {214values.add(s);215}216}217checkResult(label, profiles, values);218}219220boolean isEqual(List<String> expected, Collection<String> found) {221if (expected.size() != found.size())222return false;223224List<String> list = new ArrayList<>(found);225list.removeAll(expected);226return list.isEmpty();227}228229void error(String msg) {230System.err.println("Error: " + msg);231errors++;232}233234int errors;235236}237238239