1/*
2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 * @test
26 * @summary jdeps should flag jdk.unsupported exported API as internal
27 * @modules java.base/jdk.internal.misc
28 *          jdk.jdeps/com.sun.tools.jdeps
29 *          jdk.unsupported
30 * @build Foo Bar
31 * @run testng JDKUnsupportedTest
32 */
33
34import java.io.PrintWriter;
35import java.io.StringWriter;
36import java.nio.file.Path;
37import java.nio.file.Paths;
38import java.util.*;
39import java.util.regex.*;
40
41import org.testng.annotations.DataProvider;
42import org.testng.annotations.Test;
43import static org.testng.Assert.assertTrue;
44
45public class JDKUnsupportedTest {
46    private static final String TEST_CLASSES = System.getProperty("test.classes");
47    @DataProvider(name = "data")
48    public Object[][] expected() {
49        return new Object[][]{
50            { "Foo.class", new String[][] {
51                               new String[] { "java.lang", "java.base" },
52                               new String[] { "jdk.internal.misc", "JDK internal API (java.base)" }
53                           } },
54            { "Bar.class", new String[][] {
55                               new String[] { "java.lang", "java.base" },
56                               new String[] { "sun.misc", "JDK internal API (jdk.unsupported)" }
57                           } }
58        };
59    }
60
61    @Test(dataProvider = "data")
62    public void test(String filename, String[][] expected) {
63        Path path = Paths.get(TEST_CLASSES, filename);
64
65        Map<String, String> result = jdeps(path.toString());
66        for (String[] e : expected) {
67            String pn = e[0];
68            String module = e[1];
69            assertTrue(module.equals(result.get(pn)));
70        }
71    }
72
73    private static Map<String,String> jdeps(String... args) {
74        StringWriter sw = new StringWriter();
75        PrintWriter pw = new PrintWriter(sw);
76        System.err.println("jdeps " + Arrays.toString(args));
77        int rc = com.sun.tools.jdeps.Main.run(args, pw);
78        pw.close();
79        String out = sw.toString();
80        if (!out.isEmpty())
81            System.err.println(out);
82        if (rc != 0)
83            throw new Error("jdeps failed: rc=" + rc);
84        return findDeps(out);
85    }
86
87    // Pattern used to parse lines
88    private static Pattern linePattern = Pattern.compile(".*\r?\n");
89    private static Pattern pattern = Pattern.compile("\\s+ -> (\\S+) +(.*)");
90
91    // Use the linePattern to break the given String into lines, applying
92    // the pattern to each line to see if we have a match
93    private static Map<String,String> findDeps(String out) {
94        Map<String,String> result = new LinkedHashMap<>();
95        Matcher lm = linePattern.matcher(out);  // Line matcher
96        Matcher pm = null;                      // Pattern matcher
97        int lines = 0;
98        while (lm.find()) {
99            lines++;
100            CharSequence cs = lm.group();       // The current line
101            if (pm == null)
102                pm = pattern.matcher(cs);
103            else
104                pm.reset(cs);
105            if (pm.find())
106                result.put(pm.group(1), pm.group(2).trim());
107            if (lm.end() == out.length())
108                break;
109        }
110        return result;
111    }
112}
113