More tests for VirtualMachine.Resume command

Tests VirtualMachine.Resume does resume threads only if we perform
this command as many times we performed VirtualMachine.Suspend
command (testResume002).

Tests VirtualMachine.Resume does nothing (and returns no error) if
we did not perform any VirtualMachine.Suspend before (testResume003).

Refactors VirtualMachine.Resume test to factorize code.

Bug: 17974047

(cherry picked from commit eb5230c7c86f552a1238e29877738aa784acf75e)

Change-Id: I032ad819847c884de032d540532f5fbe0ccd48a9
diff --git a/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/VirtualMachine/ResumeTest.java b/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/VirtualMachine/ResumeTest.java
index 47c6aa8..61aeec4 100644
--- a/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/VirtualMachine/ResumeTest.java
+++ b/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/VirtualMachine/ResumeTest.java
@@ -30,9 +30,11 @@
 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
 import org.apache.harmony.jpda.tests.framework.jdwp.exceptions.ReplyErrorCodeException;
-import org.apache.harmony.jpda.tests.jdwp.ThreadReference.ResumeDebuggee;
 import org.apache.harmony.jpda.tests.jdwp.share.JDWPSyncTestCase;
 
+import java.util.ArrayList;
+import java.util.List;
+
 
 /**
  * JDWP Unit test for VirtualMachine.Resume command.
@@ -42,8 +44,17 @@
     static final String debuggeeSignature =
         "Lorg/apache/harmony/jpda/tests/jdwp/VirtualMachine/ResumeDebuggee;";
 
-   protected String getDebuggeeClassName() {
-        return "org.apache.harmony.jpda.tests.jdwp.VirtualMachine.ResumeDebuggee";
+    protected String getDebuggeeClassName() {
+        return ResumeDebuggee.class.getName();
+    }
+
+    @Override
+    protected void internalTearDown() {
+        // We need to finish the tested threads before detaching.
+        logWriter.println("Finish debuggee tested threads");
+        setStaticIntField(debuggeeSignature,
+                ResumeDebuggee.TO_FINISH_DEBUGGEE_FIELD_NAME, 99);
+        super.internalTearDown();
     }
 
     /**
@@ -56,38 +67,236 @@
      */
     public void testResume001() {
         logWriter.println("==> testResume001: START...");
+
+        // The error messages in case of test failure.
+        List<String> errorMessages = new ArrayList<String>();
+
+        // All the threads we're interested in.
+        ThreadInfo[] threadInfos = createThreadInfos();
+
+        // Suspend all threads with VirtualMachine.Suspend command.
+        suspendAll();
+
+        // Check all threads are suspended now.
+        logWriter.println("\n==> Check that all tested threads are suspended " +
+                "after VirtualMachine.Suspend command...");
+        checkThreadStatus(threadInfos, true, errorMessages);
+
+        // Resume all threads with VirtualMachine.Resume command.
+        resumeAll();
+
+        // Check all threads are NOT suspended anymore.
+        logWriter.println("\n==> Check that all tested threads are resumed " +
+                "after VirtualMachine.Resume command...");
+        checkThreadStatus(threadInfos, false, errorMessages);
+
+        if (!errorMessages.isEmpty()) {
+            // Print error messages first.
+            for (String errorMessage : errorMessages) {
+                logWriter.printError(errorMessage + "\n");
+            }
+            printErrorAndFail("\ntestResume001 FAILED");
+        } else {
+            logWriter.println("\n==> testResume001 - OK!");
+        }
+    }
+
+    /**
+     * This testcase exercises VirtualMachine.Resume command.
+     * <BR>At first the test starts ResumeDebuggee which starts and runs some
+     * tested threads.
+     * <BR> Then the test performs VirtualMachine.Suspend command twice and
+     * checks, with help of ThreadReference.Status command, that all debuggee
+     * tested threads are suspended.
+     * <BR> Then the test performs VirtualMachine.Resume command and checks
+     * that all debuggee tested threads are still suspended.
+     * <BR> Then the test performs VirtualMachine.Resume command again and
+     * checks that all debuggee tested threads are resumed.
+     */
+    public void testResume002() {
+        logWriter.println("==> testResume002: START...");
+
+        // The error messages in case of test failure.
+        List<String> errorMessages = new ArrayList<String>();
+
+        // All the threads we're interested in.
+        ThreadInfo[] threadInfos = createThreadInfos();
+
+        // Suspend all threads with VirtualMachine.Suspend command.
+        suspendAll();
+
+        // Check all threads are suspended now.
+        logWriter.println("\n==> Check that all tested threads are suspended " +
+                "after VirtualMachine.Suspend command...");
+        checkThreadStatus(threadInfos, true, errorMessages);
+
+        // Suspend all threads again.
+        suspendAll();
+
+        // Check all threads are still suspended.
+        logWriter.println("\n==> Check that all tested threads are still " +
+                "suspended after another VirtualMachine.Suspend command...");
+        checkThreadStatus(threadInfos, true, errorMessages);
+
+        // Resume all threads with VirtualMachine.Resume command.
+        resumeAll();
+
+        // Check all threads are still suspended.
+        logWriter.println("\n==> Check that all tested threads are still " +
+                "suspended after VirtualMachine.Resume command...");
+        checkThreadStatus(threadInfos, true, errorMessages);
+
+        // Resume all threads again.
+        resumeAll();
+
+        // Check all threads are NOT suspended anymore.
+        logWriter.println("\n==> Check that all tested threads are resumed " +
+                "after VirtualMachine.Resume command...");
+        checkThreadStatus(threadInfos, false, errorMessages);
+
+        if (!errorMessages.isEmpty()) {
+            // Print error messages first.
+            for (String errorMessage : errorMessages) {
+                logWriter.printError(errorMessage + "\n");
+            }
+            printErrorAndFail("\ntestResume002 FAILED");
+        } else {
+            logWriter.println("\n==> testResume002 - OK!");
+        }
+    }
+
+    /**
+     * This testcase exercises VirtualMachine.Resume command.
+     * <BR>At first the test starts ResumeDebuggee which starts and runs some
+     * tested threads.
+     * <BR> Then the test performs VirtualMachine.Resume command and checks it
+     * does not cause any error if we do not perform VirtualMachine.Suspend
+     * before.
+     * <BR> Then the test performs VirtualMachine.Suspend command and checks
+     * that all debuggee tested threads are suspended.
+     * <BR> Then the test performs VirtualMachine.Resume command and checks
+     * that all debuggee tested threads are resumed.
+     */
+    public void testResume003() {
+        logWriter.println("==> testResume002: START...");
+
+        // The error messages in case of test failure.
+        List<String> errorMessages = new ArrayList<String>();
+
+        // All the threads we're interested in.
+        ThreadInfo[] threadInfos = createThreadInfos();
+
+        // Resume all threads: should be a no-op.
+        resumeAll();
+
+        // Check all threads are NOT suspended.
+        logWriter.println("\n==> Check that no tested thread is suspended " +
+                "after VirtualMachine.Resume command...");
+        checkThreadStatus(threadInfos, false, errorMessages);
+
+        // Suspend all threads with VirtualMachine.Suspend command.
+        suspendAll();
+
+        // Check all threads are suspended now.
+        logWriter.println("\n==> Check that all tested threads are suspended " +
+                "after VirtualMachine.Suspend command...");
+        checkThreadStatus(threadInfos, true, errorMessages);
+
+        // Resume all threads with VirtualMachine.Resume command.
+        resumeAll();
+
+        // Check all threads are NOT suspended anymore.
+        logWriter.println("\n==> Check that all tested threads are resumed " +
+                "after VirtualMachine.Resume command...");
+        checkThreadStatus(threadInfos, false, errorMessages);
+
+        if (!errorMessages.isEmpty()) {
+            // Print error messages first.
+            for (String errorMessage : errorMessages) {
+                logWriter.printError(errorMessage + "\n");
+            }
+            printErrorAndFail("\ntestResume002 FAILED");
+        } else {
+            logWriter.println("\n==> testResume002 - OK!");
+        }
+    }
+    private static class ThreadInfo {
+        final String threadName;
+        long threadId = 0;
+
+        public ThreadInfo(String threadName) {
+            this.threadName = threadName;
+        }
+    }
+
+    /**
+     * Suspends all threads using VirtualMachine.Suspend command.
+     */
+    private void suspendAll() {
+        logWriter.println("\n==> Send VirtualMachine.Suspend command...");
+        CommandPacket packet = new CommandPacket(
+                JDWPCommands.VirtualMachineCommandSet.CommandSetID,
+                JDWPCommands.VirtualMachineCommandSet.SuspendCommand);
+        ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
+        checkReplyPacket(reply, "VirtualMachine.Suspend");
+        logWriter.println("==> VirtualMachine.Suspend command - OK.");
+    }
+
+    /**
+     * Resumes all threads using VirtualMachine.Resume command.
+     */
+    private void resumeAll() {
+        logWriter.println("\n==> Send VirtualMachine.Resume command...");
+        CommandPacket packet = new CommandPacket(
+                JDWPCommands.VirtualMachineCommandSet.CommandSetID,
+                JDWPCommands.VirtualMachineCommandSet.ResumeCommand);
+        ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
+        checkReplyPacket(reply, "VirtualMachine.Resume");
+        logWriter.println("==> VirtualMachine.Resume command - OK.");
+    }
+
+    /**
+     * Returns the number of threads used in the tests (including the main
+     * thread).
+     */
+    private int getThreadsNumber() {
         String debuggeeMessage = synchronizer.receiveMessage();
         int testedThreadsNumber = 0;
         try {
             testedThreadsNumber = Integer.valueOf(debuggeeMessage).intValue();
         } catch (NumberFormatException exception) {
-            logWriter.println
-                ("## FAILURE: Exception while getting number of started threads from debuggee = " + exception);
-            setStaticIntField(debuggeeSignature, ResumeDebuggee.TO_FINISH_DEBUGGEE_FIELD_NAME, 99);
-            printErrorAndFail("\n## Can NOT get number of started threads from debuggee! ");
+            logWriter.println("## FAILURE: Exception while getting number of"
+                    + " started threads from debuggee = " + exception);
+            printErrorAndFail("\n## Can NOT get number of started threads "
+                    + "from debuggee! ");
         }
-        testedThreadsNumber++; // to add debuggee main thread
-        logWriter.println("==>  Number of threads in debuggee to test = " + testedThreadsNumber);
-        String[] testedThreadsNames = new String[testedThreadsNumber];
-        long[] testedThreadsIDs = new long[testedThreadsNumber];
-        String debuggeeMainThreadName = synchronizer.receiveMessage();
-        for (int i = 0; i < testedThreadsNumber; i++) {
-            if ( i < (testedThreadsNumber-1) ) {
-                testedThreadsNames[i] = ResumeDebuggee.THREAD_NAME_PATTERN + i;
-            } else {
-                testedThreadsNames[i] = debuggeeMainThreadName;
-            }
-            testedThreadsIDs[i] = 0;
-        }
+        return testedThreadsNumber + 1;  // to add debuggee main thread
+    }
 
-        // getting ID of the tested thread
+    /**
+     * Creates ThreadInfo array containing information about each tested thread:
+     * thread name and thread JDWP id.
+     */
+    private ThreadInfo[] createThreadInfos() {
+        int testedThreadsNumber = getThreadsNumber();
+        logWriter.println("==>  Number of threads in debuggee to test = "
+                + testedThreadsNumber);
+        ThreadInfo[] threadInfos = new ThreadInfo[testedThreadsNumber];
+
+        String debuggeeMainThreadName = synchronizer.receiveMessage();
+        // Initialize all threads
+        for (int i = 0, e = threadInfos.length - 1; i < e; ++i) {
+            threadInfos[i] = new ThreadInfo(ResumeDebuggee.THREAD_NAME_PATTERN + i);
+        }
+        threadInfos[threadInfos.length - 1] = new ThreadInfo(debuggeeMainThreadName);
+
+        // Getting ID of the tested thread using VirtualMachine.AllThreads.
         ReplyPacket allThreadIDReply = null;
         try {
             allThreadIDReply = debuggeeWrapper.vmMirror.getAllThreadID();
         } catch (ReplyErrorCodeException exception) {
             logWriter.println
                 ("## FAILURE: Exception in vmMirror.getAllThreadID() = " + exception);
-            setStaticIntField(debuggeeSignature, ResumeDebuggee.TO_FINISH_DEBUGGEE_FIELD_NAME, 99);
             printErrorAndFail("\n## Can NOT get all ThreadID in debuggee! ");
         }
         int threads = allThreadIDReply.getNextValueAsInt();
@@ -102,59 +311,63 @@
                     ("==> WARNING: Can NOT get thread name for threadID = " + threadID);
                 continue;
             }
-            int k = 0;
-            for (; k < testedThreadsNumber; k++) {
-                if ( threadName.equals(testedThreadsNames[k]) ) {
-                    testedThreadsIDs[k] = threadID;
+            for (ThreadInfo threadInfo : threadInfos) {
+                if (threadInfo.threadName.equals(threadName) ) {
+                    threadInfo.threadId = threadID;
                     break;
                 }
             }
         }
 
+        // Check we found thread id for each thread.
         boolean testedThreadNotFound = false;
-        for (int i = 0; i < testedThreadsNumber; i++) {
-            if ( testedThreadsIDs[i] == 0 ) {
-                logWriter.println("## FAILURE: Tested thread is not found out among debuggee threads!");
-                logWriter.println("##          Thread name = " + testedThreadsNames[i]);
+        for (ThreadInfo threadInfo : threadInfos) {
+            if (threadInfo.threadId == 0) {
+                logWriter.println("## FAILURE: Tested thread is not found out "
+                        + "among debuggee threads!");
+                logWriter.println("##          Thread name = "
+                        + threadInfo.threadName);
                 testedThreadNotFound = true;
             }
         }
-        if ( testedThreadNotFound ) {
-            setStaticIntField(debuggeeSignature, ResumeDebuggee.TO_FINISH_DEBUGGEE_FIELD_NAME, 99);
+        if (testedThreadNotFound) {
             printErrorAndFail("\n## Some of tested threads are not found!");
         }
 
-        logWriter.println("\n==> Send VirtualMachine.Suspend command...");
-        CommandPacket packet = new CommandPacket(
-                JDWPCommands.VirtualMachineCommandSet.CommandSetID,
-                JDWPCommands.VirtualMachineCommandSet.SuspendCommand);
-        ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
-        int errorCode = reply.getErrorCode();
-        if ( errorCode !=  JDWPConstants.Error.NONE ) {
-            setStaticIntField(debuggeeSignature, ResumeDebuggee.TO_FINISH_DEBUGGEE_FIELD_NAME, 99);
-            logWriter.println("## FAILURE: VirtualMachine.Suspend command returns error = " + errorCode
-                    + "(" + JDWPConstants.Error.getName(errorCode) + ")");
-            printErrorAndFail("\nVirtualMachine.Suspend command FAILED!");
-        } else {
-            logWriter.println("==> VirtualMachine.Suspend command - OK.");
-        }
+        return threadInfos;
+    }
 
-        logWriter.println
-        ("\n==> Check that all tested threads are suspended after VirtualMachine.Suspend command...");
-
+    /**
+     * Checks suspend status of each tested thread is the expected one.
+     *
+     * @param threadInfos
+     *          the thread information
+     * @param isSuspended
+     *          if true, thread must be suspended; otherwise thread
+     *          must not be suspended.
+     * @param errorMessages
+     *          a list of String to append error message.
+     */
+    private void checkThreadStatus(ThreadInfo[] threadInfos,
+            boolean isSuspended, List<String> errorMessages) {
         boolean statusCommandFailed = false;
         boolean suspendStatusFailed = false;
-        for (int i = 0; i < testedThreadsNumber; i++) {
-            logWriter.println("\n==> Check for Thread: threadID = " + testedThreadsIDs[i]
-                + "; threadName = " + testedThreadsNames[i]);
+
+        for (ThreadInfo threadInfo : threadInfos) {
+            logWriter.println("\n==> Check for Thread: threadID = "
+                    + threadInfo.threadId
+                    + " (" + threadInfo.threadName + ")");
 
             logWriter.println("==> Send ThreadReference.Status command...");
-            packet = new CommandPacket(
+            CommandPacket packet = new CommandPacket(
                     JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
                     JDWPCommands.ThreadReferenceCommandSet.StatusCommand);
-            packet.setNextValueAsReferenceTypeID(testedThreadsIDs[i]);
-            reply = debuggeeWrapper.vmMirror.performCommand(packet);
-            if ( ! checkReplyPacketWithoutFail(reply, "ThreadReference.Status command") ) {
+            packet.setNextValueAsThreadID(threadInfo.threadId);
+            ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
+            if (!checkReplyPacketWithoutFail(reply, "ThreadReference.Status command")) {
+                logWriter.println("Can't get thread status for thread " +
+                        threadInfo.threadId +
+                        " \"" + threadInfo.threadName + "\"");
                 statusCommandFailed = true;
                 continue;
             }
@@ -162,95 +375,32 @@
             int threadStatus = reply.getNextValueAsInt();
             int suspendStatus = reply.getNextValueAsInt();
 
-            logWriter.println("==> threadStatus = " + threadStatus + "("
+            logWriter.println("==> threadStatus = " + threadStatus + " ("
                     + JDWPConstants.ThreadStatus.getName(threadStatus) + ")");
-            logWriter.println("==> suspendStatus = " + suspendStatus + "("
+            logWriter.println("==> suspendStatus = " + suspendStatus + " ("
                     + JDWPConstants.SuspendStatus.getName(suspendStatus) + ")");
-            if (suspendStatus
-                    != JDWPConstants.SuspendStatus.SUSPEND_STATUS_SUSPENDED) {
-                logWriter.println("## FAILURE: Unexpected suspendStatus for checked thread!");
+
+            boolean isThreadSuspended =
+                    (suspendStatus == JDWPConstants.SuspendStatus.SUSPEND_STATUS_SUSPENDED);
+            if (isThreadSuspended != isSuspended) {
+                logWriter.println("## FAILURE: Unexpected suspendStatus for " +
+                        "checked thread " + threadInfo.threadId +
+                        " \"" + threadInfo.threadName + "\"");
                 logWriter.println("##          Expected suspendStatus  = "
-                    + JDWPConstants.SuspendStatus.SUSPEND_STATUS_SUSPENDED
-                    + "(" + JDWPConstants.SuspendStatus.getName
-                    (JDWPConstants.SuspendStatus.SUSPEND_STATUS_SUSPENDED) +")");
+                        + JDWPConstants.SuspendStatus.SUSPEND_STATUS_SUSPENDED
+                        + "(" + JDWPConstants.SuspendStatus.getName
+                        (JDWPConstants.SuspendStatus.SUSPEND_STATUS_SUSPENDED) +")");
                 suspendStatusFailed = true;
                 continue;
             }
         }
 
-        String errorMessage = "";
-        if ( statusCommandFailed ) {
-            errorMessage = errorMessage + "## Error found out while ThreadReference.Status command performing!\n";
+        if (statusCommandFailed) {
+            errorMessages.add("## Error found out while ThreadReference.Status "
+                    + "command performing!");
         }
-        if ( suspendStatusFailed ) {
-            errorMessage = errorMessage + "## Unexpected suspendStatus found out!\n";
+        if (suspendStatusFailed) {
+            errorMessages.add("## Unexpected suspendStatus found out!");
         }
-
-        logWriter.println("\n==> Send VirtualMachine.Resume command...");
-        packet = new CommandPacket(
-                JDWPCommands.VirtualMachineCommandSet.CommandSetID,
-                JDWPCommands.VirtualMachineCommandSet.ResumeCommand);
-        reply = debuggeeWrapper.vmMirror.performCommand(packet);
-        errorCode = reply.getErrorCode();
-        if ( errorCode !=  JDWPConstants.Error.NONE ) {
-            setStaticIntField(debuggeeSignature, ResumeDebuggee.TO_FINISH_DEBUGGEE_FIELD_NAME, 99);
-            logWriter.println("## FAILURE: VirtualMachine.Resume command returns error = " + errorCode
-                    + "(" + JDWPConstants.Error.getName(errorCode) + ")");
-            printErrorAndFail("\nVirtualMachine.Resume command FAILED!");
-        } else {
-            logWriter.println("==> VirtualMachine.Resume command - OK.");
-        }
-
-        if ( ! errorMessage.equals("") ) {
-            setStaticIntField(debuggeeSignature, ResumeDebuggee.TO_FINISH_DEBUGGEE_FIELD_NAME, 99);
-            printErrorAndFail("\ntestResume001 FAILED:\n" + errorMessage);
-        }
-
-        logWriter.println
-        ("\n==> Check that all tested threads are resumed after VirtualMachine.Resume command...");
-
-        for (int i = 0; i < testedThreadsNumber; i++) {
-            logWriter.println("\n==> Check for Thread: threadID = " + testedThreadsIDs[i]
-                + "; threadName = " + testedThreadsNames[i]);
-
-            logWriter.println("==> Send ThreadReference.Status command...");
-            packet = new CommandPacket(
-                    JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
-                    JDWPCommands.ThreadReferenceCommandSet.StatusCommand);
-            packet.setNextValueAsReferenceTypeID(testedThreadsIDs[i]);
-            reply = debuggeeWrapper.vmMirror.performCommand(packet);
-            if ( ! checkReplyPacketWithoutFail(reply, "ThreadReference.Status command") ) {
-                statusCommandFailed = true;
-                continue;
-            }
-
-            int threadStatus = reply.getNextValueAsInt();
-            int suspendStatus = reply.getNextValueAsInt();
-
-            logWriter.println("==> threadStatus = " + threadStatus + "("
-                    + JDWPConstants.ThreadStatus.getName(threadStatus) + ")");
-            logWriter.println("==> suspendStatus = " + suspendStatus + "("
-                    + JDWPConstants.SuspendStatus.getName(suspendStatus) + ")");
-            if (suspendStatus
-                    == JDWPConstants.SuspendStatus.SUSPEND_STATUS_SUSPENDED) {
-                logWriter.println
-                    ("## FAILURE: Thread still is suspended after VirtualMachine.Resume commands!");
-                suspendStatusFailed = true;
-            }
-        }
-
-        if ( statusCommandFailed ) {
-            errorMessage = errorMessage + "## Error found out while ThreadReference.Status command performing!\n";
-        }
-        if ( suspendStatusFailed ) {
-            errorMessage = errorMessage + "## Unexpected suspendStatus found out!\n";
-        }
-
-        setStaticIntField(debuggeeSignature, ResumeDebuggee.TO_FINISH_DEBUGGEE_FIELD_NAME, 99);
-        if ( ! errorMessage.equals("") ) {
-            printErrorAndFail("\ntestResume001 FAILED:\n" + errorMessage);
-        }
-
-        logWriter.println("\n==> testResume001 - OK!");
     }
 }