1 /*
   2  * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 //    THIS TEST IS LINE NUMBER SENSITIVE
  25 
  26 /**
  27  * @test
  28  * @bug 4300412
  29  * @summary Test GetLocal* and SetLocal* functions
  30  * @author Serguei Spitsyn
  31  *
  32  * @run build TestScaffold VMConnection TargetListener TargetAdapter
  33  * @run compile -g GetSetLocalTest.java
  34  * @run driver GetSetLocalTest
  35  */
  36 import com.sun.jdi.*;
  37 import com.sun.jdi.event.*;
  38 import com.sun.jdi.request.*;
  39 
  40 import java.util.*;
  41 
  42     /********** target program **********/
  43 
  44 class GetSetLocalTarg {
  45     public static void main(String[] args){
  46         int intVar = 10;
  47         System.out.println("GetSetLocalTarg: Started");
  48         intVar = staticMeth(intVar);
  49         System.out.println("GetSetLocalTarg: Finished");
  50     }
  51 
  52     /*
  53      * The line numbers of this method *MUST NOT* be changed
  54      * because the testing algorithm counts on this layout!
  55      * It's in calls to resumeTo("GetSetLocalTarg", line).
  56      */
  57     public static int staticMeth(int intArg) {
  58         System.out.println("staticMeth: Started");
  59         int result;
  60         {
  61              { boolean bool_1 = false;
  62                intArg++; // START_LINE
  63              }
  64 
  65              boolean bool_2 = true;
  66              intArg++;
  67         }
  68         {
  69              { byte byte_1 = 1;
  70                intArg++;
  71              }
  72 
  73              byte byte_2 = 2;
  74              intArg++;
  75         }
  76         {
  77              { char   char_1 = '1';
  78                intArg++;
  79              }
  80 
  81              char   char_2 = '2';
  82              intArg++;
  83         }
  84         {
  85              { short  short_1 = 1;
  86                intArg++;
  87              }
  88 
  89              short  short_2 = 2;
  90              intArg++;
  91         }
  92         {
  93              { int    int_1 = 1;
  94                intArg++;
  95              }
  96 
  97              int int_2 = 2;
  98              intArg++;
  99         }
 100         {
 101              { long long_1 = 1;
 102                intArg++;
 103              }
 104 
 105              long long_2 = 2;
 106              intArg++;
 107         }
 108         {
 109              { float  float_1 = 1;
 110                intArg++;
 111              }
 112 
 113              float float_2 = 2;
 114              intArg++;
 115         }
 116         {
 117              { double double_1 = 1;
 118                intArg++;
 119              }
 120 
 121              double double_2 = 2;
 122              intArg++;
 123         }
 124         {
 125              { String string_1 = "1";
 126                intArg++;
 127              }
 128 
 129              String string_2 = "2";
 130              intArg++;
 131         }
 132         {
 133              { Object obj_1 = new Object();
 134                intArg++;
 135              }
 136 
 137              Object obj_2 = new Object();
 138              intArg++;  // STOP_LINE. Last stop is at this point.
 139                         //     Only obj_2 and intArg are valid
 140                         // Note: even result is not valid here!
 141         }
 142         result = 10;    // <- This is first init of result var
 143         System.out.println("staticMeth: Finished");
 144         return result;
 145     }
 146 }
 147 
 148 
 149     /********** test program **********/
 150 
 151 public class GetSetLocalTest extends TestScaffold {
 152     static final int START_LINE = 62;
 153     static final int STOP_LINE = 138;
 154     ReferenceType targetClass;
 155     ThreadReference mainThread;
 156 
 157     GetSetLocalTest (String args[]) {
 158         super(args);
 159     }
 160 
 161     public static void main(String[] args) throws Exception {
 162         new GetSetLocalTest(args).startTests();
 163     }
 164 
 165     /********** test assist **********/
 166 
 167     Method getMethod(String className, String methodName) {
 168         List refs = vm().classesByName(className);
 169         if (refs.size() != 1) {
 170             failure(" Failure: " + refs.size() +
 171                     " ReferenceTypes named: " + className);
 172             return null;
 173         }
 174         ReferenceType refType = (ReferenceType)refs.get(0);
 175         List meths = refType.methodsByName(methodName);
 176         if (meths.size() != 1) {
 177             failure(" Failure: " + meths.size() +
 178                     " methods named: " + methodName);
 179             return null;
 180         }
 181         return (Method)meths.get(0);
 182     }
 183 
 184     List printAllVariables(String className, String methodName) throws Exception {
 185         println("printAllVariables for method: " + className + "." + methodName);
 186         Method method = getMethod(className, methodName);
 187         List localVars;
 188         try {
 189             localVars = method.variables();
 190             println(" Success: got a list of all method variables: " + methodName);
 191         }
 192         catch (com.sun.jdi.AbsentInformationException ex) {
 193             failure(" Failure: AbsentInformationException has been thrown");
 194             return null;
 195         }
 196 
 197         int index = 0;
 198         for (Iterator it = localVars.iterator(); it.hasNext();) {
 199             LocalVariable lv = (LocalVariable) it.next();
 200             printOneVariable(lv, index++);
 201         }
 202         println("");
 203         return localVars;
 204     }
 205 
 206     void checkGetSetAllVariables(List localVars, StackFrame frame) throws Exception {
 207         println("\n checkGetSetAllVariables for method at particular frame location: ");
 208         int index = 0;
 209         for (Iterator it = localVars.iterator(); it.hasNext();) {
 210             LocalVariable lv = (LocalVariable) it.next();
 211             String lv_name = lv.name();
 212             print(" Variable " + lv_name);
 213             try {
 214                 Value val = frame.getValue(lv);
 215                 frame.setValue(lv, val);
 216                 println(" has been get/set");
 217                 if (lv_name.compareTo("intArg") != 0 &&
 218                     lv_name.compareTo("obj_2")  != 0) {
 219                     failure(" Failure: AbsentInformationException is expected");
 220                 }
 221             } catch (java.lang.IllegalArgumentException ex) {
 222                 println(" is not valid");
 223                 if (lv_name.compareTo("intArg") == 0 &&
 224                     lv_name.compareTo("obj_2")  == 0) {
 225                     failure(" Failure: AbsentInformationException was not expected");
 226                 }
 227             }
 228         }
 229         println("");
 230     }
 231 
 232     void printOneVariable(LocalVariable lv, int index) throws Exception {
 233         String tyname = lv.typeName();
 234         println("");
 235         println(" Var  name: " + lv.name());
 236         println(" Var  type: " + tyname);
 237         println(" Var index: " + index);
 238         println(" Signature: " + lv.type().signature());
 239         // Sorry, there is no way to get (and print)
 240         // a local variable slot numbers using JDI!
 241     }
 242 
 243     void printFrameVariables(StackFrame frame) throws Exception {
 244         int index = 0;
 245         List localVars = frame.visibleVariables();
 246         println("\n Visible variables at this point are: ");
 247 
 248         for (Iterator it = localVars.iterator(); it.hasNext();) {
 249             LocalVariable lv = (LocalVariable) it.next();
 250             printOneVariable(lv, index++);
 251             println(" Var value: " + frame.getValue(lv));
 252         }
 253     }
 254 
 255     BooleanValue incrValue(BooleanValue val) {
 256         boolean value = val.value();
 257         return vm().mirrorOf(!value);
 258     }
 259 
 260     ByteValue incrValue(ByteValue val) {
 261         byte value = val.value();
 262         return vm().mirrorOf(++value);
 263     }
 264 
 265     CharValue incrValue(CharValue val) {
 266         char value = val.value();
 267         return vm().mirrorOf(++value);
 268     }
 269 
 270     ShortValue incrValue(ShortValue val) {
 271         short value = val.value();
 272         return vm().mirrorOf(++value);
 273     }
 274 
 275     IntegerValue incrValue(IntegerValue val) {
 276         int value = val.value();
 277         return vm().mirrorOf(++value);
 278     }
 279 
 280     LongValue incrValue(LongValue val) {
 281         long value = val.value();
 282         return vm().mirrorOf(++value);
 283     }
 284 
 285     FloatValue incrValue(FloatValue val) {
 286         float value = val.value();
 287         return  vm().mirrorOf(++value);
 288     }
 289 
 290     DoubleValue incrValue(DoubleValue val) {
 291         double value = val.value();
 292         return vm().mirrorOf(++value);
 293     }
 294 
 295     StringReference incrValue(StringReference val) {
 296         String newstr = new String("Set String ").concat(val.value());
 297         return vm().mirrorOf(newstr);
 298     }
 299 
 300     void checkSetBooleanTypes(StackFrame frame, LocalVariable lv) throws Exception {
 301         BooleanValue get = (BooleanValue) frame.getValue(lv);
 302         BooleanValue set = incrValue(get);
 303         frame.setValue(lv, set);
 304 
 305         // To get the new value which has been set
 306         get = (BooleanValue) frame.getValue(lv);
 307         println(" Var  Set: " + set);
 308         println(" Var  Get: " + get);
 309         println("");
 310         boolean v1 = get.value();
 311         boolean v2 = set.value();
 312 
 313         // Check if set was done properly
 314         if (v1 == v2) {
 315             println(" Success: Value was set correctly!");
 316         } else {
 317             failure(" Failure: Value was NOT set correctly!");
 318         }
 319         println("");
 320     }
 321 
 322     void checkSetByteTypes(StackFrame frame, LocalVariable lv) throws Exception {
 323         ByteValue get = (ByteValue) frame.getValue(lv);
 324         ByteValue set = incrValue(get);
 325         frame.setValue(lv, set);
 326 
 327         // To get the new value which has been set
 328         get = (ByteValue) frame.getValue(lv);
 329         println(" Var  Set: " + set);
 330         println(" Var  Get: " + get);
 331         println("");
 332         byte v1 = get.value();
 333         byte v2 = set.value();
 334 
 335         // Check if set was done properly
 336         if (v1 == v2) {
 337             println(" Success: Value was set correctly!");
 338         } else {
 339             failure(" Failure: Value was NOT set correctly!");
 340         }
 341         println("");
 342     }
 343 
 344     void checkSetCharTypes(StackFrame frame, LocalVariable lv) throws Exception {
 345         CharValue get = (CharValue) frame.getValue(lv);
 346         CharValue set = incrValue(get);
 347         frame.setValue(lv, set);
 348 
 349         // To get the new value which has been set
 350         get = (CharValue) frame.getValue(lv);
 351         println(" Var  Set: " + set);
 352         println(" Var  Get: " + get);
 353         println("");
 354         char v1 = get.value();
 355         char v2 = set.value();
 356 
 357         // Check if set was done properly
 358         if (v1 == v2) {
 359             println(" Success: Value was set correctly!");
 360         } else {
 361             failure(" Failure: Value was NOT set correctly!");
 362         }
 363         println("");
 364     }
 365 
 366     void checkSetShortTypes(StackFrame frame, LocalVariable lv) throws Exception {
 367         ShortValue get = (ShortValue) frame.getValue(lv);
 368         ShortValue set = incrValue(get);
 369         frame.setValue(lv, set);
 370 
 371         // To get the new value which has been set
 372         get = (ShortValue) frame.getValue(lv);
 373         println(" Var  Set: " + set);
 374         println(" Var  Get: " + get);
 375         println("");
 376         short v1 = get.value();
 377         short v2 = set.value();
 378 
 379         // Check if set was done properly
 380         if (v1 == v2) {
 381             println(" Success: Value was set correctly!");
 382         } else {
 383             failure(" Failure: Value was NOT set correctly!");
 384         }
 385         println("");
 386     }
 387 
 388     void checkSetIntegerTypes(StackFrame frame, LocalVariable lv) throws Exception {
 389         IntegerValue get = (IntegerValue) frame.getValue(lv);
 390         IntegerValue set = incrValue(get);
 391         frame.setValue(lv, set);
 392 
 393         // To get the new value which has been set
 394         get = (IntegerValue) frame.getValue(lv);
 395         println(" Var  Set: " + set);
 396         println(" Var  Get: " + get);
 397         println("");
 398         int v1 = get.value();
 399         int v2 = set.value();
 400 
 401         // Check if set was done properly
 402         if (v1 == v2) {
 403             println(" Success: Value was set correctly!");
 404         } else {
 405             failure(" Failure: Value was NOT set correctly!");
 406         }
 407         println("");
 408     }
 409 
 410     void checkSetLongTypes(StackFrame frame, LocalVariable lv) throws Exception {
 411         LongValue get = (LongValue) frame.getValue(lv);
 412         LongValue set = incrValue(get);
 413         frame.setValue(lv, set);
 414 
 415         // To get the new value which has been set
 416         get = (LongValue) frame.getValue(lv);
 417         println(" Var  Set: " + set);
 418         println(" Var  Get: " + get);
 419         println("");
 420         long v1 = get.value();
 421         long v2 = set.value();
 422 
 423         // Check if set was done properly
 424         if (v1 == v2) {
 425             println(" Success: Value was set correctly!");
 426         } else {
 427             failure(" Failure: Value was NOT set correctly!");
 428         }
 429         println("");
 430     }
 431 
 432     void checkSetFloatTypes(StackFrame frame, LocalVariable lv) throws Exception {
 433         FloatValue get = (FloatValue) frame.getValue(lv);
 434         FloatValue set = incrValue(get);
 435         frame.setValue(lv, set);
 436 
 437         // To get the new value which has been set
 438         get = (FloatValue) frame.getValue(lv);
 439         println(" Var  Set: " + set);
 440         println(" Var  Get: " + get);
 441         println("");
 442         float v1 = get.value();
 443         float v2 = set.value();
 444 
 445         // Check if set was done properly
 446         if (v1 == v2) {
 447             println(" Success: Value was set correctly!");
 448         } else {
 449             failure(" Failure: Value was NOT set correctly!");
 450         }
 451         println("");
 452     }
 453 
 454     void checkSetDoubleTypes(StackFrame frame, LocalVariable lv) throws Exception {
 455         DoubleValue get = (DoubleValue) frame.getValue(lv);
 456         DoubleValue set = incrValue(get);
 457         frame.setValue(lv, set);
 458 
 459         // To get the new value which has been set
 460         get = (DoubleValue) frame.getValue(lv);
 461         println(" Var  Set: " + set);
 462         println(" Var  Get: " + get);
 463         println("");
 464         double v1 = get.value();
 465         double v2 = set.value();
 466 
 467         // Check if set was done properly
 468         if (v1 == v2) {
 469             println(" Success: Value was set correctly!");
 470         } else {
 471             failure(" Failure: Value was NOT set correctly!");
 472         }
 473         println("");
 474     }
 475 
 476     void checkSetStringTypes(StackFrame frame, LocalVariable lv) throws Exception {
 477         StringReference get = (StringReference) frame.getValue(lv);
 478         StringReference set = incrValue((StringReference) frame.getValue(lv));
 479         frame.setValue(lv, set);
 480 
 481         // To get the new value which has been set
 482         get = (StringReference) frame.getValue(lv);
 483         println(" Var  Set: " + set);
 484         println(" Var  Get: " + get);
 485         println("");
 486         String str1 = get.value();
 487         String str2 = set.value();
 488 
 489         // Check if set was done properly
 490         if (str1.compareTo(str2) == 0) {
 491             println(" Success: String was set correctly!");
 492         } else {
 493             failure(" Failure: String was NOT set correctly!");
 494         }
 495         println("");
 496     }
 497 
 498     void checkSetObjectTypes(StackFrame frame, LocalVariable lv) throws Exception {
 499         ObjectReference get = (ObjectReference) frame.getValue(lv);
 500         ObjectReference set = get; // FIXME: Don't know how to create a mirror of Object
 501         frame.setValue(lv, set);
 502 
 503         // To get the new value which has been set
 504         get = (ObjectReference) frame.getValue(lv);
 505         println(" Var  Set: " + set);
 506         println(" Var  Get: " + get);
 507         println("");
 508 
 509         if (set.uniqueID() == get.uniqueID()) {
 510             println(" Success: Object was set correctly!");
 511         } else {
 512             failure(" Failure: Object was NOT set correctly!");
 513         }
 514         println("");
 515     }
 516 
 517     void negativeIntegerCheck(StackFrame frame, LocalVariable lv) throws Exception {
 518         try {
 519             IntegerValue get = (IntegerValue) frame.getValue(lv);
 520             println(" Get: No ClassCastException error!");
 521         } catch(java.lang.ClassCastException ex) {
 522             println(" Success: Get: ClassCastException error has cought as expected!");
 523         }
 524         try {
 525             IntegerValue set = vm().mirrorOf((int) 0x3F);
 526             frame.setValue(lv, set);
 527             println(" Set: No InvalidTypeException with Integer error!");
 528         } catch(com.sun.jdi.InvalidTypeException ex) {
 529             println(" Success: Set: InvalidTypeException with Integer error has cought as expected!");
 530         }
 531     }
 532 
 533     void negativeFloatCheck(StackFrame frame, LocalVariable lv) throws Exception {
 534         try {
 535             FloatValue get = (FloatValue) frame.getValue(lv);
 536             println(" Get: No ClassCastException error!");
 537         } catch(java.lang.ClassCastException ex) {
 538             println(" Success: Get: ClassCastException with Float error has cought as expected!");
 539         }
 540         try {
 541             FloatValue set = vm().mirrorOf(1.2345f);
 542             frame.setValue(lv, set);
 543             println(" Set: No InvalidTypeException with Float error!");
 544         } catch(com.sun.jdi.InvalidTypeException ex) {
 545             println(" Success: Set: InvalidTypeException error has cought as expected!");
 546         }
 547     }
 548 
 549     void negativeDoubleCheck(StackFrame frame, LocalVariable lv) throws Exception {
 550         try {
 551             DoubleValue get = (DoubleValue) frame.getValue(lv);
 552             println(" Get: No ClassCastException error!");
 553         } catch(java.lang.ClassCastException ex) {
 554             println(" Success: Get: ClassCastException  with Double error has cought as expected!");
 555         }
 556         try {
 557             DoubleValue set = vm().mirrorOf(1.2345E02);
 558             frame.setValue(lv, set);
 559             println(" Set: No InvalidTypeException with Double error!");
 560         } catch(com.sun.jdi.InvalidTypeException ex) {
 561             println(" Success: Set: InvalidTypeException error has cought as expected!");
 562         }
 563     }
 564 
 565     void checkSetFrameVariables(StackFrame frame) throws Exception {
 566         List localVars = frame.visibleVariables();
 567         int index = 0;
 568         println("\n Set variable values:");
 569 
 570         for (Iterator it = localVars.iterator(); it.hasNext();index++) {
 571             LocalVariable lv = (LocalVariable) it.next();
 572             String signature = lv.type().signature();
 573 
 574             switch (signature.charAt(0)) {
 575             case 'Z': // Boolean Type
 576                 checkSetBooleanTypes(frame, lv);
 577                 negativeIntegerCheck(frame, lv);
 578                 negativeFloatCheck(frame, lv);
 579                 negativeDoubleCheck(frame, lv);
 580                 break;
 581             case 'B': // Byte Type
 582                 checkSetByteTypes(frame, lv);
 583                 negativeIntegerCheck(frame, lv);
 584                 negativeFloatCheck(frame, lv);
 585                 negativeDoubleCheck(frame, lv);
 586                 break;
 587             case 'C': // Char Type
 588                 checkSetCharTypes(frame, lv);
 589                 negativeIntegerCheck(frame, lv);
 590                 negativeFloatCheck(frame, lv);
 591                 negativeDoubleCheck(frame, lv);
 592                 break;
 593             case 'S': // Short Type
 594                 checkSetShortTypes(frame, lv);
 595                 negativeIntegerCheck(frame, lv);
 596                 negativeFloatCheck(frame, lv);
 597                 negativeDoubleCheck(frame, lv);
 598                 break;
 599             case 'I': // Integer Type
 600                 checkSetIntegerTypes(frame, lv);
 601                 if (index > 0) { // To skip integer method parameter
 602                     negativeFloatCheck(frame, lv);
 603                     negativeDoubleCheck(frame, lv);
 604                 }
 605                 break;
 606             case 'J': // Long Type
 607                 checkSetLongTypes(frame, lv);
 608                 negativeIntegerCheck(frame, lv);
 609                 negativeFloatCheck(frame, lv);
 610                 negativeDoubleCheck(frame, lv);
 611                 break;
 612             case 'F': // Float Type
 613                 checkSetFloatTypes(frame, lv);
 614                 negativeIntegerCheck(frame, lv);
 615                 negativeDoubleCheck(frame, lv);
 616                 break;
 617             case 'D': // Double Type
 618                 checkSetDoubleTypes(frame, lv);
 619                 negativeIntegerCheck(frame, lv);
 620                 negativeFloatCheck(frame, lv);
 621                 break;
 622             case 'L':
 623                 if (signature.compareTo("Ljava/lang/String;") == 0) {
 624                     checkSetStringTypes(frame, lv);
 625                     negativeIntegerCheck(frame, lv);
 626                     negativeFloatCheck(frame, lv);
 627                 }
 628                 if (signature.compareTo("Ljava/lang/Object;") == 0) {
 629                     checkSetObjectTypes(frame, lv);
 630                     negativeIntegerCheck(frame, lv);
 631                     negativeFloatCheck(frame, lv);
 632                 }
 633                 break;
 634             default:
 635                 printOneVariable(lv, index);
 636                 failure(" Failure: List of local variables has a wrong entry!");
 637             };
 638         }
 639     }
 640 
 641 
 642     /********** test core **********/
 643 
 644     protected void runTests() throws Exception {
 645 
 646         /*
 647          * Get to the top of main() to determine targetClass and mainThread
 648          */
 649         BreakpointEvent bpe = startToMain("GetSetLocalTarg");
 650         println("startToMain(GetSetLocalTarg)");
 651 
 652         List localVars = printAllVariables("GetSetLocalTarg", "staticMeth");
 653 
 654         targetClass = bpe.location().declaringType();
 655         println("targetClass");
 656 
 657         mainThread = bpe.thread();
 658         println("mainThread");
 659 
 660         EventRequestManager erm = vm().eventRequestManager();
 661         println("EventRequestManager");
 662         StackFrame frame = null;
 663 
 664         for (int line = START_LINE; line <= STOP_LINE; line += 4) {
 665             println("\n resumeTo(GetSetLocalTarg, " + line + ")");
 666             bpe = resumeTo("GetSetLocalTarg", line);
 667             frame = bpe.thread().frame(0);
 668             printFrameVariables(frame);
 669             checkSetFrameVariables(frame);
 670         }
 671         // Check if we can Get/Set all local vars using last frame state
 672         checkGetSetAllVariables(localVars, frame);
 673 
 674         /*
 675          * resume until the end
 676          */
 677         listenUntilVMDisconnect();
 678 
 679         /*
 680          * deal with results of test
 681          * if anything has called failure("foo") testFailed will be true
 682          */
 683         if (!testFailed) {
 684             println("GetSetLocalTest: passed");
 685         } else {
 686             throw new Exception("GetSetLocalTest: failed");
 687         }
 688     }
 689 }