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
19package org.apache.harmony.jpda.tests.jdwp.EventModifiers;
20
21import org.apache.harmony.jpda.tests.framework.Breakpoint;
22import org.apache.harmony.jpda.tests.framework.jdwp.Event;
23import org.apache.harmony.jpda.tests.framework.jdwp.EventBuilder;
24import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
25import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent.EventThread;
26import org.apache.harmony.jpda.tests.framework.jdwp.Value;
27import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
28
29/**
30 * JDWP Unit test for ThreadOnly event modifier.
31 */
32public 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
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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
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
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