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.Event;
22 import org.apache.harmony.jpda.tests.framework.jdwp.EventBuilder;
23 import org.apache.harmony.jpda.tests.framework.jdwp.EventPacket;
24 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
25 import org.apache.harmony.jpda.tests.framework.jdwp.Location;
26 import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent;
27 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
28 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
29 
30 import java.util.HashSet;
31 import java.util.Set;
32 
33 /**
34  * Base class to test event with LocationOnly modifier.
35  */
36 abstract class EventLocationEventTestCase extends JDWPEventTestCase {
37 
38     private Set<Integer> requestIds = new HashSet<Integer>();
39 
getDebuggeeSignature()40     protected abstract String getDebuggeeSignature();
getExpectedLocationMethodName()41     protected abstract String getExpectedLocationMethodName();
createEventBuilder(EventBuilder builder)42     protected abstract void createEventBuilder(EventBuilder builder);
checkEvent(ParsedEvent event)43     protected abstract void checkEvent(ParsedEvent event);
44 
runEventWithLocationTest(byte eventKind)45     protected void runEventWithLocationTest(byte eventKind) {
46         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
47 
48         // Request event for all possible locations in the expected
49         // method.
50         requestEventForAllLocations(eventKind);
51 
52         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
53 
54         // Wait for the event.
55         EventPacket event = debuggeeWrapper.vmMirror.receiveEvent();
56         ParsedEvent[] parsedEvents = ParsedEvent.parseEventPacket(event);
57 
58         // We expect only one event.
59         assertEquals("Invalid number of events,", 1, parsedEvents.length);
60 
61         ParsedEvent parsedEvent = parsedEvents[0];
62 
63         // Check this is the event we expect.
64         assertEquals("Invalid event kind,",
65                 eventKind,
66                 parsedEvent.getEventKind(),
67                 JDWPConstants.EventKind.getName(eventKind),
68                 JDWPConstants.EventKind.getName(parsedEvent.getEventKind()));
69 
70         // Check this is one event we requested.
71         int eventRequestId = parsedEvent.getRequestID();
72         assertTrue("Unexpected event request " + eventRequestId,
73                 requestIds.contains(Integer.valueOf(eventRequestId)));
74 
75         // Check the event is the expected one.
76         checkEvent(parsedEvent);
77 
78         // Clear all event requests.
79         clearAllEvents(eventKind);
80 
81         // Resume debuggee before leaving.
82         resumeDebuggee();
83     }
84 
85     /**
86      * Since we don't know the location where the event can be reported,
87      * we send a request for all possible locations inside the method.
88      */
requestEventForAllLocations(byte eventKind)89     private void requestEventForAllLocations(byte eventKind) {
90         // Ensure we start with no request.
91         requestIds.clear();
92 
93         // Find the method where we expect the event to occur.
94         long typeId = getClassIDBySignature(getDebuggeeSignature());
95         long methodId = getMethodID(typeId, getExpectedLocationMethodName());
96 
97         // Get its line table
98         ReplyPacket replyPacket = getLineTable(typeId, methodId);
99         long startIndex = replyPacket.getNextValueAsLong();
100         long endIndex = replyPacket.getNextValueAsLong();
101         logWriter.println("Method code index starts at " + startIndex +
102                 " and ends at " + endIndex);
103 
104         // Request event at all possible locations. We'd like to do
105         // this for each code instruction but we do not know them and
106         // do not know their size. Therefore we include any code
107         // index between start and end.
108         logWriter.println("Creating request for each possible index");
109         for (long idx = startIndex; idx <= endIndex; ++idx) {
110             Location location = new Location(JDWPConstants.TypeTag.CLASS,
111                     typeId, methodId, idx);
112             EventBuilder builder = new EventBuilder(eventKind,
113                             JDWPConstants.SuspendPolicy.ALL);
114             createEventBuilder(builder);
115             setEvent(builder, location);
116 
117         }
118         logWriter.println("Created " + requestIds.size() + " requests");
119     }
120 
setEvent(EventBuilder builder, Location location)121     private void setEvent(EventBuilder builder, Location location) {
122         builder.setLocationOnly(location);
123         Event event = builder.build();
124         ReplyPacket reply = debuggeeWrapper.vmMirror.setEvent(event);
125         int requestId = reply.getNextValueAsInt();
126         logWriter.println("=> New request " + requestId);
127         requestIds.add(Integer.valueOf(requestId));
128     }
129 
clearAllEvents(byte eventKind)130     private void clearAllEvents(byte eventKind) {
131         logWriter.println("Clear all field requests");
132         for (Integer requestId : requestIds) {
133             clearEvent(eventKind, requestId.intValue());
134         }
135         requestIds.clear();
136     }
137 
clearEvent(byte fieldEventKind, int requestId)138     private void clearEvent(byte fieldEventKind, int requestId) {
139         logWriter.println("=> Clear request " + requestId);
140         debuggeeWrapper.vmMirror.clearEvent(fieldEventKind, requestId);
141     }
142 }
143