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.ParsedEvent.EventThread;
26 import org.apache.harmony.jpda.tests.framework.jdwp.Value;
27 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
28 
29 /**
30  * JDWP Unit test for ThreadOnly event modifier.
31  */
32 public class ThreadOnlyModifierTest extends JDWPEventModifierTestCase {
33 
34     private static final
35             String DEBUGGEE_SIGNATURE = "Lorg/apache/harmony/jpda/tests/jdwp/EventModifiers/ThreadOnlyModifierDebuggee;";
36     private static final
37             String TEST_CLASS_SIGNATURE = "Lorg/apache/harmony/jpda/tests/jdwp/EventModifiers/ThreadOnlyModifierDebuggee$TestClass;";
38     private static final
39             String TEST_CLASS_NAME = "org.apache.harmony.jpda.tests.jdwp.EventModifiers.ThreadOnlyModifierDebuggee$TestClass";
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     private static final String THREAD_FIELD_NAME = "THREAD_ONLY";
48 
49     @Override
getDebuggeeClassName()50     protected String getDebuggeeClassName() {
51         return ThreadOnlyModifierDebuggee.class.getName();
52     }
53 
54     /**
55      * This testcase is for BREAKPOINT event with ThreadOnly modifier.
56      * <BR>It runs ThreadOnlyModifierDebuggee and sets BREAKPOINT to its
57      * {@link ThreadOnlyModifierDebuggee.TestClass#eventTestMethod} method.
58      * <BR>Then calls this method multiple times and verifies that requested
59      * BREAKPOINT event occurs only in the
60      * {@link ThreadOnlyModifierDebuggee#THREAD_ONLY} thread.
61      */
testBreakpoint()62     public void testBreakpoint() {
63         logWriter.println("testBreakpoint started");
64 
65         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
66 
67         byte typeTag = JDWPConstants.TypeTag.CLASS;
68         Breakpoint breakpoint = new Breakpoint(TEST_CLASS_SIGNATURE,
69                 METHOD_NAME, 0);
70         EventBuilder builder = createBreakpointEventBuilder(typeTag,
71                 breakpoint);
72         testEventWithThreadOnlyModifier(builder);
73 
74         logWriter.println("testBreakpoint done");
75     }
76 
77     /**
78      * This testcase is for METHOD_ENTRY event with ThreadOnly modifier.
79      * <BR>It runs ThreadOnlyModifierDebuggee and sets METHOD_ENTRY to the
80      * {@link ThreadOnlyModifierDebuggee.TestClass} class.
81      * <BR>Then calls
82      * {@link ThreadOnlyModifierDebuggee.TestClass#eventTestMethod} method
83      * multiple times and verifies that requested METHOD_ENTRY event occurs
84      * only in the {@link ThreadOnlyModifierDebuggee#THREAD_ONLY} thread.
85      */
testMethodEntry()86     public void testMethodEntry() {
87         logWriter.println("testMethodEntry started");
88 
89         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
90         EventBuilder builder = createMethodEntryEventBuilder(TEST_CLASS_NAME);
91         testEventWithThreadOnlyModifier(builder);
92 
93         logWriter.println("testMethodEntry done");
94     }
95 
96     /**
97      * This testcase is for METHOD_EXIT event with ThreadOnly modifier.
98      * <BR>It runs ThreadOnlyModifierDebuggee and sets METHOD_EXIT to the
99      * {@link ThreadOnlyModifierDebuggee.TestClass} class.
100      * <BR>Then calls
101      * {@link ThreadOnlyModifierDebuggee.TestClass#eventTestMethod} method
102      * multiple times and verifies that requested METHOD_EXIT event occurs only
103      * in the {@link ThreadOnlyModifierDebuggee#THREAD_ONLY} thread.
104      */
testMethodExit()105     public void testMethodExit() {
106         logWriter.println("testMethodExit started");
107 
108         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
109         EventBuilder builder = createMethodExitEventBuilder(TEST_CLASS_NAME);
110         testEventWithThreadOnlyModifier(builder);
111 
112         logWriter.println("testMethodExit done");
113     }
114 
115     /**
116      * This testcase is for METHOD_EXIT_WITH_RETURN_VALUE event with ThreadOnly
117      * modifier.
118      * <BR>It runs ThreadOnlyModifierDebuggee and sets
119      * METHOD_EXIT_WITH_RETURN_VALUE to the
120      * {@link ThreadOnlyModifierDebuggee.TestClass} class.
121      * <BR>Then calls
122      * {@link ThreadOnlyModifierDebuggee.TestClass#eventTestMethod} method
123      * multiple times and verifies that requested METHOD_EXIT_WITH_RETURN_VALUE
124      * event occurs only in the {@link ThreadOnlyModifierDebuggee#THREAD_ONLY}
125      * thread.
126      */
testMethodExitWithReturnValue()127     public void testMethodExitWithReturnValue() {
128         logWriter.println("testMethodExitWithReturnValue started");
129 
130         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
131         EventBuilder builder = createMethodExitWithReturnValueEventBuilder(TEST_CLASS_NAME);
132         testEventWithThreadOnlyModifier(builder);
133 
134         logWriter.println("testMethodExitWithReturnValue done");
135     }
136 
137     /**
138      * This testcase is for EXCEPTION event with ThreadOnly modifier.
139      * <BR>It runs ThreadOnlyModifierDebuggee and sets EXCEPTION to the
140      * {@link ThreadOnlyModifierDebuggee.TestException} class but only for
141      * caught exceptions.
142      * <BR>Then calls
143      * {@link ThreadOnlyModifierDebuggee.TestThread#throwException} method
144      * multiple times and verifies that requested EXCEPTION event occurs only
145      * in the {@link ThreadOnlyModifierDebuggee#THREAD_ONLY} thread.
146      */
testException()147     public void testException() {
148         logWriter.println("testException started");
149 
150         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
151         EventBuilder builder = createExceptionEventBuilder(
152                 "Lorg/apache/harmony/jpda/tests/jdwp/EventModifiers/ThreadOnlyModifierDebuggee$TestException;",
153                 true, false);
154         testEventWithThreadOnlyModifier(builder);
155 
156         logWriter.println("testException done");
157     }
158 
159     /**
160      * This testcase is for THREAD_START event with ThreadOnly modifier.
161      * <BR>It runs ThreadOnlyModifierDebuggee and requests THREAD_START event.
162      * <BR>Then calls {@link ThreadOnlyModifierDebuggee#runThread} method
163      * multiple times and verifies that requested THREAD_START event occurs
164      * only in the {@link ThreadOnlyModifierDebuggee#THREAD_ONLY} thread.
165      */
testThreadStart()166     public void testThreadStart() {
167         logWriter.println("testThreadStart started");
168 
169         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
170 
171         EventBuilder builder = createThreadStartBuilder();
172         testEventWithThreadOnlyModifier(builder);
173 
174         logWriter.println("testThreadStart done");
175     }
176 
177     /**
178      * This testcase is for THREAD_END event with ThreadOnly modifier.
179      * <BR>It runs ThreadOnlyModifierDebuggee and requests THREAD_END event.
180      * <BR>Then calls {@link ThreadOnlyModifierDebuggee#runThread} method
181      * multiple times and verifies that requested THREAD_END event occurs only
182      * in the {@link ThreadOnlyModifierDebuggee#THREAD_ONLY} thread.
183      */
testThreadEnd()184     public void testThreadEnd() {
185         logWriter.println("testThreadEnd started");
186 
187         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
188 
189         EventBuilder builder = createThreadEndBuilder();
190         testEventWithThreadOnlyModifier(builder);
191 
192         logWriter.println("testThreadEnd done");
193     }
194 
195     /**
196      * This testcase is for FIELD_ACCESS event with ThreadOnly modifier.
197      * <BR>It runs ThreadOnlyModifierDebuggee and requests FIELD_ACCESS event
198      * for {@link ThreadOnlyModifierDebuggee#watchedField}.
199      * <BR>Then calls
200      * {@link ThreadOnlyModifierDebuggee.TestThread#readAndWriteField} method
201      * multiple times and verifies that requested FIELD_ACCESS event occurs
202      * only in the {@link ThreadOnlyModifierDebuggee#THREAD_ONLY} thread.
203      * <BR>Note: if the VM does not support the canWatchFieldAccess capability,
204      * the test succeeds.
205      */
testFieldAccess()206     public void testFieldAccess() {
207         logWriter.println("testFieldAccess started");
208 
209         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
210 
211         if (!canWatchFieldAccessCapability()) {
212             synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
213             return;
214         }
215 
216         EventBuilder builder = createFieldAccessEventBuilder(
217                 JDWPConstants.TypeTag.CLASS, DEBUGGEE_SIGNATURE,
218                 WATCHED_FIELD_NAME);
219         testEventWithThreadOnlyModifier(builder);
220 
221         logWriter.println("testFieldAccess done");
222     }
223 
224     /**
225      * This testcase is for FIELD_MODIFICATION event with ThreadOnly modifier.
226      * <BR>It runs ThreadOnlyModifierDebuggee and requests FIELD_MODIFICATION
227      * event for {@link ThreadOnlyModifierDebuggee#watchedField}.
228      * <BR>Then calls
229      * {@link ThreadOnlyModifierDebuggee.TestThread#readAndWriteField} method
230      * multiple times and verifies that requested FIELD_MODIFICATION event
231      * occurs only in the {@link ThreadOnlyModifierDebuggee#THREAD_ONLY} thread.
232      * <BR>Note: if the VM does not support the canWatchFieldModification
233      * capability, the test succeeds.
234      */
testFieldModification()235     public void testFieldModification() {
236         logWriter.println("testFieldModification started");
237 
238         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
239 
240         if (!canWatchFieldModificationCapability()) {
241             synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
242             return;
243         }
244 
245         EventBuilder builder = createFieldModificationEventBuilder(
246                 JDWPConstants.TypeTag.CLASS, DEBUGGEE_SIGNATURE,
247                 WATCHED_FIELD_NAME);
248         testEventWithThreadOnlyModifier(builder);
249 
250         logWriter.println("testFieldModification done");
251     }
252 
getFilteredThreadId()253     private long getFilteredThreadId() {
254         Value fieldValue = getFieldValue(DEBUGGEE_SIGNATURE, THREAD_FIELD_NAME);
255         assertEquals("Invalid field value tag", JDWPConstants.Tag.THREAD_TAG,
256                 fieldValue.getTag());
257         return fieldValue.getLongValue();
258     }
259 
testEventWithThreadOnlyModifier(EventBuilder builder)260     private void testEventWithThreadOnlyModifier(EventBuilder builder) {
261         long threadID = getFilteredThreadId();
262         Event event = builder.setThreadOnly(threadID).build();
263         int requestID = requestEvent(event);
264 
265         EventThread eventThread = waitForEvent(event.eventKind, requestID);
266         assertEquals(threadID, eventThread.getThreadID());
267 
268         clearAndResume(event.eventKind, requestID);
269     }
270 }
271