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