Home | History | Annotate | Download | only in VirtualMachine
      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 
     47     protected String getDebuggeeClassName() {
     48         return ResumeDebuggee.class.getName();
     49     }
     50 
     51     @Override
     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      */
     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      */
    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      */
    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 
    227         public ThreadInfo(String threadName) {
    228             this.threadName = threadName;
    229         }
    230     }
    231 
    232     /**
    233      * Suspends all threads using VirtualMachine.Suspend command.
    234      */
    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      */
    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      */
    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      */
    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      */
    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