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

Wed, 27 Apr 2016 01:34:52 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:34:52 +0800
changeset 0
959103a6100f
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17

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

mercurial