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