ProfileOptionTest.java revision 2721:f7ce2cfa4cdb
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:
109                case JDK1_2:
110                case JDK1_3:
111                case JDK1_4:
112                case JDK1_5: // not supported
113                    continue;
114            }
115
116            for (Profile p: Profile.values()) {
117                List<String> opts = new ArrayList<>();
118                opts.addAll(Arrays.asList("-source", t.name, "-target", t.name));
119                opts.add("-Xlint:-options"); // don't warn about no -bootclasspath
120                if (p != Profile.DEFAULT)
121                    opts.addAll(Arrays.asList("-profile", p.name));
122
123                IllegalStateException ise;
124                StringWriter sw = new StringWriter();
125                try {
126                    JavacTask task = (JavacTask) javac.getTask(sw, fm, null, opts, null,
127                            Arrays.asList(fo));
128                    task.analyze();
129                    ise = null;
130                } catch (IllegalStateException e) {
131                    ise = e;
132                }
133
134                // sadly, command line errors are not (yet?) reported to
135                // the diag listener
136                String out = sw.toString();
137                if (!out.isEmpty())
138                    System.err.println(out.trim());
139
140                switch (t) {
141                    case JDK1_8:
142                    case JDK1_9:
143                        if (ise != null)
144                            error("unexpected exception from compiler: " + ise);
145                        break;
146                    default:
147                        if (p == Profile.DEFAULT)
148                            break;
149                        if (ise == null)
150                            error("IllegalStateException not thrown as expected");
151                        else if (!ise.getMessage().contains("profile " + p.name
152                                    + " is not valid for target release " + t.name)) {
153                            error("exception not thrown as expected: " + ise);
154                        }
155                }
156            }
157        }
158    }
159
160    @Test
161    void testClassesInProfiles() throws Exception {
162        for (Profile p: Profile.values()) {
163            for (Map.Entry<Profile, List<JavaFileObject>> e: testClasses.entrySet()) {
164                for (JavaFileObject fo: e.getValue()) {
165                    DiagnosticCollector<JavaFileObject> dl =
166                            new DiagnosticCollector<JavaFileObject>();
167                    List<String> opts = (p == Profile.DEFAULT)
168                            ? Collections.<String>emptyList()
169                            : Arrays.asList("-profile", p.name);
170                    JavacTask task = (JavacTask) javac.getTask(null, fm, dl, opts, null,
171                            Arrays.asList(fo));
172                    task.analyze();
173
174                    List<String> expectDiagCodes = (p.value >= e.getKey().value)
175                            ? Collections.<String>emptyList()
176                            : Arrays.asList("compiler.err.not.in.profile");
177
178                    checkDiags(opts + " " + fo.getName(), dl.getDiagnostics(), expectDiagCodes);
179                }
180            }
181        }
182    }
183
184    Map<Profile, List<JavaFileObject>> testClasses =
185            new EnumMap<Profile, List<JavaFileObject>>(Profile.class);
186
187    void initTestClasses() {
188        // The following table assumes the existence of specific classes
189        // in specific profiles, as defined in the Java SE 8 spec.
190        init(Profile.COMPACT1,
191                java.lang.String.class);
192
193        init(Profile.COMPACT2,
194                javax.xml.XMLConstants.class);
195
196        init(Profile.COMPACT3,
197                javax.sql.rowset.Predicate.class,
198                com.sun.security.auth.PolicyFile.class); // specifically included in 3
199
200        init(Profile.DEFAULT,
201                java.beans.BeanInfo.class);
202    }
203
204    void init(Profile p, Class<?>... classes) {
205        List<JavaFileObject> srcs = new ArrayList<JavaFileObject>();
206        for (Class<?> c: classes) {
207            String name = "T" + c.getSimpleName();
208            String src =
209                    "class T" + name + "{" + "\n" +
210                    "    Class<?> c = " + c.getName() + ".class;\n" +
211                    "}";
212            srcs.add(new StringJavaFileObject(name + ".java", src));
213        }
214        testClasses.put(p, srcs);
215    }
216
217    void checkDiags(String msg, List<Diagnostic<? extends JavaFileObject>> diags, List<String> expectDiagCodes) {
218        System.err.print(msg);
219        if (diags.isEmpty())
220            System.err.println(" OK");
221        else {
222            System.err.println();
223            System.err.println(diags);
224        }
225
226        List<String> foundDiagCodes = new ArrayList<String>();
227        for (Diagnostic<? extends JavaFileObject> d: diags)
228            foundDiagCodes.add(d.getCode());
229
230        if (!foundDiagCodes.equals(expectDiagCodes)) {
231            System.err.println("Found diag codes:    " + foundDiagCodes);
232            System.err.println("Expected diag codes: " + expectDiagCodes);
233            error("expected diagnostics not found");
234        }
235    }
236
237    /** Marker annotation for test cases. */
238    @Retention(RetentionPolicy.RUNTIME)
239    @interface Test { }
240
241    /** Run all test cases. */
242    void run() throws Exception {
243        try {
244            initTestClasses();
245
246            for (Method m: getClass().getDeclaredMethods()) {
247                Annotation a = m.getAnnotation(Test.class);
248                if (a != null) {
249                    System.err.println(m.getName());
250                    try {
251                        m.invoke(this, new Object[] { });
252                    } catch (InvocationTargetException e) {
253                        Throwable cause = e.getCause();
254                        throw (cause instanceof Exception) ? ((Exception) cause) : e;
255                    }
256                    System.err.println();
257                }
258            }
259
260            if (errors > 0)
261                throw new Exception(errors + " errors occurred");
262        } finally {
263            fm.close();
264        }
265    }
266
267    void error(String msg) {
268        System.err.println("Error: " + msg);
269        errors++;
270    }
271
272    int errors;
273
274    private static class StringJavaFileObject extends SimpleJavaFileObject {
275        StringJavaFileObject(String name, String text) {
276            super(URI.create(name), JavaFileObject.Kind.SOURCE);
277            this.text = text;
278        }
279        @Override
280        public CharSequence getCharContent(boolean b) {
281            return text;
282        }
283        private String text;
284    }
285}
286