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.EventModifiers;
20 
21 import org.apache.harmony.jpda.tests.framework.Breakpoint;
22 import org.apache.harmony.jpda.tests.framework.jdwp.Event;
23 import org.apache.harmony.jpda.tests.framework.jdwp.EventBuilder;
24 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
25 import org.apache.harmony.jpda.tests.framework.jdwp.Value;
26 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
27 
28 /**
29  * JDWP Unit test for Count event modifier.
30  */
31 public class CountModifierTest extends JDWPEventModifierTestCase {
32     private static final
33             String DEBUGGEE_SIGNATURE = "Lorg/apache/harmony/jpda/tests/jdwp/EventModifiers/CountModifierDebuggee;";
34     private static final
35             String TEST_CLASS_SIGNATURE = "Lorg/apache/harmony/jpda/tests/jdwp/EventModifiers/CountModifierDebuggee$TestClass;";
36     private static final
37             String TEST_CLASS_NAME = "org.apache.harmony.jpda.tests.jdwp.EventModifiers.CountModifierDebuggee$TestClass";
38     private static final
39             String EXCEPTION_SIGNATURE = "Lorg/apache/harmony/jpda/tests/jdwp/EventModifiers/CountModifierDebuggee$TestException;";
40 
41     // The name of the test method where we set our event requests.
42     private static final String METHOD_NAME = "eventTestMethod";
43 
44     // The name of the test method where we set our event requests.
45     private static final String WATCHED_FIELD_NAME = "watchedField";
46 
47     // Fields for verifying events count.
48     private static final String
49             LOCATION_COUNT_FIELD_NAME = "locationEventCount";
50     private static final String
51             EXCEPTION_EVENT_COUNT_FIELD_NAME = "exceptionEventCount";
52     private static final String THREAD_RUN_COUNT_FIELD_NAME = "threadRunCount";
53     private static final String
54             FIELD_READ_WRITE_COUNT_FIELD_NAME = "fieldReadWriteCount";
55 
56     @Override
getDebuggeeClassName()57     protected String getDebuggeeClassName() {
58         return CountModifierDebuggee.class.getName();
59     }
60 
61     /**
62      * This testcase is for BREAKPOINT event with Count modifier.
63      * <BR>It runs CountModifierDebuggee and sets BREAKPOINT to its
64      * {@link CountModifierDebuggee.TestClass#eventTestMethod()} method.
65      * <BR>Then calls this method multiple times and verifies that requested
66      * BREAKPOINT event occurs once after having called the method (count - 1)
67      * times. We check this by looking at the value in the field
68      * {@link CountModifierDebuggee#locationEventCount}.
69      */
testBreakpoint()70     public void testBreakpoint() {
71         logWriter.println("testBreakpoint started");
72 
73         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
74 
75         // Breakpoint at start of test method.
76         byte typeTag = JDWPConstants.TypeTag.CLASS;
77         Breakpoint breakpoint = new Breakpoint(TEST_CLASS_SIGNATURE,
78                 METHOD_NAME, 0);
79         EventBuilder builder = createBreakpointEventBuilder(typeTag,
80                 breakpoint);
81         testEventWithCountModifier(builder, LOCATION_COUNT_FIELD_NAME);
82 
83         logWriter.println("testBreakpoint done");
84     }
85 
86     /**
87      * This testcase is for METHOD_ENTRY event with Count modifier.
88      * <BR>It runs CountModifierDebuggee and sets METHOD_ENTRY to the
89      * {@link CountModifierDebuggee.TestClass} class.
90      * <BR>Then calls {@link CountModifierDebuggee.TestClass#eventTestMethod()}
91      * method multiple times and verifies that requested METHOD_ENTRY event
92      * occurs once after having called the method (count - 1) times. We check
93      * this by looking at the value in the field
94      * {@link CountModifierDebuggee#locationEventCount}.
95      */
testMethodEntry()96     public void testMethodEntry() {
97         logWriter.println("testMethodEntry started");
98 
99         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
100         EventBuilder builder = createMethodEntryEventBuilder(TEST_CLASS_NAME);
101         testEventWithCountModifier(builder, LOCATION_COUNT_FIELD_NAME);
102 
103         logWriter.println("testMethodEntry done");
104     }
105 
106     /**
107      * This testcase is for METHOD_EXIT event with Count modifier.
108      * <BR>It runs CountModifierDebuggee and sets METHOD_EXIT to the
109      * {@link CountModifierDebuggee.TestClass} class.
110      * <BR>Then calls {@link CountModifierDebuggee.TestClass#eventTestMethod()}
111      * method multiple times and verifies that requested METHOD_EXIT event
112      * occurs once after having called the method (count - 1) times. We check
113      * this by looking at the value in the field
114      * {@link CountModifierDebuggee#locationEventCount}.
115      */
testMethodExit()116     public void testMethodExit() {
117         logWriter.println("testMethodExit started");
118 
119         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
120         EventBuilder builder = createMethodExitEventBuilder(TEST_CLASS_NAME);
121         testEventWithCountModifier(builder, LOCATION_COUNT_FIELD_NAME);
122 
123         logWriter.println("testMethodExit done");
124     }
125 
126 
127     /**
128      * This testcase is for METHOD_EXIT_WITH_RETURN_VALUE event with Count
129      * modifier.
130      * <BR>It runs CountModifierDebuggee and sets METHOD_EXIT_WITH_RETURN_VALUE
131      * to the {@link CountModifierDebuggee.TestClass} class.
132      * <BR>Then calls {@link CountModifierDebuggee.TestClass#eventTestMethod()}
133      * method multiple times and verifies that requested
134      * METHOD_EXIT_WITH_RETURN_VALUE event occurs once after having called the
135      * method (count - 1) times. We check this by looking at the value in the
136      * field {@link CountModifierDebuggee#locationEventCount}.
137      */
testMethodExitWithReturnValue()138     public void testMethodExitWithReturnValue() {
139         logWriter.println("testMethodExitWithReturnValue started");
140 
141         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
142         EventBuilder builder = createMethodExitWithReturnValueEventBuilder(TEST_CLASS_NAME);
143         testEventWithCountModifier(builder, LOCATION_COUNT_FIELD_NAME);
144 
145         logWriter.println("testMethodExitWithReturnValue done");
146     }
147 
148     /**
149      * This testcase is for EXCEPTION event with Count modifier.
150      * <BR>It runs CountModifierDebuggee and sets EXCEPTION to the
151      * {@link CountModifierDebuggee.TestException} class but only for caught
152      * exceptions.
153      * <BR>Then calls {@link CountModifierDebuggee.TestClass#throwException}
154      * method multiple times and verifies that requested EXCEPTION event
155      * occurs once after having called the method (count - 1) times. We check
156      * this by looking at the value in the field
157      * {@link CountModifierDebuggee#exceptionEventCount}.
158      */
testException()159     public void testException() {
160         logWriter.println("testException started");
161 
162         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
163         EventBuilder builder = createExceptionEventBuilder(EXCEPTION_SIGNATURE,
164                 true, false);
165         testEventWithCountModifier(builder,
166                 EXCEPTION_EVENT_COUNT_FIELD_NAME);
167 
168         logWriter.println("testException done");
169     }
170 
171     /**
172      * This testcase is for FIELD_ACCESS event with Count modifier.
173      * <BR>It runs CountModifierDebuggee and requests FIELD_ACCESS event for
174      * {@link CountModifierDebuggee#watchedField}.
175      * <BR>Then calls {@link CountModifierDebuggee#readAndWriteField()}
176      * method multiple times and verifies that requested FIELD_ACCESS event
177      * occurs once after having called the method (count - 1) times. We check
178      * this by looking at the value in the field
179      * {@link CountModifierDebuggee#fieldReadWriteCount}.
180      * <BR>Note: if the VM does not support the canWatchFieldAccess capability,
181      * the test succeeds.
182      */
testFieldAccess()183     public void testFieldAccess() {
184         logWriter.println("testFieldAccess started");
185 
186         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
187 
188         if (!canWatchFieldAccessCapability()) {
189             synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
190             return;
191         }
192 
193         EventBuilder builder = createFieldAccessEventBuilder(
194                 JDWPConstants.TypeTag.CLASS, DEBUGGEE_SIGNATURE,
195                 WATCHED_FIELD_NAME);
196         testEventWithCountModifier(builder, FIELD_READ_WRITE_COUNT_FIELD_NAME);
197 
198         logWriter.println("testFieldAccess done");
199     }
200 
201     /**
202      * This testcase is for FIELD_MODIFICATION event with Count modifier.
203      * <BR>It runs CountModifierDebuggee and requests FIELD_MODIFICATION event
204      * for {@link CountModifierDebuggee#watchedField}.
205      * <BR>Then calls {@link CountModifierDebuggee#readAndWriteField()}
206      * method multiple times and verifies that requested FIELD_MODIFICATION
207      * event occurs once after having called the method (count - 1) times. We
208      * check this by looking at the value in the field
209      * {@link CountModifierDebuggee#fieldReadWriteCount}.
210      * <BR>Note: if the VM does not support the canWatchFieldModification
211      * capability, the test succeeds.
212      */
testFieldModification()213     public void testFieldModification() {
214         logWriter.println("testFieldModification started");
215 
216         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
217 
218         if (!canWatchFieldModificationCapability()) {
219             synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
220             return;
221         }
222 
223         EventBuilder builder = createFieldModificationEventBuilder(
224                 JDWPConstants.TypeTag.CLASS, DEBUGGEE_SIGNATURE,
225                 WATCHED_FIELD_NAME);
226         testEventWithCountModifier(builder, FIELD_READ_WRITE_COUNT_FIELD_NAME);
227 
228         logWriter.println("testFieldModification done");
229     }
230 
testEventWithCountModifier(EventBuilder builder, String countFieldName)231     private void testEventWithCountModifier(EventBuilder builder,
232             String countFieldName) {
233         // Add count modifier and build the event.
234         builder.setCount(CountModifierDebuggee.EVENT_COUNT);
235         Event event = builder.build();
236         int requestID = requestEvent(event);
237 
238         waitForEvent(event.eventKind, requestID);
239 
240         // Check we properly ignore the (count - 1) previous events.
241         int expectedCount = CountModifierDebuggee.EVENT_COUNT;
242         int actualCount = getStaticIntField(DEBUGGEE_SIGNATURE, countFieldName);
243         assertEquals("Invalid event count", expectedCount, actualCount);
244 
245         clearAndResume(event.eventKind, requestID);
246     }
247 
getStaticIntField(String classSignature, String fieldName)248     private int getStaticIntField(String classSignature, String fieldName) {
249         Value fieldValue = getFieldValue(classSignature, fieldName);
250         assertEquals("Invalid field value tag", JDWPConstants.Tag.INT_TAG,
251                 fieldValue.getTag());
252         return fieldValue.getIntValue();
253     }
254 
255 }
256