Path: blob/master/test/langtools/jdk/jshell/ClassesTest.java
40931 views
/*1* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 8145239 8129559 8080354 8189248 8010319 8246353 824745626* @summary Tests for EvaluationState.classes27* @build KullaTesting TestingInputStream ExpectedDiagnostic28* @run testng ClassesTest29*/3031import java.util.ArrayList;32import java.util.List;3334import javax.tools.Diagnostic;3536import jdk.jshell.Snippet;37import jdk.jshell.TypeDeclSnippet;38import jdk.jshell.VarSnippet;39import org.testng.annotations.DataProvider;40import org.testng.annotations.Test;4142import jdk.jshell.Diag;43import jdk.jshell.Snippet.Status;44import static java.util.stream.Collectors.toList;45import static jdk.jshell.Snippet.Status.VALID;46import static jdk.jshell.Snippet.Status.RECOVERABLE_NOT_DEFINED;47import static jdk.jshell.Snippet.Status.RECOVERABLE_DEFINED;48import static jdk.jshell.Snippet.Status.DROPPED;49import static jdk.jshell.Snippet.Status.REJECTED;50import static jdk.jshell.Snippet.Status.OVERWRITTEN;51import static jdk.jshell.Snippet.Status.NONEXISTENT;52import static jdk.jshell.Snippet.SubKind.*;53import static org.testng.Assert.assertEquals;54import static org.testng.Assert.assertTrue;5556@Test57public class ClassesTest extends KullaTesting {5859public void noClasses() {60assertNumberOfActiveClasses(0);61}6263public void testSignature1() {64TypeDeclSnippet c1 = classKey(assertEval("class A extends B {}", added(RECOVERABLE_NOT_DEFINED)));65assertTypeDeclSnippet(c1, "A", RECOVERABLE_NOT_DEFINED, CLASS_SUBKIND, 1, 0);66TypeDeclSnippet c2 = classKey(assertEval("@interface A { Class<B> f() default B.class; }",67ste(MAIN_SNIPPET, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, null),68ste(c1, RECOVERABLE_NOT_DEFINED, OVERWRITTEN, false, MAIN_SNIPPET)));69assertTypeDeclSnippet(c2, "A", RECOVERABLE_NOT_DEFINED, ANNOTATION_TYPE_SUBKIND, 1, 0);70TypeDeclSnippet c3 = classKey(assertEval("enum A {; private A(B b) {} }",71ste(MAIN_SNIPPET, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, null),72ste(c2, RECOVERABLE_NOT_DEFINED, OVERWRITTEN, false, MAIN_SNIPPET)));73assertTypeDeclSnippet(c3, "A", RECOVERABLE_NOT_DEFINED, ENUM_SUBKIND, 1, 0);74TypeDeclSnippet c4 = classKey(assertEval("interface A extends B {}",75ste(MAIN_SNIPPET, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, null),76ste(c3, RECOVERABLE_NOT_DEFINED, OVERWRITTEN, false, MAIN_SNIPPET)));77assertTypeDeclSnippet(c4, "A", RECOVERABLE_NOT_DEFINED, INTERFACE_SUBKIND, 1, 0);78TypeDeclSnippet c5 = classKey(assertEval("class A { void f(B b) {} }",79ste(MAIN_SNIPPET, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, null),80ste(c4, RECOVERABLE_NOT_DEFINED, OVERWRITTEN, false, MAIN_SNIPPET)));81assertTypeDeclSnippet(c5, "A", RECOVERABLE_NOT_DEFINED, CLASS_SUBKIND, 1, 0);82}8384public void testSignature2() {85TypeDeclSnippet c1 = (TypeDeclSnippet) assertDeclareFail("class A { void f() { return g(); } }", "compiler.err.prob.found.req");86assertTypeDeclSnippet(c1, "A", REJECTED, CLASS_SUBKIND, 0, 2);87TypeDeclSnippet c2 = classKey(assertEval("class A { int f() { return g(); } }",88ste(c1, NONEXISTENT, RECOVERABLE_DEFINED, true, null)));89assertTypeDeclSnippet(c2, "A", RECOVERABLE_DEFINED, CLASS_SUBKIND, 1, 0);90assertDrop(c2,91ste(c2, RECOVERABLE_DEFINED, DROPPED, true, null));92}9394public void classDeclaration() {95assertEval("class A { }");96assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"));97}9899100public void interfaceDeclaration() {101assertEval("interface A { }");102assertClasses(clazz(KullaTesting.ClassType.INTERFACE, "A"));103}104105public void annotationDeclaration() {106assertEval("@interface A { }");107assertClasses(clazz(KullaTesting.ClassType.ANNOTATION, "A"));108}109110public void enumDeclaration() {111assertEval("enum A { }");112assertClasses(clazz(KullaTesting.ClassType.ENUM, "A"));113}114115public void classesDeclaration() {116assertEval("interface A { }");117assertEval("class B implements A { }");118assertEval("interface C extends A { }");119assertEval("enum D implements C { }");120assertEval("@interface E { }");121assertClasses(122clazz(KullaTesting.ClassType.INTERFACE, "A"),123clazz(KullaTesting.ClassType.CLASS, "B"),124clazz(KullaTesting.ClassType.INTERFACE, "C"),125clazz(KullaTesting.ClassType.ENUM, "D"),126clazz(KullaTesting.ClassType.ANNOTATION, "E"));127assertActiveKeys();128}129130public void classesRedeclaration1() {131Snippet a = classKey(assertEval("class A { }"));132Snippet b = classKey(assertEval("interface B { }"));133assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"), clazz(KullaTesting.ClassType.INTERFACE, "B"));134assertActiveKeys();135136assertEval("interface A { }",137ste(MAIN_SNIPPET, VALID, VALID, true, null),138ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET));139assertClasses(clazz(KullaTesting.ClassType.INTERFACE, "A"),140clazz(KullaTesting.ClassType.INTERFACE, "B"));141assertActiveKeys();142143assertEval("interface B { } //again",144ste(MAIN_SNIPPET, VALID, VALID, false, null),145ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET));146assertClasses(clazz(KullaTesting.ClassType.INTERFACE, "A"),147clazz(KullaTesting.ClassType.INTERFACE, "B"));148assertActiveKeys();149}150151public void classesRedeclaration2() {152assertEval("class A { }");153assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"));154assertActiveKeys();155156Snippet b = classKey(assertEval("class B extends A { }"));157assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"),158clazz(KullaTesting.ClassType.CLASS, "B"));159assertActiveKeys();160161Snippet c = classKey(assertEval("class C extends B { }"));162assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"),163clazz(KullaTesting.ClassType.CLASS, "B"), clazz(KullaTesting.ClassType.CLASS, "C"));164assertActiveKeys();165166assertEval("interface B { }",167DiagCheck.DIAG_OK,168DiagCheck.DIAG_ERROR,169ste(MAIN_SNIPPET, VALID, VALID, true, null),170ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET),171ste(c, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET));172assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"),173clazz(KullaTesting.ClassType.INTERFACE, "B"), clazz(KullaTesting.ClassType.CLASS, "C"));174assertEval("new C();",175DiagCheck.DIAG_ERROR,176DiagCheck.DIAG_ERROR,177added(REJECTED));178assertActiveKeys();179}180181//8154496: test3 update: sig change should false182public void classesRedeclaration3() {183Snippet a = classKey(assertEval("class A { }"));184assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"));185assertActiveKeys();186187Snippet test1 = methodKey(assertEval("A test() { return null; }"));188Snippet test2 = methodKey(assertEval("void test(A a) { }"));189Snippet test3 = methodKey(assertEval("void test(int n) {A a;}"));190assertActiveKeys();191192assertEval("interface A { }",193ste(MAIN_SNIPPET, VALID, VALID, true, null),194ste(test1, VALID, VALID, true, MAIN_SNIPPET),195ste(test2, VALID, VALID, true, MAIN_SNIPPET),196ste(test3, VALID, VALID, true, MAIN_SNIPPET),197ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET));198assertClasses(clazz(KullaTesting.ClassType.INTERFACE, "A"));199assertMethods(method("()A", "test"), method("(A)void", "test"), method("(int)void", "test"));200assertActiveKeys();201}202203public void classesCyclic1() {204Snippet b = classKey(assertEval("class B extends A { }",205added(RECOVERABLE_NOT_DEFINED)));206Snippet a = classKey(assertEval("class A extends B { }", DiagCheck.DIAG_IGNORE, DiagCheck.DIAG_IGNORE,207added(REJECTED)));208/***209assertDeclareFail("class A extends B { }", "****",210added(REJECTED),211ste(b, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, MAIN_SNIPPET));212***/213// It is random which one it shows up in, but cyclic error should be there214List<Diag> diagsA = getState().diagnostics(a).collect(toList());215List<Diag> diagsB = getState().diagnostics(b).collect(toList());216List<Diag> diags;217if (diagsA.isEmpty()) {218diags = diagsB;219} else {220diags = diagsA;221assertTrue(diagsB.isEmpty());222}223assertEquals(diags.size(), 1, "Expected one error");224assertEquals(diags.get(0).getCode(), "compiler.err.cyclic.inheritance", "Expected cyclic inheritance error");225assertActiveKeys();226}227228public void classesCyclic2() {229Snippet d = classKey(assertEval("class D extends E { }", added(RECOVERABLE_NOT_DEFINED)));230assertEval("class E { D d; }",231added(VALID),232ste(d, RECOVERABLE_NOT_DEFINED, VALID, true, MAIN_SNIPPET));233assertActiveKeys();234}235236public void classesCyclic3() {237Snippet outer = classKey(assertEval("class Outer { class Inner extends Foo { } }",238added(RECOVERABLE_NOT_DEFINED)));239Snippet foo = classKey(assertEval("class Foo { } ",240added(VALID),241ste(outer, RECOVERABLE_NOT_DEFINED, VALID, true, MAIN_SNIPPET)));242assertEval(" class Foo extends Outer { }",243ste(MAIN_SNIPPET, VALID, VALID, true, null),244ste(foo, VALID, OVERWRITTEN, false, MAIN_SNIPPET),245ste(outer, VALID, VALID, true, MAIN_SNIPPET));246assertActiveKeys();247}248249public void classesIgnoredModifiers() {250assertEval("public interface A { }");251assertEval("static class B implements A { }");252assertEval("static interface C extends A { }");253assertActiveKeys();254}255256public void classesIgnoredModifiersAnnotation() {257assertEval("public @interface X { }");258assertEval("@X public interface A { }");259assertEval("@X static class B implements A { }");260assertEval("@X static interface C extends A { }");261assertActiveKeys();262}263264public void classesIgnoredModifiersOtherModifiers() {265assertEval("strictfp public interface A { }");266assertEval("strictfp static class B implements A { }");267assertEval("strictfp static interface C extends A { }");268assertActiveKeys();269}270271public void ignoreModifierSpaceIssue() {272assertEval("interface I { void f(); } ");273// there should not be a space between 'I' and '{' to reproduce the failure274assertEval("class C implements I{ public void f() {}}");275assertClasses(clazz(KullaTesting.ClassType.CLASS, "C"), clazz(KullaTesting.ClassType.INTERFACE, "I"));276assertActiveKeys();277}278279@DataProvider(name = "innerClasses")280public Object[][] innerClasses() {281List<Object[]> list = new ArrayList<>();282for (ClassType outerClassType : ClassType.values()) {283for (ClassType innerClassType : ClassType.values()) {284list.add(new Object[]{outerClassType, innerClassType});285}286}287return list.toArray(new Object[list.size()][]);288}289290@Test(dataProvider = "innerClasses")291public void innerClasses(ClassType outerClassType, ClassType innerClassType) {292String source =293outerClassType + " A {" + (outerClassType == ClassType.ENUM ? ";" : "") +294innerClassType + " B { }" +295"}";296assertEval(source);297assertNumberOfActiveClasses(1);298assertActiveKeys();299}300301public void testInnerClassesCrash() {302Snippet a = classKey(assertEval("class A { class B extends A {} }"));303Snippet a2 = classKey(assertEval("class A { interface I1 extends I2 {} interface I2 {} }",304ste(MAIN_SNIPPET, VALID, VALID, true, null),305ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));306assertEval("class A { A a = new A() {}; }",307ste(MAIN_SNIPPET, VALID, VALID, true, null),308ste(a2, VALID, OVERWRITTEN, false, MAIN_SNIPPET));309}310311public void testInnerClassesCrash1() {312assertEval("class A { class B extends A {} B getB() { return new B();} }");313assertEquals(varKey(assertEval("A a = new A();")).name(), "a");314VarSnippet variableKey = varKey(assertEval("a.getB();"));315assertEquals(variableKey.typeName(), "A.B");316}317318public void testInnerClassesCrash2() {319assertEval("class A { interface I1 extends I2 {} interface I2 {} I1 x; }");320assertEquals(varKey(assertEval("A a = new A();")).name(), "a");321VarSnippet variableKey = varKey(assertEval("a.x;"));322assertEquals(variableKey.typeName(), "A.I1");323}324325public void testCircular() {326assertEval("import java.util.function.Supplier;");327TypeDeclSnippet aClass =328classKey(assertEval("public class A<T> {\n" +329" private class SomeClass {}\n" +330" public Supplier<T> m() {\n" +331" return new B<>(this);\n" +332" }\n" +333"}",334added(RECOVERABLE_DEFINED)));335assertEval("public class B<T> implements Supplier<T> {\n" +336" public B(A<T> a) {}\n" +337" public T get() {return null;}\n" +338"}",339added(VALID),340ste(aClass, Status.RECOVERABLE_DEFINED, Status.VALID, false, null));341assertEval("new A()");342}343344}345346347