1 /* 2 * Copyright (c) 2013, 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 package vm.runtime.defmeth; 25 26 import java.util.HashMap; 27 import java.util.List; 28 import java.util.Map; 29 import nsk.share.Pair; 30 import nsk.share.TestFailure; 31 import nsk.share.test.TestBase; 32 import vm.runtime.defmeth.shared.DefMethTest; 33 import vm.runtime.defmeth.shared.DefMethTestFailure; 34 import vm.runtime.defmeth.shared.MemoryClassLoader; 35 import vm.runtime.defmeth.shared.annotation.NotApplicableFor; 36 import vm.runtime.defmeth.shared.builder.TestBuilder; 37 import vm.runtime.defmeth.shared.executor.TestExecutor; 38 import vm.runtime.defmeth.shared.data.Clazz; 39 import vm.runtime.defmeth.shared.data.ConcreteClass; 40 import vm.runtime.defmeth.shared.data.Interface; 41 import vm.runtime.defmeth.shared.data.Tester; 42 import static vm.runtime.defmeth.shared.ExecutionMode.*; 43 44 /* 45 * Basic scenarios on class redefinition. 46 */ 47 public class RedefineTest extends DefMethTest { 48 49 public static void main(String[] args) { 50 TestBase.runTest(new RedefineTest(), args); 51 } 52 53 @Override 54 protected void configure() { 55 // There are no testers being generated for reflection-based scenarios, 56 // so scenarios on class redefinition don't work 57 String mode = factory.getExecutionMode(); 58 if ( "REFLECTION".equals(mode) || "INVOKE_WITH_ARGS".equals(mode)) { 59 throw new TestFailure("RedefineTest isn't applicable to reflection-based execution scenario " + 60 "(REDEFINE & INVOKE_WITH_ARGS)."); 61 } 62 } 63 64 /** 65 * Run test {@code b1} w/ redefined {@code classes} from {@code b2}. 66 * 67 * @param b1 68 * @param b2 69 * @param classes 70 */ 71 private void redefineAndRun(TestBuilder b1, TestBuilder b2, Clazz... classes) { 72 TestExecutor executor = b1.prepare(); 73 74 getLog().info("Before"); 75 List<Pair<Tester,Throwable>> errorsBefore = 76 executor.run(); // run b1 77 78 // redefine in b1 79 MemoryClassLoader cl = executor.getLoader(); // b1.cl 80 Map<String,byte[]> cf = b2.produce(); // 81 Map<String,byte[]> forRedef = new HashMap<>(); 82 for (Clazz clz : classes) { 83 String name = clz.name(); 84 forRedef.put(name, cf.get(name)); 85 } 86 87 cl.modifyClasses(forRedef, factory.isRetransformClasses()); 88 89 getLog().info("After"); 90 List<Pair<Tester,Throwable>> errorsAfter = 91 executor.run(); 92 93 if (!errorsBefore.isEmpty()) { 94 throw new DefMethTestFailure(errorsBefore); 95 } 96 97 if (!errorsAfter.isEmpty()) { 98 throw new DefMethTestFailure(errorsAfter); 99 } 100 } 101 102 /* 103 * Before redefinition: 104 * interface I { public int m() { return 1; } } 105 * class C extends I { public int m() { return 2; } } 106 * 107 * TEST: I i = new C(); i.m() == 2 108 * TEST: C c = new C(); c.m() == 2 109 * 110 * After redefinition: 111 * interface I { public int m() { return 1; } } 112 * class C extends I { public int m() { return 3; } } 113 * 114 * TEST: I i = new C(); i.m() == 3 115 * TEST: C c = new C(); c.m() == 3 116 */ 117 @NotApplicableFor(modes = { REFLECTION, INVOKE_WITH_ARGS }) // reflection-based scenarios rely on checks in bytecode 118 public void testRedefineConcreteMethod() { 119 TestBuilder before = factory.getBuilder(); 120 { // Before redefinition 121 Interface I = before.intf("I") 122 .defaultMethod("m", "()I").returns(1).build() 123 .build(); 124 ConcreteClass C = before.clazz("C").implement(I) 125 .concreteMethod("m", "()I").returns(2).build() 126 .build(); 127 128 before.test().callSite(I, C, "m", "()I").returns(2).done() 129 .test().callSite(C, C, "m", "()I").returns(2).done(); 130 } 131 132 { // After redefinition 133 TestBuilder after = factory.getBuilder(); 134 135 Interface I = after.intf("I") 136 .defaultMethod("m", "()I").returns(1).build() 137 .build(); 138 ConcreteClass C = after.clazz("C").implement(I) 139 .concreteMethod("m", "()I").returns(3).build() 140 .build(); 141 142 Tester T1 = after.test().callSite(I, C, "m", "()I").returns(3).build(); 143 Tester T2 = after.test().callSite(C, C, "m", "()I").returns(3).build(); 144 145 redefineAndRun(before, after, C, T1, T2); 146 } 147 } 148 149 /* 150 * Before redefinition: 151 * interface I { public int m() { return 1; } } 152 * class C extends I { public int m() { return 2; } } 153 * 154 * TEST: I i = new C(); i.m() == 2 155 * TEST: C c = new C(); c.m() == 2 156 * 157 * After redefinition: 158 * interface I { public int m() { return 3; } } 159 * class C extends I { public int m() { return 2; } } 160 * 161 * TEST: I i = new C(); i.m() == 2 162 * TEST: C c = new C(); c.m() == 2 163 */ 164 @NotApplicableFor(modes = { REFLECTION, INVOKE_WITH_ARGS }) // reflection-based scenarios rely on checks in bytecode 165 public void testRedefineDefaultMethod() { 166 TestBuilder before = factory.getBuilder(); 167 { // Before redefinition 168 Interface I = before.intf("I") 169 .defaultMethod("m", "()I").returns(1).build() 170 .build(); 171 ConcreteClass C = before.clazz("C").implement(I) 172 .concreteMethod("m", "()I").returns(2).build() 173 .build(); 174 175 before.test().callSite(I, C, "m", "()I").returns(2).done() 176 .test().callSite(C, C, "m", "()I").returns(2).done(); 177 } 178 179 { // After redefinition 180 TestBuilder after = factory.getBuilder(); 181 182 Interface I = after.intf("I") 183 .defaultMethod("m", "()I").returns(3).build() 184 .build(); 185 ConcreteClass C = after.clazz("C").implement(I) 186 .concreteMethod("m", "()I").returns(2).build() 187 .build(); 188 189 redefineAndRun(before, after, C); 190 } 191 } 192 193 /* 194 * Before redefinition: 195 * interface I { public int m() { return 1; } } 196 * class C extends I {} 197 * 198 * TEST: I i = new C(); i.m() == 1 199 * TEST: C c = new C(); c.m() == 1 200 * 201 * After redefinition: 202 * interface I { public int m() { return 2; } } 203 * class C extends I {} 204 * 205 * TEST: I i = new C(); i.m() == 2 206 * TEST: C c = new C(); c.m() == 2 207 */ 208 @NotApplicableFor(modes = { REFLECTION, INVOKE_WITH_ARGS }) // reflection-based scenarios rely on checks in bytecode 209 public void testRedefineDefMethInConcreteClass() { 210 TestBuilder before = factory.getBuilder(); 211 { // Before redefinition 212 Interface I = before.intf("I") 213 .defaultMethod("m", "()I").returns(1).build() 214 .build(); 215 ConcreteClass C = before.clazz("C").implement(I).build(); 216 217 before.test().callSite(I, C, "m", "()I").returns(1).done() 218 .test().callSite(C, C, "m", "()I").returns(1).done(); 219 } 220 221 { // After redefinition 222 TestBuilder after = factory.getBuilder(); 223 224 Interface I = after.intf("I") 225 .defaultMethod("m", "()I").returns(2).build() 226 .build(); 227 ConcreteClass C = after.clazz("C").implement(I).build(); 228 229 Tester T1 = after.test().callSite(I, C, "m", "()I").returns(2).build(); 230 Tester T2 = after.test().callSite(C, C, "m", "()I").returns(2).build(); 231 232 redefineAndRun(before, after, I, T1, T2); 233 } 234 } 235 }