FunctionalInterfaceConversionTest.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 8004102 8006694 8129962
27 * @summary Add lambda tests
28 *  perform several automated checks in lambda conversion, esp. around accessibility
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 * @run main FunctionalInterfaceConversionTest
39 */
40
41import java.io.IOException;
42
43import combo.ComboInstance;
44import combo.ComboParameter;
45import combo.ComboTask.Result;
46import combo.ComboTestHelper;
47
48
49public class FunctionalInterfaceConversionTest extends ComboInstance<FunctionalInterfaceConversionTest> {
50
51    enum PackageKind implements ComboParameter {
52        NO_PKG(""),
53        PKG_A("a");
54
55        String pkg;
56
57        PackageKind(String pkg) {
58            this.pkg = pkg;
59        }
60
61        @Override
62        public String expand(String optParameter) {
63            return this == NO_PKG ?
64                "" :
65                "package " + pkg + ";";
66        }
67
68        String getImportStat() {
69            return this == NO_PKG ?
70                "" :
71                "import " + pkg + ".*;";
72        }
73    }
74
75    enum SamKind implements ComboParameter {
76        CLASS("public class Sam {  }"),
77        ABSTACT_CLASS("public abstract class Sam {  }"),
78        ANNOTATION("public @interface Sam {  }"),
79        ENUM("public enum Sam { }"),
80        INTERFACE("public interface Sam { \n #{METH1}; \n }");
81
82        String sam_str;
83
84        SamKind(String sam_str) {
85            this.sam_str = sam_str;
86        }
87
88        @Override
89        public String expand(String optParameter) {
90            return sam_str;
91        }
92    }
93
94    enum ModifierKind implements ComboParameter {
95        PUBLIC("public"),
96        PACKAGE("");
97
98        String modifier_str;
99
100        ModifierKind(String modifier_str) {
101            this.modifier_str = modifier_str;
102        }
103
104        @Override
105        public String expand(String optParameter) {
106            return modifier_str;
107        }
108    }
109
110    enum TypeKind implements ComboParameter {
111        EXCEPTION("Exception"),
112        PKG_CLASS("PackageClass");
113
114        String typeStr;
115
116        TypeKind(String typeStr) {
117            this.typeStr = typeStr;
118        }
119
120        @Override
121        public String expand(String optParameter) {
122            return typeStr;
123        }
124    }
125
126    enum ExprKind implements ComboParameter {
127        LAMBDA("x -> null"),
128        MREF("this::m");
129
130        String exprStr;
131
132        ExprKind(String exprStr) {
133            this.exprStr = exprStr;
134        }
135
136        @Override
137        public String expand(String optParameter) {
138            return exprStr;
139        }
140    }
141
142    enum MethodKind implements ComboParameter {
143        NONE(""),
144        NON_GENERIC("public abstract #{RET} m(#{ARG} s) throws #{THROWN};"),
145        GENERIC("public abstract <X> #{RET} m(#{ARG} s) throws #{THROWN};");
146
147        String methodTemplate;
148
149        MethodKind(String methodTemplate) {
150            this.methodTemplate = methodTemplate;
151        }
152
153        @Override
154        public String expand(String optParameter) {
155            return methodTemplate;
156        }
157    }
158
159    public static void main(String[] args) throws Exception {
160        new ComboTestHelper<FunctionalInterfaceConversionTest>()
161                .withDimension("PKG", (x, pkg) -> x.samPkg = pkg, PackageKind.values())
162                .withDimension("MOD", (x, mod) -> x.modKind = mod, ModifierKind.values())
163                .withDimension("CLAZZ", (x, sam) -> x.samKind = sam, SamKind.values())
164                .withDimension("METH1", (x, meth) -> x.samMeth = meth, MethodKind.values())
165                .withDimension("METH2", (x, meth) -> x.clientMeth = meth, MethodKind.values())
166                .withDimension("RET", (x, ret) -> x.retType = ret, TypeKind.values())
167                .withDimension("ARG", (x, arg) -> x.argType = arg, TypeKind.values())
168                .withDimension("THROWN", (x, thrown) -> x.thrownType = thrown, TypeKind.values())
169                .withDimension("EXPR", (x, expr) -> x.exprKind = expr, ExprKind.values())
170                .run(FunctionalInterfaceConversionTest::new);
171    }
172
173    PackageKind samPkg;
174    ModifierKind modKind;
175    SamKind samKind;
176    MethodKind samMeth;
177    MethodKind clientMeth;
178    TypeKind retType;
179    TypeKind argType;
180    TypeKind thrownType;
181    ExprKind exprKind;
182
183    String samSource = "#{PKG} \n #{CLAZZ}";
184    String pkgClassSource = "#{PKG}\n #{MOD} class PackageClass extends Exception { }";
185    String clientSource = "#{IMP}\n abstract class Client { \n" +
186                           "  Sam s = #{EXPR};\n" +
187                           "  #{METH2} \n }";
188
189    @Override
190    public void doWork() throws IOException {
191        check(newCompilationTask()
192                .withSourceFromTemplate("Sam", samSource)
193                .withSourceFromTemplate("PackageClass", pkgClassSource)
194                .withSourceFromTemplate("Client", clientSource, this::importStmt)
195                .analyze());
196    }
197
198    ComboParameter importStmt(String name) {
199        switch (name) {
200            case "IMP": return new ComboParameter.Constant<>(samPkg.getImportStat());
201            default: return null;
202        }
203    }
204
205    void check(Result<?> res) {
206        if (res.hasErrors() == checkSamConversion()) {
207            fail("Unexpected compilation result; " + res.compilationInfo());
208        }
209    }
210
211    boolean checkSamConversion() {
212        if (samKind != SamKind.INTERFACE) {
213            //sam type must be an interface
214            return false;
215        } else if (samMeth == MethodKind.NONE) {
216            //interface must have at least a method
217            return false;
218        } else if (exprKind == ExprKind.LAMBDA &&
219                samMeth != MethodKind.NON_GENERIC) {
220            //target method for lambda must be non-generic
221            return false;
222        } else if (exprKind == ExprKind.MREF &&
223                clientMeth == MethodKind.NONE) {
224            return false;
225        } else if (samPkg != PackageKind.NO_PKG &&
226                modKind != ModifierKind.PUBLIC &&
227                (retType == TypeKind.PKG_CLASS ||
228                argType == TypeKind.PKG_CLASS ||
229                thrownType == TypeKind.PKG_CLASS)) {
230            //target must not contain inaccessible types
231            return false;
232        } else {
233            return true;
234        }
235    }
236}
237