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