Merge "Add tests for DDM 'connected' & 'disconnected' calls"
diff --git a/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/DDM/DDMDebuggee.java b/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/DDM/DDMDebuggee.java
index 4a10d4d..0fa81e8 100644
--- a/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/DDM/DDMDebuggee.java
+++ b/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/DDM/DDMDebuggee.java
@@ -52,11 +52,14 @@
     }
 
     public class TestChunkHandler extends ChunkHandler {
-        @Override
-        public void connected() {}
+        public int connectCount = 0;
+        public int disconnectCount = 0;
 
         @Override
-        public void disconnected() {}
+        public void connected() { connectCount++; }
+
+        @Override
+        public void disconnected() { disconnectCount++; }
 
         @Override
         public Chunk handleChunk(Chunk request) {
@@ -67,21 +70,38 @@
             byte[] res = calculateExpectedResult(request.data, request.offset, request.length);
             return new Chunk(DDM_RESULT_TYPE, res, 0, res.length);
         }
+
+        public String toString() {
+          return "TestChunkHandler { connectCount = " + connectCount +
+                                  ", disconnectCount = " + disconnectCount + " }";
+        }
     }
 
     @Override
     public void run() {
-        ChunkHandler h = new TestChunkHandler();
+        TestChunkHandler h = new TestChunkHandler();
         DdmServer.registerHandler(DDM_TEST_TYPE, h);
         DdmServer.registrationComplete();
         logWriter.println("-> Added chunk handler type: " + DDM_TEST_TYPE + " handler: " + h);
+
         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_READY);
         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
         logWriter.println("Removing handler type: " + DDM_TEST_TYPE);
         DdmServer.unregisterHandler(DDM_TEST_TYPE);
+
         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_READY);
         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
-        logWriter.println("Test complete");
+        // Re-register the chunk handler so we can get the disconnect count.
+        DdmServer.registerHandler(DDM_TEST_TYPE, h);
+
+        synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_READY);
+        // test disposes here.
+        synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
+
+        // Tell the tester if we saw the connected message.
+        synchronizer.sendMessage(Integer.toString(h.connectCount));
+        synchronizer.sendMessage(Integer.toString(h.disconnectCount));
+        logWriter.println("Test complete with handler: " + h);
     }
 
     /**
diff --git a/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/DDM/DDMTest.java b/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/DDM/DDMTest.java
index a7a862a..05b851d 100644
--- a/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/DDM/DDMTest.java
+++ b/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/DDM/DDMTest.java
@@ -18,6 +18,7 @@
 
 package org.apache.harmony.jpda.tests.jdwp.DDM;
 
+import org.apache.harmony.jpda.tests.framework.TestOptions;
 import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands;
 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
@@ -27,11 +28,13 @@
 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
 
 import java.util.Arrays;
+import java.util.Random;
 
 /**
  * JDWP unit test for DDM.Chunk command.
  */
 public class DDMTest extends JDWPSyncTestCase {
+    public static final int REPS = 4;
 
     /**
      * JDWP DDM Command Set constants
@@ -51,11 +54,21 @@
         return "org.apache.harmony.jpda.tests.jdwp.DDM.DDMDebuggee";
     }
 
-    private CommandPacket makeCommand(byte[] test_values) {
+    @Override
+    protected void beforeConnectionSetUp() {
+        settings.setAttachConnectorKind();
+        if (settings.getTransportAddress() == null) {
+            settings.setTransportAddress(TestOptions.DEFAULT_ATTACHING_ADDRESS);
+        }
+        logWriter.println("ATTACH connector kind");
+        super.beforeConnectionSetUp();
+    }
+
+    private CommandPacket makeCommand(int type, byte[] test_values) {
         CommandPacket packet = new CommandPacket(
                 DDMCommandSet.CommandSetID,
                 DDMCommandSet.ChunkCommand);
-        packet.setNextValueAsInt(DDMDebuggee.DDM_TEST_TYPE);
+        packet.setNextValueAsInt(type);
         packet.setNextValueAsInt(test_values.length);
         for (byte b : test_values) {
           packet.setNextValueAsByte(b);
@@ -63,6 +76,10 @@
         return packet;
     }
 
+    private CommandPacket makeCommand(byte[] test_values) {
+        return makeCommand(DDMDebuggee.DDM_TEST_TYPE, test_values);
+    }
+
     /**
      * This testcase exercises DDM.Chunk command.
      * <BR>Starts <A HREF="./DDMDebuggee.html">DDMDebuggee</A> debuggee.
@@ -71,33 +88,91 @@
      */
     public void testChunk001() {
         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
-        byte[] test_values = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
-        CommandPacket packet = makeCommand(test_values);
-        logWriter.println("Send Chunk message with handler");
+        Random r = new Random();
+        // Send a few messages to make sure that everything works correctly and the connected
+        // message gets sent exactly once.
+        byte[] test_values = new byte[128];
+        for (int rep = 0; rep < REPS; rep++) {
+          r.nextBytes(test_values);
+          CommandPacket packet = makeCommand(test_values);
+          logWriter.println("Send Chunk message with handler");
 
-        byte[] expected = DDMDebuggee.calculateExpectedResult(test_values);
-        ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
-        checkReplyPacket(reply, "DDM::Chunk command");
-        int type = reply.getNextValueAsInt();
-        assertEquals("DDM::Chunk returned unexpected type", DDMDebuggee.DDM_RESULT_TYPE, type);
-        int len = reply.getNextValueAsInt();
-        assertEquals("DDM::Chunk returned unexpected amount of data", expected.length, len);
-        byte[] res = new byte[len];
-        for (int i = 0; i < len; i++) {
-          res[i] = reply.getNextValueAsByte();
+          byte[] expected = DDMDebuggee.calculateExpectedResult(test_values);
+          ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
+          checkReplyPacket(reply, "DDM::Chunk command");
+          int type = reply.getNextValueAsInt();
+          assertEquals("DDM::Chunk returned unexpected type", DDMDebuggee.DDM_RESULT_TYPE, type);
+          int len = reply.getNextValueAsInt();
+          assertEquals("DDM::Chunk returned unexpected amount of data", expected.length, len);
+          byte[] res = new byte[len];
+          for (int i = 0; i < len; i++) {
+            res[i] = reply.getNextValueAsByte();
+          }
+          if (!Arrays.equals(expected, res)) {
+            fail("Unexpected different value: expected " + Arrays.toString(expected) + " got " +
+                Arrays.toString(res));
+          }
+          assertAllDataRead(reply);
         }
-        if (!Arrays.equals(expected, res)) {
-          fail("Unexpected different value: expected " + Arrays.toString(expected) + " got " +
-              Arrays.toString(res));
-        }
-        assertAllDataRead(reply);
         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
         logWriter.println("Send same message without handler");
-        packet = makeCommand(test_values);
-        reply = debuggeeWrapper.vmMirror.performCommand(packet);
+        CommandPacket packet = makeCommand(test_values);
+        ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
         checkReplyPacket(reply, "DDM::Chunk command");
         assertAllDataRead(reply);
+
         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
+
+        // Wait for the debuggee to re-register the handler
+        synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
+
+        // Actually disconnect.
+        logWriter.println("");
+        logWriter.println("=> CLOSE CONNECTION");
+        closeConnection();
+        logWriter.println("=> CONNECTION CLOSED");
+
+        logWriter.println("Connecting and disconnecting " + REPS + " times with calls");
+        for (int rep = 0; rep < REPS; rep++) {
+          logWriter.println("");
+          logWriter.println("=> OPEN NEW CONNECTION");
+          openConnection();
+          logWriter.println("=> CONNECTION OPENED");
+
+          logWriter.println("Sending DDM.Chunk command with unused type.");
+          packet = makeCommand(Integer.MAX_VALUE, test_values);
+          reply = debuggeeWrapper.vmMirror.performCommand(packet);
+          checkReplyPacket(reply, "DDM::Chunk command");
+          assertAllDataRead(reply);
+
+          logWriter.println("");
+          logWriter.println("=> CLOSE CONNECTION");
+          closeConnection();
+          logWriter.println("=> CONNECTION CLOSED");
+        }
+        logWriter.println("Connecting and disconnecting " + REPS + " times without calls");
+        for (int rep = 0; rep < REPS; rep++) {
+          logWriter.println("");
+          logWriter.println("=> OPEN NEW CONNECTION");
+          openConnection();
+          logWriter.println("=> CONNECTION OPENED");
+
+          logWriter.println("Doing nothing!");
+
+          logWriter.println("");
+          logWriter.println("=> CLOSE CONNECTION");
+          closeConnection();
+          logWriter.println("=> CONNECTION CLOSED");
+        }
+        synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
+
+        // Get the message saying how many times we got a disconnect/connect.
+        int active_cnt = Integer.parseInt(synchronizer.receiveMessage());
+        assertEquals("Connected got called an unexpected number of times",
+            REPS + 1, active_cnt);
+        int deactive_cnt = Integer.parseInt(synchronizer.receiveMessage());
+        assertEquals("Disconnected got called an unexpected number of times",
+            REPS + 1, deactive_cnt);
     }
 }