1/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This code is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11 * version 2 for more details (a copy is included in the LICENSE file that
12 * accompanied this code).
13 *
14 * You should have received a copy of the GNU General Public License version
15 * 2 along with this work; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 */
22
23/*
24 * This file is available under and governed by the GNU General Public
25 * License version 2 only, as published by the Free Software Foundation.
26 * However, the following notice accompanied the original version of this
27 * file:
28 *
29 * Written by Doug Lea with assistance from members of JCP JSR-166
30 * Expert Group and released to the public domain, as explained at
31 * http://creativecommons.org/publicdomain/zero/1.0/
32 */
33
34/*
35 * @test
36 * @bug 8005697
37 * @summary Basic tests for StampedLock
38 * @library /lib/testlibrary/
39 * @author Chris Hegarty
40 */
41
42import static java.util.concurrent.TimeUnit.SECONDS;
43import static java.util.concurrent.TimeUnit.MILLISECONDS;
44import static java.util.concurrent.TimeUnit.NANOSECONDS;
45
46import java.util.Iterator;
47import java.util.concurrent.Phaser;
48import java.util.concurrent.TimeUnit;
49import java.util.concurrent.atomic.AtomicInteger;
50import java.util.concurrent.locks.Lock;
51import java.util.concurrent.locks.ReadWriteLock;
52import java.util.concurrent.locks.StampedLock;
53import jdk.testlibrary.Utils;
54
55public class Basic {
56    static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
57
58    static void checkResult(Locker l, Class<? extends Throwable> c) {
59        Throwable t = l.thrown();
60        if (! ((t == null && c == null) || (c != null && c.isInstance(t)))) {
61            fail("Mismatch in thread " +
62                 l.getName() + ": " +
63                 t + ", " +
64                 (c == null ? "<null>" : c.getName()));
65        }
66
67        if (c == null)
68            check(l.stamp() != 0L);  // must have acquired the lock
69        else
70            check(l.stamp() == 0L);  // must NOT have acquired the lock
71    }
72
73    //----------------------------------------------------------------
74    // Mechanism to get all test threads into "running" mode.
75    //----------------------------------------------------------------
76    static void toTheStartingGate(Phaser gate) {
77        try {
78            gate.arriveAndAwaitAdvance();
79        } catch (Throwable t) {
80            unexpected(t);
81        }
82    }
83
84    abstract static class Locker extends Thread {
85        static AtomicInteger count = new AtomicInteger(1);
86        private volatile Throwable thrown;
87        private volatile long stamp;
88        protected void thrown(Throwable thrown) { this.thrown = thrown; }
89        public Throwable thrown() { return thrown; }
90        protected void stamp(long stamp) { this.stamp = stamp; }
91        public long stamp() { return stamp; }
92
93        Locker() {
94            this("Locker");
95        }
96
97        Locker(String name) {
98            this.setName(name + ":" + count.getAndIncrement());
99            this.setDaemon(true);
100        }
101    }
102
103    abstract static class Reader extends Locker {
104        Reader() { super("Reader"); }
105        Reader(String name) { super(name); }
106    }
107
108    static Reader reader(final StampedLock sl, final Phaser gate) {
109        return new Reader() { public void run() {
110            if (gate != null ) toTheStartingGate(gate);
111            stamp(sl.readLock());
112            try {
113                check(sl.validate(stamp()));
114                check(sl.isReadLocked());
115                check(!sl.isWriteLocked());
116            } finally { sl.unlockRead(stamp()); } }};
117    }
118
119    static Reader readerView(final StampedLock sl, final Phaser gate) {
120        return new Reader("ReaderView") { public void run() {
121            if (gate != null ) toTheStartingGate(gate);
122            final Lock rl = sl.asReadLock();
123            rl.lock();
124            try {
125                stamp(1L);   // got the lock
126                check(sl.isReadLocked());
127                check(!sl.isWriteLocked());
128            } finally { rl.unlock(); } }};
129    }
130
131    static Reader reader(StampedLock sl, Phaser gate, boolean view) {
132        return view ? readerView(sl, gate) : reader(sl, gate);
133    }
134
135    static Reader interruptibleReader(final StampedLock sl,
136                                      final long timeout,
137                                      final TimeUnit unit,
138                                      final Phaser gate) {
139        return new Reader("InterruptibleReader") { public void run() {
140            if (gate != null ) toTheStartingGate(gate);
141            try {
142                if (timeout < 0)
143                    stamp(sl.readLockInterruptibly());
144                else
145                    stamp(sl.tryReadLock(timeout, unit));
146                check(sl.validate(stamp()));
147                check(sl.isReadLocked());
148                check(!sl.isWriteLocked());
149            } catch (Throwable x) { thrown(x);
150            } finally { if (stamp() != 0L) sl.unlockRead(stamp()); } }};
151    }
152
153    static Reader interruptibleReaderView(final StampedLock sl,
154                                          final long timeout,
155                                          final TimeUnit unit,
156                                          final Phaser gate) {
157        return new Reader("InterruptibleReaderView") { public void run() {
158            if (gate != null ) toTheStartingGate(gate);
159            final Lock rl = sl.asReadLock();
160
161            try {
162                if (timeout < 0)
163                    rl.lockInterruptibly();
164                else
165                    rl.tryLock(timeout, unit);
166                stamp(1L);  // got the lock
167                check(sl.isReadLocked());
168                check(!sl.isWriteLocked());
169            } catch (Throwable x) { thrown(x);
170            } finally { if (stamp() != 0L) rl.unlock(); } }};
171    }
172
173    static Reader interruptibleReader(final StampedLock sl,
174                                      final long timeout,
175                                      final TimeUnit unit,
176                                      final Phaser gate,
177                                      final boolean view) {
178        return view ? interruptibleReaderView(sl, timeout, unit, gate)
179                    : interruptibleReader(sl, timeout, unit, gate);
180    }
181
182    abstract static class Writer extends Locker {
183        Writer() { super("Writer"); }
184        Writer(String name) { super(name); }
185    }
186
187    static Writer writer(final StampedLock sl, final Phaser gate) {
188        return new Writer() { public void run() {
189            if (gate != null ) toTheStartingGate(gate);
190            try {
191                stamp(sl.writeLock());
192                check(sl.validate(stamp()));
193                check(!sl.isReadLocked());
194                check(sl.isWriteLocked());
195            } finally { sl.unlockWrite(stamp()); } }};
196    }
197
198    static Writer writerView(final StampedLock sl, final Phaser gate) {
199        return new Writer("WriterView") { public void run() {
200            if (gate != null ) toTheStartingGate(gate);
201            Lock wl = sl.asWriteLock();
202            wl.lock();
203            try {
204                stamp(1L);  // got the lock
205                check(!sl.isReadLocked());
206                check(sl.isWriteLocked());
207            } finally { wl.unlock(); } }};
208    }
209
210    static Writer writer(StampedLock sl, Phaser gate, boolean view) {
211        return view ? writerView(sl, gate) : writer(sl, gate);
212    }
213
214    static Writer interruptibleWriter(final StampedLock sl,
215                                      final long timeout,
216                                      final TimeUnit unit,
217                                      final Phaser gate) {
218        return new Writer("InterruptibleWriter") { public void run() {
219            if (gate != null ) toTheStartingGate(gate);
220            try {
221                if (timeout < 0)
222                    stamp(sl.writeLockInterruptibly());
223                else
224                    stamp(sl.tryWriteLock(timeout, unit));
225                check(sl.validate(stamp()));
226                check(!sl.isReadLocked());
227                check(sl.isWriteLocked());
228            } catch (Throwable x) { thrown(x);
229            } finally { if (stamp() != 0L) sl.unlockWrite(stamp()); } }};
230    }
231
232    static Writer interruptibleWriterView(final StampedLock sl,
233                                          final long timeout,
234                                          final TimeUnit unit,
235                                          final Phaser gate) {
236        return new Writer("InterruptibleWriterView") { public void run() {
237            if (gate != null ) toTheStartingGate(gate);
238            Lock wl = sl.asWriteLock();
239            try {
240                if (timeout < 0)
241                    wl.lockInterruptibly();
242                else
243                    wl.tryLock(timeout, unit);
244                stamp(1L);  // got the lock
245                check(!sl.isReadLocked());
246                check(sl.isWriteLocked());
247            } catch (Throwable x) { thrown(x);
248            } finally { if (stamp() != 0L) wl.unlock(); } }};
249    }
250
251    static Writer interruptibleWriter(final StampedLock sl,
252                                      final long timeout,
253                                      final TimeUnit unit,
254                                      final Phaser gate,
255                                      final boolean view) {
256        return view ? interruptibleWriterView(sl, timeout, unit, gate)
257                    : interruptibleWriter(sl, timeout, unit, gate);
258    }
259
260    // Returns an infinite lazy list of all possible reader combinations.
261    static Iterator<Reader> readerIterator(final StampedLock sl,
262                                           final Phaser gate) {
263        return new Iterator<Reader>() {
264            int i = 0;
265            boolean view = false;
266            public boolean hasNext() { return true; }
267            public Reader next() {
268                switch ((i++)&7) {
269                    case 1: case 4: case 7:
270                        return reader(sl, gate, view ^= true);
271                    case 2: case 5:
272                        return interruptibleReader(sl, -1, SECONDS, gate, view ^= true);
273                    default:
274                        return interruptibleReader(sl, LONG_DELAY_MS, MILLISECONDS, gate, view ^= true); }}
275            public void remove() {throw new UnsupportedOperationException();}};
276    }
277
278    // Returns an infinite lazy list of all possible writer combinations.
279    static Iterator<Writer> writerIterator(final StampedLock sl,
280                                           final Phaser gate) {
281        return new Iterator<Writer>() {
282            int i = 0;
283            boolean view = false;
284            public boolean hasNext() { return true; }
285            public Writer next() {
286                switch ((i++)&7) {
287                    case 1: case 4: case 7:
288                        return writer(sl, gate, view ^= true);
289                    case 2: case 5:
290                        return interruptibleWriter(sl, -1, SECONDS, gate, view ^= true);
291                    default:
292                        return interruptibleWriter(sl, LONG_DELAY_MS, MILLISECONDS, gate, view ^= true); }}
293            public void remove() {throw new UnsupportedOperationException();}};
294    }
295
296    static class SimpleTimer {
297        long startTime = System.nanoTime();
298        long elapsedMillis() {
299            long now = System.nanoTime();
300            long elapsed = NANOSECONDS.toMillis(now - startTime);
301            startTime = now;
302            return elapsed;
303        }
304        void printElapsed() { System.out.println(elapsedMillis() + " ms"); }
305    }
306
307    static void waitForThreadToBlock(Thread thread) {
308        for (long startTime = 0;;) {
309            Thread.State state = thread.getState();
310            if (state == Thread.State.WAITING ||
311                state == Thread.State.TIMED_WAITING)
312                break;
313            if (startTime == 0) startTime = System.nanoTime();
314            else if (System.nanoTime() - startTime > 10L * 1000L * 1000L * 1000L)
315                throw new AssertionError("timed out waiting for thread to block");
316        }
317    }
318
319    private static void realMain(String[] args) throws Throwable {
320        SimpleTimer timer = new SimpleTimer();
321
322        //----------------------------------------------------------------
323        System.out.print("Some basic sanity: ");
324        //----------------------------------------------------------------
325        try {
326            final StampedLock sl = new StampedLock();
327            check(!sl.isReadLocked());
328            check(!sl.isWriteLocked());
329            long stamp = sl.tryOptimisticRead();
330            check(stamp != 0L);
331            check(sl.validate(stamp));
332            check(!sl.validate(0));
333
334            stamp = sl.writeLock();
335            try {
336                check(sl.validate(stamp));
337                check(!sl.isReadLocked());
338                check(sl.isWriteLocked());
339                check(sl.tryReadLock() == 0L);
340                check(sl.tryReadLock(1, MILLISECONDS) == 0L);
341                check(sl.tryOptimisticRead() == 0L);
342                check(sl.tryWriteLock() == 0L);
343                check(sl.tryWriteLock(1, MILLISECONDS) == 0L);
344                check(!sl.tryUnlockRead());
345                check(sl.tryConvertToWriteLock(stamp) == stamp);
346                try {
347                    sl.unlockRead(stamp);
348                    fail("Expected unlockRead to throw when not holding read lock");
349                } catch (IllegalMonitorStateException x) {
350                    pass();
351                }
352                check(sl.validate(stamp));
353            } finally {
354                sl.unlockWrite(stamp);
355            }
356            check(!sl.isWriteLocked());
357
358            stamp = sl.readLock();
359            try {
360                check(sl.validate(stamp));
361                check(sl.isReadLocked());
362                check(!sl.isWriteLocked());
363                check(sl.tryOptimisticRead() != 0L);
364                check(sl.tryWriteLock() == 0L);
365                check(sl.tryWriteLock(1, MILLISECONDS) == 0L);
366                check(!sl.tryUnlockWrite());
367                check(sl.tryConvertToReadLock(stamp) == stamp);
368                try {
369                    sl.unlockWrite(stamp);
370                    fail("Expected unlockWrite to throw when not holding read lock");
371                } catch (IllegalMonitorStateException x) {
372                    pass();
373                }
374                check(sl.validate(stamp));
375            } finally {
376                sl.unlockRead(stamp);
377            }
378            check(!sl.isReadLocked());
379
380            stamp = sl.tryReadLock(1, MILLISECONDS);
381            try {
382                check(stamp != 0L);
383            } finally {
384                sl.unlockRead(stamp);
385            }
386        } catch (Throwable t) { unexpected(t); }
387        timer.printElapsed();
388
389        //----------------------------------------------------------------
390        System.out.print("Multiple writers single reader: ");
391        //----------------------------------------------------------------
392        try {
393            StampedLock sl = new StampedLock();
394            int nThreads = 10;
395            Phaser gate = new Phaser(nThreads + 2);
396            Iterator<Writer> writers = writerIterator(sl, gate);
397            Iterator<Reader> readers = readerIterator(sl, gate);
398            for (int i = 0; i < 2; i++) {
399                check(!sl.isReadLocked());
400                check(!sl.isWriteLocked());
401                check(!sl.tryUnlockRead());
402                check(!sl.tryUnlockWrite());
403                check(sl.tryOptimisticRead() != 0L);
404                Locker[] wThreads = new Locker[nThreads];
405                for (int j=0; j<nThreads; j++)
406                    wThreads[j] = writers.next();
407                for (int j=0; j<nThreads; j++)
408                    wThreads[j].start();
409                Reader reader = readers.next(); reader.start();
410                toTheStartingGate(gate);
411                reader.join();
412                for (int j=0; j<nThreads; j++)
413                    wThreads[j].join();
414                for (int j=0; j<nThreads; j++)
415                    checkResult(wThreads[j], null);
416                checkResult(reader, null);
417            }
418        } catch (Throwable t) { unexpected(t); }
419        timer.printElapsed();
420
421        //----------------------------------------------------------------
422        System.out.print("Multiple readers single writer: ");
423        //----------------------------------------------------------------
424        try {
425            StampedLock sl = new StampedLock();
426            int nThreads = 10;
427            Phaser gate = new Phaser(nThreads + 2);
428            Iterator<Writer> writers = writerIterator(sl, gate);
429            Iterator<Reader> readers = readerIterator(sl, gate);
430            for (int i = 0; i < 2; i++) {
431                check(!sl.isReadLocked());
432                check(!sl.isWriteLocked());
433                check(!sl.tryUnlockRead());
434                check(!sl.tryUnlockWrite());
435                check(sl.tryOptimisticRead() != 0L);
436                Locker[] rThreads = new Locker[nThreads];
437                for (int j=0; j<nThreads; j++)
438                    rThreads[j] = readers.next();
439                for (int j=0; j<nThreads; j++)
440                    rThreads[j].start();
441                Writer writer = writers.next(); writer.start();
442                toTheStartingGate(gate);
443                writer.join();
444                for (int j=0; j<nThreads; j++)
445                    rThreads[j].join();
446                for (int j=0; j<nThreads; j++)
447                    checkResult(rThreads[j], null);
448                checkResult(writer, null);
449            }
450        } catch (Throwable t) { unexpected(t); }
451        timer.printElapsed();
452
453        //----------------------------------------------------------------
454        System.out.print("thread interrupted: ");
455        //----------------------------------------------------------------
456        try {
457            // We test interrupting both before and after trying to acquire
458            boolean view = false;
459            StampedLock sl = new StampedLock();
460            for (long timeout : new long[] { -1L, LONG_DELAY_MS, -1L, LONG_DELAY_MS }) {
461                long stamp;
462                Thread.State state;
463
464                stamp = sl.writeLock();
465                try {
466                    Reader r = interruptibleReader(sl, timeout, MILLISECONDS, null, view);
467                    r.start();
468                    r.interrupt();
469                    r.join();
470                    checkResult(r, InterruptedException.class);
471                } finally {
472                    sl.unlockWrite(stamp);
473                }
474
475                stamp = sl.writeLock();
476                try {
477                    Reader r = interruptibleReader(sl, timeout, MILLISECONDS, null, view);
478                    r.start();
479                    waitForThreadToBlock(r);
480                    r.interrupt();
481                    r.join();
482                    checkResult(r, InterruptedException.class);
483                } finally {
484                    sl.unlockWrite(stamp);
485                }
486
487                stamp = sl.readLock();
488                try {
489                    Writer w = interruptibleWriter(sl, timeout, MILLISECONDS, null, view);
490                    w.start();
491                    w.interrupt();
492                    w.join();
493                    checkResult(w, InterruptedException.class);
494                } finally {
495                    sl.unlockRead(stamp);
496                }
497
498                stamp = sl.readLock();
499                try {
500                    Writer w = interruptibleWriter(sl, timeout, MILLISECONDS, null, view);
501                    w.start();
502                    waitForThreadToBlock(w);
503                    w.interrupt();
504                    w.join();
505                    checkResult(w, InterruptedException.class);
506                } finally {
507                    sl.unlockRead(stamp);
508                }
509
510                check(!sl.isReadLocked());
511                check(!sl.isWriteLocked());
512                check(!sl.tryUnlockRead());
513                check(!sl.tryUnlockWrite());
514                check(sl.tryOptimisticRead() != 0L);
515                if (timeout == LONG_DELAY_MS)
516                    view = true;
517            }
518        } catch (Throwable t) { unexpected(t); }
519        timer.printElapsed();
520
521        //----------------------------------------------------------------
522        System.out.print("timeout: ");
523        //----------------------------------------------------------------
524        try {
525            StampedLock sl = new StampedLock();
526            for (long timeout : new long[] { 0L, 5L }) {
527                long stamp = sl.writeLock();
528                try {
529                    check(sl.tryReadLock(timeout, MILLISECONDS) == 0L);
530                } finally {
531                    sl.unlockWrite(stamp);
532                }
533                stamp = sl.readLock();
534                try {
535                    check(sl.tryWriteLock(timeout, MILLISECONDS) == 0L);
536                } finally {
537                    sl.unlockRead(stamp);
538                }
539                check(!sl.isReadLocked());
540                check(!sl.isWriteLocked());
541                check(!sl.tryUnlockRead());
542                check(!sl.tryUnlockWrite());
543                check(sl.tryOptimisticRead() != 0L);
544            }
545        } catch (Throwable t) { unexpected(t); }
546        timer.printElapsed();
547
548        //----------------------------------------------------------------
549        System.out.print("optimistic read: ");
550        //----------------------------------------------------------------
551        try {
552            StampedLock sl = new StampedLock();
553            Iterator<Writer> writers = writerIterator(sl, null);
554            Iterator<Reader> readers = readerIterator(sl, null);
555            for (int i = 0; i < 10; i++) {
556                check(!sl.isReadLocked());
557                check(!sl.isWriteLocked());
558                check(!sl.tryUnlockRead());
559                check(!sl.tryUnlockWrite());
560                long stamp = sl.tryOptimisticRead();
561                check(stamp != 0L);
562                check(sl.tryConvertToOptimisticRead(stamp) == stamp);
563                Reader r = readers.next(); r.start();
564                r.join();
565                checkResult(r, null);
566                check(sl.validate(stamp));
567                check(sl.tryConvertToOptimisticRead(stamp) == stamp);
568                Writer w = writers.next(); w.start();
569                w.join();
570                checkResult(w, null);
571                check(sl.validate(stamp) == false);
572            }
573        } catch (Throwable t) { unexpected(t); }
574        timer.printElapsed();
575
576        //----------------------------------------------------------------
577        System.out.print("convert: ");
578        //----------------------------------------------------------------
579        try {
580            StampedLock sl = new StampedLock();
581            for (int i = 0; i < 2; i++) {
582                check(!sl.isReadLocked());
583                check(!sl.isWriteLocked());
584                check(!sl.tryUnlockRead());
585                check(!sl.tryUnlockWrite());
586                long stamp = sl.tryOptimisticRead();
587                check(stamp != 0L);
588                check((stamp = sl.tryConvertToReadLock(stamp)) != 0L);
589                check(sl.validate(stamp));
590                check(sl.isReadLocked());
591                check(sl.tryWriteLock() == 0L);
592                check(sl.tryWriteLock(1L, MILLISECONDS) == 0L);
593                check((stamp = sl.tryConvertToWriteLock(stamp)) != 0L);
594                check(sl.validate(stamp));
595                check(!sl.isReadLocked());
596                check(sl.isWriteLocked());
597                check(sl.tryReadLock(1L, MILLISECONDS) == 0L);
598                if (i != 0) {
599                    sl.unlockWrite(stamp);
600                    continue;
601                }
602                // convert down
603                check((stamp = sl.tryConvertToReadLock(stamp)) != 0L);
604                check(sl.validate(stamp));
605                check(sl.isReadLocked());
606                check(!sl.isWriteLocked());
607                check(sl.tryWriteLock() == 0L);
608                check(sl.tryWriteLock(1L, MILLISECONDS) == 0L);
609                check((stamp = sl.tryConvertToOptimisticRead(stamp)) != 0L);
610                check(sl.validate(stamp));
611                check(!sl.isReadLocked());
612                check(!sl.isWriteLocked());
613                check(sl.validate(stamp));
614            }
615        } catch (Throwable t) { unexpected(t); }
616        timer.printElapsed();
617
618        //----------------------------------------------------------------
619        System.out.print("views: ");
620        //----------------------------------------------------------------
621        try {
622            StampedLock sl = new StampedLock();
623
624            Lock rl = sl.asReadLock();
625            Lock wl = sl.asWriteLock();
626            for (int i = 0; i < 2; i++) {
627                rl.lock();
628                try {
629                    check(sl.isReadLocked());
630                    check(!sl.isWriteLocked());
631                    check(sl.tryWriteLock() == 0L);
632                    check(sl.tryWriteLock(1L, MILLISECONDS) == 0L);
633                } finally {
634                    rl.unlock();
635                }
636                check(!sl.isReadLocked());
637                check(!sl.isWriteLocked());
638
639                wl.lock();
640                try {
641                    check(!sl.isReadLocked());
642                    check(sl.isWriteLocked());
643                    check(sl.tryWriteLock() == 0L);
644                    check(sl.tryWriteLock(1L, MILLISECONDS) == 0L);
645                } finally {
646                    wl.unlock();
647                }
648                check(!sl.isReadLocked());
649                check(!sl.isWriteLocked());
650
651                ReadWriteLock rwl = sl.asReadWriteLock();
652                rl = rwl.readLock();
653                wl = rwl.writeLock();
654            }
655        } catch (Throwable t) { unexpected(t); }
656        timer.printElapsed();
657    }
658
659    //--------------------- Infrastructure ---------------------------
660    static volatile int passed = 0, failed = 0;
661    static void pass() {passed++;}
662    static void fail() {failed++; Thread.dumpStack();}
663    static void fail(String msg) {System.out.println(msg); fail();}
664    static void unexpected(Throwable t) {failed++; t.printStackTrace();}
665    static void check(boolean cond) {if (cond) pass(); else fail();}
666    static void equal(Object x, Object y) {
667        if (x == null ? y == null : x.equals(y)) pass();
668        else fail(x + " not equal to " + y);}
669    public static void main(String[] args) throws Throwable {
670        try {realMain(args);} catch (Throwable t) {unexpected(t);}
671        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
672        if (failed > 0) throw new AssertionError("Some tests failed");}
673}
674