1 /*
2  * Copyright (c) 2016, 2019, 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 8159111 8159740
27  * @summary test wrappers and dependencies
28  * @modules jdk.jshell/jdk.jshell
29  * @build KullaTesting
30  * @run testng WrapperTest
31  */
32 
33 import java.util.Collection;
34 import java.util.List;
35 import org.testng.annotations.Test;
36 import jdk.jshell.ErroneousSnippet;
37 import jdk.jshell.Snippet;
38 import jdk.jshell.Snippet.Kind;
39 import jdk.jshell.SourceCodeAnalysis.SnippetWrapper;
40 import static org.testng.Assert.assertEquals;
41 import static org.testng.Assert.assertTrue;
42 import static jdk.jshell.Snippet.Status.RECOVERABLE_DEFINED;
43 import static jdk.jshell.Snippet.Status.VALID;
44 
45 @Test
46 public class WrapperTest extends KullaTesting {
47 
testMethod()48     public void testMethod() {
49         String src = "void glib() { System.out.println(\"hello\"); }";
50         List<SnippetWrapper> swl = getState().sourceCodeAnalysis().wrappers(src);
51         assertEquals(swl.size(), 1, "unexpected list length");
52         assertWrapperHas(swl.get(0), src, Kind.METHOD, "void", "glib", "println");
53         assertPosition(swl.get(0), src, 0, 4);
54         assertPosition(swl.get(0), src, 5, 4);
55         assertPosition(swl.get(0), src, 15, 6);
56 
57         Snippet g = methodKey(assertEval(src, added(VALID)));
58         SnippetWrapper swg = getState().sourceCodeAnalysis().wrapper(g);
59         assertWrapperHas(swg, src, Kind.METHOD, "void", "glib", "println");
60         assertPosition(swg, src, 0, 4);
61         assertPosition(swg, src, 5, 4);
62         assertPosition(swg, src, 15, 6);
63     }
64 
65     // test 8159740
testMethodCorralled()66     public void testMethodCorralled() {
67         String src = "void glib() { f(); }";
68         //            _123456789_123456789
69         Snippet g = methodKey(assertEval(src, added(RECOVERABLE_DEFINED)));
70         SnippetWrapper swg = getState().sourceCodeAnalysis().wrapper(g);
71         assertWrapperHas(swg, src, Kind.METHOD, "SPIResolutionException",
72                 "void", "glib");
73         assertPosition(swg, src, 0, 4);
74         assertPosition(swg, src, 5, 4);
75     }
76 
77     // test 8159740
testClassCorralled0()78     public void testClassCorralled0() {
79         String src = "class AAA { float mmm(double d1234) { return (float) (f0 * d1234); } }";
80         //            _123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
81         Snippet a = classKey(assertEval(src, added(RECOVERABLE_DEFINED)));
82         SnippetWrapper swa = getState().sourceCodeAnalysis().wrapper(a);
83         assertWrapperHas(swa, src, Kind.TYPE_DECL, "SPIResolutionException",
84                 "class", "AAA", "float", "mmm", "double", "d1234");
85         assertPosition(swa, src, 0, 5);
86         assertPosition(swa, src, 6, 3);
87         assertPosition(swa, src, 12, 5);
88         assertPosition(swa, src, 18, 3);
89         assertPosition(swa, src, 22, 6);
90         assertPosition(swa, src, 29, 5);
91     }
92 
93     // test 8159740
testClassCorralled()94     public void testClassCorralled() {
95         String src = "class AAA { int xxx = x0 + 4; float mmm(float ffff) { return f0 * ffff; } }";
96         //            _123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
97         Snippet a = classKey(assertEval(src, added(RECOVERABLE_DEFINED)));
98         SnippetWrapper swa = getState().sourceCodeAnalysis().wrapper(a);
99         assertWrapperHas(swa, src, Kind.TYPE_DECL, "SPIResolutionException",
100                 "class", "AAA", "int", "xxx", "float", "mmm", "ffff");
101         assertPosition(swa, src, 0, 5);
102         assertPosition(swa, src, 6, 3);
103         assertPosition(swa, src, 12, 3);
104         assertPosition(swa, src, 16, 3);
105         assertPosition(swa, src, 30, 5);
106         assertPosition(swa, src, 36, 3);
107         assertPosition(swa, src, 40, 5);
108         assertPosition(swa, src, 46, 4);
109     }
110 
111     // test 8159740
testClassWithConstructorCorralled()112     public void testClassWithConstructorCorralled() {
113         String src = "public class AAA { AAA(String b) {} int xxx = x0 + 4; float mmm(float ffff) { return f0 * ffff; } }";
114         //            _123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
115         Snippet a = classKey(assertEval(src, added(RECOVERABLE_DEFINED)));
116         SnippetWrapper swa = getState().sourceCodeAnalysis().wrapper(a);
117         assertWrapperHas(swa, src, Kind.TYPE_DECL, "SPIResolutionException",
118                 "class", "AAA", "String", "int", "xxx", "float", "mmm", "ffff");
119         assertPosition(swa, src, 7, 5);
120         assertPosition(swa, src, 13, 3);
121         assertPosition(swa, src, 19, 3);
122         assertPosition(swa, src, 23, 5);
123         assertPosition(swa, src, 30, 1);
124         assertPosition(swa, src, 36, 3);
125         assertPosition(swa, src, 40, 3);
126         assertPosition(swa, src, 54, 5);
127         assertPosition(swa, src, 60, 3);
128         assertPosition(swa, src, 64, 5);
129         assertPosition(swa, src, 70, 4);
130     }
131 
132     // test 8159740
testInterfaceCorralled()133     public void testInterfaceCorralled() {
134         String src = "interface AAA { default float mmm(double d1234) { return (float) (f0 * d1234); } }";
135         //            _123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
136         Snippet a = classKey(assertEval(src, added(RECOVERABLE_DEFINED)));
137         SnippetWrapper swa = getState().sourceCodeAnalysis().wrapper(a);
138         assertWrapperHas(swa, src, Kind.TYPE_DECL, "SPIResolutionException",
139                 "interface", "AAA", "float", "mmm", "double", "d1234");
140         assertPosition(swa, src, 0, 9);
141         assertPosition(swa, src, 10, 3);
142         assertPosition(swa, src, 16, 7);
143         assertPosition(swa, src, 24, 5);
144         assertPosition(swa, src, 30, 3);
145         assertPosition(swa, src, 34, 6);
146         assertPosition(swa, src, 41, 5);
147     }
148 
149     // test 8159740
testEnumCorralled()150     public void testEnumCorralled() {
151         String src =
152                 "public enum Planet {\n" +
153                 "    MERCURY (3.303e+23, 2.4397e6),\n" +
154                 "    VENUS   (4.869e+24, 6.0518e6),\n" +
155                 "    EARTH   (5.976e+24, 6.37814e6),\n" +
156                 "    MARS    (6.421e+23, 3.3972e6),\n" +
157                 "    JUPITER (1.9e+27,   7.1492e7),\n" +
158                 "    SATURN  (5.688e+26, 6.0268e7),\n" +
159                 "    URANUS  (8.686e+25, 2.5559e7),\n" +
160                 "    NEPTUNE (1.024e+26, 2.4746e7);\n" +
161                 "\n" +
162                 "    private final double mass;   // in kilograms\n" +
163                 "    private final double radius; // in meters\n" +
164                 "    Planet(double mass, double radius) {\n" +
165                 "        this.mass = mass;\n" +
166                 "        this.radius = radius;\n" +
167                 "    }\n" +
168                 "    private double mass() { return mass; }\n" +
169                 "    private double radius() { return radius; }\n" +
170                 "\n" +
171                 "    double surfaceGravity() {\n" +
172                 "        return GRAVITATIONAL_CONSTANT * mass / (radius * radius);\n" +
173                 "    }\n" +
174                 "    double surfaceWeight(double otherMass) {\n" +
175                 "        return otherMass * surfaceGravity();\n" +
176                 "    }\n" +
177                 "}\n";
178         Snippet a = classKey(assertEval(src, added(RECOVERABLE_DEFINED)));
179         SnippetWrapper swa = getState().sourceCodeAnalysis().wrapper(a);
180         assertWrapperHas(swa, src, Kind.TYPE_DECL, "SPIResolutionException",
181                 "enum", "Planet", "double", "mass", "EARTH", "NEPTUNE", "MERCURY",
182                 "radius", "surfaceGravity", "surfaceWeight");
183     }
184 
testMethodBad()185     public void testMethodBad() {
186         String src = "void flob() { ?????; }";
187         List<SnippetWrapper> swl = getState().sourceCodeAnalysis().wrappers(src);
188         assertEquals(swl.size(), 1, "unexpected list length");
189         assertWrapperHas(swl.get(0), src, Kind.METHOD, "void", "flob", "?????");
190         assertPosition(swl.get(0), src, 9, 2);
191 
192         Snippet f = key(assertEvalFail(src));
193         assertEquals(f.kind(), Kind.ERRONEOUS);
194         assertEquals(((ErroneousSnippet)f).probableKind(), Kind.METHOD);
195         SnippetWrapper sw = getState().sourceCodeAnalysis().wrapper(f);
196         assertWrapperHas(sw, src, Kind.METHOD, "void", "flob", "?????");
197         assertPosition(swl.get(0), src, 14, 5);
198     }
199 
testVar()200     public void testVar() {
201         String src = "int gx = 1234;";
202         List<SnippetWrapper> swl = getState().sourceCodeAnalysis().wrappers(src);
203         assertEquals(swl.size(), 1, "unexpected list length");
204         assertWrapperHas(swl.get(0), src, Kind.VAR, "int", "gx", "1234");
205         assertPosition(swl.get(0), src, 4, 2);
206 
207         Snippet g = varKey(assertEval(src, added(VALID)));
208         SnippetWrapper swg = getState().sourceCodeAnalysis().wrapper(g);
209         assertWrapperHas(swg, src, Kind.VAR, "int", "gx", "1234");
210         assertPosition(swg, src, 0, 3);
211     }
212 
testVarBad()213     public void testVarBad() {
214         String src = "double dd = ?????;";
215         List<SnippetWrapper> swl = getState().sourceCodeAnalysis().wrappers(src);
216         assertEquals(swl.size(), 1, "unexpected list length");
217         assertWrapperHas(swl.get(0), src, Kind.VAR, "double", "dd", "?????");
218         assertPosition(swl.get(0), src, 9, 2);
219 
220         Snippet f = key(assertEvalFail(src));
221         assertEquals(f.kind(), Kind.ERRONEOUS);
222         assertEquals(((ErroneousSnippet)f).probableKind(), Kind.VAR);
223         SnippetWrapper sw = getState().sourceCodeAnalysis().wrapper(f);
224         assertWrapperHas(sw, src, Kind.VAR, "double", "dd", "?????");
225         assertPosition(swl.get(0), src, 12, 5);
226     }
227 
testImport()228     public void testImport() {
229         String src = "import java.lang.*;";
230         List<SnippetWrapper> swl = getState().sourceCodeAnalysis().wrappers(src);
231         assertEquals(swl.size(), 1, "unexpected list length");
232         assertWrapperHas(swl.get(0), src, Kind.IMPORT, "import", "java.lang");
233         assertPosition(swl.get(0), src, 7, 4);
234 
235         Snippet g = key(assertEval(src, added(VALID)));
236         SnippetWrapper swg = getState().sourceCodeAnalysis().wrapper(g);
237         assertWrapperHas(swg, src, Kind.IMPORT, "import", "java.lang");
238         assertPosition(swg, src, 0, 6);
239     }
240 
testImportBad()241     public void testImportBad() {
242         String src = "import java.?????;";
243         List<SnippetWrapper> swl = getState().sourceCodeAnalysis().wrappers(src);
244         assertEquals(swl.size(), 1, "unexpected list length");
245         assertWrapperHas(swl.get(0), src, Kind.IMPORT, "import", "?????");
246         assertPosition(swl.get(0), src, 7, 4);
247 
248         Snippet f = key(assertEvalFail(src));
249         assertEquals(f.kind(), Kind.ERRONEOUS);
250         assertEquals(((ErroneousSnippet)f).probableKind(), Kind.IMPORT);
251         SnippetWrapper sw = getState().sourceCodeAnalysis().wrapper(f);
252         assertWrapperHas(sw, src, Kind.IMPORT, "import", "?????");
253         assertPosition(swl.get(0), src, 0, 6);
254     }
255 
testErroneous()256     public void testErroneous() {
257         String src = "@@@@@@@@@@";
258         List<SnippetWrapper> swl = getState().sourceCodeAnalysis().wrappers(src);
259         assertEquals(swl.size(), 1, "unexpected list length");
260         assertWrapperHas(swl.get(0), src, Kind.ERRONEOUS, "@@@@@@@@@@");
261         assertPosition(swl.get(0), src, 0, 10);
262 
263         Snippet f = key(assertEvalFail(src));
264         assertEquals(f.kind(), Kind.ERRONEOUS);
265         assertEquals(((ErroneousSnippet)f).probableKind(), Kind.ERRONEOUS);
266         SnippetWrapper sw = getState().sourceCodeAnalysis().wrapper(f);
267         assertWrapperHas(sw, src, Kind.ERRONEOUS, "@@@@@@@@@@");
268         assertPosition(swl.get(0), src, 0, 10);
269     }
270 
testEmpty()271     public void testEmpty() {
272         String src = "";
273         List<SnippetWrapper> swl = getState().sourceCodeAnalysis().wrappers(src);
274         assertEquals(swl.size(), 0, "expected empty list");
275     }
276 
testDependencies()277     public void testDependencies() {
278         Snippet a = key(assertEval("int aaa = 6;", added(VALID)));
279         Snippet b = key(assertEval("class B { B(int x) { aaa = x; } }", added(VALID)));
280         Snippet c = key(assertEval("B ccc() { return new B(aaa); }", added(VALID)));
281         Collection<Snippet> dep;
282         dep = getState().sourceCodeAnalysis().dependents(c);
283         assertEquals(dep.size(), 0);
284         dep = getState().sourceCodeAnalysis().dependents(b);
285         assertEquals(dep.size(), 1);
286         assertTrue(dep.contains(c));
287         dep = getState().sourceCodeAnalysis().dependents(a);
288         assertEquals(dep.size(), 2);
289         assertTrue(dep.contains(c));
290         assertTrue(dep.contains(b));
291     }
292 
assertWrapperHas(SnippetWrapper sw, String source, Kind kind, String... has)293     private void assertWrapperHas(SnippetWrapper sw, String source, Kind kind, String... has) {
294         assertEquals(sw.source(), source);
295         assertEquals(sw.kind(), kind);
296         String s = sw.wrapped();
297         if (kind == Kind.IMPORT) {
298             assertHas(s, "import");
299         } else {
300             String cn = sw.fullClassName();
301             int idx = cn.lastIndexOf(".");
302             assertHas(s, cn.substring(idx+1));
303             assertHas(s, "class");
304         }
305         for (String hx : has) {
306             assertHas(s, hx);
307         }
308     }
309 
assertHas(String s, String has)310     private void assertHas(String s, String has) {
311         assertTrue(s.contains(has), "Expected to find '" + has + "' in: '" + s + "'");
312     }
313 
assertPosition(SnippetWrapper sw, String source, int start, int length)314     private void assertPosition(SnippetWrapper sw, String source, int start, int length) {
315         //System.err.printf("\n#assertPosition:\n#  debug-source: %s\n#  SnippetWrapper --\n#    source: %s\n#    wrapped: %s\n",
316         //        source, sw.source(), sw.wrapped());
317         //System.err.printf("#  start: %d    length: %d\n", start, length);
318         int wpg = sw.sourceToWrappedPosition(start);
319         //System.err.printf("#  wrappedPos: %d\n", wpg);
320         String wrappedPart = sw.wrapped().substring(wpg, wpg+length);
321         String sourcePart = source.substring(start, start+length);
322         //System.err.printf("#  wrapped @ wrappedPos: %s\n", wrappedPart);
323         //System.err.printf("#  source @ start: %s\n", sourcePart);
324 
325         assertEquals(wrappedPart, sourcePart,
326                 "position " + wpg + " in " + sw.wrapped());
327         assertEquals(sw.wrappedToSourcePosition(wpg), start);
328     }
329 }
330