1 /*
   2  * Copyright (c) 2014, 2018, 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 /*
  25  * @test TestStableByte
  26  * @summary tests on stable fields and arrays
  27  * @library /test/lib /
  28  * @modules java.base/jdk.internal.misc
  29  * @modules java.base/jdk.internal.vm.annotation
  30  * @build sun.hotspot.WhiteBox
  31  *
  32  * @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
  33  *                                 -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
  34  *                                 -XX:-TieredCompilation
  35  *                                 -XX:+FoldStableValues
  36  *                                 compiler.stable.TestStableByte
  37  * @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
  38  *                                 -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
  39  *                                 -XX:-TieredCompilation
  40  *                                 -XX:-FoldStableValues
  41  *                                 compiler.stable.TestStableByte
  42  *
  43  * @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
  44  *                                 -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
  45  *                                 -XX:+TieredCompilation -XX:TieredStopAtLevel=1
  46  *                                 -XX:+FoldStableValues
  47  *                                 compiler.stable.TestStableByte
  48  * @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
  49  *                                 -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
  50  *                                 -XX:+TieredCompilation -XX:TieredStopAtLevel=1
  51  *                                 -XX:-FoldStableValues
  52  *                                 compiler.stable.TestStableByte
  53  */
  54 
  55 package compiler.stable;
  56 
  57 import jdk.internal.vm.annotation.Stable;
  58 
  59 import java.lang.reflect.InvocationTargetException;
  60 
  61 public class TestStableByte {
  62     static final boolean isStableEnabled    = StableConfiguration.isStableEnabled;
  63 
  64     public static void main(String[] args) throws Exception {
  65         run(DefaultValue.class);
  66         run(ByteStable.class);
  67         run(DefaultStaticValue.class);
  68         run(StaticByteStable.class);
  69         run(VolatileByteStable.class);
  70 
  71         // @Stable arrays: Dim 1-4
  72         run(ByteArrayDim1.class);
  73         run(ByteArrayDim2.class);
  74         run(ByteArrayDim3.class);
  75         run(ByteArrayDim4.class);
  76 
  77         // @Stable Object field: dynamic arrays
  78         run(ObjectArrayLowerDim0.class);
  79         run(ObjectArrayLowerDim1.class);
  80         run(ObjectArrayLowerDim2.class);
  81 
  82         // Nested @Stable fields
  83         run(NestedStableField.class);
  84         run(NestedStableField1.class);
  85         run(NestedStableField2.class);
  86         run(NestedStableField3.class);
  87 
  88         if (failed) {
  89             throw new Error("TEST FAILED");
  90         }
  91     }
  92 
  93     /* ==================================================== */
  94 
  95     static class DefaultValue {
  96         public @Stable byte v;
  97 
  98         public static final DefaultValue c = new DefaultValue();
  99         public static byte get() { return c.v; }
 100         public static void test() throws Exception {
 101                      byte val1 = get();
 102             c.v = 1; byte val2 = get();
 103             assertEquals(val1, 0);
 104             assertEquals(val2, 1);
 105         }
 106     }
 107 
 108     /* ==================================================== */
 109 
 110     static class ByteStable {
 111         public @Stable byte v;
 112 
 113         public static final ByteStable c = new ByteStable();
 114         public static byte get() { return c.v; }
 115         public static void test() throws Exception {
 116             c.v = 5;   byte val1 = get();
 117             c.v = 127; byte val2 = get();
 118             assertEquals(val1, 5);
 119             assertEquals(val2, (isStableEnabled ? 5 : 127));
 120         }
 121     }
 122 
 123     /* ==================================================== */
 124 
 125     static class DefaultStaticValue {
 126         public static @Stable byte v;
 127 
 128         public static final DefaultStaticValue c = new DefaultStaticValue();
 129         public static byte get() { return c.v; }
 130         public static void test() throws Exception {
 131                      byte val1 = get();
 132             c.v = 1; byte val2 = get();
 133             assertEquals(val1, 0);
 134             assertEquals(val2, 1);
 135         }
 136     }
 137 
 138     /* ==================================================== */
 139 
 140     static class StaticByteStable {
 141         public static @Stable byte v;
 142 
 143         public static final StaticByteStable c = new StaticByteStable();
 144         public static byte get() { return c.v; }
 145         public static void test() throws Exception {
 146             c.v = 5;   byte val1 = get();
 147             c.v = 127; byte val2 = get();
 148             assertEquals(val1, 5);
 149             assertEquals(val2, (isStableEnabled ? 5 : 127));
 150         }
 151     }
 152 
 153     /* ==================================================== */
 154 
 155     static class VolatileByteStable {
 156         public @Stable volatile byte v;
 157 
 158         public static final VolatileByteStable c = new VolatileByteStable();
 159         public static byte get() { return c.v; }
 160         public static void test() throws Exception {
 161             c.v = 5;   byte val1 = get();
 162             c.v = 127; byte val2 = get();
 163             assertEquals(val1, 5);
 164             assertEquals(val2, (isStableEnabled ? 5 : 127));
 165         }
 166     }
 167 
 168     /* ==================================================== */
 169     // @Stable array == field && all components are stable
 170 
 171     static class ByteArrayDim1 {
 172         public @Stable byte[] v;
 173 
 174         public static final ByteArrayDim1 c = new ByteArrayDim1();
 175         public static byte get() { return c.v[0]; }
 176         public static byte get1() { return c.v[10]; }
 177         public static byte[] get2() { return c.v; }
 178         public static void test() throws Exception {
 179             {
 180                 c.v = new byte[1]; c.v[0] = 1; byte val1 = get();
 181                                    c.v[0] = 2; byte val2 = get();
 182                 assertEquals(val1, 1);
 183                 assertEquals(val2, (isStableEnabled ? 1 : 2));
 184 
 185                 c.v = new byte[1]; c.v[0] = 3; byte val3 = get();
 186                 assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2)
 187                                                     : 3));
 188             }
 189 
 190             {
 191                 c.v = new byte[20]; c.v[10] = 1; byte val1 = get1();
 192                                     c.v[10] = 2; byte val2 = get1();
 193                 assertEquals(val1, 1);
 194                 assertEquals(val2, (isStableEnabled ? 1 : 2));
 195 
 196                 c.v = new byte[20]; c.v[10] = 3; byte val3 = get1();
 197                 assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2)
 198                                                     : 3));
 199             }
 200 
 201             {
 202                 c.v = new byte[1]; byte[] val1 = get2();
 203                 c.v = new byte[1]; byte[] val2 = get2();
 204                 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
 205             }
 206         }
 207     }
 208 
 209     /* ==================================================== */
 210 
 211     static class ByteArrayDim2 {
 212         public @Stable byte[][] v;
 213 
 214         public static final ByteArrayDim2 c = new ByteArrayDim2();
 215         public static byte get() { return c.v[0][0]; }
 216         public static byte[] get1() { return c.v[0]; }
 217         public static byte[][] get2() { return c.v; }
 218         public static void test() throws Exception {
 219             {
 220                 c.v = new byte[1][1]; c.v[0][0] = 1; byte val1 = get();
 221                                       c.v[0][0] = 2; byte val2 = get();
 222                 assertEquals(val1, 1);
 223                 assertEquals(val2, (isStableEnabled ? 1 : 2));
 224 
 225                 c.v = new byte[1][1]; c.v[0][0] = 3; byte val3 = get();
 226                 assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2)
 227                                                     : 3));
 228 
 229                 c.v[0] = new byte[1]; c.v[0][0] = 4; byte val4 = get();
 230                 assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2)
 231                                                     : 4));
 232             }
 233 
 234             {
 235                 c.v = new byte[1][1]; byte[] val1 = get1();
 236                 c.v[0] = new byte[1]; byte[] val2 = get1();
 237                 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
 238             }
 239 
 240             {
 241                 c.v = new byte[1][1]; byte[][] val1 = get2();
 242                 c.v = new byte[1][1]; byte[][] val2 = get2();
 243                 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
 244             }
 245         }
 246     }
 247 
 248     /* ==================================================== */
 249 
 250     static class ByteArrayDim3 {
 251         public @Stable byte[][][] v;
 252 
 253         public static final ByteArrayDim3 c = new ByteArrayDim3();
 254         public static byte get() { return c.v[0][0][0]; }
 255         public static byte[] get1() { return c.v[0][0]; }
 256         public static byte[][] get2() { return c.v[0]; }
 257         public static byte[][][] get3() { return c.v; }
 258         public static void test() throws Exception {
 259             {
 260                 c.v = new byte[1][1][1]; c.v[0][0][0] = 1; byte val1 = get();
 261                                          c.v[0][0][0] = 2; byte val2 = get();
 262                 assertEquals(val1, 1);
 263                 assertEquals(val2, (isStableEnabled ? 1 : 2));
 264 
 265                 c.v = new byte[1][1][1]; c.v[0][0][0] = 3; byte val3 = get();
 266                 assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2)
 267                                                     : 3));
 268 
 269                 c.v[0] = new byte[1][1]; c.v[0][0][0] = 4; byte val4 = get();
 270                 assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2)
 271                                                     : 4));
 272 
 273                 c.v[0][0] = new byte[1]; c.v[0][0][0] = 5; byte val5 = get();
 274                 assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2)
 275                                                     : 5));
 276             }
 277 
 278             {
 279                 c.v = new byte[1][1][1]; byte[] val1 = get1();
 280                 c.v[0][0] = new byte[1]; byte[] val2 = get1();
 281                 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
 282             }
 283 
 284             {
 285                 c.v = new byte[1][1][1]; byte[][] val1 = get2();
 286                 c.v[0] = new byte[1][1]; byte[][] val2 = get2();
 287                 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
 288             }
 289 
 290             {
 291                 c.v = new byte[1][1][1]; byte[][][] val1 = get3();
 292                 c.v = new byte[1][1][1]; byte[][][] val2 = get3();
 293                 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
 294             }
 295         }
 296     }
 297 
 298     /* ==================================================== */
 299 
 300     static class ByteArrayDim4 {
 301         public @Stable byte[][][][] v;
 302 
 303         public static final ByteArrayDim4 c = new ByteArrayDim4();
 304         public static byte get() { return c.v[0][0][0][0]; }
 305         public static byte[] get1() { return c.v[0][0][0]; }
 306         public static byte[][] get2() { return c.v[0][0]; }
 307         public static byte[][][] get3() { return c.v[0]; }
 308         public static byte[][][][] get4() { return c.v; }
 309         public static void test() throws Exception {
 310             {
 311                 c.v = new byte[1][1][1][1]; c.v[0][0][0][0] = 1; byte val1 = get();
 312                                             c.v[0][0][0][0] = 2; byte val2 = get();
 313                 assertEquals(val1, 1);
 314                 assertEquals(val2, (isStableEnabled ? 1 : 2));
 315 
 316                 c.v = new byte[1][1][1][1]; c.v[0][0][0][0] = 3; byte val3 = get();
 317                 assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2)
 318                                                     : 3));
 319 
 320                 c.v[0] = new byte[1][1][1]; c.v[0][0][0][0] = 4; byte val4 = get();
 321                 assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2)
 322                                                     : 4));
 323 
 324                 c.v[0][0] = new byte[1][1]; c.v[0][0][0][0] = 5; byte val5 = get();
 325                 assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2)
 326                                                     : 5));
 327 
 328                 c.v[0][0][0] = new byte[1]; c.v[0][0][0][0] = 6; byte val6 = get();
 329                 assertEquals(val6, (isStableEnabled ? (isStableEnabled ? 1 : 2)
 330                                                     : 6));
 331             }
 332 
 333             {
 334                 c.v = new byte[1][1][1][1]; byte[] val1 = get1();
 335                 c.v[0][0][0] = new byte[1]; byte[] val2 = get1();
 336                 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
 337             }
 338 
 339             {
 340                 c.v = new byte[1][1][1][1]; byte[][] val1 = get2();
 341                 c.v[0][0] = new byte[1][1]; byte[][] val2 = get2();
 342                 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
 343             }
 344 
 345             {
 346                 c.v = new byte[1][1][1][1]; byte[][][] val1 = get3();
 347                 c.v[0] = new byte[1][1][1]; byte[][][] val2 = get3();
 348                 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
 349             }
 350 
 351             {
 352                 c.v = new byte[1][1][1][1]; byte[][][][] val1 = get4();
 353                 c.v = new byte[1][1][1][1]; byte[][][][] val2 = get4();
 354                 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
 355             }
 356 
 357         }
 358     }
 359 
 360     /* ==================================================== */
 361     // Dynamic Dim is higher than static
 362 
 363     static class ObjectArrayLowerDim0 {
 364         public @Stable Object v;
 365 
 366         public static final ObjectArrayLowerDim0 c = new ObjectArrayLowerDim0();
 367         public static byte get() { return ((byte[])c.v)[0]; }
 368         public static byte[] get1() { return (byte[])c.v; }
 369 
 370         public static void test() throws Exception {
 371             {
 372                 c.v = new byte[1]; ((byte[])c.v)[0] = 1; byte val1 = get();
 373                                    ((byte[])c.v)[0] = 2; byte val2 = get();
 374 
 375                 assertEquals(val1, 1);
 376                 assertEquals(val2, 2);
 377             }
 378 
 379             {
 380                 c.v = new byte[1]; byte[] val1 = get1();
 381                 c.v = new byte[1]; byte[] val2 = get1();
 382                 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
 383             }
 384         }
 385     }
 386 
 387     /* ==================================================== */
 388 
 389     static class ObjectArrayLowerDim1 {
 390         public @Stable Object[] v;
 391 
 392         public static final ObjectArrayLowerDim1 c = new ObjectArrayLowerDim1();
 393         public static byte get() { return ((byte[][])c.v)[0][0]; }
 394         public static byte[] get1() { return (byte[])(c.v[0]); }
 395         public static Object[] get2() { return c.v; }
 396 
 397         public static void test() throws Exception {
 398             {
 399                 c.v = new byte[1][1]; ((byte[][])c.v)[0][0] = 1; byte val1 = get();
 400                                       ((byte[][])c.v)[0][0] = 2; byte val2 = get();
 401 
 402                 assertEquals(val1, 1);
 403                 assertEquals(val2, 2);
 404             }
 405 
 406             {
 407                 c.v = new byte[1][1]; c.v[0] = new byte[0]; byte[] val1 = get1();
 408                                       c.v[0] = new byte[0]; byte[] val2 = get1();
 409 
 410                 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
 411             }
 412 
 413             {
 414                 c.v = new byte[0][0]; Object[] val1 = get2();
 415                 c.v = new byte[0][0]; Object[] val2 = get2();
 416 
 417                 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
 418             }
 419         }
 420     }
 421 
 422     /* ==================================================== */
 423 
 424     static class ObjectArrayLowerDim2 {
 425         public @Stable Object[][] v;
 426 
 427         public static final ObjectArrayLowerDim2 c = new ObjectArrayLowerDim2();
 428         public static byte get() { return ((byte[][][])c.v)[0][0][0]; }
 429         public static byte[] get1() { return (byte[])(c.v[0][0]); }
 430         public static byte[][] get2() { return (byte[][])(c.v[0]); }
 431         public static Object[][] get3() { return c.v; }
 432 
 433         public static void test() throws Exception {
 434             {
 435                 c.v = new byte[1][1][1]; ((byte[][][])c.v)[0][0][0] = 1; byte val1 = get();
 436                                          ((byte[][][])c.v)[0][0][0] = 2; byte val2 = get();
 437 
 438                 assertEquals(val1, 1);
 439                 assertEquals(val2, 2);
 440             }
 441 
 442             {
 443                 c.v = new byte[1][1][1]; c.v[0][0] = new byte[0]; byte[] val1 = get1();
 444                                          c.v[0][0] = new byte[0]; byte[] val2 = get1();
 445 
 446                 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
 447             }
 448 
 449             {
 450                 c.v = new byte[1][1][1]; c.v[0] = new byte[0][0]; byte[][] val1 = get2();
 451                                          c.v[0] = new byte[0][0]; byte[][] val2 = get2();
 452 
 453                 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
 454             }
 455 
 456             {
 457                 c.v = new byte[0][0][0]; Object[][] val1 = get3();
 458                 c.v = new byte[0][0][0]; Object[][] val2 = get3();
 459 
 460                 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
 461             }
 462         }
 463     }
 464 
 465     /* ==================================================== */
 466 
 467     static class NestedStableField {
 468         static class A {
 469             public @Stable byte a;
 470 
 471         }
 472         public @Stable A v;
 473 
 474         public static final NestedStableField c = new NestedStableField();
 475         public static A get() { return c.v; }
 476         public static byte get1() { return get().a; }
 477 
 478         public static void test() throws Exception {
 479             {
 480                 c.v = new A(); c.v.a = 1; A val1 = get();
 481                                c.v.a = 2; A val2 = get();
 482 
 483                 assertEquals(val1.a, 2);
 484                 assertEquals(val2.a, 2);
 485             }
 486 
 487             {
 488                 c.v = new A(); c.v.a = 1; byte val1 = get1();
 489                                c.v.a = 2; byte val2 = get1();
 490                 c.v = new A(); c.v.a = 3; byte val3 = get1();
 491 
 492                 assertEquals(val1, 1);
 493                 assertEquals(val2, (isStableEnabled ? 1 : 2));
 494                 assertEquals(val3, (isStableEnabled ? 1 : 3));
 495             }
 496         }
 497     }
 498 
 499     /* ==================================================== */
 500 
 501     static class NestedStableField1 {
 502         static class A {
 503             public @Stable byte a;
 504             public @Stable A next;
 505         }
 506         public @Stable A v;
 507 
 508         public static final NestedStableField1 c = new NestedStableField1();
 509         public static A get() { return c.v.next.next.next.next.next.next.next; }
 510         public static byte get1() { return get().a; }
 511 
 512         public static void test() throws Exception {
 513             {
 514                 c.v = new A(); c.v.next = new A();   c.v.next.next  = c.v;
 515                                c.v.a = 1; c.v.next.a = 1; A val1 = get();
 516                                c.v.a = 2; c.v.next.a = 2; A val2 = get();
 517 
 518                 assertEquals(val1.a, 2);
 519                 assertEquals(val2.a, 2);
 520             }
 521 
 522             {
 523                 c.v = new A(); c.v.next = c.v;
 524                                c.v.a = 1; byte val1 = get1();
 525                                c.v.a = 2; byte val2 = get1();
 526                 c.v = new A(); c.v.next = c.v;
 527                                c.v.a = 3; byte val3 = get1();
 528 
 529                 assertEquals(val1, 1);
 530                 assertEquals(val2, (isStableEnabled ? 1 : 2));
 531                 assertEquals(val3, (isStableEnabled ? 1 : 3));
 532             }
 533         }
 534     }
 535    /* ==================================================== */
 536 
 537     static class NestedStableField2 {
 538         static class A {
 539             public @Stable byte a;
 540             public @Stable A left;
 541             public         A right;
 542         }
 543 
 544         public @Stable A v;
 545 
 546         public static final NestedStableField2 c = new NestedStableField2();
 547         public static byte get() { return c.v.left.left.left.a; }
 548         public static byte get1() { return c.v.left.left.right.left.a; }
 549 
 550         public static void test() throws Exception {
 551             {
 552                 c.v = new A(); c.v.left = c.v.right = c.v;
 553                                c.v.a = 1; byte val1 = get(); byte val2 = get1();
 554                                c.v.a = 2; byte val3 = get(); byte val4 = get1();
 555 
 556                 assertEquals(val1, 1);
 557                 assertEquals(val3, (isStableEnabled ? 1 : 2));
 558 
 559                 assertEquals(val2, 1);
 560                 assertEquals(val4, 2);
 561             }
 562         }
 563     }
 564 
 565     /* ==================================================== */
 566 
 567     static class NestedStableField3 {
 568         static class A {
 569             public @Stable byte a;
 570             public @Stable A[] left;
 571             public         A[] right;
 572         }
 573 
 574         public @Stable A[] v;
 575 
 576         public static final NestedStableField3 c = new NestedStableField3();
 577         public static byte get() { return c.v[0].left[1].left[0].left[1].a; }
 578         public static byte get1() { return c.v[1].left[0].left[1].right[0].left[1].a; }
 579 
 580         public static void test() throws Exception {
 581             {
 582                 A elem = new A();
 583                 c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
 584                                elem.a = 1; byte val1 = get(); byte val2 = get1();
 585                                elem.a = 2; byte val3 = get(); byte val4 = get1();
 586 
 587                 assertEquals(val1, 1);
 588                 assertEquals(val3, (isStableEnabled ? 1 : 2));
 589 
 590                 assertEquals(val2, 1);
 591                 assertEquals(val4, 2);
 592             }
 593         }
 594     }
 595 
 596     /* ==================================================== */
 597     // Auxiliary methods
 598     static void assertEquals(int i, int j) { if (i != j)  throw new AssertionError(i + " != " + j); }
 599     static void assertTrue(boolean b) { if (!b)  throw new AssertionError(); }
 600 
 601     static boolean failed = false;
 602 
 603     public static void run(Class<?> test) {
 604         Throwable ex = null;
 605         System.out.print(test.getName()+": ");
 606         try {
 607             test.getMethod("test").invoke(null);
 608         } catch (InvocationTargetException e) {
 609             ex = e.getCause();
 610         } catch (Throwable e) {
 611             ex = e;
 612         } finally {
 613             if (ex == null) {
 614                 System.out.println("PASSED");
 615             } else {
 616                 failed = true;
 617                 System.out.println("FAILED");
 618                 ex.printStackTrace(System.out);
 619             }
 620         }
 621     }
 622 }