1 /*
2  * Copyright (c) 2015, 2020, 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 8080357 8167643 8187359 8199762 8080353 8246353 8247456
27  * @summary Tests for EvaluationState.methods
28  * @build KullaTesting TestingInputStream ExpectedDiagnostic
29  * @run testng MethodsTest
30  */
31 
32 import javax.tools.Diagnostic;
33 
34 import jdk.jshell.Snippet;
35 import jdk.jshell.MethodSnippet;
36 import jdk.jshell.Snippet.Status;
37 import org.testng.annotations.Test;
38 
39 import java.util.List;
40 import java.util.stream.Collectors;
41 
42 import static jdk.jshell.Snippet.Status.*;
43 import static org.testng.Assert.assertEquals;
44 
45 @Test
46 public class MethodsTest extends KullaTesting {
47 
noMethods()48     public void noMethods() {
49         assertNumberOfActiveMethods(0);
50     }
51 
testSignature1()52     public void testSignature1() {
53         MethodSnippet m1 = methodKey(assertEval("void f() { g(); }", added(RECOVERABLE_DEFINED)));
54         assertMethodDeclSnippet(m1, "f", "()void", RECOVERABLE_DEFINED, 1, 0);
55         MethodSnippet m2 = methodKey(assertEval("void g() { }",
56                 added(VALID),
57                 ste(m1, RECOVERABLE_DEFINED, VALID, false, null)));
58         assertMethodDeclSnippet(m2, "g", "()void", VALID, 0, 0);
59     }
60 
testSignature2()61     public void testSignature2() {
62         MethodSnippet m1 = (MethodSnippet) assertDeclareFail("void f() { return g(); }", "compiler.err.prob.found.req");
63         assertMethodDeclSnippet(m1, "f", "()void", REJECTED, 0, 2);
64         MethodSnippet m2 = methodKey(assertEval("int f() { return g(); }",
65                 added(RECOVERABLE_DEFINED)));
66         assertMethodDeclSnippet(m1, "f", "()void", REJECTED, 0, 2);
67         assertMethodDeclSnippet(m2, "f", "()int", RECOVERABLE_DEFINED, 1, 0);
68     }
69 
70     @Test(enabled = false) // TODO 8081690
testSignature3()71     public void testSignature3() {
72         MethodSnippet m1 = methodKey(assertEval("void f(Bar b) { }", added(RECOVERABLE_NOT_DEFINED)));
73         assertMethodDeclSnippet(m1, "f", "(Bar)void", RECOVERABLE_NOT_DEFINED, 1, 0);
74         MethodSnippet m2 = methodKey(assertEval("void f(A.Bar b) { }", added(RECOVERABLE_NOT_DEFINED)));
75         assertMethodDeclSnippet(m1, "f", "(Bar)void", RECOVERABLE_NOT_DEFINED, 1, 0);
76         assertMethodDeclSnippet(m2, "f", "(A.Bar)void", RECOVERABLE_NOT_DEFINED, 1, 0);
77         assertDrop(m1, ste(m1, RECOVERABLE_NOT_DEFINED, DROPPED, false, null));
78         assertMethodDeclSnippet(m1, "f", "(Bar)void", DROPPED, 1, 0);
79     }
80 
81     // 8080357
testNonReplUnresolved()82     public void testNonReplUnresolved() {
83         // internal case
84         assertEval("class CCC {}", added(VALID));
85         assertEval("void f1() { CCC.xxxx(); }", added(RECOVERABLE_DEFINED));
86         // external case, not recoverable
87         assertDeclareFail("void f2() { System.xxxx(); }", "compiler.err.cant.resolve.location.args");
88     }
89 
methods()90     public void methods() {
91         assertEval("int x() { return 10; }");
92         assertEval("String y() { return null; }");
93         assertEval("long z() { return 0; }");
94         assertMethods(method("()int", "x"), method("()String", "y"), method("()long", "z"));
95         assertActiveKeys();
96     }
97 
methodOverload()98     public void methodOverload() {
99         assertEval("int m() { return 1; }");
100         assertEval("int m(int x) { return 2; }");
101         assertEval("int m(String s) { return 3; }");
102         assertEval("int m(int x, int y) { return 4; }");
103         assertEval("int m(int x, String z) { return 5; }");
104         assertEval("int m(int x, String z, long g) { return 6; }");
105         assertMethods(
106                 method("()int", "m"),
107                 method("(int)int", "m"),
108                 method("(String)int", "m"),
109                 method("(int,int)int", "m"),
110                 method("(int,String)int", "m"),
111                 method("(int,String,long)int", "m")
112         );
113         assertEval("m();", "1");
114         assertEval("m(3);", "2");
115         assertEval("m(\"hi\");", "3");
116         assertEval("m(7, 8);", "4");
117         assertEval("m(7, \"eight\");", "5");
118         assertEval("m(7, \"eight\", 9L);", "6");
119         assertActiveKeys();
120     }
121 
122     /***
123     public void methodOverloadDependent() {
124         assertEval("String m(String s) { return s + s; }");
125         assertEval("String m(double d) { return m(\"#\" + d); }");
126         assertEval("String m(int x) { return m(2.25 * x); }");
127         assertEval("String m() { return m(3); }");
128         assertMethods(
129                 method("(String)String", "m"),
130                 method("(double)String", "m"),
131                 method("(int)String", "m"),
132                 method("()String", "m")
133         );
134         assertEval("m();", "\"#6.75#6.75\"");
135         assertEval("m(2);", "\"#4.5#4.5\"");
136         assertEval("m(3.14);", "\"#3.14#3.14\"");
137         assertEval("m(\"hi\");", "\"hihi\"");
138         assertActiveKeys();
139     }
140     ***/
141 
methodsRedeclaration1()142     public void methodsRedeclaration1() {
143         Snippet x = methodKey(assertEval("int x() { return 10; }"));
144         Snippet y = methodKey(assertEval("String y() { return \"\"; }"));
145         assertMethods(method("()int", "x"), method("()String", "y"));
146         assertActiveKeys();
147 
148         assertEval("long x() { return 0; }",
149                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
150                 ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
151         assertMethods(method("()long", "x"), method("()String", "y"));
152         assertActiveKeys();
153 
154         assertEval("String y() { return null; }",
155                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
156                 ste(y, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
157         assertMethods(method("()long", "x"), method("()String", "y"));
158         assertActiveKeys();
159     }
160 
methodsRedeclaration2()161     public void methodsRedeclaration2() {
162         assertEval("int a() { return 1; }");
163         assertMethods(method("()int", "a"));
164         assertActiveKeys();
165 
166         Snippet b = methodKey(assertEval("Integer b() { return a(); }"));
167         assertMethods(method("()int", "a"), method("()Integer", "b"));
168         assertActiveKeys();
169 
170         Snippet c = methodKey(assertEval("double c() { return b(); }"));
171         assertMethods(method("()int", "a"), method("()Integer", "b"), method("()double", "c"));
172         assertActiveKeys();
173 
174         assertEval("double b() { return 3.14159; }",
175                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
176                 ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
177         assertMethods(method("()int", "a"), method("()double", "b"), method("()double", "c"));
178         assertEval("c();", "3.14159");
179         assertActiveKeys();
180     }
181 
methodsRedeclaration3()182     public void methodsRedeclaration3() {
183         Snippet x = methodKey(assertEval("int x(Object...a) { return 10; }"));
184         assertMethods(method("(Object...)int", "x"));
185         assertActiveKeys();
186 
187         assertEval("int x(Object[]a) { return 10; }",
188                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
189                 ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
190         assertMethods(method("(Object[])int", "x"));
191         assertActiveKeys();
192     }
193 
194 
methodsRedeclaration4()195     public void methodsRedeclaration4() {
196         Snippet a = methodKey(assertEval("int foo(int a) { return a; }"));
197         assertEval("int x = foo(10);");
198         assertActiveKeys();
199         assertMethods(method("(int)int", "foo"));
200         assertEval("int foo(int a) { return a * a; }",
201                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
202                 ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
203         assertActiveKeys();
204     }
205 
206     // 8199762
methodsRedeclaration5()207     public void methodsRedeclaration5() {
208         Snippet m1 = methodKey(assertEval("int m(Object o) { return 10; }"));
209         assertMethods(method("(Object)int", "m"));
210 
211         Snippet m2 = methodKey(assertEval("int m(Object o) { return 30; }",
212                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
213                 ste(m1, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
214 
215         assertEval("<T> int m(T o) { return 30; }",
216                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
217                 ste(m2, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
218         assertMethods(method("(T)int", "m"));
219         assertEval("m(null)", "30");
220         assertActiveKeys();
221     }
222 
methodsAbstract()223     public void methodsAbstract() {
224         MethodSnippet m1 = methodKey(assertEval("abstract String f();",
225                 ste(MAIN_SNIPPET, NONEXISTENT, RECOVERABLE_DEFINED, true, null)));
226         assertEquals(getState().unresolvedDependencies(m1).collect(Collectors.toList()),
227                 List.of("method f()"));
228         MethodSnippet m2 = methodKey(assertEval("abstract int mm(Blah b);",
229                 ste(MAIN_SNIPPET, NONEXISTENT, RECOVERABLE_NOT_DEFINED, false, null)));
230         List<String> unr = getState().unresolvedDependencies(m2).collect(Collectors.toList());
231         assertEquals(unr.size(), 2);
232         unr.remove("class Blah");
233         unr.remove("method mm(Blah)");
234         assertEquals(unr.size(), 0, "unexpected entry: " + unr);
235         assertNumberOfActiveMethods(2);
236         assertActiveKeys();
237     }
238 
methodsErrors()239     public void methodsErrors() {
240         assertDeclareFail("String f();",
241                 new ExpectedDiagnostic("compiler.err.missing.meth.body.or.decl.abstract", 0, 11, 7, -1, -1, Diagnostic.Kind.ERROR));
242         assertNumberOfActiveMethods(0);
243         assertActiveKeys();
244 
245         assertDeclareFail("native String f();",
246                 new ExpectedDiagnostic("jdk.eval.error.illegal.modifiers", 0, 6, 0, -1, -1, Diagnostic.Kind.ERROR));
247         assertNumberOfActiveMethods(0);
248         assertActiveKeys();
249 
250         assertDeclareFail("synchronized String f() {return null;}",
251                 new ExpectedDiagnostic("jdk.eval.error.illegal.modifiers", 0, 12, 0, -1, -1, Diagnostic.Kind.ERROR));
252         assertNumberOfActiveMethods(0);
253         assertActiveKeys();
254 
255         assertDeclareFail("default void f() { }",
256                 new ExpectedDiagnostic("jdk.eval.error.illegal.modifiers", 0, 7, 0, -1, -1, Diagnostic.Kind.ERROR));
257         assertNumberOfActiveMethods(0);
258         assertActiveKeys();
259 
260         assertDeclareFail("int f() {}", "compiler.err.missing.ret.stmt",
261                 added(REJECTED));
262         assertNumberOfActiveMethods(0);
263         assertActiveKeys();
264 
265         assertEval("String x() { return \"\"; };");
266         assertMethods(method("()String", "x"));
267         assertActiveKeys();
268     }
269 
objectMethodNamedMethodsErrors()270     public void objectMethodNamedMethodsErrors() {
271         assertDeclareFail("boolean equals(double d1, double d2) {  return d1 == d2; }",
272                 new ExpectedDiagnostic("jdk.eval.error.object.method", 8, 14, 8, -1, -1, Diagnostic.Kind.ERROR));
273         assertNumberOfActiveMethods(0);
274         assertActiveKeys();
275 
276         assertDeclareFail("void          wait() { }",
277                 new ExpectedDiagnostic("jdk.eval.error.object.method", 14, 18, 14, -1, -1, Diagnostic.Kind.ERROR));
278         assertNumberOfActiveMethods(0);
279         assertActiveKeys();
280 
281         assertDeclareFail("  String   toString() throws NullPointerException{ }",
282                 new ExpectedDiagnostic("jdk.eval.error.object.method", 11, 19, 11, -1, -1, Diagnostic.Kind.ERROR));
283         assertNumberOfActiveMethods(0);
284         assertActiveKeys();
285 
286     }
287 
288 
methodsAccessModifierIgnored()289     public void methodsAccessModifierIgnored() {
290         Snippet f = methodKey(assertEval("public String f() {return null;}",
291                 added(VALID)));
292         assertNumberOfActiveMethods(1);
293         assertActiveKeys();
294 
295         f = methodKey(assertEval("protected String f() {return null;}",
296                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
297                 ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
298         assertNumberOfActiveMethods(1);
299         assertActiveKeys();
300 
301         assertEval("private String f() {return null;}",
302                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
303                 ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
304         assertNumberOfActiveMethods(1);
305         assertActiveKeys();
306     }
307 
methodsIgnoredModifiers()308     public void methodsIgnoredModifiers() {
309         Snippet f = methodKey(assertEval("static String f() {return null;}"));
310         assertNumberOfActiveMethods(1);
311         assertActiveKeys();
312 
313         assertDeclareWarn1("final String f() {return null;}",
314                 null,
315                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
316                 ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
317         assertNumberOfActiveMethods(1);
318         assertActiveKeys();
319     }
320 
methodSignatureUnresolved()321     public void methodSignatureUnresolved() {
322         MethodSnippet key = (MethodSnippet) methodKey(assertEval("und m() { return new und(); }", added(RECOVERABLE_NOT_DEFINED)));
323         assertMethodDeclSnippet(key, "m", "()und", RECOVERABLE_NOT_DEFINED, 1, 0);
324         assertUnresolvedDependencies1(key, Status.RECOVERABLE_NOT_DEFINED, "class und");
325         assertEval("class und {}",
326                 added(VALID),
327                 ste(key, RECOVERABLE_NOT_DEFINED, VALID, true, null));
328         assertMethodDeclSnippet(key, "m", "()und", Status.VALID, 0, 0);
329         assertNumberOfActiveMethods(1);
330         assertActiveKeys();
331     }
332 
333     @Test(enabled = false) // TODO 8081689
classMethodsAreNotVisible()334     public void classMethodsAreNotVisible() {
335         assertEval(
336             "class A {" +
337                 "int foo() {" +
338                     "int x = 10;" +
339                     "int y = 2 * x;" +
340                     "return x * y;" +
341                 "}" +
342             "}");
343         assertNumberOfActiveMethods(0);
344         assertEval("int x = 10;", "10");
345         assertEval("int foo() {" +
346                         "int y = 2 * x;" +
347                         "return x * y;" +
348                         "}");
349         assertMethods(method("()int", "foo"));
350         assertEval("foo();", "200");
351         assertActiveKeys();
352     }
353 
lambdas()354     public void lambdas() {
355         assertEval("class Inner1 implements Runnable {" +
356                 "public Runnable lambda1 = () -> {};" +
357                 "public void function() {}" +
358                 "public void run() {}" +
359                 "}");
360 
361         assertEval("class Inner2 {" +
362                 "private Runnable lambda1 = () -> {};" +
363                 "private static void staticFunction() {}" +
364                 "}");
365 
366         // the following method references and lambda functions
367         // generate synthetic methods
368         assertEval("Runnable run = () -> {};");
369         assertEval("Inner1 inner = new Inner1();");
370         assertEval("Runnable l1 = inner::function;");
371         assertEval("Runnable l2 = Inner1::new;");
372         assertEval("inner.lambda1 = inner::function;");
373         assertEval("java.util.stream.IntStream.of(2).mapToObj(int[]::new);");
374         assertNumberOfActiveMethods(0);
375         assertActiveKeys();
376     }
377 }
378