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.Location; 26 import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent.EventThreadLocation; 27 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket; 28 import org.apache.harmony.jpda.tests.framework.jdwp.Value; 29 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer; 30 31 /** 32 * JDWP Unit test for InstanceOnly event modifier. 33 */ 34 public class InstanceOnlyModifierTest extends JDWPEventModifierTestCase { 35 36 private static final 37 String DEBUGGEE_SIGNATURE = "Lorg/apache/harmony/jpda/tests/jdwp/EventModifiers/InstanceOnlyModifierDebuggee;"; 38 private static final 39 String TEST_CLASS_SIGNATURE = "Lorg/apache/harmony/jpda/tests/jdwp/EventModifiers/InstanceOnlyModifierDebuggee$TestClass;"; 40 private static final 41 String TEST_CLASS_NAME = "org.apache.harmony.jpda.tests.jdwp.EventModifiers.InstanceOnlyModifierDebuggee$TestClass"; 42 43 // The name of the test method where we set our event requests. 44 private static final String METHOD_NAME = "eventTestMethod"; 45 46 // The name of the test method where we set our event requests. 47 private static final String WATCHED_FIELD_NAME = "watchedField"; 48 49 private static final String INSTANCE_FIELD_NAME = "INSTANCE_ONLY"; 50 51 @Override getDebuggeeClassName()52 protected String getDebuggeeClassName() { 53 return InstanceOnlyModifierDebuggee.class.getName(); 54 } 55 56 /** 57 * This testcase is for BREAKPOINT event with InstanceOnly modifier. 58 * <BR>It runs InstanceOnlyModifierDebuggee and sets BREAKPOINT to its 59 * {@link InstanceOnlyModifierDebuggee.TestClass#eventTestMethod} method. 60 * <BR>Then calls this method multiple times and verifies that requested 61 * BREAKPOINT event occurs only when 'this' object is the object in field 62 * {@link InstanceOnlyModifierDebuggee#INSTANCE_ONLY}. 63 * <BR>Note: if the VM does not support the canUseInstanceFilters 64 * capability, the test succeeds. 65 */ testBreakpoint()66 public void testBreakpoint() { 67 logWriter.println("testBreakpoint started"); 68 69 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); 70 71 if (!checkCanUseInstanceFilterCapability()) { 72 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 73 return; 74 } 75 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 testEventWithInstanceOnlyModifier(builder); 82 logWriter.println("testBreakpoint done"); 83 } 84 85 /** 86 * This testcase is for METHOD_ENTRY event with InstanceOnly modifier. 87 * <BR>It runs InstanceOnlyModifierDebuggee and sets METHOD_ENTRY to the 88 * {@link InstanceOnlyModifierDebuggee.TestClass} class. 89 * <BR>Then calls 90 * {@link InstanceOnlyModifierDebuggee.TestClass#eventTestMethod} method 91 * multiple times and verifies that requested METHOD_ENTRY event occurs 92 * only when 'this' object is the object in field 93 * {@link InstanceOnlyModifierDebuggee#INSTANCE_ONLY}. 94 * <BR>Note: if the VM does not support the canUseInstanceFilters 95 * capability, the test succeeds. 96 */ testMethodEntry()97 public void testMethodEntry() { 98 logWriter.println("testMethodEntry started"); 99 100 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); 101 102 if (!checkCanUseInstanceFilterCapability()) { 103 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 104 return; 105 } 106 107 EventBuilder builder = createMethodEntryEventBuilder(TEST_CLASS_NAME); 108 testEventWithInstanceOnlyModifier(builder); 109 110 logWriter.println("testMethodEntry done"); 111 } 112 113 /** 114 * This testcase is for METHOD_EXIT event with InstanceOnly modifier. 115 * <BR>It runs InstanceOnlyModifierDebuggee and sets METHOD_EXIT to the 116 * {@link InstanceOnlyModifierDebuggee.TestClass} class. 117 * <BR>Then calls 118 * {@link InstanceOnlyModifierDebuggee.TestClass#eventTestMethod} method 119 * multiple times and verifies that requested METHOD_EXIT event occurs 120 * only when 'this' object is the object in field 121 * {@link InstanceOnlyModifierDebuggee#INSTANCE_ONLY}. 122 * <BR>Note: if the VM does not support the canUseInstanceFilters 123 * capability, the test succeeds. 124 */ testMethodExit()125 public void testMethodExit() { 126 logWriter.println("testMethodExit started"); 127 128 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); 129 130 if (!checkCanUseInstanceFilterCapability()) { 131 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 132 return; 133 } 134 135 EventBuilder builder = createMethodExitEventBuilder(TEST_CLASS_NAME); 136 testEventWithInstanceOnlyModifier(builder); 137 138 logWriter.println("testMethodExit done"); 139 } 140 141 /** 142 * This testcase is for METHOD_EXIT_WITH_RETURN_VALUE event with 143 * InstanceOnly modifier. 144 * <BR>It runs InstanceOnlyModifierDebuggee and sets 145 * METHOD_EXIT_WITH_RETURN_VALUE to the 146 * {@link InstanceOnlyModifierDebuggee.TestClass} class. 147 * <BR>Then calls 148 * {@link InstanceOnlyModifierDebuggee.TestClass#eventTestMethod} method 149 * multiple times and verifies that requested METHOD_EXIT_WITH_RETURN_VALUE 150 * event occurs only when 'this' object is the object in field 151 * {@link InstanceOnlyModifierDebuggee#INSTANCE_ONLY}. 152 * <BR>Note: if the VM does not support the canUseInstanceFilters 153 * capability, the test succeeds. 154 */ testMethodExitWithReturnValue()155 public void testMethodExitWithReturnValue() { 156 logWriter.println("testMethodExitWithReturnValue started"); 157 158 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); 159 160 if (!checkCanUseInstanceFilterCapability()) { 161 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 162 return; 163 } 164 165 EventBuilder builder = createMethodExitWithReturnValueEventBuilder(TEST_CLASS_NAME); 166 testEventWithInstanceOnlyModifier(builder); 167 168 logWriter.println("testMethodExitWithReturnValue done"); 169 } 170 171 /** 172 * This testcase is for EXCEPTION event with ThreadOnly modifier. 173 * <BR>It runs InstanceOnlyModifierDebuggee and sets EXCEPTION to the 174 * {@link InstanceOnlyModifierDebuggee.TestException} class but only for 175 * caught exceptions. 176 * <BR>Then calls 177 * {@link InstanceOnlyModifierDebuggee.TestClass#throwException} method 178 * multiple times and verifies that requested EXCEPTION event occurs only 179 * when 'this' object is the object in field 180 * {@link InstanceOnlyModifierDebuggee#INSTANCE_ONLY}. 181 */ testException()182 public void testException() { 183 logWriter.println("testException started"); 184 185 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); 186 187 if (!checkCanUseInstanceFilterCapability()) { 188 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 189 return; 190 } 191 192 String exceptionClassSignature = 193 "Lorg/apache/harmony/jpda/tests/jdwp/EventModifiers/InstanceOnlyModifierDebuggee$TestException;"; 194 EventBuilder builder = createExceptionEventBuilder(exceptionClassSignature, true, false); 195 testEventWithInstanceOnlyModifier(builder); 196 197 logWriter.println("testException done"); 198 } 199 200 /** 201 * This testcase is for FIELD_ACCESS event with InstanceOnly modifier. 202 * <BR>It runs InstanceOnlyModifierDebuggee and requests FIELD_ACCESS event 203 * for {@link InstanceOnlyModifierDebuggee.TestClass#watchedField}. 204 * <BR>Then calls 205 * {@link InstanceOnlyModifierDebuggee.TestClass#readAndWriteField} method 206 * multiple times and verifies that requested FIELD_ACCESS event occurs 207 * only when 'this' object is the object in field 208 * {@link InstanceOnlyModifierDebuggee#INSTANCE_ONLY}. 209 * <BR>Note: if the VM does not support the canUseInstanceFilters and 210 * canWatchFieldAccess capabilities, the test succeeds. 211 */ testFieldAccess()212 public void testFieldAccess() { 213 logWriter.println("testFieldAccess started"); 214 215 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); 216 217 if (!checkCanUseInstanceFilterCapability()) { 218 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 219 return; 220 } 221 222 if (!canWatchFieldAccessCapability()) { 223 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 224 return; 225 } 226 227 EventBuilder builder = createFieldAccessEventBuilder( 228 JDWPConstants.TypeTag.CLASS, TEST_CLASS_SIGNATURE, 229 WATCHED_FIELD_NAME); 230 testEventWithInstanceOnlyModifier(builder); 231 232 logWriter.println("testFieldAccess done"); 233 } 234 235 /** 236 * This testcase is for FIELD_MODIFICATION event with InstanceOnly modifier. 237 * <BR>It runs InstanceOnlyModifierDebuggee and requests FIELD_MODIFICATION 238 * event for {@link InstanceOnlyModifierDebuggee.TestClass#watchedField}. 239 * <BR>Then calls 240 * {@link InstanceOnlyModifierDebuggee.TestClass#readAndWriteField} method 241 * multiple times and verifies that requested FIELD_MODIFICATION event 242 * occurs only when 'this' object is the object in field 243 * {@link InstanceOnlyModifierDebuggee#INSTANCE_ONLY}. 244 * <BR>Note: if the VM does not support the canUseInstanceFilters and 245 * canWatchFieldModification capabilities, the test succeeds. 246 */ testFieldModification()247 public void testFieldModification() { 248 logWriter.println("testFieldModification started"); 249 250 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); 251 252 if (!checkCanUseInstanceFilterCapability()) { 253 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 254 return; 255 } 256 257 if (!canWatchFieldModificationCapability()) { 258 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 259 return; 260 } 261 262 EventBuilder builder = createFieldModificationEventBuilder( 263 JDWPConstants.TypeTag.CLASS, TEST_CLASS_SIGNATURE, 264 WATCHED_FIELD_NAME); 265 testEventWithInstanceOnlyModifier(builder); 266 267 logWriter.println("testFieldModification done"); 268 } 269 checkCanUseInstanceFilterCapability()270 private boolean checkCanUseInstanceFilterCapability() { 271 logWriter.println("Checking canUseInstanceFilters capability"); 272 boolean result = debuggeeWrapper.vmMirror.canUseInstanceFilters(); 273 if (!result) { 274 logCapabilityWarning("canUseInstanceFilters"); 275 } 276 return result; 277 } 278 getInstanceObjectId()279 private long getInstanceObjectId() { 280 Value fieldValue = getFieldValue(DEBUGGEE_SIGNATURE, 281 INSTANCE_FIELD_NAME); 282 assertEquals("Invalid field value tag", JDWPConstants.Tag.OBJECT_TAG, 283 fieldValue.getTag()); 284 return fieldValue.getLongValue(); 285 } 286 testEventWithInstanceOnlyModifier(EventBuilder builder)287 private void testEventWithInstanceOnlyModifier(EventBuilder builder) { 288 long objectID = getInstanceObjectId(); 289 builder.setInstanceOnly(objectID); 290 Event event = builder.build(); 291 int requestID = requestEvent(event); 292 293 EventThreadLocation eventThread = 294 (EventThreadLocation) waitForEvent(event.eventKind, requestID); 295 296 checkThisObject(eventThread, objectID); 297 298 clearAndResume(event.eventKind, requestID); 299 } 300 checkThisObject(EventThreadLocation eventThread, long objectID)301 private void checkThisObject(EventThreadLocation eventThread, long objectID) { 302 long threadID = eventThread.getThreadID(); 303 assertTrue(threadID != 0); 304 305 Location location = eventThread.getLocation(); 306 307 logWriter.println("Search the frame ID of the event location in thread " + threadID); 308 long frameID = -1; 309 int framesCount = debuggeeWrapper.vmMirror.getFrameCount(threadID); 310 ReplyPacket reply = debuggeeWrapper.vmMirror.getThreadFrames(threadID, 311 0, framesCount); 312 checkReplyPacket(reply, "Failed to get frames for thread " + threadID); 313 int frames = reply.getNextValueAsInt(); 314 for (int i = 0; i < frames; ++i) { 315 long currentFrameID = reply.getNextValueAsLong(); 316 Location currentFrameLocation = reply.getNextValueAsLocation(); 317 if (currentFrameLocation.equals(location)) { 318 frameID = currentFrameID; 319 break; 320 } 321 } 322 assertTrue("Failed to find frame for event location", frameID != -1); 323 324 logWriter.println("Check this object of frame " + frameID); 325 long thisObjectID = debuggeeWrapper.vmMirror.getThisObject(threadID, 326 frameID); 327 assertEquals("Event is not related to the object we're looking for", 328 objectID, thisObjectID); 329 } 330 } 331