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.Deoptimization;
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.share.JDWPSyncTestCase;
26 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
27 
28 public class DeoptimizationWithExceptionHandlingTest extends JDWPSyncTestCase {
29 
30     @Override
getDebuggeeClassName()31     protected String getDebuggeeClassName() {
32         return DeoptimizationWithExceptionHandlingDebuggee.class.getName();
33     }
34 
35     /**
36      * This tests checks we properly handle exception event when we fully
37      * deoptimize the stack.
38      * We first set a BREAKPOINT event to suspend the debuggee. Once we
39      * hit the breakpoint, we set a METHOD_ENTRY event on the debuggee class
40      * to cause a full deoptimization of the stack and resume it.
41      * Finally, we wait for the debuggee to send us the result of the test
42      * (an integer as a string) and check this is the expected result.
43      */
testDeoptimizationWithExceptionHandling_001()44     public void testDeoptimizationWithExceptionHandling_001() {
45         logWriter.println("testDeoptimizationWithExceptionHandling_001 starts");
46         runTestDeoptimizationWithExceptionHandling(false);
47         logWriter.println("testDeoptimizationWithExceptionHandling_001 ends");
48     }
49 
50     /**
51      * This tests checks we properly handle exception event when we fully
52      * deoptimize the stack and are able to receive EXCEPTION event for the
53      * thrown exception.
54      * We first set a BREAKPOINT event to suspend the debuggee. Once we
55      * hit the breakpoint, we set a METHOD_ENTRY event on the debuggee class
56      * to cause a full deoptimization of the stack and an EXCEPTION event
57      * to check we do suspend the debuggee for the thrown exception, and
58      * we resume the debuggee.
59      * Then we wait for the EXCEPTION event to be posted and resume the
60      * debuggee again.
61      * Finally, we wait for the debuggee to send us the result of the test
62      * (an integer as a string) and check this is the expected result.
63      */
testDeoptimizationWithExceptionHandling_002()64     public void testDeoptimizationWithExceptionHandling_002() {
65         logWriter.println("testDeoptimizationWithExceptionHandling_002 starts");
66         runTestDeoptimizationWithExceptionHandling(true);
67         logWriter.println("testDeoptimizationWithExceptionHandling_002 ends");
68     }
69 
runTestDeoptimizationWithExceptionHandling(boolean withExceptionEvent)70     private void runTestDeoptimizationWithExceptionHandling(boolean withExceptionEvent) {
71         // Suspend debuggee on a breakpoint.
72         stopOnBreakpoint();
73 
74         // Request MethodEntry event to cause full deoptimization of the debuggee.
75         installMethodEntry();
76 
77         int exceptionRequestID = -1;
78         if (withExceptionEvent) {
79             // Request Exception event to test we suspend for this event during deoptimization.
80             exceptionRequestID = requestExceptionEvent();
81         }
82 
83         // Resume the debuggee from the breakpoint.
84         debuggeeWrapper.vmMirror.resume();
85 
86         if (exceptionRequestID != -1) {
87             // Wait for the Exception event.
88             waitForExceptionEvent(exceptionRequestID);
89 
90             // Resume the debuggee from the exception.
91             debuggeeWrapper.vmMirror.resume();
92         }
93 
94         // Wait for result from debuggee
95         String resultAsString = synchronizer.receiveMessage();
96         int result = Integer.parseInt(resultAsString);
97 
98         assertEquals("Incorrect result",
99                      DeoptimizationWithExceptionHandlingDebuggee.SUCCESS_RESULT, result);
100     }
101 
stopOnBreakpoint()102     private void stopOnBreakpoint() {
103         // Wait for debuggee to start.
104         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
105 
106         long debuggeeClassID = getClassIDBySignature(getDebuggeeClassSignature());
107         int requestID = debuggeeWrapper.vmMirror.setBreakpointAtMethodBegin(debuggeeClassID,
108                                                                             "breakpointMethod");
109 
110         // Continue debuggee.
111         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
112 
113         // Wait for breakpoint.
114         debuggeeWrapper.vmMirror.waitForBreakpoint(requestID);
115 
116         // Remove breakpoint.
117         debuggeeWrapper.vmMirror.clearBreakpoint(requestID);
118     }
119 
installMethodEntry()120     private void installMethodEntry() {
121         ReplyPacket replyPacket = debuggeeWrapper.vmMirror.setMethodEntry(getDebuggeeClassName());
122         replyPacket.getNextValueAsInt();  // unused 'requestID'
123         assertAllDataRead(replyPacket);
124     }
125 
requestExceptionEvent()126     private int requestExceptionEvent() {
127         final String exceptionClassSignature = "Ljava/lang/NullPointerException;";
128         ReplyPacket replyPacket =
129                 debuggeeWrapper.vmMirror.setException(exceptionClassSignature, true, false);
130         int requestID = replyPacket.getNextValueAsInt();
131         assertAllDataRead(replyPacket);
132         return requestID;
133     }
134 
waitForExceptionEvent(int requestID)135     private void waitForExceptionEvent(int requestID) {
136         final byte eventKind = JDWPConstants.EventKind.EXCEPTION;
137         EventPacket event = debuggeeWrapper.vmMirror.receiveCertainEvent(eventKind);
138 
139         ParsedEvent[] parsedEvents = ParsedEvent.parseEventPacket(event);
140         assertNotNull("Expected an exception event", parsedEvents);
141         assertEquals("Expected only one event", 1, parsedEvents.length);
142         assertEquals("Not the excepted event", requestID, parsedEvents[0].getRequestID());
143 
144         // Clear the event
145         debuggeeWrapper.vmMirror.clearEvent(eventKind, requestID);
146     }
147 }
148