StructuralMostSpecificTest.java revision 3019:176472b94f2e
1/* 2 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/* 25 * @test 26 * @bug 8003280 8006694 8129962 27 * @summary Add lambda tests 28 * Automatic test for checking correctness of structural most specific test routine 29 * temporarily workaround combo tests are causing time out in several platforms 30 * @library /tools/javac/lib 31 * @modules jdk.compiler/com.sun.tools.javac.api 32 * jdk.compiler/com.sun.tools.javac.code 33 * jdk.compiler/com.sun.tools.javac.comp 34 * jdk.compiler/com.sun.tools.javac.main 35 * jdk.compiler/com.sun.tools.javac.tree 36 * jdk.compiler/com.sun.tools.javac.util 37 * @build combo.ComboTestHelper 38 39 * @run main StructuralMostSpecificTest 40 */ 41 42import javax.lang.model.element.Element; 43import javax.tools.Diagnostic; 44import javax.tools.JavaFileObject; 45import com.sun.tools.javac.api.ClientCodeWrapper; 46import com.sun.tools.javac.util.JCDiagnostic; 47import com.sun.tools.javac.util.List; 48import combo.ComboInstance; 49import combo.ComboParameter; 50import combo.ComboTask.Result; 51import combo.ComboTestHelper; 52 53public class StructuralMostSpecificTest extends ComboInstance<StructuralMostSpecificTest> { 54 55 enum RetTypeKind implements ComboParameter { 56 SHORT("short"), 57 INT("int"), 58 OBJECT("Object"), 59 INTEGER("Integer"), 60 VOID("void"), 61 J_L_VOID("Void"); 62 63 String retTypeStr; 64 65 RetTypeKind(String retTypeStr) { 66 this.retTypeStr = retTypeStr; 67 } 68 69 boolean moreSpecificThan(RetTypeKind rk) { 70 return moreSpecificThan[this.ordinal()][rk.ordinal()]; 71 } 72 73 static boolean[][] moreSpecificThan = { 74 // SHORT | INT | OBJECT | INTEGER | VOID | J_L_VOID 75 /* SHORT */ { true , true , true , false , false , false }, 76 /* INT */ { false , true , true , true , false , false }, 77 /* OBJECT */ { false , false , true , false , false , false }, 78 /* INTEGER */ { false , false , true , true , false , false }, 79 /* VOID */ { false , false , false , false , true , true }, 80 /* J_L_VOID */{ false , false , true , false , false , true } }; 81 82 public String expand(String optParameter) { 83 return retTypeStr; 84 } 85 } 86 87 enum ArgTypeKind implements ComboParameter { 88 SHORT("short"), 89 INT("int"), 90 BOOLEAN("boolean"), 91 OBJECT("Object"), 92 INTEGER("Integer"), 93 DOUBLE("Double"); 94 95 String argTypeStr; 96 97 ArgTypeKind(String typeStr) { 98 this.argTypeStr = typeStr; 99 } 100 101 public String expand(String optParameter) { 102 return argTypeStr; 103 } 104 } 105 106 enum ExceptionKind implements ComboParameter { 107 NONE(""), 108 EXCEPTION("throws Exception"), 109 SQL_EXCEPTION("throws java.sql.SQLException"), 110 IO_EXCEPTION("throws java.io.IOException"); 111 112 String exceptionStr; 113 114 ExceptionKind(String exceptionStr) { 115 this.exceptionStr = exceptionStr; 116 } 117 118 public String expand(String optParameter) { 119 return exceptionStr; 120 } 121 } 122 123 enum LambdaReturnKind implements ComboParameter { 124 VOID("return;"), 125 SHORT("return (short)0;"), 126 INT("return 0;"), 127 INTEGER("return (Integer)null;"), 128 NULL("return null;"); 129 130 String retStr; 131 132 LambdaReturnKind(String retStr) { 133 this.retStr = retStr; 134 } 135 136 boolean compatibleWith(RetTypeKind rk) { 137 return compatibleWith[rk.ordinal()][ordinal()]; 138 } 139 140 static boolean[][] compatibleWith = { 141 // VOID | SHORT | INT | INTEGER | NULL 142 /* SHORT */ { false , true , false , false , false }, 143 /* INT */ { false , true , true , true , false }, 144 /* OBJECT */ { false , true , true , true , true }, 145 /* INTEGER */ { false , false , true , true , true }, 146 /* VOID */ { true , false , false , false , false }, 147 /* J_L_VOID */{ false , false , false , false , true } }; 148 149 boolean needsConversion(RetTypeKind rk) { 150 return needsConversion[rk.ordinal()][ordinal()]; 151 } 152 153 static boolean[][] needsConversion = { 154 // VOID | SHORT | INT | INTEGER | NULL 155 /* SHORT */ { false , false , false , false , false }, 156 /* INT */ { false , false , false , true , false }, 157 /* OBJECT */ { false , true , true , false , false }, 158 /* INTEGER */ { false , false , true , false , false }, 159 /* VOID */ { false , false , false , false , false }, 160 /* J_L_VOID */{ true , false , false , false , false } }; 161 162 public String expand(String optParameter) { 163 return retStr; 164 } 165 } 166 167 static final String sourceTemplate = 168 "interface SAM1 {\n" + 169 " #{RET[0]} m(#{ARG[0]} a1) #{EX[0]};\n" + 170 "}\n" + 171 "interface SAM2 {\n" + 172 " #{RET[1]} m(#{ARG[1]} a1) #{EX[1]};\n" + 173 "}\n" + 174 "class Test {\n" + 175 " void m(SAM1 s) { }\n" + 176 " void m(SAM2 s) { }\n" + 177 " { m((#{ARG[0]} x)->{ #{EXPR} }); }\n" + 178 "}\n"; 179 180 public static void main(String... args) throws Exception { 181 new ComboTestHelper<StructuralMostSpecificTest>() 182 .withFilter(StructuralMostSpecificTest::hasSameArguments) 183 .withFilter(StructuralMostSpecificTest::hasCompatibleReturns) 184 .withFilter(StructuralMostSpecificTest::hasSameOverloadPhase) 185 .withDimension("EXPR", (x, expr) -> x.lambdaReturnKind = expr, LambdaReturnKind.values()) 186 .withArrayDimension("RET", (x, ret, idx) -> x.returnType[idx] = ret, 2, RetTypeKind.values()) 187 .withArrayDimension("EX", 2, ExceptionKind.values()) 188 .withArrayDimension("ARG", (x, arg, idx) -> x.argumentKind[idx] = arg, 2, ArgTypeKind.values()) 189 .run(StructuralMostSpecificTest::new); 190 } 191 192 LambdaReturnKind lambdaReturnKind; 193 RetTypeKind[] returnType = new RetTypeKind[2]; 194 ArgTypeKind[] argumentKind = new ArgTypeKind[2]; 195 196 boolean hasSameArguments() { 197 return argumentKind[0] == argumentKind[1]; 198 } 199 200 boolean hasCompatibleReturns() { 201 return lambdaReturnKind.compatibleWith(returnType[0]) && 202 lambdaReturnKind.compatibleWith(returnType[1]); 203 } 204 205 boolean hasSameOverloadPhase() { 206 return lambdaReturnKind.needsConversion(returnType[0]) == lambdaReturnKind.needsConversion(returnType[1]); 207 } 208 209 @Override 210 public void doWork() throws Throwable { 211 check(newCompilationTask() 212 .withSourceFromTemplate(sourceTemplate) 213 .withOption("-XDverboseResolution=all,-predef,-internal,-object-init") 214 .analyze()); 215 } 216 217 void check(Result<Iterable<? extends Element>> result) { 218 boolean m1MoreSpecific = returnType[0].moreSpecificThan(returnType[1]); 219 boolean m2MoreSpecific = returnType[1].moreSpecificThan(returnType[0]); 220 221 boolean ambiguous = (m1MoreSpecific == m2MoreSpecific); 222 223 if (ambiguous != ambiguityFound(result)) { 224 fail("invalid diagnostics for combo:\n" + 225 result.compilationInfo() + "\n" + 226 "\nAmbiguity found: " + ambiguityFound(result) + 227 "\nm1 more specific: " + m1MoreSpecific + 228 "\nm2 more specific: " + m2MoreSpecific + 229 "\nexpected ambiguity: " + ambiguous); 230 } 231 232 if (!ambiguous) { 233 String sigToCheck = m1MoreSpecific ? "m(SAM1)" : "m(SAM2)"; 234 if (!sigToCheck.equals(mostSpecificSignature(result))) { 235 fail("invalid most specific method selected:\n" + 236 result.compilationInfo() + "\n" + 237 "\nMost specific found: " + mostSpecificSignature(result) + 238 "\nm1 more specific: " + m1MoreSpecific + 239 "\nm2 more specific: " + m2MoreSpecific); 240 } 241 } 242 } 243 244 boolean ambiguityFound(Result<Iterable<? extends Element>> result) { 245 return result.containsKey("compiler.err.ref.ambiguous"); 246 } 247 248 String mostSpecificSignature(Result<Iterable<? extends Element>> result) { 249 List<Diagnostic<? extends JavaFileObject>> rsDiag = 250 result.diagnosticsForKey("compiler.note.verbose.resolve.multi"); 251 if (rsDiag.nonEmpty()) { 252 ClientCodeWrapper.DiagnosticSourceUnwrapper dsu = 253 (ClientCodeWrapper.DiagnosticSourceUnwrapper)rsDiag.head; 254 JCDiagnostic.MultilineDiagnostic mdiag = 255 (JCDiagnostic.MultilineDiagnostic)dsu.d; 256 int mostSpecificIndex = (Integer)mdiag.getArgs()[2]; 257 return mdiag.getSubdiagnostics().get(mostSpecificIndex).getArgs()[1].toString(); 258 } else { 259 return null; 260 } 261 } 262} 263