diff options
author | Calin Juravle <calin@google.com> | 2013-08-01 17:26:00 +0100 |
---|---|---|
committer | Calin Juravle <calin@google.com> | 2013-08-14 19:15:59 +0100 |
commit | 8f0d92bba199d906c70a5e40d7f3516c1a424117 (patch) | |
tree | 3762e8e4275ac7535ce011915fb0e0f7a343deea /jsr166-tests/src/test/java/jsr166/LockSupportTest.java | |
parent | 75a06e56a4cc4599946e21422513e4bafa759509 (diff) | |
download | libcore-8f0d92bba199d906c70a5e40d7f3516c1a424117.zip libcore-8f0d92bba199d906c70a5e40d7f3516c1a424117.tar.gz libcore-8f0d92bba199d906c70a5e40d7f3516c1a424117.tar.bz2 |
Added jsr166 tck tests as part of the libcore testsuite.
Change-Id: I6094d734f818fa043f2b277cf2b4ec7fec68e26e
Diffstat (limited to 'jsr166-tests/src/test/java/jsr166/LockSupportTest.java')
-rw-r--r-- | jsr166-tests/src/test/java/jsr166/LockSupportTest.java | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/jsr166-tests/src/test/java/jsr166/LockSupportTest.java b/jsr166-tests/src/test/java/jsr166/LockSupportTest.java new file mode 100644 index 0000000..051de35 --- /dev/null +++ b/jsr166-tests/src/test/java/jsr166/LockSupportTest.java @@ -0,0 +1,362 @@ +/* + * Written by Doug Lea and Martin Buchholz with assistance from + * members of JCP JSR-166 Expert Group and released to the public + * domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +package jsr166; + +import junit.framework.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.LockSupport; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +public class LockSupportTest extends JSR166TestCase { + + /** + * Returns the blocker object used by tests in this file. + * Any old object will do; we'll return a convenient one. + */ + static Object theBlocker() { + return LockSupportTest.class; + } + + enum ParkMethod { + park() { + void park() { + LockSupport.park(); + } + void park(long millis) { + throw new UnsupportedOperationException(); + } + }, + parkUntil() { + void park(long millis) { + LockSupport.parkUntil(deadline(millis)); + } + }, + parkNanos() { + void park(long millis) { + LockSupport.parkNanos(MILLISECONDS.toNanos(millis)); + } + }, + parkBlocker() { + void park() { + LockSupport.park(theBlocker()); + } + void park(long millis) { + throw new UnsupportedOperationException(); + } + }, + parkUntilBlocker() { + void park(long millis) { + LockSupport.parkUntil(theBlocker(), deadline(millis)); + } + }, + parkNanosBlocker() { + void park(long millis) { + LockSupport.parkNanos(theBlocker(), + MILLISECONDS.toNanos(millis)); + } + }; + + void park() { park(2 * LONG_DELAY_MS); } + abstract void park(long millis); + + /** Returns a deadline to use with parkUntil. */ + long deadline(long millis) { + // beware of rounding + return System.currentTimeMillis() + millis + 1; + } + } + + /** + * park is released by subsequent unpark + */ + public void testParkBeforeUnpark_park() { + testParkBeforeUnpark(ParkMethod.park); + } + public void testParkBeforeUnpark_parkNanos() { + testParkBeforeUnpark(ParkMethod.parkNanos); + } + public void testParkBeforeUnpark_parkUntil() { + testParkBeforeUnpark(ParkMethod.parkUntil); + } + public void testParkBeforeUnpark_parkBlocker() { + testParkBeforeUnpark(ParkMethod.parkBlocker); + } + public void testParkBeforeUnpark_parkNanosBlocker() { + testParkBeforeUnpark(ParkMethod.parkNanosBlocker); + } + public void testParkBeforeUnpark_parkUntilBlocker() { + testParkBeforeUnpark(ParkMethod.parkUntilBlocker); + } + public void testParkBeforeUnpark(final ParkMethod parkMethod) { + final CountDownLatch pleaseUnpark = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + pleaseUnpark.countDown(); + parkMethod.park(); + }}); + + await(pleaseUnpark); + LockSupport.unpark(t); + awaitTermination(t); + } + + /** + * park is released by preceding unpark + */ + public void testParkAfterUnpark_park() { + testParkAfterUnpark(ParkMethod.park); + } + public void testParkAfterUnpark_parkNanos() { + testParkAfterUnpark(ParkMethod.parkNanos); + } + public void testParkAfterUnpark_parkUntil() { + testParkAfterUnpark(ParkMethod.parkUntil); + } + public void testParkAfterUnpark_parkBlocker() { + testParkAfterUnpark(ParkMethod.parkBlocker); + } + public void testParkAfterUnpark_parkNanosBlocker() { + testParkAfterUnpark(ParkMethod.parkNanosBlocker); + } + public void testParkAfterUnpark_parkUntilBlocker() { + testParkAfterUnpark(ParkMethod.parkUntilBlocker); + } + public void testParkAfterUnpark(final ParkMethod parkMethod) { + final CountDownLatch pleaseUnpark = new CountDownLatch(1); + final AtomicBoolean pleasePark = new AtomicBoolean(false); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + pleaseUnpark.countDown(); + while (!pleasePark.get()) + Thread.yield(); + parkMethod.park(); + }}); + + await(pleaseUnpark); + LockSupport.unpark(t); + pleasePark.set(true); + awaitTermination(t); + } + + /** + * park is released by subsequent interrupt + */ + public void testParkBeforeInterrupt_park() { + testParkBeforeInterrupt(ParkMethod.park); + } + public void testParkBeforeInterrupt_parkNanos() { + testParkBeforeInterrupt(ParkMethod.parkNanos); + } + public void testParkBeforeInterrupt_parkUntil() { + testParkBeforeInterrupt(ParkMethod.parkUntil); + } + public void testParkBeforeInterrupt_parkBlocker() { + testParkBeforeInterrupt(ParkMethod.parkBlocker); + } + public void testParkBeforeInterrupt_parkNanosBlocker() { + testParkBeforeInterrupt(ParkMethod.parkNanosBlocker); + } + public void testParkBeforeInterrupt_parkUntilBlocker() { + testParkBeforeInterrupt(ParkMethod.parkUntilBlocker); + } + public void testParkBeforeInterrupt(final ParkMethod parkMethod) { + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + pleaseInterrupt.countDown(); + do { + parkMethod.park(); + // park may return spuriously + } while (! Thread.currentThread().isInterrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * park is released by preceding interrupt + */ + public void testParkAfterInterrupt_park() { + testParkAfterInterrupt(ParkMethod.park); + } + public void testParkAfterInterrupt_parkNanos() { + testParkAfterInterrupt(ParkMethod.parkNanos); + } + public void testParkAfterInterrupt_parkUntil() { + testParkAfterInterrupt(ParkMethod.parkUntil); + } + public void testParkAfterInterrupt_parkBlocker() { + testParkAfterInterrupt(ParkMethod.parkBlocker); + } + public void testParkAfterInterrupt_parkNanosBlocker() { + testParkAfterInterrupt(ParkMethod.parkNanosBlocker); + } + public void testParkAfterInterrupt_parkUntilBlocker() { + testParkAfterInterrupt(ParkMethod.parkUntilBlocker); + } + public void testParkAfterInterrupt(final ParkMethod parkMethod) { + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + final AtomicBoolean pleasePark = new AtomicBoolean(false); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + pleaseInterrupt.countDown(); + while (!pleasePark.get()) + Thread.yield(); + assertTrue(Thread.currentThread().isInterrupted()); + parkMethod.park(); + assertTrue(Thread.currentThread().isInterrupted()); + }}); + + await(pleaseInterrupt); + t.interrupt(); + pleasePark.set(true); + awaitTermination(t); + } + + /** + * timed park times out if not unparked + */ + public void testParkTimesOut_parkNanos() { + testParkTimesOut(ParkMethod.parkNanos); + } + public void testParkTimesOut_parkUntil() { + testParkTimesOut(ParkMethod.parkUntil); + } + public void testParkTimesOut_parkNanosBlocker() { + testParkTimesOut(ParkMethod.parkNanosBlocker); + } + public void testParkTimesOut_parkUntilBlocker() { + testParkTimesOut(ParkMethod.parkUntilBlocker); + } + public void testParkTimesOut(final ParkMethod parkMethod) { + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + for (;;) { + long startTime = System.nanoTime(); + parkMethod.park(timeoutMillis()); + // park may return spuriously + if (millisElapsedSince(startTime) >= timeoutMillis()) + return; + } + }}); + + awaitTermination(t); + } + + /** + * getBlocker(null) throws NullPointerException + */ + public void testGetBlockerNull() { + try { + LockSupport.getBlocker(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * getBlocker returns the blocker object passed to park + */ + public void testGetBlocker_parkBlocker() { + testGetBlocker(ParkMethod.parkBlocker); + } + public void testGetBlocker_parkNanosBlocker() { + testGetBlocker(ParkMethod.parkNanosBlocker); + } + public void testGetBlocker_parkUntilBlocker() { + testGetBlocker(ParkMethod.parkUntilBlocker); + } + public void testGetBlocker(final ParkMethod parkMethod) { + final CountDownLatch started = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + Thread t = Thread.currentThread(); + started.countDown(); + do { + assertNull(LockSupport.getBlocker(t)); + parkMethod.park(); + assertNull(LockSupport.getBlocker(t)); + // park may return spuriously + } while (! Thread.currentThread().isInterrupted()); + }}); + + long startTime = System.nanoTime(); + await(started); + for (;;) { + Object x = LockSupport.getBlocker(t); + if (x == theBlocker()) { // success + t.interrupt(); + awaitTermination(t); + assertNull(LockSupport.getBlocker(t)); + return; + } else { + assertNull(x); // ok + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + fail("timed out"); + Thread.yield(); + } + } + } + + /** + * timed park(0) returns immediately. + * + * Requires hotspot fix for: + * 6763959 java.util.concurrent.locks.LockSupport.parkUntil(0) blocks forever + * which is in jdk7-b118 and 6u25. + */ + public void testPark0_parkNanos() { + testPark0(ParkMethod.parkNanos); + } + public void testPark0_parkUntil() { + testPark0(ParkMethod.parkUntil); + } + public void testPark0_parkNanosBlocker() { + testPark0(ParkMethod.parkNanosBlocker); + } + public void testPark0_parkUntilBlocker() { + testPark0(ParkMethod.parkUntilBlocker); + } + public void testPark0(final ParkMethod parkMethod) { + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + parkMethod.park(0L); + }}); + + awaitTermination(t); + } + + /** + * timed park(Long.MIN_VALUE) returns immediately. + */ + public void testParkNeg_parkNanos() { + testParkNeg(ParkMethod.parkNanos); + } + public void testParkNeg_parkUntil() { + testParkNeg(ParkMethod.parkUntil); + } + public void testParkNeg_parkNanosBlocker() { + testParkNeg(ParkMethod.parkNanosBlocker); + } + public void testParkNeg_parkUntilBlocker() { + testParkNeg(ParkMethod.parkUntilBlocker); + } + public void testParkNeg(final ParkMethod parkMethod) { + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + parkMethod.park(Long.MIN_VALUE); + }}); + + awaitTermination(t); + } +} |