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