1 /* 2 * Copyright (c) 2015, 2018, 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 8145239 8129559 8080354 8189248 8010319 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 jdk.jshell.Snippet.Status; 45 import static java.util.stream.Collectors.toList; 46 import static jdk.jshell.Snippet.Status.VALID; 47 import static jdk.jshell.Snippet.Status.RECOVERABLE_NOT_DEFINED; 48 import static jdk.jshell.Snippet.Status.RECOVERABLE_DEFINED; 49 import static jdk.jshell.Snippet.Status.DROPPED; 50 import static jdk.jshell.Snippet.Status.REJECTED; 51 import static jdk.jshell.Snippet.Status.OVERWRITTEN; 52 import static jdk.jshell.Snippet.Status.NONEXISTENT; 53 import static jdk.jshell.Snippet.SubKind.*; 54 import static org.testng.Assert.assertEquals; 55 import static org.testng.Assert.assertTrue; 56 57 @Test 58 public class ClassesTest extends KullaTesting { 59 60 public void noClasses() { 61 assertNumberOfActiveClasses(0); 62 } 63 64 public void testSignature1() { 65 TypeDeclSnippet c1 = classKey(assertEval("class A extends B {}", added(RECOVERABLE_NOT_DEFINED))); 66 assertTypeDeclSnippet(c1, "A", RECOVERABLE_NOT_DEFINED, CLASS_SUBKIND, 1, 0); 67 TypeDeclSnippet c2 = classKey(assertEval("@interface A { Class<B> f() default B.class; }", 68 ste(MAIN_SNIPPET, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, null), 69 ste(c1, RECOVERABLE_NOT_DEFINED, OVERWRITTEN, false, MAIN_SNIPPET))); 70 assertTypeDeclSnippet(c2, "A", RECOVERABLE_NOT_DEFINED, ANNOTATION_TYPE_SUBKIND, 1, 0); 71 TypeDeclSnippet c3 = classKey(assertEval("enum A {; private A(B b) {} }", 72 ste(MAIN_SNIPPET, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, null), 73 ste(c2, RECOVERABLE_NOT_DEFINED, OVERWRITTEN, false, MAIN_SNIPPET))); 74 assertTypeDeclSnippet(c3, "A", RECOVERABLE_NOT_DEFINED, ENUM_SUBKIND, 1, 0); 75 TypeDeclSnippet c4 = classKey(assertEval("interface A extends B {}", 76 ste(MAIN_SNIPPET, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, null), 77 ste(c3, RECOVERABLE_NOT_DEFINED, OVERWRITTEN, false, MAIN_SNIPPET))); 78 assertTypeDeclSnippet(c4, "A", RECOVERABLE_NOT_DEFINED, INTERFACE_SUBKIND, 1, 0); 79 TypeDeclSnippet c5 = classKey(assertEval("class A { void f(B b) {} }", 80 ste(MAIN_SNIPPET, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, null), 81 ste(c4, RECOVERABLE_NOT_DEFINED, OVERWRITTEN, false, MAIN_SNIPPET))); 82 assertTypeDeclSnippet(c5, "A", RECOVERABLE_NOT_DEFINED, CLASS_SUBKIND, 1, 0); 83 } 84 85 public void testSignature2() { 86 TypeDeclSnippet c1 = (TypeDeclSnippet) assertDeclareFail("class A { void f() { return g(); } }", "compiler.err.prob.found.req"); 87 assertTypeDeclSnippet(c1, "A", REJECTED, CLASS_SUBKIND, 0, 2); 88 TypeDeclSnippet c2 = classKey(assertEval("class A { int f() { return g(); } }", 89 ste(c1, NONEXISTENT, RECOVERABLE_DEFINED, true, null))); 90 assertTypeDeclSnippet(c2, "A", RECOVERABLE_DEFINED, CLASS_SUBKIND, 1, 0); 91 assertDrop(c2, 92 ste(c2, RECOVERABLE_DEFINED, DROPPED, true, null)); 93 } 94 95 public void classDeclaration() { 96 assertEval("class A { }"); 97 assertClasses(clazz(KullaTesting.ClassType.CLASS, "A")); 98 } 99 100 101 public void interfaceDeclaration() { 102 assertEval("interface A { }"); 103 assertClasses(clazz(KullaTesting.ClassType.INTERFACE, "A")); 104 } 105 106 public void annotationDeclaration() { 107 assertEval("@interface A { }"); 108 assertClasses(clazz(KullaTesting.ClassType.ANNOTATION, "A")); 109 } 110 111 public void enumDeclaration() { 112 assertEval("enum A { }"); 113 assertClasses(clazz(KullaTesting.ClassType.ENUM, "A")); 114 } 115 116 public void classesDeclaration() { 117 assertEval("interface A { }"); 118 assertEval("class B implements A { }"); 119 assertEval("interface C extends A { }"); 120 assertEval("enum D implements C { }"); 121 assertEval("@interface E { }"); 122 assertClasses( 123 clazz(KullaTesting.ClassType.INTERFACE, "A"), 124 clazz(KullaTesting.ClassType.CLASS, "B"), 125 clazz(KullaTesting.ClassType.INTERFACE, "C"), 126 clazz(KullaTesting.ClassType.ENUM, "D"), 127 clazz(KullaTesting.ClassType.ANNOTATION, "E")); 128 assertActiveKeys(); 129 } 130 131 public void classesRedeclaration1() { 132 Snippet a = classKey(assertEval("class A { }")); 133 Snippet b = classKey(assertEval("interface B { }")); 134 assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"), clazz(KullaTesting.ClassType.INTERFACE, "B")); 135 assertActiveKeys(); 136 137 assertEval("interface A { }", 138 ste(MAIN_SNIPPET, VALID, VALID, true, null), 139 ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); 140 assertClasses(clazz(KullaTesting.ClassType.INTERFACE, "A"), 141 clazz(KullaTesting.ClassType.INTERFACE, "B")); 142 assertActiveKeys(); 143 144 assertEval("interface B { } //again", 145 ste(MAIN_SNIPPET, VALID, VALID, false, null), 146 ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); 147 assertClasses(clazz(KullaTesting.ClassType.INTERFACE, "A"), 148 clazz(KullaTesting.ClassType.INTERFACE, "B")); 149 assertActiveKeys(); 150 } 151 152 public void classesRedeclaration2() { 153 assertEval("class A { }"); 154 assertClasses(clazz(KullaTesting.ClassType.CLASS, "A")); 155 assertActiveKeys(); 156 157 Snippet b = classKey(assertEval("class B extends A { }")); 158 assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"), 159 clazz(KullaTesting.ClassType.CLASS, "B")); 160 assertActiveKeys(); 161 162 Snippet c = classKey(assertEval("class C extends B { }")); 163 assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"), 164 clazz(KullaTesting.ClassType.CLASS, "B"), clazz(KullaTesting.ClassType.CLASS, "C")); 165 assertActiveKeys(); 166 167 assertEval("interface B { }", 168 DiagCheck.DIAG_OK, 169 DiagCheck.DIAG_ERROR, 170 ste(MAIN_SNIPPET, VALID, VALID, true, null), 171 ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET), 172 ste(c, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET)); 173 assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"), 174 clazz(KullaTesting.ClassType.INTERFACE, "B"), clazz(KullaTesting.ClassType.CLASS, "C")); 175 assertEval("new C();", 176 DiagCheck.DIAG_ERROR, 177 DiagCheck.DIAG_ERROR, 178 added(REJECTED)); 179 assertActiveKeys(); 180 } 181 182 //8154496: test3 update: sig change should false 183 public void classesRedeclaration3() { 184 Snippet a = classKey(assertEval("class A { }")); 185 assertClasses(clazz(KullaTesting.ClassType.CLASS, "A")); 186 assertActiveKeys(); 187 188 Snippet test1 = methodKey(assertEval("A test() { return null; }")); 189 Snippet test2 = methodKey(assertEval("void test(A a) { }")); 190 Snippet test3 = methodKey(assertEval("void test(int n) {A a;}")); 191 assertActiveKeys(); 192 193 assertEval("interface A { }", 194 ste(MAIN_SNIPPET, VALID, VALID, true, null), 195 ste(test1, VALID, VALID, true, MAIN_SNIPPET), 196 ste(test2, VALID, VALID, true, MAIN_SNIPPET), 197 ste(test3, VALID, VALID, true, MAIN_SNIPPET), 198 ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); 199 assertClasses(clazz(KullaTesting.ClassType.INTERFACE, "A")); 200 assertMethods(method("()A", "test"), method("(A)void", "test"), method("(int)void", "test")); 201 assertActiveKeys(); 202 } 203 204 public void classesCyclic1() { 205 Snippet b = classKey(assertEval("class B extends A { }", 206 added(RECOVERABLE_NOT_DEFINED))); 207 Snippet a = classKey(assertEval("class A extends B { }", DiagCheck.DIAG_IGNORE, DiagCheck.DIAG_IGNORE, 208 added(REJECTED))); 209 /*** 210 assertDeclareFail("class A extends B { }", "****", 211 added(REJECTED), 212 ste(b, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, MAIN_SNIPPET)); 213 ***/ 214 // It is random which one it shows up in, but cyclic error should be there 215 List<Diag> diagsA = getState().diagnostics(a).collect(toList()); 216 List<Diag> diagsB = getState().diagnostics(b).collect(toList()); 217 List<Diag> diags; 218 if (diagsA.isEmpty()) { 219 diags = diagsB; 220 } else { 221 diags = diagsA; 222 assertTrue(diagsB.isEmpty()); 223 } 224 assertEquals(diags.size(), 1, "Expected one error"); 225 assertEquals(diags.get(0).getCode(), "compiler.err.cyclic.inheritance", "Expected cyclic inheritance error"); 226 assertActiveKeys(); 227 } 228 229 public void classesCyclic2() { 230 Snippet d = classKey(assertEval("class D extends E { }", added(RECOVERABLE_NOT_DEFINED))); 231 assertEval("class E { D d; }", 232 added(VALID), 233 ste(d, RECOVERABLE_NOT_DEFINED, VALID, true, MAIN_SNIPPET)); 234 assertActiveKeys(); 235 } 236 237 public void classesCyclic3() { 238 Snippet outer = classKey(assertEval("class Outer { class Inner extends Foo { } }", 239 added(RECOVERABLE_NOT_DEFINED))); 240 Snippet foo = classKey(assertEval("class Foo { } ", 241 added(VALID), 242 ste(outer, RECOVERABLE_NOT_DEFINED, VALID, true, MAIN_SNIPPET))); 243 assertEval(" class Foo extends Outer { }", 244 ste(MAIN_SNIPPET, VALID, VALID, true, null), 245 ste(foo, VALID, OVERWRITTEN, false, MAIN_SNIPPET), 246 ste(outer, VALID, VALID, true, MAIN_SNIPPET)); 247 assertActiveKeys(); 248 } 249 250 public void classesIgnoredModifiers() { 251 assertEval("public interface A { }"); 252 assertDeclareWarn1("static class B implements A { }", 253 new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 6, 0, -1, -1, Diagnostic.Kind.WARNING)); 254 assertDeclareWarn1("final interface C extends A { }", 255 new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 5, 0, -1, -1, Diagnostic.Kind.WARNING)); 256 assertActiveKeys(); 257 } 258 259 public void classesIgnoredModifiersAnnotation() { 260 assertEval("public @interface X { }"); 261 assertEval("@X public interface A { }"); 262 assertDeclareWarn1("@X static class B implements A { }", 263 new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 9, 0, -1, -1, Diagnostic.Kind.WARNING)); 264 assertDeclareWarn1("@X final interface C extends A { }", 265 new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 8, 0, -1, -1, Diagnostic.Kind.WARNING)); 266 assertActiveKeys(); 267 } 268 269 public void classesIgnoredModifiersOtherModifiers() { 270 assertEval("strictfp public interface A { }"); 271 assertDeclareWarn1("strictfp static class B implements A { }", 272 new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 15, 0, -1, -1, Diagnostic.Kind.WARNING)); 273 assertDeclareWarn1("strictfp final interface C extends A { }", 274 new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 14, 0, -1, -1, Diagnostic.Kind.WARNING)); 275 assertActiveKeys(); 276 } 277 278 public void ignoreModifierSpaceIssue() { 279 assertEval("interface I { void f(); } "); 280 // there should not be a space between 'I' and '{' to reproduce the failure 281 assertEval("class C implements I{ public void f() {}}"); 282 assertClasses(clazz(KullaTesting.ClassType.CLASS, "C"), clazz(KullaTesting.ClassType.INTERFACE, "I")); 283 assertActiveKeys(); 284 } 285 286 @DataProvider(name = "innerClasses") 287 public Object[][] innerClasses() { 288 List<Object[]> list = new ArrayList<>(); 289 for (ClassType outerClassType : ClassType.values()) { 290 for (ClassType innerClassType : ClassType.values()) { 291 list.add(new Object[]{outerClassType, innerClassType}); 292 } 293 } 294 return list.toArray(new Object[list.size()][]); 295 } 296 297 @Test(dataProvider = "innerClasses") 298 public void innerClasses(ClassType outerClassType, ClassType innerClassType) { 299 String source = 300 outerClassType + " A {" + (outerClassType == ClassType.ENUM ? ";" : "") + 301 innerClassType + " B { }" + 302 "}"; 303 assertEval(source); 304 assertNumberOfActiveClasses(1); 305 assertActiveKeys(); 306 } 307 308 public void testInnerClassesCrash() { 309 Snippet a = classKey(assertEval("class A { class B extends A {} }")); 310 Snippet a2 = classKey(assertEval("class A { interface I1 extends I2 {} interface I2 {} }", 311 ste(MAIN_SNIPPET, VALID, VALID, true, null), 312 ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET))); 313 assertEval("class A { A a = new A() {}; }", 314 ste(MAIN_SNIPPET, VALID, VALID, true, null), 315 ste(a2, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); 316 } 317 318 public void testInnerClassesCrash1() { 319 assertEval("class A { class B extends A {} B getB() { return new B();} }"); 320 assertEquals(varKey(assertEval("A a = new A();")).name(), "a"); 321 VarSnippet variableKey = varKey(assertEval("a.getB();")); 322 assertEquals(variableKey.typeName(), "A.B"); 323 } 324 325 public void testInnerClassesCrash2() { 326 assertEval("class A { interface I1 extends I2 {} interface I2 {} I1 x; }"); 327 assertEquals(varKey(assertEval("A a = new A();")).name(), "a"); 328 VarSnippet variableKey = varKey(assertEval("a.x;")); 329 assertEquals(variableKey.typeName(), "A.I1"); 330 } 331 332 public void testCircular() { 333 assertEval("import java.util.function.Supplier;"); 334 TypeDeclSnippet aClass = 335 classKey(assertEval("public class A<T> {\n" + 336 " private class SomeClass {}\n" + 337 " public Supplier<T> m() {\n" + 338 " return new B<>(this);\n" + 339 " }\n" + 340 "}", 341 added(RECOVERABLE_DEFINED))); 342 assertEval("public class B<T> implements Supplier<T> {\n" + 343 " public B(A<T> a) {}\n" + 344 " public T get() {return null;}\n" + 345 "}", 346 added(VALID), 347 ste(aClass, Status.RECOVERABLE_DEFINED, Status.VALID, true, null)); 348 assertEval("new A()"); 349 } 350 351 }