test/langtools/jdk/jshell/ReplaceTest.java
changeset 47216 71c04702a3d5
parent 43366 9e917e04f53c
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2015, 2016, 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 8080069 8152925
       
    26  * @summary Test of Snippet redefinition and replacement.
       
    27  * @build KullaTesting TestingInputStream
       
    28  * @run testng ReplaceTest
       
    29  */
       
    30 
       
    31 import java.util.Iterator;
       
    32 import java.util.stream.Stream;
       
    33 import jdk.jshell.Snippet;
       
    34 import jdk.jshell.MethodSnippet;
       
    35 import jdk.jshell.TypeDeclSnippet;
       
    36 import jdk.jshell.VarSnippet;
       
    37 import org.testng.annotations.Test;
       
    38 
       
    39 import static org.testng.Assert.assertFalse;
       
    40 import static jdk.jshell.Snippet.Status.*;
       
    41 import static jdk.jshell.Snippet.SubKind.*;
       
    42 import static org.testng.Assert.assertTrue;
       
    43 
       
    44 @Test
       
    45 public class ReplaceTest extends KullaTesting {
       
    46 
       
    47     public void testRedefine() {
       
    48         Snippet vx = varKey(assertEval("int x;"));
       
    49         Snippet mu = methodKey(assertEval("int mu() { return x * 4; }"));
       
    50         Snippet c = classKey(assertEval("class C { String v() { return \"#\" + mu(); } }"));
       
    51         assertEval("C c0  = new C();");
       
    52         assertEval("c0.v();", "\"#0\"");
       
    53         assertEval("int x = 10;", "10",
       
    54                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
       
    55                 ste(vx, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
       
    56         assertEval("c0.v();", "\"#40\"");
       
    57         assertEval("C c = new C();");
       
    58         assertEval("c.v();", "\"#40\"");
       
    59         assertEval("int mu() { return x * 3; }",
       
    60                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
       
    61                 ste(mu, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
       
    62         assertEval("c.v();", "\"#30\"");
       
    63         assertEval("class C { String v() { return \"@\" + mu(); } }",
       
    64                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
       
    65                 ste(c, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
       
    66         assertEval("c0.v();", "\"@30\"");
       
    67         assertEval("c = new C();");
       
    68         assertEval("c.v();", "\"@30\"");
       
    69         assertActiveKeys();
       
    70     }
       
    71 
       
    72     public void testReplaceClassToVar() {
       
    73         Snippet oldA = classKey(assertEval("class A { public String toString() { return \"old\"; } }"));
       
    74         Snippet v = varKey(assertEval("A a = new A();", "old"));
       
    75         assertEval("a;", "old");
       
    76         Snippet midA = classKey(assertEval("class A { public String toString() { return \"middle\"; } }",
       
    77                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
       
    78                 ste(oldA, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
       
    79         assertEval("a;", "middle");
       
    80         assertEval("class A { int x; public String toString() { return \"new\"; } }",
       
    81                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
       
    82                 ste(midA, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
       
    83                 ste(v, VALID, VALID, true, MAIN_SNIPPET));
       
    84         assertEval("a;", "null");
       
    85         assertActiveKeys();
       
    86     }
       
    87 
       
    88     private <T extends Snippet> void identityMatch(Stream<T> got, T expected) {
       
    89         Iterator<T> it = got.iterator();
       
    90         assertTrue(it.hasNext(), "expected exactly one");
       
    91         assertTrue(expected == it.next(), "Identity must not change");
       
    92         assertFalse(it.hasNext(), "expected exactly one");
       
    93     }
       
    94 
       
    95     public void testReplaceVarToMethod() {
       
    96         Snippet x = varKey(assertEval("int x;"));
       
    97         MethodSnippet musn = methodKey(assertEval("double mu() { return x * 4; }"));
       
    98         assertEval("x == 0;", "true");
       
    99         assertEval("mu() == 0.0;", "true");
       
   100         assertEval("double x = 2.5;",
       
   101                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
       
   102                 ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
       
   103         identityMatch(getState().methods(), musn);
       
   104         assertEval("x == 2.5;", "true");
       
   105         assertEval("mu() == 10.0;", "true");  // Auto redefine
       
   106         assertActiveKeys();
       
   107     }
       
   108 
       
   109     public void testReplaceMethodToMethod() {
       
   110         Snippet a = methodKey(assertEval("double a() { return 2; }"));
       
   111         Snippet b = methodKey(assertEval("double b() { return a() * 10; }"));
       
   112         assertEval("double c() { return b() * 3; }");
       
   113         assertEval("double d() { return c() + 1000; }");
       
   114         assertEval("d();", "1060.0");
       
   115         assertEval("int a() { return 5; }",
       
   116                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
       
   117                 ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
       
   118         assertEval("d();", "1150.0");
       
   119         assertActiveKeys();
       
   120     }
       
   121 
       
   122     public void testReplaceClassToMethod() {
       
   123         Snippet c = classKey(assertEval("class C { int f() { return 7; } }"));
       
   124         Snippet m = methodKey(assertEval("int m() { return new C().f(); }"));
       
   125         assertEval("m();", "7");
       
   126         assertEval("class C { int x = 99; int f() { return x; } }",
       
   127                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
       
   128                 ste(c, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
       
   129         assertEval("m();", "99");
       
   130         assertActiveKeys();
       
   131     }
       
   132 
       
   133     public void testReplaceVarToClass() {
       
   134         Snippet x = varKey(assertEval("int x;"));
       
   135         TypeDeclSnippet c = classKey(assertEval("class A { double a = 4 * x; }"));
       
   136         assertEval("x == 0;", "true");
       
   137         assertEval("new A().a == 0.0;", "true");
       
   138         assertEval("double x = 2.5;",
       
   139                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
       
   140                 ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
       
   141         identityMatch(getState().types(), c);
       
   142         assertEval("x == 2.5;", "true");
       
   143         assertEval("new A().a == 10.0;", "true");
       
   144         assertActiveKeys();
       
   145     }
       
   146 
       
   147     public void testReplaceMethodToClass() {
       
   148         Snippet x = methodKey(assertEval("int x() { return 0; }"));
       
   149         TypeDeclSnippet c = classKey(assertEval("class A { double a = 4 * x(); }"));
       
   150         assertEval("x() == 0;", "true");
       
   151         assertEval("new A().a == 0.0;", "true");
       
   152         assertEval("double x() { return 2.5; }",
       
   153                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
       
   154                 ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
       
   155         assertEval("x();", "2.5");
       
   156         identityMatch(getState().types(), c);
       
   157         assertEval("x() == 2.5;", "true");
       
   158         assertEval("new A().a == 10.0;", "true");
       
   159         assertActiveKeys();
       
   160     }
       
   161 
       
   162     public void testReplaceClassToClass() {
       
   163         TypeDeclSnippet a = classKey(assertEval("class A {}"));
       
   164         assertTypeDeclSnippet(a, "A", VALID, CLASS_SUBKIND, 0, 0);
       
   165         TypeDeclSnippet b = classKey(assertEval("class B extends A {}"));
       
   166         TypeDeclSnippet c = classKey(assertEval("class C extends B {}"));
       
   167         TypeDeclSnippet d = classKey(assertEval("class D extends C {}"));
       
   168         assertEval("class A { int x; public String toString() { return \"NEW\"; } }",
       
   169                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
       
   170                 ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
       
   171                 ste(b, VALID, VALID, true, MAIN_SNIPPET),
       
   172                 ste(c, VALID, VALID, true, b),
       
   173                 ste(d, VALID, VALID, true, c));
       
   174         assertTypeDeclSnippet(b, "B", VALID, CLASS_SUBKIND, 0, 0);
       
   175         assertTypeDeclSnippet(c, "C", VALID, CLASS_SUBKIND, 0, 0);
       
   176         assertTypeDeclSnippet(d, "D", VALID, CLASS_SUBKIND, 0, 0);
       
   177         assertEval("new D();", "NEW");
       
   178         assertActiveKeys();
       
   179     }
       
   180 
       
   181     public void testOverwriteReplaceMethod() {
       
   182         MethodSnippet k1 = methodKey(assertEval("String m(Integer i) { return i.toString(); }"));
       
   183         MethodSnippet k2 = methodKey(assertEval("String m(java.lang.Integer i) { return \"java.lang.\" + i.toString(); }",
       
   184                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
       
   185                 ste(k1, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
       
   186         assertMethodDeclSnippet(k1, "m", "(Integer)String", OVERWRITTEN, 0, 0);
       
   187         assertEval("m(6);", "\"java.lang.6\"");
       
   188         assertEval("String m(Integer i) { return i.toString(); }",
       
   189                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
       
   190                 ste(k2, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
       
   191         assertMethodDeclSnippet(k2, "m", "(java.lang.Integer)String", OVERWRITTEN, 0, 0);
       
   192         assertEval("m(6);", "\"6\"");
       
   193         assertActiveKeys();
       
   194     }
       
   195 
       
   196     public void testImportDeclare() {
       
   197         Snippet singleImport = importKey(assertEval("import java.util.List;", added(VALID)));
       
   198         Snippet importOnDemand = importKey(assertEval("import java.util.*;", added(VALID)));
       
   199         Snippet singleStaticImport = importKey(assertEval("import static java.lang.Math.abs;", added(VALID)));
       
   200         Snippet staticImportOnDemand = importKey(assertEval("import static java.lang.Math.*;", added(VALID)));
       
   201         assertEval("import java.util.List; //again",
       
   202                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
       
   203                 ste(singleImport, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
       
   204         assertEval("import java.util.*; //again",
       
   205                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
       
   206                 ste(importOnDemand, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
       
   207         assertEval("import static java.lang.Math.abs; //again",
       
   208                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
       
   209                 ste(singleStaticImport, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
       
   210         assertEval("import static java.lang.Math.*; //again",
       
   211                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
       
   212                 ste(staticImportOnDemand, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
       
   213         assertActiveKeys();
       
   214     }
       
   215 
       
   216     @Test(enabled = false) // TODO 8129420
       
   217     public void testLocalClassEvolve() {
       
   218         Snippet j = methodKey(assertEval("Object j() { return null; }", added(VALID)));
       
   219         assertEval("Object j() { class B {}; return null; }",
       
   220                 ste(MAIN_SNIPPET, VALID, VALID, false, null));
       
   221         assertEval("Object j() { class B {}; return new B(); }",
       
   222                 ste(MAIN_SNIPPET, VALID, VALID, false, null));
       
   223         assertEval("j().getClass().getSimpleName();", "\"B\"");
       
   224         assertEval("Object j() { class B { int p; public String toString() { return \"Yep\";} }; return new B(); }",
       
   225                 ste(MAIN_SNIPPET, VALID, VALID, false, null));
       
   226         assertEval("j().getClass().getSimpleName();", "\"B\"");
       
   227         assertEval("j();", "Yep");
       
   228     }
       
   229 
       
   230     public void testReplaceCausesMethodReferenceError() {
       
   231         Snippet l = classKey(assertEval("interface Logger { public void log(String message); }", added(VALID)));
       
   232         Snippet v = varKey(assertEval("Logger l = System.out::println;", added(VALID)));
       
   233         assertEval("interface Logger { public boolean accept(String message);  }",
       
   234                 DiagCheck.DIAG_OK,
       
   235                 DiagCheck.DIAG_ERROR,
       
   236                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
       
   237                 ste(l, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
       
   238                 ste(v, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET));
       
   239     }
       
   240 
       
   241     public void testReplaceCausesClassCompilationError() {
       
   242         Snippet l = classKey(assertEval("interface L { }", added(VALID)));
       
   243         Snippet c = classKey(assertEval("class C implements L { }", added(VALID)));
       
   244         assertEval("interface L { void m(); }",
       
   245                 DiagCheck.DIAG_OK,
       
   246                 DiagCheck.DIAG_ERROR,
       
   247                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
       
   248                 ste(l, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
       
   249                 ste(c, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET));
       
   250     }
       
   251 
       
   252     public void testOverwriteNoUpdate() {
       
   253         String xsi = "int x = 5;";
       
   254         String xsd = "double x = 3.14159;";
       
   255         VarSnippet xi = varKey(assertEval(xsi, added(VALID)));
       
   256         String ms1 = "double m(Integer i) { return i + x; }";
       
   257         String ms2 = "double m(java.lang.Integer i) { return i + x; }";
       
   258         MethodSnippet k1 = methodKey(assertEval(ms1, added(VALID)));
       
   259         VarSnippet xd = varKey(assertEval(xsd,
       
   260                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
       
   261                 ste(xi, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
       
   262         MethodSnippet k2 = methodKey(assertEval(ms2,
       
   263                 ste(MAIN_SNIPPET, VALID, VALID, true, null), //TODO: technically, should be false
       
   264                 ste(k1, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
       
   265         VarSnippet xi2 = varKey(assertEval(xsi,
       
   266                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
       
   267                 ste(xd, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
       
   268         varKey(assertEval(xsd,
       
   269                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
       
   270                 ste(xi2, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
       
   271     }
       
   272 }