ClassesTest.java revision 3062:15bdc18525ff
1/*
2 * Copyright (c) 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 * @summary Tests for EvaluationState.classes
27 * @build KullaTesting TestingInputStream ExpectedDiagnostic
28 * @run testng ClassesTest
29 */
30
31import java.util.ArrayList;
32import java.util.List;
33
34import javax.tools.Diagnostic;
35
36import jdk.jshell.Snippet;
37import jdk.jshell.TypeDeclSnippet;
38import jdk.jshell.VarSnippet;
39import org.testng.annotations.DataProvider;
40import org.testng.annotations.Test;
41
42import jdk.jshell.Diag;
43import static jdk.jshell.Snippet.Status.VALID;
44import static jdk.jshell.Snippet.Status.RECOVERABLE_NOT_DEFINED;
45import static jdk.jshell.Snippet.Status.DROPPED;
46import static jdk.jshell.Snippet.Status.REJECTED;
47import static jdk.jshell.Snippet.SubKind.*;
48import static org.testng.Assert.assertEquals;
49import static org.testng.Assert.assertTrue;
50import static jdk.jshell.Snippet.Status.OVERWRITTEN;
51
52@Test
53public class ClassesTest extends KullaTesting {
54
55    public void noClasses() {
56        assertNumberOfActiveClasses(0);
57    }
58
59    public void testSignature1() {
60        TypeDeclSnippet c1 = classKey(assertEval("class A extends B {}", added(RECOVERABLE_NOT_DEFINED)));
61        assertTypeDeclSnippet(c1, "A", RECOVERABLE_NOT_DEFINED, CLASS_SUBKIND, 1, 0);
62        TypeDeclSnippet c2 = classKey(assertEval("@interface A { Class<B> f() default B.class; }",
63                ste(MAIN_SNIPPET, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, null),
64                ste(c1, RECOVERABLE_NOT_DEFINED, OVERWRITTEN, false, MAIN_SNIPPET)));
65        assertTypeDeclSnippet(c2, "A", RECOVERABLE_NOT_DEFINED, ANNOTATION_TYPE_SUBKIND, 1, 0);
66        TypeDeclSnippet c3 = classKey(assertEval("enum A {; private A(B b) {} }",
67                ste(MAIN_SNIPPET, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, null),
68                ste(c2, RECOVERABLE_NOT_DEFINED, OVERWRITTEN, false, MAIN_SNIPPET)));
69        assertTypeDeclSnippet(c3, "A", RECOVERABLE_NOT_DEFINED, ENUM_SUBKIND, 1, 0);
70        TypeDeclSnippet c4 = classKey(assertEval("interface A extends B {}",
71                ste(MAIN_SNIPPET, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, null),
72                ste(c3, RECOVERABLE_NOT_DEFINED, OVERWRITTEN, false, MAIN_SNIPPET)));
73        assertTypeDeclSnippet(c4, "A", RECOVERABLE_NOT_DEFINED, INTERFACE_SUBKIND, 1, 0);
74        TypeDeclSnippet c5 = classKey(assertEval("class A { void f(B b) {} }",
75                ste(MAIN_SNIPPET, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, null),
76                ste(c4, RECOVERABLE_NOT_DEFINED, OVERWRITTEN, false, MAIN_SNIPPET)));
77        assertTypeDeclSnippet(c5, "A", RECOVERABLE_NOT_DEFINED, CLASS_SUBKIND, 1, 0);
78    }
79
80    public void testSignature2() {
81        TypeDeclSnippet c1 = (TypeDeclSnippet) assertDeclareFail("class A { void f() { return g(); } }", "compiler.err.prob.found.req");
82        assertTypeDeclSnippet(c1, "A", REJECTED, CLASS_SUBKIND, 0, 2);
83        TypeDeclSnippet c2 = classKey(assertEval("class A { int f() { return g(); } }",
84                ste(c1, REJECTED, RECOVERABLE_NOT_DEFINED, false, null)));
85        assertTypeDeclSnippet(c2, "A", RECOVERABLE_NOT_DEFINED, CLASS_SUBKIND, 1, 0);
86        assertDrop(c2,
87                ste(c2, RECOVERABLE_NOT_DEFINED, DROPPED, false, null));
88    }
89
90    public void classDeclaration() {
91        assertEval("class A { }");
92        assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"));
93    }
94
95
96    public void interfaceDeclaration() {
97        assertEval("interface A { }");
98        assertClasses(clazz(KullaTesting.ClassType.INTERFACE, "A"));
99    }
100
101    public void annotationDeclaration() {
102        assertEval("@interface A { }");
103        assertClasses(clazz(KullaTesting.ClassType.ANNOTATION, "A"));
104    }
105
106    public void enumDeclaration() {
107        assertEval("enum A { }");
108        assertClasses(clazz(KullaTesting.ClassType.ENUM, "A"));
109    }
110
111    public void classesDeclaration() {
112        assertEval("interface A { }");
113        assertEval("class B implements A { }");
114        assertEval("interface C extends A { }");
115        assertEval("enum D implements C { }");
116        assertEval("@interface E { }");
117        assertClasses(
118                clazz(KullaTesting.ClassType.INTERFACE, "A"),
119                clazz(KullaTesting.ClassType.CLASS, "B"),
120                clazz(KullaTesting.ClassType.INTERFACE, "C"),
121                clazz(KullaTesting.ClassType.ENUM, "D"),
122                clazz(KullaTesting.ClassType.ANNOTATION, "E"));
123        assertActiveKeys();
124    }
125
126    public void classesRedeclaration1() {
127        Snippet a = classKey(assertEval("class A { }"));
128        Snippet b = classKey(assertEval("interface B { }"));
129        assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"), clazz(KullaTesting.ClassType.INTERFACE, "B"));
130        assertActiveKeys();
131
132        assertEval("interface A { }",
133                ste(MAIN_SNIPPET, VALID, VALID, true, null),
134                ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
135        assertClasses(clazz(KullaTesting.ClassType.INTERFACE, "A"),
136                clazz(KullaTesting.ClassType.INTERFACE, "B"));
137        assertActiveKeys();
138
139        assertEval("interface B { } //again",
140                ste(MAIN_SNIPPET, VALID, VALID, false, null),
141                ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
142        assertClasses(clazz(KullaTesting.ClassType.INTERFACE, "A"),
143                clazz(KullaTesting.ClassType.INTERFACE, "B"));
144        assertActiveKeys();
145    }
146
147    public void classesRedeclaration2() {
148        assertEval("class A { }");
149        assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"));
150        assertActiveKeys();
151
152        Snippet b = classKey(assertEval("class B extends A { }"));
153        assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"),
154                clazz(KullaTesting.ClassType.CLASS, "B"));
155        assertActiveKeys();
156
157        Snippet c = classKey(assertEval("class C extends B { }"));
158        assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"),
159                clazz(KullaTesting.ClassType.CLASS, "B"), clazz(KullaTesting.ClassType.CLASS, "C"));
160        assertActiveKeys();
161
162        assertEval("interface B { }",
163                DiagCheck.DIAG_OK,
164                DiagCheck.DIAG_ERROR,
165                ste(MAIN_SNIPPET, VALID, VALID, true, null),
166                ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
167                ste(c, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET));
168        assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"),
169                clazz(KullaTesting.ClassType.INTERFACE, "B"), clazz(KullaTesting.ClassType.CLASS, "C"));
170        assertEval("new C();",
171                DiagCheck.DIAG_ERROR,
172                DiagCheck.DIAG_ERROR,
173                added(REJECTED));
174        assertActiveKeys();
175    }
176
177    public void classesCyclic1() {
178        Snippet b = classKey(assertEval("class B extends A { }",
179                added(RECOVERABLE_NOT_DEFINED)));
180        Snippet a = classKey(assertEval("class A extends B { }", DiagCheck.DIAG_IGNORE, DiagCheck.DIAG_IGNORE,
181                added(RECOVERABLE_NOT_DEFINED),
182                ste(b, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, MAIN_SNIPPET)));
183        /***
184        assertDeclareFail("class A extends B { }", "****",
185                added(REJECTED),
186                ste(b, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, MAIN_SNIPPET));
187        ***/
188        // It is random which one it shows up in, but cyclic error should be there
189        List<Diag> diagsA = getState().diagnostics(a);
190        List<Diag> diagsB = getState().diagnostics(b);
191        List<Diag> diags;
192        if (diagsA.isEmpty()) {
193            diags = diagsB;
194        } else {
195            diags = diagsA;
196            assertTrue(diagsB.isEmpty());
197        }
198        assertEquals(diags.size(), 1, "Expected one error");
199        assertEquals(diags.get(0).getCode(), "compiler.err.cyclic.inheritance", "Expected cyclic inheritance error");
200        assertActiveKeys();
201    }
202
203    public void classesCyclic2() {
204        Snippet d = classKey(assertEval("class D extends E { }", added(RECOVERABLE_NOT_DEFINED)));
205        assertEval("class E { D d; }",
206                added(VALID),
207                ste(d, RECOVERABLE_NOT_DEFINED, VALID, true, MAIN_SNIPPET));
208        assertActiveKeys();
209    }
210
211    public void classesCyclic3() {
212        Snippet outer = classKey(assertEval("class Outer { class Inner extends Foo { } }",
213                added(RECOVERABLE_NOT_DEFINED)));
214        Snippet foo = classKey(assertEval("class Foo { } ",
215                added(VALID),
216                ste(outer, RECOVERABLE_NOT_DEFINED, VALID, true, MAIN_SNIPPET)));
217        assertEval(" class Foo extends Outer { }",
218                ste(MAIN_SNIPPET, VALID, VALID, true, null),
219                ste(foo, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
220                ste(outer, VALID, VALID, true, MAIN_SNIPPET));
221        assertActiveKeys();
222    }
223
224    public void classesIgnoredModifiers() {
225        assertDeclareWarn1("public interface A { }",
226                new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 6, 0, -1, -1, Diagnostic.Kind.WARNING));
227        assertDeclareWarn1("static class B implements A { }",
228                new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 6, 0, -1, -1, Diagnostic.Kind.WARNING));
229        assertDeclareWarn1("final interface C extends A { }",
230                new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 5, 0, -1, -1, Diagnostic.Kind.WARNING));
231        assertDeclareWarn1("protected enum D implements C { }",
232                new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 9, 0, -1, -1, Diagnostic.Kind.WARNING));
233        assertActiveKeys();
234    }
235
236    public void ignoreModifierSpaceIssue() {
237        assertEval("interface I { void f(); } ");
238        // there should not be a space between 'I' and '{' to reproduce the failure
239        assertEval("class C implements I{ public void f() {}}");
240        assertClasses(clazz(KullaTesting.ClassType.CLASS, "C"), clazz(KullaTesting.ClassType.INTERFACE, "I"));
241        assertActiveKeys();
242    }
243
244    @DataProvider(name = "innerClasses")
245    public Object[][] innerClasses() {
246        List<Object[]> list = new ArrayList<>();
247        for (ClassType outerClassType : ClassType.values()) {
248            for (ClassType innerClassType : ClassType.values()) {
249                list.add(new Object[]{outerClassType, innerClassType});
250            }
251        }
252        return list.toArray(new Object[list.size()][]);
253    }
254
255    @Test(dataProvider = "innerClasses")
256    public void innerClasses(ClassType outerClassType, ClassType innerClassType) {
257        String source =
258                outerClassType + " A {" + (outerClassType == ClassType.ENUM ? ";" : "") +
259                innerClassType + " B { }" +
260                "}";
261        assertEval(source);
262        assertNumberOfActiveClasses(1);
263        assertActiveKeys();
264    }
265
266    public void testInnerClassesCrash() {
267        Snippet a = classKey(assertEval("class A { class B extends A {} }"));
268        Snippet a2 = classKey(assertEval("class A { interface I1 extends I2 {} interface I2 {} }",
269                ste(MAIN_SNIPPET, VALID, VALID, false, null),
270                ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
271        assertEval("class A { A a = new A() {}; }",
272                ste(MAIN_SNIPPET, VALID, VALID, true, null),
273                ste(a2, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
274    }
275
276    public void testInnerClassesCrash1() {
277        assertEval("class A { class B extends A {} B getB() { return new B();} }");
278        assertEquals(varKey(assertEval("A a = new A();")).name(), "a");
279        VarSnippet variableKey = varKey(assertEval("a.getB();"));
280        assertEquals(variableKey.typeName(), "A.B");
281    }
282
283    public void testInnerClassesCrash2() {
284        assertEval("class A { interface I1 extends I2 {} interface I2 {} I1 x; }");
285        assertEquals(varKey(assertEval("A a = new A();")).name(), "a");
286        VarSnippet variableKey = varKey(assertEval("a.x;"));
287        assertEquals(variableKey.typeName(), "A.I1");
288    }
289}
290