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