Home | History | Annotate | Download | only in jsr166
      1 /*
      2  * Written by Doug Lea with assistance from members of JCP JSR-166
      3  * Expert Group and released to the public domain, as explained at
      4  * http://creativecommons.org/publicdomain/zero/1.0/
      5  */
      6 
      7 package jsr166;
      8 
      9 import java.util.concurrent.ThreadLocalRandom;
     10 import java.util.concurrent.atomic.AtomicLong;
     11 import java.util.concurrent.atomic.AtomicReference;
     12 
     13 import junit.framework.Test;
     14 import junit.framework.TestSuite;
     15 
     16 public class ThreadLocalRandomTest extends JSR166TestCase {
     17 
     18     // android-note: Removed because the CTS runner does a bad job of
     19     // retrying tests that have suite() declarations.
     20     //
     21     // public static void main(String[] args) {
     22     //     main(suite(), args);
     23     // }
     24     // public static Test suite() {
     25     //     return new TestSuite(ThreadLocalRandomTest.class);
     26     // }
     27 
     28     /*
     29      * Testing coverage notes:
     30      *
     31      * We don't test randomness properties, but only that repeated
     32      * calls, up to NCALLS tries, produce at least one different
     33      * result.  For bounded versions, we sample various intervals
     34      * across multiples of primes.
     35      */
     36 
     37     // max numbers of calls to detect getting stuck on one value
     38     static final int NCALLS = 10000;
     39 
     40     // max sampled int bound
     41     static final int MAX_INT_BOUND = (1 << 28);
     42 
     43     // max sampled long bound
     44     static final long MAX_LONG_BOUND = (1L << 42);
     45 
     46     // Number of replications for other checks
     47     static final int REPS = 20;
     48 
     49     /**
     50      * setSeed throws UnsupportedOperationException
     51      */
     52     public void testSetSeed() {
     53         try {
     54             ThreadLocalRandom.current().setSeed(17);
     55             shouldThrow();
     56         } catch (UnsupportedOperationException success) {}
     57     }
     58 
     59     /**
     60      * Repeated calls to nextInt produce at least two distinct results
     61      */
     62     public void testNextInt() {
     63         int f = ThreadLocalRandom.current().nextInt();
     64         int i = 0;
     65         while (i < NCALLS && ThreadLocalRandom.current().nextInt() == f)
     66             ++i;
     67         assertTrue(i < NCALLS);
     68     }
     69 
     70     /**
     71      * Repeated calls to nextLong produce at least two distinct results
     72      */
     73     public void testNextLong() {
     74         long f = ThreadLocalRandom.current().nextLong();
     75         int i = 0;
     76         while (i < NCALLS && ThreadLocalRandom.current().nextLong() == f)
     77             ++i;
     78         assertTrue(i < NCALLS);
     79     }
     80 
     81     /**
     82      * Repeated calls to nextBoolean produce at least two distinct results
     83      */
     84     public void testNextBoolean() {
     85         boolean f = ThreadLocalRandom.current().nextBoolean();
     86         int i = 0;
     87         while (i < NCALLS && ThreadLocalRandom.current().nextBoolean() == f)
     88             ++i;
     89         assertTrue(i < NCALLS);
     90     }
     91 
     92     /**
     93      * Repeated calls to nextFloat produce at least two distinct results
     94      */
     95     public void testNextFloat() {
     96         float f = ThreadLocalRandom.current().nextFloat();
     97         int i = 0;
     98         while (i < NCALLS && ThreadLocalRandom.current().nextFloat() == f)
     99             ++i;
    100         assertTrue(i < NCALLS);
    101     }
    102 
    103     /**
    104      * Repeated calls to nextDouble produce at least two distinct results
    105      */
    106     public void testNextDouble() {
    107         double f = ThreadLocalRandom.current().nextDouble();
    108         int i = 0;
    109         while (i < NCALLS && ThreadLocalRandom.current().nextDouble() == f)
    110             ++i;
    111         assertTrue(i < NCALLS);
    112     }
    113 
    114     /**
    115      * Repeated calls to nextGaussian produce at least two distinct results
    116      */
    117     public void testNextGaussian() {
    118         double f = ThreadLocalRandom.current().nextGaussian();
    119         int i = 0;
    120         while (i < NCALLS && ThreadLocalRandom.current().nextGaussian() == f)
    121             ++i;
    122         assertTrue(i < NCALLS);
    123     }
    124 
    125     /**
    126      * nextInt(non-positive) throws IllegalArgumentException
    127      */
    128     public void testNextIntBoundNonPositive() {
    129         ThreadLocalRandom rnd = ThreadLocalRandom.current();
    130         for (int bound : new int[] { 0, -17, Integer.MIN_VALUE }) {
    131             try {
    132                 rnd.nextInt(bound);
    133                 shouldThrow();
    134             } catch (IllegalArgumentException success) {}
    135         }
    136     }
    137 
    138     /**
    139      * nextInt(least >= bound) throws IllegalArgumentException
    140      */
    141     public void testNextIntBadBounds() {
    142         int[][] badBoundss = {
    143             { 17, 2 },
    144             { -42, -42 },
    145             { Integer.MAX_VALUE, Integer.MIN_VALUE },
    146         };
    147         ThreadLocalRandom rnd = ThreadLocalRandom.current();
    148         for (int[] badBounds : badBoundss) {
    149             try {
    150                 rnd.nextInt(badBounds[0], badBounds[1]);
    151                 shouldThrow();
    152             } catch (IllegalArgumentException success) {}
    153         }
    154     }
    155 
    156     /**
    157      * nextInt(bound) returns 0 <= value < bound;
    158      * repeated calls produce at least two distinct results
    159      */
    160     public void testNextIntBounded() {
    161         // sample bound space across prime number increments
    162         for (int bound = 2; bound < MAX_INT_BOUND; bound += 524959) {
    163             int f = ThreadLocalRandom.current().nextInt(bound);
    164             assertTrue(0 <= f && f < bound);
    165             int i = 0;
    166             int j;
    167             while (i < NCALLS &&
    168                    (j = ThreadLocalRandom.current().nextInt(bound)) == f) {
    169                 assertTrue(0 <= j && j < bound);
    170                 ++i;
    171             }
    172             assertTrue(i < NCALLS);
    173         }
    174     }
    175 
    176     /**
    177      * nextInt(least, bound) returns least <= value < bound;
    178      * repeated calls produce at least two distinct results
    179      */
    180     public void testNextIntBounded2() {
    181         for (int least = -15485863; least < MAX_INT_BOUND; least += 524959) {
    182             for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 49979687) {
    183                 int f = ThreadLocalRandom.current().nextInt(least, bound);
    184                 assertTrue(least <= f && f < bound);
    185                 int i = 0;
    186                 int j;
    187                 while (i < NCALLS &&
    188                        (j = ThreadLocalRandom.current().nextInt(least, bound)) == f) {
    189                     assertTrue(least <= j && j < bound);
    190                     ++i;
    191                 }
    192                 assertTrue(i < NCALLS);
    193             }
    194         }
    195     }
    196 
    197     /**
    198      * nextLong(non-positive) throws IllegalArgumentException
    199      */
    200     public void testNextLongBoundNonPositive() {
    201         ThreadLocalRandom rnd = ThreadLocalRandom.current();
    202         for (long bound : new long[] { 0L, -17L, Long.MIN_VALUE }) {
    203             try {
    204                 rnd.nextLong(bound);
    205                 shouldThrow();
    206             } catch (IllegalArgumentException success) {}
    207         }
    208     }
    209 
    210     /**
    211      * nextLong(least >= bound) throws IllegalArgumentException
    212      */
    213     public void testNextLongBadBounds() {
    214         long[][] badBoundss = {
    215             { 17L, 2L },
    216             { -42L, -42L },
    217             { Long.MAX_VALUE, Long.MIN_VALUE },
    218         };
    219         ThreadLocalRandom rnd = ThreadLocalRandom.current();
    220         for (long[] badBounds : badBoundss) {
    221             try {
    222                 rnd.nextLong(badBounds[0], badBounds[1]);
    223                 shouldThrow();
    224             } catch (IllegalArgumentException success) {}
    225         }
    226     }
    227 
    228     /**
    229      * nextLong(bound) returns 0 <= value < bound;
    230      * repeated calls produce at least two distinct results
    231      */
    232     public void testNextLongBounded() {
    233         for (long bound = 2; bound < MAX_LONG_BOUND; bound += 15485863) {
    234             long f = ThreadLocalRandom.current().nextLong(bound);
    235             assertTrue(0 <= f && f < bound);
    236             int i = 0;
    237             long j;
    238             while (i < NCALLS &&
    239                    (j = ThreadLocalRandom.current().nextLong(bound)) == f) {
    240                 assertTrue(0 <= j && j < bound);
    241                 ++i;
    242             }
    243             assertTrue(i < NCALLS);
    244         }
    245     }
    246 
    247     /**
    248      * nextLong(least, bound) returns least <= value < bound;
    249      * repeated calls produce at least two distinct results
    250      */
    251     public void testNextLongBounded2() {
    252         for (long least = -86028121; least < MAX_LONG_BOUND; least += 982451653L) {
    253             for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
    254                 long f = ThreadLocalRandom.current().nextLong(least, bound);
    255                 assertTrue(least <= f && f < bound);
    256                 int i = 0;
    257                 long j;
    258                 while (i < NCALLS &&
    259                        (j = ThreadLocalRandom.current().nextLong(least, bound)) == f) {
    260                     assertTrue(least <= j && j < bound);
    261                     ++i;
    262                 }
    263                 assertTrue(i < NCALLS);
    264             }
    265         }
    266     }
    267 
    268     /**
    269      * nextDouble(non-positive) throws IllegalArgumentException
    270      */
    271     public void testNextDoubleBoundNonPositive() {
    272         ThreadLocalRandom rnd = ThreadLocalRandom.current();
    273         double[] badBounds = {
    274             0.0d,
    275             -17.0d,
    276             -Double.MIN_VALUE,
    277             Double.NEGATIVE_INFINITY,
    278             Double.NaN,
    279         };
    280         for (double bound : badBounds) {
    281             try {
    282                 rnd.nextDouble(bound);
    283                 shouldThrow();
    284             } catch (IllegalArgumentException success) {}
    285         }
    286     }
    287 
    288     /**
    289      * nextDouble(least, bound) returns least <= value < bound;
    290      * repeated calls produce at least two distinct results
    291      */
    292     public void testNextDoubleBounded2() {
    293         for (double least = 0.0001; least < 1.0e20; least *= 8) {
    294             for (double bound = least * 1.001; bound < 1.0e20; bound *= 16) {
    295                 double f = ThreadLocalRandom.current().nextDouble(least, bound);
    296                 assertTrue(least <= f && f < bound);
    297                 int i = 0;
    298                 double j;
    299                 while (i < NCALLS &&
    300                        (j = ThreadLocalRandom.current().nextDouble(least, bound)) == f) {
    301                     assertTrue(least <= j && j < bound);
    302                     ++i;
    303                 }
    304                 assertTrue(i < NCALLS);
    305             }
    306         }
    307     }
    308 
    309     /**
    310      * Different threads produce different pseudo-random sequences
    311      */
    312     public void testDifferentSequences() {
    313         // Don't use main thread's ThreadLocalRandom - it is likely to
    314         // be polluted by previous tests.
    315         final AtomicReference<ThreadLocalRandom> threadLocalRandom =
    316             new AtomicReference<ThreadLocalRandom>();
    317         final AtomicLong rand = new AtomicLong();
    318 
    319         long firstRand = 0;
    320         ThreadLocalRandom firstThreadLocalRandom = null;
    321 
    322         Runnable getRandomState = new CheckedRunnable() {
    323             public void realRun() {
    324                 ThreadLocalRandom current = ThreadLocalRandom.current();
    325                 assertSame(current, ThreadLocalRandom.current());
    326                 // test bug: the following is not guaranteed and not true in JDK8
    327                 //                assertNotSame(current, threadLocalRandom.get());
    328                 rand.set(current.nextLong());
    329                 threadLocalRandom.set(current);
    330             }};
    331 
    332         Thread first = newStartedThread(getRandomState);
    333         awaitTermination(first);
    334         firstRand = rand.get();
    335         firstThreadLocalRandom = threadLocalRandom.get();
    336 
    337         for (int i = 0; i < NCALLS; i++) {
    338             Thread t = newStartedThread(getRandomState);
    339             awaitTermination(t);
    340             if (firstRand != rand.get())
    341                 return;
    342         }
    343         fail("all threads generate the same pseudo-random sequence");
    344     }
    345 
    346 }
    347