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