test/tools/javac/lambda/lambdaExpression/SamConversionComboTest.java

Tue, 24 Dec 2013 09:17:37 -0800

author
ksrini
date
Tue, 24 Dec 2013 09:17:37 -0800
changeset 2227
998b10c43157
parent 1510
7873d37f5b37
child 2370
acd64168cf8b
permissions
-rw-r--r--

8029230: Update copyright year to match last edit in jdk8 langtools repository for 2013
Reviewed-by: ksrini
Contributed-by: steve.sides@oracle.com

mcimadamore@1415 1 /*
ksrini@2227 2 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
mcimadamore@1415 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
mcimadamore@1415 4 *
mcimadamore@1415 5 * This code is free software; you can redistribute it and/or modify it
mcimadamore@1415 6 * under the terms of the GNU General Public License version 2 only, as
mcimadamore@1415 7 * published by the Free Software Foundation.
mcimadamore@1415 8 *
mcimadamore@1415 9 * This code is distributed in the hope that it will be useful, but WITHOUT
mcimadamore@1415 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
mcimadamore@1415 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
mcimadamore@1415 12 * version 2 for more details (a copy is included in the LICENSE file that
mcimadamore@1415 13 * accompanied this code).
mcimadamore@1415 14 *
mcimadamore@1415 15 * You should have received a copy of the GNU General Public License version
mcimadamore@1415 16 * 2 along with this work; if not, write to the Free Software Foundation,
mcimadamore@1415 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
mcimadamore@1415 18 *
mcimadamore@1415 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
mcimadamore@1415 20 * or visit www.oracle.com if you need additional information or have any
mcimadamore@1415 21 * questions.
mcimadamore@1415 22 */
mcimadamore@1415 23
mcimadamore@1415 24 /**
mcimadamore@1415 25 * @test
mcimadamore@1415 26 * @bug 8003280
mcimadamore@1415 27 * @summary Add lambda tests
mcimadamore@1415 28 * Test SAM conversion of lambda expressions in combinations of different contexts,
mcimadamore@1415 29 * lambda body types(statement/expression), explict/implicit target type etc, to verify
mcimadamore@1415 30 * SAM conversion being conducted successfully as expected.
mcimadamore@1415 31 */
mcimadamore@1415 32
mcimadamore@1415 33 import com.sun.source.util.JavacTask;
mcimadamore@1415 34 import java.net.URI;
mcimadamore@1415 35 import java.util.Arrays;
mcimadamore@1415 36 import javax.tools.Diagnostic;
mcimadamore@1415 37 import javax.tools.JavaCompiler;
mcimadamore@1415 38 import javax.tools.JavaFileObject;
mcimadamore@1415 39 import javax.tools.SimpleJavaFileObject;
mcimadamore@1415 40 import javax.tools.ToolProvider;
mcimadamore@1415 41
mcimadamore@1415 42 public class SamConversionComboTest {
mcimadamore@1415 43
mcimadamore@1415 44 enum FInterface {
mcimadamore@1415 45 A("A", "interface A { Integer m(int i); }"),
mcimadamore@1415 46 B("B", "interface B { int m(Integer i); }"),
mcimadamore@1415 47 C("C", "interface C { int m(Integer i) throws Exception; }");
mcimadamore@1415 48
mcimadamore@1415 49 String interfaceType;
mcimadamore@1415 50 String interfaceDef;
mcimadamore@1415 51
mcimadamore@1415 52 FInterface(String interfaceType, String interfaceDef) {
mcimadamore@1415 53 this.interfaceType = interfaceType;
mcimadamore@1415 54 this.interfaceDef = interfaceDef;
mcimadamore@1415 55 }
mcimadamore@1415 56
mcimadamore@1415 57 String getParameterType() {
mcimadamore@1415 58 switch(this) {
mcimadamore@1415 59 case A:
mcimadamore@1415 60 return "int";
mcimadamore@1415 61 case B:
mcimadamore@1415 62 case C:
mcimadamore@1415 63 return "Integer";
mcimadamore@1415 64 default:
mcimadamore@1415 65 return null;
mcimadamore@1415 66 }
mcimadamore@1415 67 }
mcimadamore@1415 68 }
mcimadamore@1415 69
mcimadamore@1415 70 enum Context {
mcimadamore@1415 71 ASSIGNMENT("#FType f = #LBody;"),
mcimadamore@1415 72 METHOD_CALL("void method1(#FType f) { }\n" +
mcimadamore@1415 73 " void method2() {\n" +
mcimadamore@1415 74 " method1(#LBody);\n" +
mcimadamore@1415 75 " }"),
mcimadamore@1415 76 CONSTRUCTOR("X x = new X(#LBody);"),
mcimadamore@1415 77 RETURN_OF_METHOD("#FType method1() {\n" +
mcimadamore@1415 78 " return #LBody;\n" +
mcimadamore@1415 79 "}"),
mcimadamore@1415 80 ARRAY_INITIALIZER("Object[] oarray = {\"a\", 1, (#FType)#LBody};"),
mcimadamore@1415 81 LAMBDA_BODY("#FType f = n -> ((#FType)#LBody).m(n);"),
mcimadamore@1415 82 CAST("void test() throws Exception { int n = ((#FType)#LBody).m(1); }"),
mcimadamore@1415 83 CONDITIONAL_EXPRESSION("#FType f = 2 > 1 ? #LBody : null;");
mcimadamore@1415 84
mcimadamore@1415 85 String context;
mcimadamore@1415 86
mcimadamore@1415 87 Context(String context) {
mcimadamore@1415 88 this.context = context;
mcimadamore@1415 89 }
mcimadamore@1415 90
mcimadamore@1415 91 String getContext(FInterface f, LambdaKind lk, LambdaBody lb, ReturnValue rv) {
mcimadamore@1415 92 return context.replace("#FType", f.interfaceType).replace("#LBody", lb.getLambdaBody(f, lk, rv));
mcimadamore@1415 93 }
mcimadamore@1415 94 }
mcimadamore@1415 95
mcimadamore@1415 96 enum LambdaKind {
mcimadamore@1415 97 EXPRESSION("#VAL"),
mcimadamore@1415 98 STATEMENT("{return #VAL;}"),
mcimadamore@1415 99 EXCEPTION_STMT("{throw new Exception();}");
mcimadamore@1415 100
mcimadamore@1415 101 String stmt;
mcimadamore@1415 102
mcimadamore@1415 103 LambdaKind(String stmt) {
mcimadamore@1415 104 this.stmt = stmt;
mcimadamore@1415 105 }
mcimadamore@1415 106 }
mcimadamore@1415 107
mcimadamore@1415 108 enum ReturnValue {
mcimadamore@1415 109 INT("i + 1"),
mcimadamore@1415 110 INTEGER("new Integer(i+1)"),
mcimadamore@1415 111 INT2("i.intValue() + 1"),
mcimadamore@1415 112 STRING("i + \"\""),
mcimadamore@1415 113 DOUBLE("i * 1.0");
mcimadamore@1415 114
mcimadamore@1415 115 String rValue;
mcimadamore@1415 116
mcimadamore@1415 117 ReturnValue(String rValue) {
mcimadamore@1415 118 this.rValue = rValue;
mcimadamore@1415 119 }
mcimadamore@1415 120 }
mcimadamore@1415 121
mcimadamore@1415 122 enum LambdaBody {
mcimadamore@1415 123 IMPLICIT("i -> #RET"),//type inferred
mcimadamore@1415 124 EXPLICIT("(#Type i) -> #RET");//explicit type
mcimadamore@1415 125
mcimadamore@1415 126 String bodyStr;
mcimadamore@1415 127
mcimadamore@1415 128 LambdaBody(String bodyStr) {
mcimadamore@1415 129 this.bodyStr = bodyStr;
mcimadamore@1415 130 }
mcimadamore@1415 131
mcimadamore@1415 132 String getLambdaBody(FInterface fi, LambdaKind lk, ReturnValue rv) {
mcimadamore@1415 133 return bodyStr.replace("#Type", fi.getParameterType()).replace("#RET", lk.stmt.replace("#VAL", rv.rValue));
mcimadamore@1415 134 }
mcimadamore@1415 135 }
mcimadamore@1415 136
mcimadamore@1415 137 boolean checkSamConversion() {
mcimadamore@1415 138 if(lambdaKind != LambdaKind.EXCEPTION_STMT && (returnValue == ReturnValue.DOUBLE || returnValue == ReturnValue.STRING)) //return type mismatch
mcimadamore@1415 139 return false;
mcimadamore@1415 140 if(context != Context.CONSTRUCTOR) {//context other than construcotr argument
mcimadamore@1415 141 if(fInterface != FInterface.C && lambdaKind == LambdaKind.EXCEPTION_STMT)
mcimadamore@1415 142 return false;
mcimadamore@1415 143 if(fInterface == FInterface.A && returnValue == ReturnValue.INT2)
mcimadamore@1415 144 return false;
mcimadamore@1415 145 }
mcimadamore@1415 146 else { //constructor argument context
mcimadamore@1415 147 //match X(A a) or X(B b) or X(C c)
mcimadamore@1415 148 if (lambdaKind == LambdaKind.EXCEPTION_STMT) {
mcimadamore@1415 149 return false; //ambiguous target type
mcimadamore@1415 150 }
mcimadamore@1415 151 else if(lambdaBody == LambdaBody.IMPLICIT) {
mcimadamore@1510 152 return false;
mcimadamore@1415 153 }
mcimadamore@1415 154 else { //explicit parameter type
mcimadamore@1415 155 if(fInterface.getParameterType().equals("Integer")) //ambiguous target type
mcimadamore@1415 156 //e.g. X x = new X((Integer i) -> i + 1);
mcimadamore@1415 157 return false;
mcimadamore@1415 158 if(returnValue == ReturnValue.INT2)
mcimadamore@1415 159 //e.g. X x = new X(int i -> i.intValue() + 1);
mcimadamore@1415 160 return false;
mcimadamore@1415 161 }
mcimadamore@1415 162 }
mcimadamore@1415 163 return true;
mcimadamore@1415 164 }
mcimadamore@1415 165
mcimadamore@1415 166 SourceFile samSourceFile = new SourceFile("FInterface.java", "#C") {
mcimadamore@1415 167 public String toString() {
mcimadamore@1415 168 String interfaces = "";
mcimadamore@1415 169 for(FInterface fi : FInterface.values())
mcimadamore@1415 170 interfaces += fi.interfaceDef + "\n";
mcimadamore@1415 171 return template.replace("#C", interfaces);
mcimadamore@1415 172 }
mcimadamore@1415 173 };
mcimadamore@1415 174
mcimadamore@1415 175 String clientTemplate = "class Client {\n" +
mcimadamore@1415 176 " #Context\n" +
mcimadamore@1415 177 "}\n\n" +
mcimadamore@1415 178
mcimadamore@1415 179 "class X {\n" +
mcimadamore@1415 180 " int value = 0;\n\n" +
mcimadamore@1415 181
mcimadamore@1415 182 " X(A a) {\n" +
mcimadamore@1415 183 " value = a.m(6);\n" +
mcimadamore@1415 184 " }\n\n" +
mcimadamore@1415 185
mcimadamore@1415 186 " X(B b) {\n" +
mcimadamore@1415 187 " value = b.m(7);\n" +
mcimadamore@1415 188 " }\n\n" +
mcimadamore@1415 189
mcimadamore@1415 190 " X(C c) {\n" +
mcimadamore@1415 191 " try {\n" +
mcimadamore@1415 192 " value = c.m(8);\n" +
mcimadamore@1415 193 " } catch (Exception e){}\n" +
mcimadamore@1415 194 " }\n" +
mcimadamore@1415 195 "}";
mcimadamore@1415 196 SourceFile clientSourceFile = new SourceFile("Client.java", clientTemplate) {
mcimadamore@1415 197 public String toString() {
mcimadamore@1415 198 return template.replace("#Context", context.getContext(fInterface, lambdaKind, lambdaBody, returnValue));
mcimadamore@1415 199 }
mcimadamore@1415 200 };
mcimadamore@1415 201
mcimadamore@1415 202 void test() throws Exception {
mcimadamore@1415 203 System.out.println("\n====================================");
mcimadamore@1415 204 System.out.println(fInterface + ", " + context + ", " + lambdaKind + ", " + lambdaBody + ", " + returnValue);
mcimadamore@1415 205 System.out.println(samSourceFile + "\n");
mcimadamore@1415 206 String clientFileStr = clientSourceFile.toString();
mcimadamore@1415 207 System.out.println(clientFileStr.substring(0, clientFileStr.indexOf("\n\n")));
mcimadamore@1415 208
mcimadamore@1415 209 final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
mcimadamore@1415 210 DiagnosticChecker dc = new DiagnosticChecker();
mcimadamore@1415 211 JavacTask ct = (JavacTask)tool.getTask(null, null, dc, null, null, Arrays.asList(samSourceFile, clientSourceFile));
mcimadamore@1415 212 ct.analyze();
mcimadamore@1415 213 if (dc.errorFound == checkSamConversion()) {
mcimadamore@1415 214 throw new AssertionError(samSourceFile + "\n\n" + clientSourceFile);
mcimadamore@1415 215 }
mcimadamore@1415 216 count++;
mcimadamore@1415 217 }
mcimadamore@1415 218
mcimadamore@1415 219 abstract class SourceFile extends SimpleJavaFileObject {
mcimadamore@1415 220
mcimadamore@1415 221 protected String template;
mcimadamore@1415 222
mcimadamore@1415 223 public SourceFile(String filename, String template) {
mcimadamore@1415 224 super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE);
mcimadamore@1415 225 this.template = template;
mcimadamore@1415 226 }
mcimadamore@1415 227
mcimadamore@1415 228 @Override
mcimadamore@1415 229 public CharSequence getCharContent(boolean ignoreEncodingErrors) {
mcimadamore@1415 230 return toString();
mcimadamore@1415 231 }
mcimadamore@1415 232
mcimadamore@1415 233 public abstract String toString();
mcimadamore@1415 234 }
mcimadamore@1415 235
mcimadamore@1415 236 static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
mcimadamore@1415 237
mcimadamore@1415 238 boolean errorFound = false;
mcimadamore@1415 239
mcimadamore@1415 240 public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
mcimadamore@1415 241 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
mcimadamore@1415 242 errorFound = true;
mcimadamore@1415 243 }
mcimadamore@1415 244 }
mcimadamore@1415 245 }
mcimadamore@1415 246
mcimadamore@1415 247 FInterface fInterface;
mcimadamore@1415 248 Context context;
mcimadamore@1415 249 LambdaBody lambdaBody;
mcimadamore@1415 250 LambdaKind lambdaKind;
mcimadamore@1415 251 ReturnValue returnValue;
mcimadamore@1415 252 static int count = 0;
mcimadamore@1415 253
mcimadamore@1415 254 SamConversionComboTest(FInterface f, Context c, LambdaBody lb, LambdaKind lk, ReturnValue rv) {
mcimadamore@1415 255 fInterface = f;
mcimadamore@1415 256 context = c;
mcimadamore@1415 257 lambdaKind = lk;
mcimadamore@1415 258 lambdaBody = lb;
mcimadamore@1415 259 returnValue = rv;
mcimadamore@1415 260 }
mcimadamore@1415 261
mcimadamore@1415 262 public static void main(String[] args) throws Exception {
mcimadamore@1415 263 for(Context ct : Context.values()) {
mcimadamore@1415 264 for (FInterface fi : FInterface.values()) {
mcimadamore@1415 265 for (LambdaKind lk: LambdaKind.values()) {
mcimadamore@1415 266 for (LambdaBody lb : LambdaBody.values()) {
mcimadamore@1415 267 for(ReturnValue rv : ReturnValue.values()) {
mcimadamore@1415 268 new SamConversionComboTest(fi, ct, lb, lk, rv).test();
mcimadamore@1415 269 }
mcimadamore@1415 270 }
mcimadamore@1415 271 }
mcimadamore@1415 272 }
mcimadamore@1415 273 }
mcimadamore@1415 274 System.out.println("total tests: " + count);
mcimadamore@1415 275 }
mcimadamore@1415 276 }

mercurial