--- /dev/null 2012-10-30 13:53:25.609028996 -0400 +++ new/test/tools/javac/profiles/ProfileOptionTest.java 2013-01-18 02:50:47.870679661 -0500 @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8004182 + * @summary Add support for profiles in javac + */ + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +import javax.tools.Diagnostic; +import javax.tools.DiagnosticCollector; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; + +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.jvm.Profile; +import com.sun.tools.javac.jvm.Target; + + +public class ProfileOptionTest { + public static void main(String... args) throws Exception { + new ProfileOptionTest().run(); + } + + private final JavaCompiler javac = JavacTool.create(); + private final StandardJavaFileManager fm = javac.getStandardFileManager(null, null, null); + + + // ---------- Test cases, invoked reflectively via run. ---------- + + @Test + void testInvalidProfile_CommandLine() throws Exception { + JavaFileObject fo = new StringJavaFileObject("Test.java", "class Test { }"); + String badName = "foo"; + List opts = Arrays.asList("-profile", badName); + StringWriter sw = new StringWriter(); + try { + JavacTask task = (JavacTask) javac.getTask(sw, fm, null, opts, null, + Arrays.asList(fo)); + throw new Exception("expected exception not thrown"); + } catch (IllegalArgumentException e) { + // expected + } + } + + @Test + void testInvalidProfile_API() throws Exception { + String badName = "foo"; + String[] opts = { "-profile", badName }; + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc = com.sun.tools.javac.Main.compile(opts, pw); + + // sadly, command line errors are not (yet?) reported to + // the diag listener + String out = sw.toString(); + if (!out.isEmpty()) + System.err.println(out.trim()); + + if (!out.contains("invalid profile: " + badName)) { + error("expected message not found"); + } + } + + @Test + void testTargetProfileCombinations() throws Exception { + JavaFileObject fo = new StringJavaFileObject("Test.java", "class Test { }"); + for (Target t: Target.values()) { + switch (t) { + case JDK1_1: case JDK1_2: // no equivalent -source + case JDK1_4_1: case JDK1_4_2: case JSR14: // transitional values + continue; + } + + for (Profile p: Profile.values()) { + List opts = new ArrayList(); + opts.addAll(Arrays.asList("-source", t.name, "-target", t.name)); + opts.add("-Xlint:-options"); // dont warn about no -bootclasspath + if (p != Profile.DEFAULT) + opts.addAll(Arrays.asList("-profile", p.name)); + StringWriter sw = new StringWriter(); + JavacTask task = (JavacTask) javac.getTask(sw, fm, null, opts, null, + Arrays.asList(fo)); + task.analyze(); + + // sadly, command line errors are not (yet?) reported to + // the diag listener + String out = sw.toString(); + if (!out.isEmpty()) + System.err.println(out.trim()); + + switch (t) { + case JDK1_8: + if (!out.isEmpty()) + error("unexpected output from compiler"); + break; + default: + if (p != Profile.DEFAULT + && !out.contains("profile " + p.name + + " is not valid for target release " + t.name)) { + error("expected message not found"); + } + } + } + } + } + + @Test + void testClassesInProfiles() throws Exception { + for (Profile p: Profile.values()) { + for (Map.Entry> e: testClasses.entrySet()) { + for (JavaFileObject fo: e.getValue()) { + DiagnosticCollector dl = + new DiagnosticCollector(); + List opts = (p == Profile.DEFAULT) + ? Collections.emptyList() + : Arrays.asList("-profile", p.name); + JavacTask task = (JavacTask) javac.getTask(null, fm, dl, opts, null, + Arrays.asList(fo)); + task.analyze(); + + List expectDiagCodes = (p.value >= e.getKey().value) + ? Collections.emptyList() + : Arrays.asList("compiler.err.not.in.profile"); + + checkDiags(opts + " " + fo.getName(), dl.getDiagnostics(), expectDiagCodes); + } + } + } + } + + Map> testClasses = + new EnumMap>(Profile.class); + + void initTestClasses() { + // The following table assumes the existence of specific classes + // in specific profiles, as defined in the Java SE 8 spec. + init(Profile.COMPACT1, + java.lang.String.class); + + init(Profile.COMPACT2, + javax.xml.XMLConstants.class); + + init(Profile.COMPACT3, + javax.script.Bindings.class, + com.sun.security.auth.PolicyFile.class); // specifically included in 3 + + init(Profile.DEFAULT, + java.beans.BeanInfo.class, + javax.management.remote.rmi._RMIServer_Stub.class); // specifically excluded in 3 + } + + void init(Profile p, Class... classes) { + List srcs = new ArrayList(); + for (Class c: classes) { + String name = "T" + c.getSimpleName(); + String src = + "class T" + name + "{" + "\n" + + " Class c = " + c.getName() + ".class;\n" + + "}"; + srcs.add(new StringJavaFileObject(name + ".java", src)); + } + testClasses.put(p, srcs); + } + + void checkDiags(String msg, List> diags, List expectDiagCodes) { + System.err.print(msg); + if (diags.isEmpty()) + System.err.println(" OK"); + else { + System.err.println(); + System.err.println(diags); + } + + List foundDiagCodes = new ArrayList(); + for (Diagnostic d: diags) + foundDiagCodes.add(d.getCode()); + + if (!foundDiagCodes.equals(expectDiagCodes)) { + System.err.println("Found diag codes: " + foundDiagCodes); + System.err.println("Expected diag codes: " + expectDiagCodes); + error("expected diagnostics not found"); + } + } + + /** Marker annotation for test cases. */ + @Retention(RetentionPolicy.RUNTIME) + @interface Test { } + + /** Run all test cases. */ + void run() throws Exception { + initTestClasses(); + + for (Method m: getClass().getDeclaredMethods()) { + Annotation a = m.getAnnotation(Test.class); + if (a != null) { + System.err.println(m.getName()); + try { + m.invoke(this, new Object[] { }); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + throw (cause instanceof Exception) ? ((Exception) cause) : e; + } + System.err.println(); + } + } + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + int errors; + + private static class StringJavaFileObject extends SimpleJavaFileObject { + StringJavaFileObject(String name, String text) { + super(URI.create(name), JavaFileObject.Kind.SOURCE); + this.text = text; + } + @Override + public CharSequence getCharContent(boolean b) { + return text; + } + private String text; + } +}