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 package org.apache.harmony.jpda.tests.jdwp.Events;
20 
21 import org.apache.harmony.jpda.tests.framework.jdwp.EventPacket;
22 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
23 import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent;
24 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
25 import org.apache.harmony.jpda.tests.jdwp.Events.CombinedExceptionEventsDebuggee.SubDebuggeeException;
26 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
27 
28 import java.util.Arrays;
29 
30 /**
31  * JDWP Unit test for combined EXCEPTION events.
32  */
33 public class CombinedExceptionEventsTest extends CombinedEventsTestCase {
34     @Override
getDebuggeeClassName()35     protected String getDebuggeeClassName() {
36         return CombinedExceptionEventsDebuggee.class.getName();
37     }
38 
39     /**
40      * Tests combined EXCEPTION events for caught exception. It runs the
41      * CombinedExceptionEventsDebuggee and verifies we only received
42      * EXCEPTION events for caught exception.
43      */
testCombinedExceptionEvents_CaughtExceptionOnly()44     public void testCombinedExceptionEvents_CaughtExceptionOnly() {
45         runCombinedExceptionEventsTest(false);
46     }
47 
48     /**
49      * Tests combined EXCEPTION events for uncaught exception. It runs the
50      * CombinedExceptionEventsDebuggee and verifies we only received
51      * EXCEPTION events for uncaught exception.
52      */
testCombinedExceptionEvents_UncaughtExceptionOnly()53     public void testCombinedExceptionEvents_UncaughtExceptionOnly() {
54         runCombinedExceptionEventsTest(true);
55     }
56 
57     /**
58      * Tests combined EXCEPTION events. It runs the CombinedExceptionEventsDebuggee
59      * and requests the following EXCEPTION events:
60      * <ol>
61      * <li>only caught DebuggeeException (and subclasses)</li>
62      * <li>only caught SubDebuggeeException (and subclasses)</li>
63      * <li>only uncaught DebuggeeException (and subclasses)</li>
64      * <li>only uncaught SubDebuggeeException (and subclasses)</li>
65      * <li>caught and uncaught DebuggeeException (and subclasses)</li>
66      * <li>caught and uncaught SubDebuggeeException (and subclasses)</li>
67      * </ol>
68      *
69      * Finally it verifies we received only the expected events.
70      *
71      * @param testUncaughtException
72      *          true to test uncaught exception, false to test caught exception.
73      */
runCombinedExceptionEventsTest(boolean testUncaughtException)74     private void runCombinedExceptionEventsTest(boolean testUncaughtException) {
75         // Wait for debuggee.
76         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
77 
78         String superExceptionClassSignature = getClassSignature(
79                 DebuggeeException.class);
80         String subExceptionClassSignature = getClassSignature(
81                 SubDebuggeeException.class);
82 
83         long superExceptionClassID = debuggeeWrapper.vmMirror.getClassID(
84                 superExceptionClassSignature);
85         long subExceptionClassID = debuggeeWrapper.vmMirror.getClassID(
86                 subExceptionClassSignature);
87 
88         // Request "caught only" exceptions with super and sub classes.
89         int request1 = requestException(superExceptionClassID, true, false);
90         int request2 = requestException(subExceptionClassID, true, false);
91 
92         // Request "uncaught only" exceptions with super and sub classes.
93         int request3 = requestException(superExceptionClassID, false, true);
94         int request4 = requestException(subExceptionClassID, false, true);
95 
96         // Request "caught & uncaught" exceptions with super and sub classes.
97         int request5 = requestException(superExceptionClassID, true, true);
98         int request6 = requestException(subExceptionClassID, true, true);
99 
100         int[] expectedRequests = null;
101         String signalMessage = null;
102         if (testUncaughtException) {
103             // We expect requests 3, 4, 5 and 6.
104             expectedRequests = new int[] { request3, request4, request5, request6 };
105             signalMessage = CombinedExceptionEventsDebuggee.TEST_UNCAUGHT_EXCEPTION_SIGNAL;
106         } else {
107             // We expect requests 1, 2, 5 and 6.
108             expectedRequests = new int[] { request1, request2, request5, request6 };
109             signalMessage = CombinedExceptionEventsDebuggee.TEST_CAUGHT_EXCEPTION_SIGNAL;
110         }
111 
112         // Signal debuggee.
113         synchronizer.sendMessage(signalMessage);
114 
115         printTestLog("=> receiveEvent()...");
116         EventPacket event = debuggeeWrapper.vmMirror.receiveEvent();
117         ParsedEvent[] parsedEvents = ParsedEvent.parseEventPacket(event);
118         printTestLog("Received " + parsedEvents.length + " + event(s).");
119 
120         int[] receivedRequests = new int[parsedEvents.length];
121         long eventThreadID = -1;
122         long exceptionObjectID = -1;
123         for (int i = 0; i < parsedEvents.length; ++i) {
124             ParsedEvent parsedEvent = parsedEvents[i];
125             byte eventKind = parsedEvent.getEventKind();
126             int requestID = parsedEvent.getRequestID();
127             printTestLog("Event #" + i + ": kind="
128                     + JDWPConstants.EventKind.getName(eventKind)
129                     + ", requestID=" + requestID);
130             assertEquals("Invalid event kind,",
131                     JDWPConstants.EventKind.EXCEPTION, eventKind,
132                     JDWPConstants.EventKind.getName(
133                             JDWPConstants.EventKind.EXCEPTION),
134                     JDWPConstants.EventKind.getName(eventKind));
135 
136             ParsedEvent.Event_EXCEPTION exceptionEvent = (ParsedEvent.Event_EXCEPTION) parsedEvent;
137 
138             long currentEventThreadID = exceptionEvent.getThreadID();
139             long currentExceptionObjectID = exceptionEvent
140                     .getException().objectID;
141             // Checks all events are for the same thread.
142             if (eventThreadID != -1) {
143                 assertEquals("Invalid event thread ID", eventThreadID,
144                         currentEventThreadID);
145             } else {
146                 eventThreadID = currentEventThreadID;
147             }
148             // Checks all events are for the same exception.
149             if (exceptionObjectID != -1) {
150                 assertEquals("Invalid exception object ID", exceptionObjectID,
151                         currentExceptionObjectID);
152             } else {
153                 exceptionObjectID = currentExceptionObjectID;
154             }
155             // Check thread is properly suspended.
156             checkThreadState(eventThreadID, JDWPConstants.ThreadStatus.RUNNING,
157                     JDWPConstants.SuspendStatus.SUSPEND_STATUS_SUSPENDED);
158 
159             receivedRequests[i] = requestID;
160         }
161 
162         // Check we receive all expected events.
163         Arrays.sort(expectedRequests);
164         Arrays.sort(receivedRequests);
165         if (!Arrays.equals(expectedRequests, receivedRequests)) {
166             String expectedArrayString = Arrays.toString(expectedRequests);
167             String receivedArrayString = Arrays.toString(receivedRequests);
168             fail("Unexpected event: expected " + expectedArrayString
169                     + " but got " + receivedArrayString);
170         }
171     }
172 
requestException(long exceptionClassID, boolean caught, boolean uncaught)173     private int requestException(long exceptionClassID, boolean caught,
174             boolean uncaught) {
175         printTestLog("Request EXCEPTION event: class=" + exceptionClassID + ", caught="
176                 + caught + ", uncaught=" + uncaught);
177         ReplyPacket replyPacket = debuggeeWrapper.vmMirror.setException(
178                 exceptionClassID, caught, uncaught);
179         int requestID = replyPacket.getNextValueAsInt();
180         assertAllDataRead(replyPacket);
181         printTestLog("Created request " + requestID);
182         return requestID;
183     }
184 }
185