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.Method; 20 21 import java.util.ArrayList; 22 import java.util.HashMap; 23 import java.util.List; 24 import java.util.Map; 25 import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket; 26 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands; 27 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket; 28 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer; 29 30 /** 31 * JDWP Unit test for Method.VariableTable command. 32 */ 33 abstract class JDWPMethodVariableTableTestCase extends JDWPMethodTestCase { 34 35 // All methods that must be checked against VariableTable[WithGeneric] reply. 36 private final Map<String, VariableTableChecker> checkerMap = 37 new HashMap<String, VariableTableChecker>(); 38 39 @Override getDebuggeeClassName()40 protected final String getDebuggeeClassName() { 41 return MethodVariableTestDebuggee.class.getName(); 42 } 43 JDWPMethodVariableTableTestCase()44 protected JDWPMethodVariableTableTestCase() { 45 initCheckerMap(); 46 } 47 initCheckerMap()48 private void initCheckerMap() { 49 initStaticMethods(); 50 initInstanceMethods(); 51 } 52 initStaticMethods()53 private void initStaticMethods() { 54 { 55 VariableTableChecker checker = new VariableTableChecker("static_NoParam"); 56 addCheckerToMap(checker); 57 } 58 { 59 VariableTableChecker checker = new VariableTableChecker("static_BooleanParam"); 60 checker.addParameter("booleanParam", "Z", 0); 61 addCheckerToMap(checker); 62 } 63 { 64 VariableTableChecker checker = new VariableTableChecker("static_ByteParam"); 65 checker.addParameter("byteParam", "B", 0); 66 addCheckerToMap(checker); 67 } 68 { 69 VariableTableChecker checker = new VariableTableChecker("static_CharParam"); 70 checker.addParameter("charParam", "C", 0); 71 addCheckerToMap(checker); 72 } 73 { 74 VariableTableChecker checker = new VariableTableChecker("static_ShortParam"); 75 checker.addParameter("shortParam", "S", 0); 76 addCheckerToMap(checker); 77 } 78 { 79 VariableTableChecker checker = new VariableTableChecker("static_IntParam"); 80 checker.addParameter("intParam", "I", 0); 81 addCheckerToMap(checker); 82 } 83 { 84 VariableTableChecker checker = new VariableTableChecker("static_FloatParam"); 85 checker.addParameter("floatParam", "F", 0); 86 addCheckerToMap(checker); 87 } 88 { 89 VariableTableChecker checker = new VariableTableChecker("static_LongParam"); 90 checker.addParameter("longParam", "J", 0); 91 addCheckerToMap(checker); 92 } 93 { 94 VariableTableChecker checker = new VariableTableChecker("static_DoubleParam"); 95 checker.addParameter("doubleParam", "D", 0); 96 addCheckerToMap(checker); 97 } 98 { 99 VariableTableChecker checker = new VariableTableChecker("static_ObjectParam"); 100 checker.addParameter("objectParam", "Ljava/lang/Object;", 0); 101 addCheckerToMap(checker); 102 } 103 { 104 VariableTableChecker checker = new VariableTableChecker("static_StringParam"); 105 checker.addParameter("stringParam", "Ljava/lang/String;", 0); 106 addCheckerToMap(checker); 107 } 108 { 109 VariableTableChecker checker = new VariableTableChecker("static_ListOfStringsParam"); 110 checker.addParameter("listOfStringsParam", "Ljava/util/List;", 0); 111 addCheckerToMap(checker); 112 } 113 { 114 VariableTableChecker checker = new VariableTableChecker("static_GenericParam"); 115 checker.addParameter("genericParam", "Ljava/lang/CharSequence;", 0); 116 addCheckerToMap(checker); 117 } 118 { 119 VariableTableChecker checker = new VariableTableChecker("static_IntArrayParam"); 120 checker.addParameter("intArrayParam", "[I", 0); 121 addCheckerToMap(checker); 122 } 123 { 124 VariableTableChecker checker = new VariableTableChecker("static_StringMultiArrayParam"); 125 checker.addParameter("stringMultiArrayParam", "[[Ljava/lang/String;", 0); 126 addCheckerToMap(checker); 127 } 128 { 129 VariableTableChecker checker = new VariableTableChecker("static_IntLongParam"); 130 checker.addParameter("intParam", "I", 0); 131 checker.addParameter("longParam", "J", 1); 132 addCheckerToMap(checker); 133 } 134 { 135 VariableTableChecker checker = new VariableTableChecker("static_LongIntParam"); 136 checker.addParameter("longParam", "J", 0); 137 checker.addParameter("intParam", "I", 2); 138 addCheckerToMap(checker); 139 } 140 141 { 142 VariableTableChecker checker = new VariableTableChecker("static_NoParamWithLocal"); 143 checker.addLocal("i", "I"); 144 checker.addLocal("l", "J"); 145 addCheckerToMap(checker); 146 } 147 } 148 initInstanceMethods()149 private void initInstanceMethods() { 150 { 151 VariableTableChecker checker = new VariableTableChecker("instance_NoParam"); 152 checker.addParameter("this", getDebuggeeClassSignature(), 0); 153 addCheckerToMap(checker); 154 } 155 { 156 VariableTableChecker checker = new VariableTableChecker("instance_BooleanParam"); 157 checker.addParameter("this", getDebuggeeClassSignature(), 0); 158 checker.addParameter("booleanParam", "Z", 1); 159 addCheckerToMap(checker); 160 } 161 { 162 VariableTableChecker checker = new VariableTableChecker("instance_ByteParam"); 163 checker.addParameter("this", getDebuggeeClassSignature(), 0); 164 checker.addParameter("byteParam", "B", 1); 165 addCheckerToMap(checker); 166 } 167 { 168 VariableTableChecker checker = new VariableTableChecker("instance_CharParam"); 169 checker.addParameter("this", getDebuggeeClassSignature(), 0); 170 checker.addParameter("charParam", "C", 1); 171 addCheckerToMap(checker); 172 } 173 { 174 VariableTableChecker checker = new VariableTableChecker("instance_ShortParam"); 175 checker.addParameter("this", getDebuggeeClassSignature(), 0); 176 checker.addParameter("shortParam", "S", 1); 177 addCheckerToMap(checker); 178 } 179 { 180 VariableTableChecker checker = new VariableTableChecker("instance_IntParam"); 181 checker.addParameter("this", getDebuggeeClassSignature(), 0); 182 checker.addParameter("intParam", "I", 1); 183 addCheckerToMap(checker); 184 } 185 { 186 VariableTableChecker checker = new VariableTableChecker("instance_FloatParam"); 187 checker.addParameter("this", getDebuggeeClassSignature(), 0); 188 checker.addParameter("floatParam", "F", 1); 189 addCheckerToMap(checker); 190 } 191 { 192 VariableTableChecker checker = new VariableTableChecker("instance_LongParam"); 193 checker.addParameter("this", getDebuggeeClassSignature(), 0); 194 checker.addParameter("longParam", "J", 1); 195 addCheckerToMap(checker); 196 } 197 { 198 VariableTableChecker checker = new VariableTableChecker("instance_DoubleParam"); 199 checker.addParameter("this", getDebuggeeClassSignature(), 0); 200 checker.addParameter("doubleParam", "D", 1); 201 addCheckerToMap(checker); 202 } 203 { 204 VariableTableChecker checker = new VariableTableChecker("instance_ObjectParam"); 205 checker.addParameter("this", getDebuggeeClassSignature(), 0); 206 checker.addParameter("objectParam", "Ljava/lang/Object;", 1); 207 addCheckerToMap(checker); 208 } 209 { 210 VariableTableChecker checker = new VariableTableChecker("instance_StringParam"); 211 checker.addParameter("this", getDebuggeeClassSignature(), 0); 212 checker.addParameter("stringParam", "Ljava/lang/String;", 1); 213 addCheckerToMap(checker); 214 } 215 { 216 VariableTableChecker checker = new VariableTableChecker("instance_ListOfStringsParam"); 217 checker.addParameter("this", getDebuggeeClassSignature(), 0); 218 checker.addParameter("listOfStringsParam", "Ljava/util/List;", 1); 219 addCheckerToMap(checker); 220 } 221 { 222 VariableTableChecker checker = new VariableTableChecker("instance_GenericParam"); 223 checker.addParameter("this", getDebuggeeClassSignature(), 0); 224 checker.addParameter("genericParam", "Ljava/lang/CharSequence;", 1); 225 addCheckerToMap(checker); 226 } 227 { 228 VariableTableChecker checker = new VariableTableChecker("instance_IntArrayParam"); 229 checker.addParameter("this", getDebuggeeClassSignature(), 0); 230 checker.addParameter("intArrayParam", "[I", 1); 231 addCheckerToMap(checker); 232 } 233 { 234 VariableTableChecker checker = new VariableTableChecker( 235 "instance_StringMultiArrayParam"); 236 checker.addParameter("this", getDebuggeeClassSignature(), 0); 237 checker.addParameter("stringMultiArrayParam", "[[Ljava/lang/String;", 1); 238 addCheckerToMap(checker); 239 } 240 { 241 VariableTableChecker checker = new VariableTableChecker("instance_IntLongParam"); 242 checker.addParameter("this", getDebuggeeClassSignature(), 0); 243 checker.addParameter("intParam", "I", 1); 244 checker.addParameter("longParam", "J", 2); 245 addCheckerToMap(checker); 246 } 247 { 248 VariableTableChecker checker = new VariableTableChecker("instance_LongIntParam"); 249 checker.addParameter("this", getDebuggeeClassSignature(), 0); 250 checker.addParameter("longParam", "J", 1); 251 checker.addParameter("intParam", "I", 3); 252 addCheckerToMap(checker); 253 } 254 255 { 256 VariableTableChecker checker = new VariableTableChecker("instance_NoParamWithLocal"); 257 checker.addParameter("this", getDebuggeeClassSignature(), 0); 258 checker.addLocal("i", "I"); 259 checker.addLocal("l", "J"); 260 addCheckerToMap(checker); 261 } 262 } 263 addCheckerToMap(VariableTableChecker checker)264 private void addCheckerToMap(VariableTableChecker checker) { 265 checkerMap.put(checker.methodName, checker); 266 } 267 268 /** 269 * This testcase exercises Method.VariableTable[WithGeneric] command. <BR> 270 * It runs MethodDebuggee, receives methods of debuggee. For each received 271 * method sends Method.VariableTable command and checks the returned 272 * VariableTable. 273 * 274 * @param withGenerics 275 * true to test Method.VariableTableWithGeneric, false to test 276 * Method.VariableTable. 277 */ checkMethodVariableTable(boolean withGenerics)278 protected void checkMethodVariableTable(boolean withGenerics) { 279 final String testName = getName(); 280 logWriter.println(testName + " started"); 281 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); 282 283 long classID = getClassIDBySignature(getDebuggeeClassSignature()); 284 285 MethodInfo[] methodsInfo = jdwpGetMethodsInfo(classID); 286 assertFalse("Invalid number of methods: 0", methodsInfo.length == 0); 287 288 final byte commandCode; 289 final String commandName; 290 if (withGenerics) { 291 // Testing Method.VariableTableWithGeneric command. 292 commandCode = JDWPCommands.MethodCommandSet.VariableTableWithGenericCommand; 293 commandName = "Method::VariableTableWithGeneric"; 294 } else { 295 // Testing Method.VariableTable command. 296 commandCode = JDWPCommands.MethodCommandSet.VariableTableCommand; 297 commandName = "Method::VariableTable"; 298 } 299 300 int checkedMethodsCount = 0; 301 for (MethodInfo methodInfo : methodsInfo) { 302 logWriter.println(methodInfo.toString()); 303 304 // get variable table for this class 305 CommandPacket packet = new CommandPacket(JDWPCommands.MethodCommandSet.CommandSetID, 306 commandCode); 307 packet.setNextValueAsClassID(classID); 308 packet.setNextValueAsMethodID(methodInfo.getMethodID()); 309 ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); 310 checkReplyPacket(reply, commandName + " command"); 311 312 int argCnt = reply.getNextValueAsInt(); 313 logWriter.println("argCnt = " + argCnt); 314 int slots = reply.getNextValueAsInt(); 315 logWriter.println("slots = " + slots); 316 317 VariableTableChecker checker = getCheckerForMethod(methodInfo.getName()); 318 if (checker != null) { 319 ++checkedMethodsCount; 320 logWriter.println("# Check method \"" + checker.methodName + "\""); 321 322 // Check argCount. 323 int expectedArgsCount = checker.getArgCount(); 324 assertEquals("Invalid argCount", expectedArgsCount, argCnt); 325 } 326 int checkedVariablesCount = 0; 327 for (int j = 0; j < slots; j++) { 328 long codeIndex = reply.getNextValueAsLong(); 329 logWriter.println("codeIndex = " + codeIndex); 330 String name = reply.getNextValueAsString(); 331 logWriter.println("name = \"" + name + "\""); 332 String signature = reply.getNextValueAsString(); 333 logWriter.println("signature = \"" + signature + "\""); 334 String genericSignature = ""; 335 if (withGenerics) { 336 reply.getNextValueAsString(); 337 logWriter.println("genericSignature = \"" + genericSignature + "\""); 338 } 339 int length = reply.getNextValueAsInt(); 340 logWriter.println("length = " + length); 341 int slot = reply.getNextValueAsInt(); 342 logWriter.println("slot = " + slot); 343 344 if (checker != null) { 345 VariableInfo variableInfo = checker.getVariableInfo(name); 346 if (variableInfo != null) { 347 ++checkedVariablesCount; 348 logWriter.println("## Check variable \"" + variableInfo.name + "\""); 349 350 // Check signature 351 assertEquals("Invalid variable type signature", 352 variableInfo.signature, signature); 353 354 if (variableInfo.isParameter) { 355 // Check parameter's slot 356 assertTrue("Invalid slot " + variableInfo.expectedParameterSlot + 357 " for parameter \"" + name + "\"", 358 variableInfo.expectedParameterSlot < argCnt); 359 assertEquals("Invalid slot for parameter \"" + name + "\"", 360 variableInfo.expectedParameterSlot, slot); 361 362 // A parameter's scope start is == 0. 363 assertEquals("Invalid codeIndex " + codeIndex + " for parameter \"" + 364 name + "\"", 0, codeIndex); 365 } else { 366 // A local variable's slot must be >= argCount. 367 assertTrue("Invalid slot " + slot + " for local var \"" + name + "\"", 368 slot >= argCnt); 369 370 // A local variable's scope start is >= 0. 371 assertTrue("Invalid codeIndex " + codeIndex + " for local var \"" + 372 name + "\"", codeIndex >= 0); 373 } 374 } 375 } 376 } 377 378 if (checker != null) { 379 // Check that we found all the variables we want to check for the current method. 380 assertEquals("Not all variables have been checked for method " + checker.methodName, 381 checker.variableInfos.size(), checkedVariablesCount); 382 } 383 384 } 385 386 // Checks that we found all the methods that we want to check. 387 assertEquals("Not all methods have been checked", checkerMap.size(), checkedMethodsCount); 388 389 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 390 logWriter.println(testName + " ends"); 391 } 392 getCheckerForMethod(String methodName)393 private VariableTableChecker getCheckerForMethod(String methodName) { 394 return checkerMap.get(methodName); 395 } 396 397 private static class VariableTableChecker { 398 final String methodName; 399 private final List<VariableInfo> variableInfos = 400 new ArrayList<JDWPMethodVariableTableTestCase.VariableInfo>(); 401 VariableTableChecker(String methodName)402 public VariableTableChecker(String methodName) { 403 this.methodName = methodName; 404 } 405 addVariableInfo(VariableInfo variableInfo)406 private void addVariableInfo(VariableInfo variableInfo) { 407 variableInfos.add(variableInfo); 408 } 409 addParameter(String name, String signature, int slot)410 public void addParameter(String name, String signature, int slot) { 411 addVariableInfo(new VariableInfo(true, name, signature, slot)); 412 } 413 addLocal(String name, String signature)414 public void addLocal(String name, String signature) { 415 addVariableInfo(new VariableInfo(false, name, signature, -1)); 416 } 417 getArgCount()418 public int getArgCount() { 419 int argsCount = 0; 420 for (VariableInfo variableInfo : variableInfos) { 421 if (variableInfo.isParameter) { 422 String sig = variableInfo.signature; 423 if (sig.equals("J") || sig.equals("D")) { 424 // long and double take 2 slots. 425 argsCount += 2; 426 } else { 427 argsCount += 1; 428 } 429 } 430 } 431 return argsCount; 432 } 433 getVariableInfo(String variableName)434 public VariableInfo getVariableInfo(String variableName) { 435 for (VariableInfo v : variableInfos) { 436 if (v.name.equals(variableName)) { 437 return v; 438 } 439 } 440 return null; 441 } 442 } 443 444 private static class VariableInfo { 445 // Is it a parameter ? 446 private final boolean isParameter; 447 // The variable's name. 448 private final String name; 449 // The variable's signature. 450 private final String signature; 451 // The expected slot for parameters only. 452 private final int expectedParameterSlot; 453 VariableInfo(boolean isParameter, String variableName, String variableSignature, int expectedParameterSlot)454 public VariableInfo(boolean isParameter, String variableName, String variableSignature, 455 int expectedParameterSlot) { 456 this.isParameter = isParameter; 457 this.name = variableName; 458 this.signature = variableSignature; 459 this.expectedParameterSlot = expectedParameterSlot; 460 } 461 } 462 } 463