ProfileOptionTest.java revision 2599:50b448c5be54
1/*
2 * Copyright (c) 2011, 2014, 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 * @bug 8004182 8028545
27 * @summary Add support for profiles in javac
28 */
29
30import java.io.PrintWriter;
31import java.io.StringWriter;
32import java.lang.annotation.Annotation;
33import java.lang.annotation.Retention;
34import java.lang.annotation.RetentionPolicy;
35import java.lang.reflect.InvocationTargetException;
36import java.lang.reflect.Method;
37import java.net.URI;
38import java.util.ArrayList;
39import java.util.Arrays;
40import java.util.Collections;
41import java.util.EnumMap;
42import java.util.List;
43import java.util.Map;
44
45import javax.tools.Diagnostic;
46import javax.tools.DiagnosticCollector;
47import javax.tools.JavaCompiler;
48import javax.tools.JavaFileObject;
49import javax.tools.SimpleJavaFileObject;
50import javax.tools.StandardJavaFileManager;
51
52import com.sun.source.util.JavacTask;
53import com.sun.tools.javac.api.JavacTool;
54import com.sun.tools.javac.jvm.Profile;
55import com.sun.tools.javac.jvm.Target;
56
57
58public class ProfileOptionTest {
59    public static void main(String... args) throws Exception {
60        new ProfileOptionTest().run();
61    }
62
63    private final JavaCompiler javac = JavacTool.create();
64    private final StandardJavaFileManager fm = javac.getStandardFileManager(null, null, null);
65
66
67    // ---------- Test cases, invoked reflectively via run. ----------
68
69    @Test
70    void testInvalidProfile_API() throws Exception {
71        JavaFileObject fo = new StringJavaFileObject("Test.java", "class Test { }");
72        String badName = "foo";
73        List<String> opts = Arrays.asList("-profile", badName);
74        StringWriter sw = new StringWriter();
75        try {
76            JavacTask task = (JavacTask) javac.getTask(sw, fm, null, opts, null,
77                Arrays.asList(fo));
78            throw new Exception("expected exception not thrown");
79        } catch (IllegalArgumentException e) {
80            // expected
81        }
82    }
83
84    @Test
85    void testInvalidProfile_CommandLine() throws Exception {
86        String badName = "foo";
87        String[] opts = { "-profile", badName };
88        StringWriter sw = new StringWriter();
89        PrintWriter pw = new PrintWriter(sw);
90        int rc = com.sun.tools.javac.Main.compile(opts, pw);
91
92        // sadly, command line errors are not (yet?) reported to
93        // the diag listener
94        String out = sw.toString();
95        if (!out.isEmpty())
96            System.err.println(out.trim());
97
98        if (!out.contains("invalid profile: " + badName)) {
99            error("expected message not found");
100        }
101    }
102
103    @Test
104    void testTargetProfileCombinations() throws Exception {
105        JavaFileObject fo = new StringJavaFileObject("Test.java", "class Test { }");
106        for (Target t: Target.values()) {
107            switch (t) {
108                case JDK1_1: case JDK1_2: // no equivalent -source
109                    continue;
110            }
111
112            for (Profile p: Profile.values()) {
113                List<String> opts = new ArrayList<>();
114                opts.addAll(Arrays.asList("-source", t.name, "-target", t.name));
115                opts.add("-Xlint:-options"); // dont warn about no -bootclasspath
116                if (p != Profile.DEFAULT)
117                    opts.addAll(Arrays.asList("-profile", p.name));
118
119                IllegalStateException ise;
120                StringWriter sw = new StringWriter();
121                try {
122                    JavacTask task = (JavacTask) javac.getTask(sw, fm, null, opts, null,
123                            Arrays.asList(fo));
124                    task.analyze();
125                    ise = null;
126                } catch (IllegalStateException e) {
127                    ise = e;
128                }
129
130                // sadly, command line errors are not (yet?) reported to
131                // the diag listener
132                String out = sw.toString();
133                if (!out.isEmpty())
134                    System.err.println(out.trim());
135
136                switch (t) {
137                    case JDK1_8:
138                    case JDK1_9:
139                        if (ise != null)
140                            error("unexpected exception from compiler: " + ise);
141                        break;
142                    default:
143                        if (p == Profile.DEFAULT)
144                            break;
145                        if (ise == null)
146                            error("IllegalStateException not thrown as expected");
147                        else if (!ise.getMessage().contains("profile " + p.name
148                                    + " is not valid for target release " + t.name)) {
149                            error("exception not thrown as expected: " + ise);
150                        }
151                }
152            }
153        }
154    }
155
156    @Test
157    void testClassesInProfiles() throws Exception {
158        for (Profile p: Profile.values()) {
159            for (Map.Entry<Profile, List<JavaFileObject>> e: testClasses.entrySet()) {
160                for (JavaFileObject fo: e.getValue()) {
161                    DiagnosticCollector<JavaFileObject> dl =
162                            new DiagnosticCollector<JavaFileObject>();
163                    List<String> opts = (p == Profile.DEFAULT)
164                            ? Collections.<String>emptyList()
165                            : Arrays.asList("-profile", p.name);
166                    JavacTask task = (JavacTask) javac.getTask(null, fm, dl, opts, null,
167                            Arrays.asList(fo));
168                    task.analyze();
169
170                    List<String> expectDiagCodes = (p.value >= e.getKey().value)
171                            ? Collections.<String>emptyList()
172                            : Arrays.asList("compiler.err.not.in.profile");
173
174                    checkDiags(opts + " " + fo.getName(), dl.getDiagnostics(), expectDiagCodes);
175                }
176            }
177        }
178    }
179
180    Map<Profile, List<JavaFileObject>> testClasses =
181            new EnumMap<Profile, List<JavaFileObject>>(Profile.class);
182
183    void initTestClasses() {
184        // The following table assumes the existence of specific classes
185        // in specific profiles, as defined in the Java SE 8 spec.
186        init(Profile.COMPACT1,
187                java.lang.String.class);
188
189        init(Profile.COMPACT2,
190                javax.xml.XMLConstants.class);
191
192        init(Profile.COMPACT3,
193                javax.sql.rowset.Predicate.class,
194                com.sun.security.auth.PolicyFile.class); // specifically included in 3
195
196        init(Profile.DEFAULT,
197                java.beans.BeanInfo.class);
198    }
199
200    void init(Profile p, Class<?>... classes) {
201        List<JavaFileObject> srcs = new ArrayList<JavaFileObject>();
202        for (Class<?> c: classes) {
203            String name = "T" + c.getSimpleName();
204            String src =
205                    "class T" + name + "{" + "\n" +
206                    "    Class<?> c = " + c.getName() + ".class;\n" +
207                    "}";
208            srcs.add(new StringJavaFileObject(name + ".java", src));
209        }
210        testClasses.put(p, srcs);
211    }
212
213    void checkDiags(String msg, List<Diagnostic<? extends JavaFileObject>> diags, List<String> expectDiagCodes) {
214        System.err.print(msg);
215        if (diags.isEmpty())
216            System.err.println(" OK");
217        else {
218            System.err.println();
219            System.err.println(diags);
220        }
221
222        List<String> foundDiagCodes = new ArrayList<String>();
223        for (Diagnostic<? extends JavaFileObject> d: diags)
224            foundDiagCodes.add(d.getCode());
225
226        if (!foundDiagCodes.equals(expectDiagCodes)) {
227            System.err.println("Found diag codes:    " + foundDiagCodes);
228            System.err.println("Expected diag codes: " + expectDiagCodes);
229            error("expected diagnostics not found");
230        }
231    }
232
233    /** Marker annotation for test cases. */
234    @Retention(RetentionPolicy.RUNTIME)
235    @interface Test { }
236
237    /** Run all test cases. */
238    void run() throws Exception {
239        initTestClasses();
240
241        for (Method m: getClass().getDeclaredMethods()) {
242            Annotation a = m.getAnnotation(Test.class);
243            if (a != null) {
244                System.err.println(m.getName());
245                try {
246                    m.invoke(this, new Object[] { });
247                } catch (InvocationTargetException e) {
248                    Throwable cause = e.getCause();
249                    throw (cause instanceof Exception) ? ((Exception) cause) : e;
250                }
251                System.err.println();
252            }
253        }
254
255        if (errors > 0)
256            throw new Exception(errors + " errors occurred");
257    }
258
259    void error(String msg) {
260        System.err.println("Error: " + msg);
261        errors++;
262    }
263
264    int errors;
265
266    private static class StringJavaFileObject extends SimpleJavaFileObject {
267        StringJavaFileObject(String name, String text) {
268            super(URI.create(name), JavaFileObject.Kind.SOURCE);
269            this.text = text;
270        }
271        @Override
272        public CharSequence getCharContent(boolean b) {
273            return text;
274        }
275        private String text;
276    }
277}
278