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