1 /* 2 * Copyright (c) 2001, 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 4467564 27 * @summary Test the popping of frames in synchronous context 28 * (that is, when stopped at an event) 29 * 30 * @author Robert Field 31 * 32 * @run build TestScaffold VMConnection TargetListener TargetAdapter 33 * @run compile -g PopSynchronousTest.java 34 * @run driver PopSynchronousTest 35 */ 36 import com.sun.jdi.*; 37 import com.sun.jdi.event.*; 38 import com.sun.jdi.request.*; 39 40 import java.util.*; 41 42 /********** target program **********/ 43 44 class PopSynchronousTarg { 45 static String s; 46 static PopSynchronousTarg sole; 47 48 synchronized void a(int y, boolean w) { 49 if (y == 6 && w) { 50 s += "@"; 51 } else { 52 s += " aArgFail "; 53 } 54 } 55 String b(String h) { 56 if (h.equals("yo")) { 57 s += "["; 58 } else { 59 s += " bArgFail "; 60 } 61 a(6, true); 62 s += "]"; 63 return s; 64 } 65 long c() { 66 s += "<"; 67 synchronized (s) { 68 b("yo"); 69 } 70 s += ">"; 71 return 17; 72 } 73 static void p() { 74 s += "("; 75 if (sole.c() != 17) { 76 s += " cReturnFail "; 77 } 78 s += ")"; 79 } 80 static void report() { 81 } 82 public static void main(String[] args){ 83 s = new String(); 84 sole = new PopSynchronousTarg(); 85 for (int i = 0; i < 100; ++i) { 86 p(); 87 // System.out.println(s); 88 report(); 89 } 90 } 91 } 92 93 /********** test program **********/ 94 95 public class PopSynchronousTest extends TestScaffold { 96 ReferenceType targetClass; 97 ThreadReference mainThread; 98 int stateIndex = 0; 99 String expected = ""; 100 static final String[] calls = {"a", "b", "c", "p", "main"}; 101 static final int popMax = calls.length - 1; 102 static final String[] states = 103 {"main-i", "p-e", "p-i", "c-e", "c-i", "b-e", "b-i", "a-e", "a-l", "b-l", "c-l", "p-l", "main-r", "report-e"}; 104 static final String[] output = 105 {"", "", "(", "", "<", "", "[", "", "@", "]", ">", ")", "", ""}; 106 107 108 PopSynchronousTest (String args[]) { 109 super(args); 110 } 111 112 public static void main(String[] args) throws Exception { 113 new PopSynchronousTest(args).startTests(); 114 } 115 116 117 /********** test assist **********/ 118 119 StackFrame frameFor(String methodName) throws Exception { 120 Iterator it = mainThread.frames().iterator(); 121 122 while (it.hasNext()) { 123 StackFrame frame = (StackFrame)it.next(); 124 if (frame.location().method().name().equals(methodName)) { 125 return frame; 126 } 127 } 128 failure("FAIL: " + methodName + " not on stack"); 129 return null; 130 } 131 132 String actual() throws Exception { 133 Field field = targetClass.fieldByName("s"); 134 StringReference sr = (StringReference)(targetClass.getValue(field)); 135 return sr.value(); 136 } 137 138 void checkExpected() throws Exception { 139 if (!actual().equals(expected)) { 140 failure("FAIL: expected value: " + expected + 141 " got: " + actual()); 142 } 143 } 144 145 int methodIndex(String methodName) { 146 for (int i = 0; i < popMax; ++i) { 147 if (methodName.equals(calls[i])) { 148 return i; 149 } 150 } 151 return -1; 152 } 153 154 boolean isTop(String methodName) throws Exception { 155 return mainThread.frame(0).location().method().name().equals(methodName); 156 } 157 158 void checkTop(String methodName, boolean atStart) throws Exception { 159 Location loc = mainThread.frame(0).location(); 160 Method meth = loc.method(); 161 String name = meth.name(); 162 if (!isTop(methodName)) { 163 failure("FAIL: expected " + methodName + 164 " at top of stack, instead: " + name); 165 } else if ((meth.location().codeIndex() == loc.codeIndex()) != atStart) { 166 failure("FAIL: not at expect position: " + loc.codeIndex()); 167 } 168 } 169 170 void checkState() throws Exception { 171 String name = states[stateIndex]; 172 int dash = name.indexOf('-'); 173 String methodName = name.substring(0,dash); 174 String posName = name.substring(dash+1); 175 checkTop(methodName, posName.equals("e")); 176 checkExpected(); 177 } 178 179 void incrementState() { 180 stateIndex = (stateIndex + 1) % (states.length); 181 } 182 183 void resetState(String stateName) { 184 for (int i=0; i < states.length; ++i) { 185 if (states[i].equals(stateName)) { 186 stateIndex = i; 187 return; 188 } 189 } 190 failure("TEST FAILURE: cannot find state: " + stateName); 191 } 192 193 void resetExpected() throws Exception { 194 println("Current value: " + actual()); 195 Field field = targetClass.fieldByName("s"); 196 expected = ""; 197 ((ClassType)targetClass).setValue(field, vm().mirrorOf(expected)); 198 } 199 200 void stateTo(String stateName) { 201 do { 202 incrementState(); 203 expected += output[stateIndex]; 204 } while(!states[stateIndex].equals(stateName)); 205 } 206 207 void resumeTo(String methodName) throws Exception { 208 List meths = targetClass.methodsByName(methodName); 209 Method meth = (Method)(meths.get(0)); 210 resumeTo(meth.location()); 211 stateTo(methodName + "-e"); 212 checkState(); 213 } 214 215 void pop(String methodName) throws Exception { 216 mainThread.popFrames(frameFor(methodName)); 217 resetState(methodName + "-e"); 218 --stateIndex; 219 checkState(); 220 } 221 222 void reenter(String methodName) throws Exception { 223 pop(methodName); 224 stepIntoInstruction(mainThread); 225 incrementState(); 226 checkState(); 227 } 228 229 /********** test core **********/ 230 231 protected void runTests() throws Exception { 232 /* 233 * Get to the top of main() 234 * to determine targetClass and mainThread 235 */ 236 BreakpointEvent bpe = startToMain("PopSynchronousTarg"); 237 targetClass = bpe.location().declaringType(); 238 mainThread = bpe.thread(); 239 240 /* 241 * Testing 242 */ 243 244 /* individual tests */ 245 for (int i = 0; i < popMax; ++i) { 246 String from = calls[i]; 247 for (int j = i; j < popMax; ++j) { 248 String to = calls[j]; 249 String prev = calls[j+1]; 250 println("TEST pop from '" + from + "' to '" + to + "'"); 251 resumeTo(from); 252 reenter(to); 253 resumeTo("report"); 254 resetExpected(); 255 } 256 } 257 258 /* sequential tests */ 259 260 println("TEST pop a b c p"); 261 resumeTo("a"); 262 pop("a"); 263 pop("b"); 264 pop("c"); 265 pop("p"); 266 resumeTo("report"); 267 resetExpected(); 268 269 println("TEST pop a c p"); 270 resumeTo("a"); 271 pop("a"); 272 pop("c"); 273 pop("p"); 274 resumeTo("report"); 275 resetExpected(); 276 277 println("TEST stress a"); 278 resumeTo("a"); 279 for (int i = 0; i < 100; ++i) { 280 reenter("a"); 281 } 282 resumeTo("report"); 283 resetExpected(); 284 285 println("TEST stress c"); 286 resumeTo("c"); 287 for (int i = 0; i < 100; ++i) { 288 reenter("c"); 289 } 290 resumeTo("report"); 291 resetExpected(); 292 293 /* 294 * we are done, get rid of target 295 */ 296 vm().dispose(); 297 298 /* 299 * deal with results of test 300 * if anything has called failure("foo") testFailed will be true 301 */ 302 if (!testFailed) { 303 println("PopSynchronousTest: passed"); 304 } else { 305 throw new Exception("PopSynchronousTest: failed"); 306 } 307 } 308 }