InterfaceMethodHidingTest.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 8005166 8129962
27 * @summary Add support for static interface methods
28 *          Smoke test for static interface method hiding
29 * @library /tools/javac/lib
30 * @modules jdk.compiler/com.sun.tools.javac.api
31 *          jdk.compiler/com.sun.tools.javac.code
32 *          jdk.compiler/com.sun.tools.javac.comp
33 *          jdk.compiler/com.sun.tools.javac.main
34 *          jdk.compiler/com.sun.tools.javac.tree
35 *          jdk.compiler/com.sun.tools.javac.util
36 * @build combo.ComboTestHelper
37 * @run main InterfaceMethodHidingTest
38 */
39
40import java.io.IOException;
41
42import combo.ComboInstance;
43import combo.ComboParameter;
44import combo.ComboTask.Result;
45import combo.ComboTestHelper;
46
47public class InterfaceMethodHidingTest extends ComboInstance<InterfaceMethodHidingTest> {
48
49    enum SignatureKind implements ComboParameter {
50        VOID_INTEGER("void m(Integer s)", false),
51        STRING_INTEGER("String m(Integer s)", true),
52        VOID_STRING("void m(String s)", false),
53        STRING_STRING("String m(String s)", true);
54
55        String sigStr;
56        boolean needsReturn;
57
58        SignatureKind(String sigStr, boolean needsReturn) {
59            this.sigStr = sigStr;
60            this.needsReturn = needsReturn;
61        }
62
63        boolean overrideEquivalentWith(SignatureKind s2) {
64            switch (this) {
65                case VOID_INTEGER:
66                case STRING_INTEGER:
67                    return s2 == VOID_INTEGER || s2 == STRING_INTEGER;
68                case VOID_STRING:
69                case STRING_STRING:
70                    return s2 == VOID_STRING || s2 == STRING_STRING;
71                default:
72                    throw new AssertionError("bad signature kind");
73            }
74        }
75
76        @Override
77        public String expand(String optParameter) {
78            return sigStr;
79        }
80    }
81
82    enum MethodKind implements ComboParameter {
83        VIRTUAL("#{SIG[#IDX]};"),
84        STATIC("static #{SIG[#IDX]} { #{BODY[#IDX]}; #{RET.#IDX} }"),
85        DEFAULT("default #{SIG[#IDX]} { #{BODY[#IDX]}; #{RET.#IDX} }");
86
87        String methTemplate;
88
89        MethodKind(String methTemplate) {
90            this.methTemplate = methTemplate;
91        }
92
93        boolean inherithed() {
94            return this != STATIC;
95        }
96
97        static boolean overrides(MethodKind mk1, SignatureKind sk1, MethodKind mk2, SignatureKind sk2) {
98            return sk1 == sk2 &&
99                    mk2.inherithed() &&
100                    mk1 != STATIC;
101        }
102
103        @Override
104        public String expand(String optParameter) {
105            return methTemplate.replaceAll("#IDX", optParameter);
106        }
107    }
108
109    enum BodyExpr implements ComboParameter {
110        NONE(""),
111        THIS("Object o = this");
112
113        String bodyExprStr;
114
115        BodyExpr(String bodyExprStr) {
116            this.bodyExprStr = bodyExprStr;
117        }
118
119        boolean allowed(MethodKind mk) {
120            return this == NONE ||
121                    mk != MethodKind.STATIC;
122        }
123
124        @Override
125        public String expand(String optParameter) {
126            return bodyExprStr;
127        }
128    }
129
130    public static void main(String... args) throws Exception {
131        new ComboTestHelper<InterfaceMethodHidingTest>()
132                .withArrayDimension("SIG", (x, sig, idx) -> x.signatureKinds[idx] = sig, 3, SignatureKind.values())
133                .withArrayDimension("BODY", (x, body, idx) -> x.bodyExprs[idx] = body, 3, BodyExpr.values())
134                .withArrayDimension("MET", (x, meth, idx) -> x.methodKinds[idx] = meth, 3, MethodKind.values())
135                .run(InterfaceMethodHidingTest::new);
136    }
137
138    MethodKind[] methodKinds = new MethodKind[3];
139    SignatureKind[] signatureKinds = new SignatureKind[3];
140    BodyExpr[] bodyExprs = new BodyExpr[3];
141
142    String template = "interface Sup {\n" +
143                          "   default void sup() { }\n" +
144                          "}\n" +
145                          "interface A extends Sup {\n" +
146                          "   #{MET[0].0}\n" +
147                          "}\n" +
148                          "interface B extends A, Sup {\n" +
149                          "   #{MET[1].1}\n" +
150                          "}\n" +
151                          "interface C extends B, Sup {\n" +
152                          "   #{MET[2].2}\n" +
153                          "}\n";
154
155    @Override
156    public void doWork() throws IOException {
157        check(newCompilationTask()
158                .withOption("-XDallowStaticInterfaceMethods")
159                .withSourceFromTemplate(template, this::returnExpr)
160                .analyze());
161    }
162
163    ComboParameter returnExpr(String name) {
164        switch (name) {
165            case "RET":
166                return optParameter -> {
167                    int idx = new Integer(optParameter);
168                    return signatureKinds[idx].needsReturn ? "return null;" : "return;";
169                };
170            default:
171                return null;
172        }
173    }
174
175    void check(Result<?> res) {
176        boolean errorExpected = !bodyExprs[0].allowed(methodKinds[0]) ||
177                !bodyExprs[1].allowed(methodKinds[1]) ||
178                !bodyExprs[2].allowed(methodKinds[2]);
179
180        if (methodKinds[0].inherithed()) {
181            errorExpected |= signatureKinds[1].overrideEquivalentWith(signatureKinds[0]) &&
182                    !MethodKind.overrides(methodKinds[1], signatureKinds[1], methodKinds[0], signatureKinds[0]) ||
183                    signatureKinds[2].overrideEquivalentWith(signatureKinds[0]) &&
184                    !MethodKind.overrides(methodKinds[2], signatureKinds[2], methodKinds[0], signatureKinds[0]);
185        }
186
187        if (methodKinds[1].inherithed()) {
188            errorExpected |= signatureKinds[2].overrideEquivalentWith(signatureKinds[1]) &&
189                    !MethodKind.overrides(methodKinds[2], signatureKinds[2], methodKinds[1], signatureKinds[1]);
190        }
191
192        if (res.hasErrors() != errorExpected) {
193            fail("Problem when compiling source:\n" + res.compilationInfo() +
194                    "\nfound error: " + res.hasErrors());
195        }
196    }
197}
198