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