mcimadamore@1415: /* mcimadamore@1415: * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. mcimadamore@1415: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. mcimadamore@1415: * mcimadamore@1415: * This code is free software; you can redistribute it and/or modify it mcimadamore@1415: * under the terms of the GNU General Public License version 2 only, as mcimadamore@1415: * published by the Free Software Foundation. mcimadamore@1415: * mcimadamore@1415: * This code is distributed in the hope that it will be useful, but WITHOUT mcimadamore@1415: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or mcimadamore@1415: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License mcimadamore@1415: * version 2 for more details (a copy is included in the LICENSE file that mcimadamore@1415: * accompanied this code). mcimadamore@1415: * mcimadamore@1415: * You should have received a copy of the GNU General Public License version mcimadamore@1415: * 2 along with this work; if not, write to the Free Software Foundation, mcimadamore@1415: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. mcimadamore@1415: * mcimadamore@1415: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA mcimadamore@1415: * or visit www.oracle.com if you need additional information or have any mcimadamore@1415: * questions. mcimadamore@1415: */ mcimadamore@1415: mcimadamore@1415: /** mcimadamore@1415: * @test mcimadamore@1415: * @bug 8003280 mcimadamore@1415: * @summary Add lambda tests mcimadamore@1415: * Test SAM conversion of method references in combinations of different contexts, mcimadamore@1415: * lambda body types(statement/expression), boxing/unboxing etc, to verify mcimadamore@1415: * SAM conversion being conducted successfully as expected. mcimadamore@1415: */ mcimadamore@1415: mcimadamore@1415: import com.sun.source.util.JavacTask; mcimadamore@1415: import java.net.URI; mcimadamore@1415: import java.util.Arrays; mcimadamore@1415: import javax.tools.Diagnostic; mcimadamore@1415: import javax.tools.JavaCompiler; mcimadamore@1415: import javax.tools.JavaFileObject; mcimadamore@1415: import javax.tools.SimpleJavaFileObject; mcimadamore@1415: import javax.tools.ToolProvider; mcimadamore@1415: import javax.tools.StandardJavaFileManager; mcimadamore@1415: mcimadamore@1415: public class SamConversionComboTest { mcimadamore@1415: mcimadamore@1415: enum FInterface { mcimadamore@1415: A("A", "interface A { Integer m(int i); }"), mcimadamore@1415: B("B", "interface B { int m(Integer i); }"), mcimadamore@1415: C("C", "interface C { int m(int i) throws Exception; }"); mcimadamore@1415: mcimadamore@1415: String interfaceType; mcimadamore@1415: String interfaceDef; mcimadamore@1415: mcimadamore@1415: FInterface(String interfaceType, String interfaceDef) { mcimadamore@1415: this.interfaceType = interfaceType; mcimadamore@1415: this.interfaceDef = interfaceDef; mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: enum Context { mcimadamore@1415: ASSIGNMENT("#FType f = #MR;"), mcimadamore@1415: METHOD_CALL("void method1(#FType f) { }\n" + mcimadamore@1415: "void method2() {\n" + mcimadamore@1415: " method1(#MR);\n" + mcimadamore@1415: "}"), mcimadamore@1415: CONSTRUCTOR("X x = new X(#MR);"), mcimadamore@1415: RETURN_OF_METHOD("#FType method1() {\n" + mcimadamore@1415: " return #MR;\n" + mcimadamore@1415: "}"), mcimadamore@1415: ARRAY_INITIALIZER("#FType[] oarray = {#MR};"), mcimadamore@1415: LAMBDA_BODY("#FType f = n -> ((#FType)#MR).m(n);"), mcimadamore@1415: CAST("void test() throws Exception { int n = ((#FType)#MR).m(1); }"), mcimadamore@1415: CONDITIONAL_EXPRESSION("#FType f = 2 > 1 ? #MR : null;"); mcimadamore@1415: mcimadamore@1415: String context; mcimadamore@1415: mcimadamore@1415: Context(String context) { mcimadamore@1415: this.context = context; mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: String getContext(FInterface f, MethodReference mr) { mcimadamore@1415: return context.replace("#FType", f.interfaceType).replace("#MR", mr.mrValue); mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: enum MethodReference { mcimadamore@1415: METHOD1("X::method1"), mcimadamore@1415: METHOD2("new X()::method2"), mcimadamore@1415: METHOD3("X::method3"), mcimadamore@1415: METHOD4("new X()::method4"), mcimadamore@1415: METHOD5("new X()::method5"), mcimadamore@1415: METHOD6("X::method6"), mcimadamore@1415: METHOD7("X::method7"), mcimadamore@1415: METHOD8("X::method8"); mcimadamore@1415: mcimadamore@1415: String mrValue; mcimadamore@1415: mcimadamore@1415: MethodReference(String mr) { mcimadamore@1415: mrValue = mr; mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: enum MethodDef { mcimadamore@1415: METHOD1(" static Integer method1(int n) {\n" + mcimadamore@1415: " return n + 1;\n" + mcimadamore@1415: " }\n", 0), mcimadamore@1415: METHOD2(" int method2(Integer n) {\n" + mcimadamore@1415: " return value == 0 ? n + 2 : n + value;\n" + mcimadamore@1415: " }\n", 1), mcimadamore@1415: METHOD3(" static int method3(int n) {\n" + mcimadamore@1415: " return n + 3;\n" + mcimadamore@1415: " }\n", 2), mcimadamore@1415: METHOD4(" Integer method4(Integer n) {\n" + mcimadamore@1415: " return value == 0 ? n + 4 : n + value;\n" + mcimadamore@1415: " }\n", 3), mcimadamore@1415: METHOD5(" Integer method5(Integer n) {\n" + mcimadamore@1415: " return value == 0 ? new Integer(n + 5) : new Integer(n + value);\n" + mcimadamore@1415: " }\n", 4), mcimadamore@1415: METHOD6(" static int method6(Integer n) throws Exception{\n" + mcimadamore@1415: " throw new Exception();\n" + mcimadamore@1415: " }\n", 5), mcimadamore@1415: METHOD7(" static int method7(String s){\n" + mcimadamore@1415: " return s.length();\n" + mcimadamore@1415: " }\n", 6), mcimadamore@1415: METHOD8(" static String method8(Integer n){\n" + mcimadamore@1415: " return n + \"\";\n" + mcimadamore@1415: " }\n", 7); mcimadamore@1415: mcimadamore@1415: String methodStr; mcimadamore@1415: int index; mcimadamore@1415: mcimadamore@1415: MethodDef(String ms, int i) { mcimadamore@1415: methodStr = ms; mcimadamore@1415: index = i; mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: MethodReference getMethodReference() { mcimadamore@1415: return MethodReference.values()[index]; mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: SourceFile samSourceFile = new SourceFile("FInterface.java", "#C") { mcimadamore@1415: public String toString() { mcimadamore@1415: String interfaces = ""; mcimadamore@1415: for(FInterface fi : FInterface.values()) mcimadamore@1415: interfaces += fi.interfaceDef + "\n"; mcimadamore@1415: return template.replace("#C", interfaces); mcimadamore@1415: } mcimadamore@1415: }; mcimadamore@1415: mcimadamore@1415: String clientTemplate = "class Client {\n" + mcimadamore@1415: " #Context\n" + mcimadamore@1415: "}\n\n" + mcimadamore@1415: mcimadamore@1415: "class X {\n" + mcimadamore@1415: " int value = 0;\n\n" + mcimadamore@1415: mcimadamore@1415: " X() {\n" + mcimadamore@1415: " }\n\n" + mcimadamore@1415: mcimadamore@1415: " X(A a) {\n" + mcimadamore@1415: " value = a.m(9);\n" + mcimadamore@1415: " }\n\n" + mcimadamore@1415: mcimadamore@1415: " X(B b) {\n" + mcimadamore@1415: " value = b.m(9);\n" + mcimadamore@1415: " }\n\n" + mcimadamore@1415: mcimadamore@1415: " X(C c) {\n" + mcimadamore@1415: " try {\n" + mcimadamore@1415: " value = c.m(9);\n" + mcimadamore@1415: " } catch (Exception e){}\n" + mcimadamore@1415: " }\n\n" + mcimadamore@1415: mcimadamore@1415: "#MethodDef" + mcimadamore@1415: "}"; mcimadamore@1415: mcimadamore@1415: SourceFile clientSourceFile = new SourceFile("Client.java", clientTemplate) { mcimadamore@1415: public String toString() { mcimadamore@1415: return template.replace("#Context", context.getContext(fInterface, methodReference)).replace("#MethodDef", methodDef.methodStr); mcimadamore@1415: } mcimadamore@1415: }; mcimadamore@1415: mcimadamore@1415: boolean checkSamConversion() { mcimadamore@1415: if(methodDef == MethodDef.METHOD7 || methodDef == MethodDef.METHOD8)//method signature mismatch mcimadamore@1415: return false; mcimadamore@1415: if(context != Context.CONSTRUCTOR && fInterface != FInterface.C && methodDef == MethodDef.METHOD6) mcimadamore@1415: //method that throws exceptions not thrown by the interface method is a mismatch mcimadamore@1415: return false; mcimadamore@1415: if(context == Context.CONSTRUCTOR && mcimadamore@1415: methodReference != MethodReference.METHOD1 && mcimadamore@1415: methodReference != MethodReference.METHOD2 && mcimadamore@1415: methodReference != MethodReference.METHOD3)//ambiguous reference mcimadamore@1415: return false; mcimadamore@1415: return true; mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: void test() throws Exception { mcimadamore@1415: System.out.println("\n===================================="); mcimadamore@1415: System.out.println(fInterface + ", " + context + ", " + methodReference); mcimadamore@1415: System.out.println(samSourceFile + "\n" + clientSourceFile); mcimadamore@1415: mcimadamore@1415: DiagnosticChecker dc = new DiagnosticChecker(); mcimadamore@1415: JavacTask ct = (JavacTask)comp.getTask(null, fm, dc, null, null, Arrays.asList(samSourceFile, clientSourceFile)); mcimadamore@1415: ct.analyze(); mcimadamore@1415: if (dc.errorFound == checkSamConversion()) { mcimadamore@1415: throw new AssertionError(samSourceFile + "\n\n" + clientSourceFile); mcimadamore@1415: } mcimadamore@1415: count++; mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: abstract class SourceFile extends SimpleJavaFileObject { mcimadamore@1415: mcimadamore@1415: protected String template; mcimadamore@1415: mcimadamore@1415: public SourceFile(String filename, String template) { mcimadamore@1415: super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE); mcimadamore@1415: this.template = template; mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: @Override mcimadamore@1415: public CharSequence getCharContent(boolean ignoreEncodingErrors) { mcimadamore@1415: return toString(); mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: public abstract String toString(); mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: static class DiagnosticChecker implements javax.tools.DiagnosticListener { mcimadamore@1415: mcimadamore@1415: boolean errorFound = false; mcimadamore@1415: mcimadamore@1415: public void report(Diagnostic diagnostic) { mcimadamore@1415: if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { mcimadamore@1415: errorFound = true; mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: FInterface fInterface; mcimadamore@1415: Context context; mcimadamore@1415: MethodDef methodDef; mcimadamore@1415: MethodReference methodReference; mcimadamore@1415: static int count = 0; mcimadamore@1415: mcimadamore@1415: static JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); mcimadamore@1415: static StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); mcimadamore@1415: mcimadamore@1415: SamConversionComboTest(FInterface f, Context c, MethodDef md) { mcimadamore@1415: fInterface = f; mcimadamore@1415: context = c; mcimadamore@1415: methodDef = md; mcimadamore@1415: methodReference = md.getMethodReference(); mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: public static void main(String[] args) throws Exception { mcimadamore@1415: for(Context ct : Context.values()) { mcimadamore@1415: for (FInterface fi : FInterface.values()) { mcimadamore@1415: for (MethodDef md: MethodDef.values()) { mcimadamore@1415: new SamConversionComboTest(fi, ct, md).test(); mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: System.out.println("total tests: " + count); mcimadamore@1415: } mcimadamore@1415: }