StructuralMostSpecificTest.java revision 1414:01c9d4161882
1292915Sdim/* 2292915Sdim * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 3292915Sdim * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4292915Sdim * 5292915Sdim * This code is free software; you can redistribute it and/or modify it 6292915Sdim * under the terms of the GNU General Public License version 2 only, as 7292915Sdim * published by the Free Software Foundation. 8292915Sdim * 9292915Sdim * This code is distributed in the hope that it will be useful, but WITHOUT 10292915Sdim * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11292915Sdim * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12292915Sdim * version 2 for more details (a copy is included in the LICENSE file that 13292915Sdim * accompanied this code). 14292915Sdim * 15292915Sdim * You should have received a copy of the GNU General Public License version 16292915Sdim * 2 along with this work; if not, write to the Free Software Foundation, 17292915Sdim * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18292915Sdim * 19292915Sdim * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20292915Sdim * or visit www.oracle.com if you need additional information or have any 21292915Sdim * questions. 22294024Sdim */ 23294024Sdim 24292915Sdim/* 25292915Sdim * @test 26292915Sdim * @bug 8003280 27292915Sdim * @summary Add lambda tests 28292915Sdim * Automatic test for checking correctness of structural most specific test routine 29292915Sdim * @run main/timeout=360 StructuralMostSpecificTest 30292915Sdim */ 31292915Sdim 32292915Sdimimport com.sun.source.util.JavacTask; 33292915Sdimimport com.sun.tools.javac.api.ClientCodeWrapper; 34292915Sdimimport com.sun.tools.javac.util.JCDiagnostic; 35294024Sdimimport java.net.URI; 36292915Sdimimport java.util.Arrays; 37292915Sdimimport javax.tools.Diagnostic; 38292915Sdimimport javax.tools.JavaCompiler; 39292915Sdimimport javax.tools.JavaFileObject; 40292915Sdimimport javax.tools.SimpleJavaFileObject; 41292915Sdimimport javax.tools.StandardJavaFileManager; 42292915Sdimimport javax.tools.ToolProvider; 43292915Sdim 44292915Sdimpublic class StructuralMostSpecificTest { 45292915Sdim 46292915Sdim static int checkCount = 0; 47292915Sdim 48292915Sdim enum RetTypeKind { 49292915Sdim SHORT("short"), 50292915Sdim INT("int"), 51292915Sdim OBJECT("Object"), 52292915Sdim INTEGER("Integer"), 53292915Sdim VOID("void"), 54292915Sdim J_L_VOID("Void"); 55292915Sdim 56292915Sdim String retTypeStr; 57292915Sdim 58292915Sdim RetTypeKind(String retTypeStr) { 59292915Sdim this.retTypeStr = retTypeStr; 60292915Sdim } 61292915Sdim 62292915Sdim boolean moreSpecificThan(RetTypeKind rk) { 63292915Sdim return moreSpecificThan[this.ordinal()][rk.ordinal()]; 64292915Sdim } 65292915Sdim 66292915Sdim static boolean[][] moreSpecificThan = { 67292915Sdim // SHORT | INT | OBJECT | INTEGER | VOID | J_L_VOID 68292915Sdim /* SHORT */ { true , true , true , false , false , false }, 69292915Sdim /* INT */ { false , true , true , true , false , false }, 70292915Sdim /* OBJECT */ { false , false , true , false , false , false }, 71292915Sdim /* INTEGER */ { false , false , true , true , false , false }, 72292915Sdim /* VOID */ { false , false , false , false , true , true }, 73292915Sdim /* J_L_VOID */{ false , false , true , false , false , true } }; 74292915Sdim } 75292915Sdim 76292915Sdim enum ArgTypeKind { 77292915Sdim SHORT("short"), 78292915Sdim INT("int"), 79292915Sdim BOOLEAN("boolean"), 80292915Sdim OBJECT("Object"), 81292915Sdim INTEGER("Integer"), 82292915Sdim DOUBLE("Double"); 83294024Sdim 84292915Sdim String argTypeStr; 85294024Sdim 86292915Sdim ArgTypeKind(String typeStr) { 87294024Sdim this.argTypeStr = typeStr; 88292915Sdim } 89292915Sdim } 90292915Sdim 91292915Sdim enum ExceptionKind { 92292915Sdim NONE(""), 93292915Sdim EXCEPTION("throws Exception"), 94292915Sdim SQL_EXCEPTION("throws java.sql.SQLException"), 95292915Sdim IO_EXCEPTION("throws java.io.IOException"); 96292915Sdim 97292915Sdim String exceptionStr; 98292915Sdim 99292915Sdim ExceptionKind(String exceptionStr) { 100292915Sdim this.exceptionStr = exceptionStr; 101292915Sdim } 102292915Sdim } 103292915Sdim 104292915Sdim enum LambdaReturnKind { 105292915Sdim VOID("return;"), 106292915Sdim SHORT("return (short)0;"), 107292915Sdim INT("return 0;"), 108292915Sdim INTEGER("return (Integer)null"), 109292915Sdim NULL("return null;"); 110292915Sdim 111292915Sdim String retStr; 112292915Sdim 113292915Sdim LambdaReturnKind(String retStr) { 114292915Sdim this.retStr = retStr; 115292915Sdim } 116292915Sdim 117292915Sdim boolean compatibleWith(RetTypeKind rk) { 118292915Sdim return compatibleWith[rk.ordinal()][ordinal()]; 119292915Sdim } 120292915Sdim 121292915Sdim static boolean[][] compatibleWith = { 122292915Sdim // VOID | SHORT | INT | INTEGER | NULL 123292915Sdim /* SHORT */ { false , true , false , false , false }, 124292915Sdim /* INT */ { false , true , true , true , false }, 125292915Sdim /* OBJECT */ { false , true , true , true , true }, 126292915Sdim /* INTEGER */ { false , false , true , true , true }, 127292915Sdim /* VOID */ { true , false , false , false , false }, 128292915Sdim /* J_L_VOID */{ false , false , false , false , true } }; 129292915Sdim 130292915Sdim boolean needsConversion(RetTypeKind rk) { 131292915Sdim return needsConversion[rk.ordinal()][ordinal()]; 132292915Sdim } 133292915Sdim 134292915Sdim static boolean[][] needsConversion = { 135292915Sdim // VOID | SHORT | INT | INTEGER | NULL 136292915Sdim /* SHORT */ { false , false , false , false , false }, 137292915Sdim /* INT */ { false , false , false , true , false }, 138292915Sdim /* OBJECT */ { false , true , true , false , false }, 139292915Sdim /* INTEGER */ { false , false , true , false , false }, 140292915Sdim /* VOID */ { false , false , false , false , false }, 141292915Sdim /* J_L_VOID */{ true , false , false , false , false } }; 142292915Sdim } 143292915Sdim 144292915Sdim public static void main(String... args) throws Exception { 145292915Sdim 146292915Sdim //create default shared JavaCompiler - reused across multiple compilations 147292915Sdim JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); 148292915Sdim StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); 149292915Sdim 150292915Sdim for (LambdaReturnKind lrk : LambdaReturnKind.values()) { 151292915Sdim for (RetTypeKind rk1 : RetTypeKind.values()) { 152292915Sdim for (RetTypeKind rk2 : RetTypeKind.values()) { 153292915Sdim for (ExceptionKind ek1 : ExceptionKind.values()) { 154292915Sdim for (ExceptionKind ek2 : ExceptionKind.values()) { 155292915Sdim for (ArgTypeKind ak11 : ArgTypeKind.values()) { 156292915Sdim for (ArgTypeKind ak12 : ArgTypeKind.values()) { 157292915Sdim new StructuralMostSpecificTest(lrk, rk1, rk2, ek1, ek2, ak11, ak12).run(comp, fm); 158292915Sdim } 159292915Sdim } 160292915Sdim } 161292915Sdim } 162292915Sdim } 163292915Sdim } 164292915Sdim } 165292915Sdim System.out.println("Total check executed: " + checkCount); 166292915Sdim } 167292915Sdim 168292915Sdim LambdaReturnKind lrk; 169292915Sdim RetTypeKind rt1, rt2; 170292915Sdim ArgTypeKind ak1, ak2; 171292915Sdim ExceptionKind ek1, ek2; 172292915Sdim JavaSource source; 173292915Sdim DiagnosticChecker diagChecker; 174292915Sdim 175292915Sdim StructuralMostSpecificTest(LambdaReturnKind lrk, RetTypeKind rt1, RetTypeKind rt2, 176292915Sdim ExceptionKind ek1, ExceptionKind ek2, ArgTypeKind ak1, ArgTypeKind ak2) { 177292915Sdim this.lrk = lrk; 178292915Sdim this.rt1 = rt1; 179292915Sdim this.rt2 = rt2; 180292915Sdim this.ek1 = ek1; 181292915Sdim this.ek2 = ek2; 182292915Sdim this.ak1 = ak1; 183292915Sdim this.ak2 = ak2; 184292915Sdim this.source = new JavaSource(); 185292915Sdim this.diagChecker = new DiagnosticChecker(); 186292915Sdim } 187292915Sdim 188292915Sdim class JavaSource extends SimpleJavaFileObject { 189292915Sdim 190292915Sdim String template = "interface SAM1 {\n" + 191292915Sdim " #R1 m(#A1 a1) #E1;\n" + 192292915Sdim "}\n" + 193292915Sdim "interface SAM2 {\n" + 194292915Sdim " #R2 m(#A2 a1) #E2;\n" + 195292915Sdim "}\n" + 196292915Sdim "class Test {\n" + 197292915Sdim " void m(SAM1 s) { }\n" + 198292915Sdim " void m(SAM2 s) { }\n" + 199292915Sdim " { m(x->{ #LR }); }\n" + 200292915Sdim "}\n"; 201292915Sdim 202292915Sdim String source; 203292915Sdim 204292915Sdim public JavaSource() { 205292915Sdim super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); 206292915Sdim source = template.replaceAll("#LR", lrk.retStr) 207292915Sdim .replaceAll("#R1", rt1.retTypeStr) 208292915Sdim .replaceAll("#R2", rt2.retTypeStr) 209292915Sdim .replaceAll("#A1", ak1.argTypeStr) 210292915Sdim .replaceAll("#A2", ak2.argTypeStr) 211292915Sdim .replaceAll("#E1", ek1.exceptionStr) 212292915Sdim .replaceAll("#E2", ek2.exceptionStr); 213292915Sdim } 214292915Sdim 215292915Sdim @Override 216292915Sdim public CharSequence getCharContent(boolean ignoreEncodingErrors) { 217292915Sdim return source; 218292915Sdim } 219292915Sdim } 220292915Sdim 221292915Sdim void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception { 222292915Sdim JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker, 223292915Sdim Arrays.asList("-XDverboseResolution=all,-predef,-internal,-object-init"), 224292915Sdim null, Arrays.asList(source)); 225292915Sdim try { 226292915Sdim ct.analyze(); 227294024Sdim } catch (Throwable ex) { 228292915Sdim throw new AssertionError("Error thron when analyzing the following source:\n" + source.getCharContent(true)); 229292915Sdim } 230294024Sdim check(); 231292915Sdim } 232292915Sdim 233294024Sdim void check() { 234292915Sdim checkCount++; 235292915Sdim 236294024Sdim if (!lrk.compatibleWith(rt1) || !lrk.compatibleWith(rt2)) 237292915Sdim return; 238294024Sdim 239292915Sdim if (lrk.needsConversion(rt1) != lrk.needsConversion(rt2)) 240292915Sdim return; 241292915Sdim 242292915Sdim boolean m1MoreSpecific = moreSpecific(rt1, rt2, ek1, ek2, ak1, ak2); 243292915Sdim boolean m2MoreSpecific = moreSpecific(rt2, rt1, ek2, ek1, ak2, ak1); 244292915Sdim 245292915Sdim boolean ambiguous = (m1MoreSpecific == m2MoreSpecific); 246292915Sdim 247294024Sdim if (ambiguous != diagChecker.ambiguityFound) { 248292915Sdim throw new Error("invalid diagnostics for source:\n" + 249292915Sdim source.getCharContent(true) + 250292915Sdim "\nAmbiguity found: " + diagChecker.ambiguityFound + 251294024Sdim "\nm1 more specific: " + m1MoreSpecific + 252292915Sdim "\nm2 more specific: " + m2MoreSpecific + 253292915Sdim "\nexpected ambiguity: " + ambiguous); 254292915Sdim } 255294024Sdim 256292915Sdim if (!ambiguous) { 257294024Sdim String sigToCheck = m1MoreSpecific ? "m(SAM1)" : "m(SAM2)"; 258292915Sdim if (!sigToCheck.equals(diagChecker.mostSpecificSig)) { 259292915Sdim throw new Error("invalid most specific method selected:\n" + 260294024Sdim source.getCharContent(true) + 261294024Sdim "\nMost specific found: " + diagChecker.mostSpecificSig + 262292915Sdim "\nm1 more specific: " + m1MoreSpecific + 263292915Sdim "\nm2 more specific: " + m2MoreSpecific); 264292915Sdim } 265292915Sdim } 266292915Sdim } 267294024Sdim 268292915Sdim boolean moreSpecific(RetTypeKind rk1, RetTypeKind rk2, ExceptionKind ek1, ExceptionKind ek2, 269292915Sdim ArgTypeKind ak1, ArgTypeKind ak2) { 270294024Sdim if (!rk1.moreSpecificThan(rk2)) 271292915Sdim return false; 272292915Sdim 273292915Sdim if (ak1 != ak2) 274292915Sdim return false; 275292915Sdim 276292915Sdim return true; 277292915Sdim } 278292915Sdim 279292915Sdim static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> { 280294024Sdim 281292915Sdim boolean ambiguityFound; 282292915Sdim String mostSpecificSig; 283292915Sdim 284292915Sdim public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 285292915Sdim try { 286292915Sdim if (diagnostic.getKind() == Diagnostic.Kind.ERROR && 287292915Sdim diagnostic.getCode().equals("compiler.err.ref.ambiguous")) { 288292915Sdim ambiguityFound = true; 289292915Sdim } else if (diagnostic.getKind() == Diagnostic.Kind.NOTE && 290294024Sdim diagnostic.getCode().equals("compiler.note.verbose.resolve.multi")) { 291294024Sdim ClientCodeWrapper.DiagnosticSourceUnwrapper dsu = 292294024Sdim (ClientCodeWrapper.DiagnosticSourceUnwrapper)diagnostic; 293294024Sdim JCDiagnostic.MultilineDiagnostic mdiag = (JCDiagnostic.MultilineDiagnostic)dsu.d; 294294024Sdim int mostSpecificIndex = (Integer)mdiag.getArgs()[2]; 295294024Sdim mostSpecificSig = ((JCDiagnostic)mdiag.getSubdiagnostics().get(mostSpecificIndex)).getArgs()[1].toString(); 296292915Sdim } 297292915Sdim } catch (RuntimeException t) { 298292915Sdim t.printStackTrace(); 299294024Sdim throw t; 300292915Sdim } 301294024Sdim } 302292915Sdim } 303292915Sdim} 304292915Sdim