1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 /** 20 * @author Vitaly A. Provodin, Anatoly F. Bondarenko 21 */ 22 23 /** 24 * Created on 10.02.2005 25 */ 26 package org.apache.harmony.jpda.tests.jdwp.VirtualMachine; 27 28 import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket; 29 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands; 30 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants; 31 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket; 32 import org.apache.harmony.jpda.tests.framework.jdwp.exceptions.ReplyErrorCodeException; 33 import org.apache.harmony.jpda.tests.jdwp.share.JDWPSyncTestCase; 34 35 import java.util.ArrayList; 36 import java.util.List; 37 38 39 /** 40 * JDWP Unit test for VirtualMachine.Resume command. 41 */ 42 public class ResumeTest extends JDWPSyncTestCase { 43 44 static final String debuggeeSignature = 45 "Lorg/apache/harmony/jpda/tests/jdwp/VirtualMachine/ResumeDebuggee;"; 46 getDebuggeeClassName()47 protected String getDebuggeeClassName() { 48 return ResumeDebuggee.class.getName(); 49 } 50 51 @Override internalTearDown()52 protected void internalTearDown() { 53 // We need to finish the tested threads before detaching. 54 logWriter.println("Finish debuggee tested threads"); 55 setStaticIntField(debuggeeSignature, 56 ResumeDebuggee.TO_FINISH_DEBUGGEE_FIELD_NAME, 99); 57 super.internalTearDown(); 58 } 59 60 /** 61 * This testcase exercises VirtualMachine.Resume command. 62 * <BR>At first the test starts ResumeDebuggee which starts and runs some tested threads. 63 * <BR> Then the test performs VirtualMachine.Suspend command and checks with help of 64 * ThreadReference.Status command that all debuggee tested threads are suspended. 65 * <BR> Then the test performs VirtualMachine.Resume command and checks with help of 66 * ThreadReference.Status command that all debuggee tested threads are resumed. 67 */ testResume001()68 public void testResume001() { 69 logWriter.println("==> testResume001: START..."); 70 71 // The error messages in case of test failure. 72 List<String> errorMessages = new ArrayList<String>(); 73 74 // All the threads we're interested in. 75 ThreadInfo[] threadInfos = createThreadInfos(); 76 77 // Suspend all threads with VirtualMachine.Suspend command. 78 suspendAll(); 79 80 // Check all threads are suspended now. 81 logWriter.println("\n==> Check that all tested threads are suspended " + 82 "after VirtualMachine.Suspend command..."); 83 checkThreadStatus(threadInfos, true, errorMessages); 84 85 // Resume all threads with VirtualMachine.Resume command. 86 resumeAll(); 87 88 // Check all threads are NOT suspended anymore. 89 logWriter.println("\n==> Check that all tested threads are resumed " + 90 "after VirtualMachine.Resume command..."); 91 checkThreadStatus(threadInfos, false, errorMessages); 92 93 if (!errorMessages.isEmpty()) { 94 // Print error messages first. 95 for (String errorMessage : errorMessages) { 96 logWriter.printError(errorMessage + "\n"); 97 } 98 printErrorAndFail("\ntestResume001 FAILED"); 99 } else { 100 logWriter.println("\n==> testResume001 - OK!"); 101 } 102 } 103 104 /** 105 * This testcase exercises VirtualMachine.Resume command. 106 * <BR>At first the test starts ResumeDebuggee which starts and runs some 107 * tested threads. 108 * <BR> Then the test performs VirtualMachine.Suspend command twice and 109 * checks, with help of ThreadReference.Status command, that all debuggee 110 * tested threads are suspended. 111 * <BR> Then the test performs VirtualMachine.Resume command and checks 112 * that all debuggee tested threads are still suspended. 113 * <BR> Then the test performs VirtualMachine.Resume command again and 114 * checks that all debuggee tested threads are resumed. 115 */ testResume002()116 public void testResume002() { 117 logWriter.println("==> testResume002: START..."); 118 119 // The error messages in case of test failure. 120 List<String> errorMessages = new ArrayList<String>(); 121 122 // All the threads we're interested in. 123 ThreadInfo[] threadInfos = createThreadInfos(); 124 125 // Suspend all threads with VirtualMachine.Suspend command. 126 suspendAll(); 127 128 // Check all threads are suspended now. 129 logWriter.println("\n==> Check that all tested threads are suspended " + 130 "after VirtualMachine.Suspend command..."); 131 checkThreadStatus(threadInfos, true, errorMessages); 132 133 // Suspend all threads again. 134 suspendAll(); 135 136 // Check all threads are still suspended. 137 logWriter.println("\n==> Check that all tested threads are still " + 138 "suspended after another VirtualMachine.Suspend command..."); 139 checkThreadStatus(threadInfos, true, errorMessages); 140 141 // Resume all threads with VirtualMachine.Resume command. 142 resumeAll(); 143 144 // Check all threads are still suspended. 145 logWriter.println("\n==> Check that all tested threads are still " + 146 "suspended after VirtualMachine.Resume command..."); 147 checkThreadStatus(threadInfos, true, errorMessages); 148 149 // Resume all threads again. 150 resumeAll(); 151 152 // Check all threads are NOT suspended anymore. 153 logWriter.println("\n==> Check that all tested threads are resumed " + 154 "after VirtualMachine.Resume command..."); 155 checkThreadStatus(threadInfos, false, errorMessages); 156 157 if (!errorMessages.isEmpty()) { 158 // Print error messages first. 159 for (String errorMessage : errorMessages) { 160 logWriter.printError(errorMessage + "\n"); 161 } 162 printErrorAndFail("\ntestResume002 FAILED"); 163 } else { 164 logWriter.println("\n==> testResume002 - OK!"); 165 } 166 } 167 168 /** 169 * This testcase exercises VirtualMachine.Resume command. 170 * <BR>At first the test starts ResumeDebuggee which starts and runs some 171 * tested threads. 172 * <BR> Then the test performs VirtualMachine.Resume command and checks it 173 * does not cause any error if we do not perform VirtualMachine.Suspend 174 * before. 175 * <BR> Then the test performs VirtualMachine.Suspend command and checks 176 * that all debuggee tested threads are suspended. 177 * <BR> Then the test performs VirtualMachine.Resume command and checks 178 * that all debuggee tested threads are resumed. 179 */ testResume003()180 public void testResume003() { 181 logWriter.println("==> testResume002: START..."); 182 183 // The error messages in case of test failure. 184 List<String> errorMessages = new ArrayList<String>(); 185 186 // All the threads we're interested in. 187 ThreadInfo[] threadInfos = createThreadInfos(); 188 189 // Resume all threads: should be a no-op. 190 resumeAll(); 191 192 // Check all threads are NOT suspended. 193 logWriter.println("\n==> Check that no tested thread is suspended " + 194 "after VirtualMachine.Resume command..."); 195 checkThreadStatus(threadInfos, false, errorMessages); 196 197 // Suspend all threads with VirtualMachine.Suspend command. 198 suspendAll(); 199 200 // Check all threads are suspended now. 201 logWriter.println("\n==> Check that all tested threads are suspended " + 202 "after VirtualMachine.Suspend command..."); 203 checkThreadStatus(threadInfos, true, errorMessages); 204 205 // Resume all threads with VirtualMachine.Resume command. 206 resumeAll(); 207 208 // Check all threads are NOT suspended anymore. 209 logWriter.println("\n==> Check that all tested threads are resumed " + 210 "after VirtualMachine.Resume command..."); 211 checkThreadStatus(threadInfos, false, errorMessages); 212 213 if (!errorMessages.isEmpty()) { 214 // Print error messages first. 215 for (String errorMessage : errorMessages) { 216 logWriter.printError(errorMessage + "\n"); 217 } 218 printErrorAndFail("\ntestResume002 FAILED"); 219 } else { 220 logWriter.println("\n==> testResume002 - OK!"); 221 } 222 } 223 private static class ThreadInfo { 224 final String threadName; 225 long threadId = 0; 226 ThreadInfo(String threadName)227 public ThreadInfo(String threadName) { 228 this.threadName = threadName; 229 } 230 } 231 232 /** 233 * Suspends all threads using VirtualMachine.Suspend command. 234 */ suspendAll()235 private void suspendAll() { 236 logWriter.println("\n==> Send VirtualMachine.Suspend command..."); 237 CommandPacket packet = new CommandPacket( 238 JDWPCommands.VirtualMachineCommandSet.CommandSetID, 239 JDWPCommands.VirtualMachineCommandSet.SuspendCommand); 240 ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); 241 checkReplyPacket(reply, "VirtualMachine.Suspend"); 242 logWriter.println("==> VirtualMachine.Suspend command - OK."); 243 } 244 245 /** 246 * Resumes all threads using VirtualMachine.Resume command. 247 */ resumeAll()248 private void resumeAll() { 249 logWriter.println("\n==> Send VirtualMachine.Resume command..."); 250 CommandPacket packet = new CommandPacket( 251 JDWPCommands.VirtualMachineCommandSet.CommandSetID, 252 JDWPCommands.VirtualMachineCommandSet.ResumeCommand); 253 ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); 254 checkReplyPacket(reply, "VirtualMachine.Resume"); 255 logWriter.println("==> VirtualMachine.Resume command - OK."); 256 } 257 258 /** 259 * Returns the number of threads used in the tests (including the main 260 * thread). 261 */ getThreadsNumber()262 private int getThreadsNumber() { 263 String debuggeeMessage = synchronizer.receiveMessage(); 264 int testedThreadsNumber = 0; 265 try { 266 testedThreadsNumber = Integer.valueOf(debuggeeMessage).intValue(); 267 } catch (NumberFormatException exception) { 268 logWriter.println("## FAILURE: Exception while getting number of" 269 + " started threads from debuggee = " + exception); 270 printErrorAndFail("\n## Can NOT get number of started threads " 271 + "from debuggee! "); 272 } 273 return testedThreadsNumber + 1; // to add debuggee main thread 274 } 275 276 /** 277 * Creates ThreadInfo array containing information about each tested thread: 278 * thread name and thread JDWP id. 279 */ createThreadInfos()280 private ThreadInfo[] createThreadInfos() { 281 int testedThreadsNumber = getThreadsNumber(); 282 logWriter.println("==> Number of threads in debuggee to test = " 283 + testedThreadsNumber); 284 ThreadInfo[] threadInfos = new ThreadInfo[testedThreadsNumber]; 285 286 String debuggeeMainThreadName = synchronizer.receiveMessage(); 287 // Initialize all threads 288 for (int i = 0, e = threadInfos.length - 1; i < e; ++i) { 289 threadInfos[i] = new ThreadInfo(ResumeDebuggee.THREAD_NAME_PATTERN + i); 290 } 291 threadInfos[threadInfos.length - 1] = new ThreadInfo(debuggeeMainThreadName); 292 293 // Getting ID of the tested thread using VirtualMachine.AllThreads. 294 ReplyPacket allThreadIDReply = null; 295 try { 296 allThreadIDReply = debuggeeWrapper.vmMirror.getAllThreadID(); 297 } catch (ReplyErrorCodeException exception) { 298 logWriter.println 299 ("## FAILURE: Exception in vmMirror.getAllThreadID() = " + exception); 300 printErrorAndFail("\n## Can NOT get all ThreadID in debuggee! "); 301 } 302 int threads = allThreadIDReply.getNextValueAsInt(); 303 logWriter.println("==> Number of all threads in debuggee = " + threads); 304 for (int i = 0; i < threads; i++) { 305 long threadID = allThreadIDReply.getNextValueAsThreadID(); 306 String threadName = null; 307 try { 308 threadName = debuggeeWrapper.vmMirror.getThreadName(threadID); 309 } catch (ReplyErrorCodeException exception) { 310 logWriter.println 311 ("==> WARNING: Can NOT get thread name for threadID = " + threadID); 312 continue; 313 } 314 for (ThreadInfo threadInfo : threadInfos) { 315 if (threadInfo.threadName.equals(threadName) ) { 316 threadInfo.threadId = threadID; 317 break; 318 } 319 } 320 } 321 322 // Check we found thread id for each thread. 323 boolean testedThreadNotFound = false; 324 for (ThreadInfo threadInfo : threadInfos) { 325 if (threadInfo.threadId == 0) { 326 logWriter.println("## FAILURE: Tested thread is not found out " 327 + "among debuggee threads!"); 328 logWriter.println("## Thread name = " 329 + threadInfo.threadName); 330 testedThreadNotFound = true; 331 } 332 } 333 if (testedThreadNotFound) { 334 printErrorAndFail("\n## Some of tested threads are not found!"); 335 } 336 337 return threadInfos; 338 } 339 340 /** 341 * Checks suspend status of each tested thread is the expected one. 342 * 343 * @param threadInfos 344 * the thread information 345 * @param isSuspended 346 * if true, thread must be suspended; otherwise thread 347 * must not be suspended. 348 * @param errorMessages 349 * a list of String to append error message. 350 */ checkThreadStatus(ThreadInfo[] threadInfos, boolean isSuspended, List<String> errorMessages)351 private void checkThreadStatus(ThreadInfo[] threadInfos, 352 boolean isSuspended, List<String> errorMessages) { 353 boolean statusCommandFailed = false; 354 boolean suspendStatusFailed = false; 355 356 for (ThreadInfo threadInfo : threadInfos) { 357 logWriter.println("\n==> Check for Thread: threadID = " 358 + threadInfo.threadId 359 + " (" + threadInfo.threadName + ")"); 360 361 logWriter.println("==> Send ThreadReference.Status command..."); 362 CommandPacket packet = new CommandPacket( 363 JDWPCommands.ThreadReferenceCommandSet.CommandSetID, 364 JDWPCommands.ThreadReferenceCommandSet.StatusCommand); 365 packet.setNextValueAsThreadID(threadInfo.threadId); 366 ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); 367 if (!checkReplyPacketWithoutFail(reply, "ThreadReference.Status command")) { 368 logWriter.println("Can't get thread status for thread " + 369 threadInfo.threadId + 370 " \"" + threadInfo.threadName + "\""); 371 statusCommandFailed = true; 372 continue; 373 } 374 375 int threadStatus = reply.getNextValueAsInt(); 376 int suspendStatus = reply.getNextValueAsInt(); 377 378 logWriter.println("==> threadStatus = " + threadStatus + " (" 379 + JDWPConstants.ThreadStatus.getName(threadStatus) + ")"); 380 logWriter.println("==> suspendStatus = " + suspendStatus + " (" 381 + JDWPConstants.SuspendStatus.getName(suspendStatus) + ")"); 382 383 boolean isThreadSuspended = 384 (suspendStatus == JDWPConstants.SuspendStatus.SUSPEND_STATUS_SUSPENDED); 385 if (isThreadSuspended != isSuspended) { 386 logWriter.println("## FAILURE: Unexpected suspendStatus for " + 387 "checked thread " + threadInfo.threadId + 388 " \"" + threadInfo.threadName + "\""); 389 logWriter.println("## Expected suspendStatus = " 390 + JDWPConstants.SuspendStatus.SUSPEND_STATUS_SUSPENDED 391 + "(" + JDWPConstants.SuspendStatus.getName 392 (JDWPConstants.SuspendStatus.SUSPEND_STATUS_SUSPENDED) +")"); 393 suspendStatusFailed = true; 394 continue; 395 } 396 } 397 398 if (statusCommandFailed) { 399 errorMessages.add("## Error found out while ThreadReference.Status " 400 + "command performing!"); 401 } 402 if (suspendStatusFailed) { 403 errorMessages.add("## Unexpected suspendStatus found out!"); 404 } 405 } 406 } 407