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