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 junit.framework.*;
     10 import java.util.*;
     11 import java.util.concurrent.ThreadLocalRandom;
     12 import java.util.concurrent.atomic.AtomicLong;
     13 import java.util.concurrent.atomic.AtomicReference;
     14 
     15 public class ThreadLocalRandomTest extends JSR166TestCase {
     16 
     17     /*
     18      * Testing coverage notes:
     19      *
     20      * We don't test randomness properties, but only that repeated
     21      * calls, up to NCALLS tries, produce at least one different
     22      * result.  For bounded versions, we sample various intervals
     23      * across multiples of primes.
     24      */
     25 
     26     //
     27     static final int NCALLS = 10000;
     28 
     29     // max sampled int bound
     30     static final int MAX_INT_BOUND = (1 << 28);
     31 
     32     // Max sampled long bound
     33     static final long MAX_LONG_BOUND = (1L << 42);
     34 
     35     /**
     36      * setSeed throws UnsupportedOperationException
     37      */
     38     public void testSetSeed() {
     39         try {
     40             ThreadLocalRandom.current().setSeed(17);
     41             shouldThrow();
     42         } catch (UnsupportedOperationException success) {}
     43     }
     44 
     45     /**
     46      * Repeated calls to nextInt produce at least one different result
     47      */
     48     public void testNextInt() {
     49         int f = ThreadLocalRandom.current().nextInt();
     50         int i = 0;
     51         while (i < NCALLS && ThreadLocalRandom.current().nextInt() == f)
     52             ++i;
     53         assertTrue(i < NCALLS);
     54     }
     55 
     56     /**
     57      * Repeated calls to nextLong produce at least one different result
     58      */
     59     public void testNextLong() {
     60         long f = ThreadLocalRandom.current().nextLong();
     61         int i = 0;
     62         while (i < NCALLS && ThreadLocalRandom.current().nextLong() == f)
     63             ++i;
     64         assertTrue(i < NCALLS);
     65     }
     66 
     67     /**
     68      * Repeated calls to nextBoolean produce at least one different result
     69      */
     70     public void testNextBoolean() {
     71         boolean f = ThreadLocalRandom.current().nextBoolean();
     72         int i = 0;
     73         while (i < NCALLS && ThreadLocalRandom.current().nextBoolean() == f)
     74             ++i;
     75         assertTrue(i < NCALLS);
     76     }
     77 
     78     /**
     79      * Repeated calls to nextFloat produce at least one different result
     80      */
     81     public void testNextFloat() {
     82         float f = ThreadLocalRandom.current().nextFloat();
     83         int i = 0;
     84         while (i < NCALLS && ThreadLocalRandom.current().nextFloat() == f)
     85             ++i;
     86         assertTrue(i < NCALLS);
     87     }
     88 
     89     /**
     90      * Repeated calls to nextDouble produce at least one different result
     91      */
     92     public void testNextDouble() {
     93         double f = ThreadLocalRandom.current().nextDouble();
     94         double i = 0;
     95         while (i < NCALLS && ThreadLocalRandom.current().nextDouble() == f)
     96             ++i;
     97         assertTrue(i < NCALLS);
     98     }
     99 
    100     /**
    101      * Repeated calls to nextGaussian produce at least one different result
    102      */
    103     public void testNextGaussian() {
    104         double f = ThreadLocalRandom.current().nextGaussian();
    105         int i = 0;
    106         while (i < NCALLS && ThreadLocalRandom.current().nextGaussian() == f)
    107             ++i;
    108         assertTrue(i < NCALLS);
    109     }
    110 
    111     /**
    112      * nextInt(negative) throws IllegalArgumentException;
    113      */
    114     public void testNextIntBoundedNeg() {
    115         try {
    116             int f = ThreadLocalRandom.current().nextInt(-17);
    117             shouldThrow();
    118         } catch (IllegalArgumentException success) {}
    119     }
    120 
    121     /**
    122      * nextInt(least >= bound) throws IllegalArgumentException;
    123      */
    124     public void testNextIntBadBounds() {
    125         try {
    126             int f = ThreadLocalRandom.current().nextInt(17, 2);
    127             shouldThrow();
    128         } catch (IllegalArgumentException success) {}
    129     }
    130 
    131     /**
    132      * nextInt(bound) returns 0 <= value < bound;
    133      * repeated calls produce at least one different result
    134      */
    135     public void testNextIntBounded() {
    136         // sample bound space across prime number increments
    137         for (int bound = 2; bound < MAX_INT_BOUND; bound += 524959) {
    138             int f = ThreadLocalRandom.current().nextInt(bound);
    139             assertTrue(0 <= f && f < bound);
    140             int i = 0;
    141             int j;
    142             while (i < NCALLS &&
    143                    (j = ThreadLocalRandom.current().nextInt(bound)) == f) {
    144                 assertTrue(0 <= j && j < bound);
    145                 ++i;
    146             }
    147             assertTrue(i < NCALLS);
    148         }
    149     }
    150 
    151     /**
    152      * nextInt(least, bound) returns least <= value < bound;
    153      * repeated calls produce at least one different result
    154      */
    155     public void testNextIntBounded2() {
    156         for (int least = -15485863; least < MAX_INT_BOUND; least += 524959) {
    157             for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 49979687) {
    158                 int f = ThreadLocalRandom.current().nextInt(least, bound);
    159                 assertTrue(least <= f && f < bound);
    160                 int i = 0;
    161                 int j;
    162                 while (i < NCALLS &&
    163                        (j = ThreadLocalRandom.current().nextInt(least, bound)) == f) {
    164                     assertTrue(least <= j && j < bound);
    165                     ++i;
    166                 }
    167                 assertTrue(i < NCALLS);
    168             }
    169         }
    170     }
    171 
    172     /**
    173      * nextLong(negative) throws IllegalArgumentException;
    174      */
    175     public void testNextLongBoundedNeg() {
    176         try {
    177             long f = ThreadLocalRandom.current().nextLong(-17);
    178             shouldThrow();
    179         } catch (IllegalArgumentException success) {}
    180     }
    181 
    182     /**
    183      * nextLong(least >= bound) throws IllegalArgumentException;
    184      */
    185     public void testNextLongBadBounds() {
    186         try {
    187             long f = ThreadLocalRandom.current().nextLong(17, 2);
    188             shouldThrow();
    189         } catch (IllegalArgumentException success) {}
    190     }
    191 
    192     /**
    193      * nextLong(bound) returns 0 <= value < bound;
    194      * repeated calls produce at least one different result
    195      */
    196     public void testNextLongBounded() {
    197         for (long bound = 2; bound < MAX_LONG_BOUND; bound += 15485863) {
    198             long f = ThreadLocalRandom.current().nextLong(bound);
    199             assertTrue(0 <= f && f < bound);
    200             int i = 0;
    201             long j;
    202             while (i < NCALLS &&
    203                    (j = ThreadLocalRandom.current().nextLong(bound)) == f) {
    204                 assertTrue(0 <= j && j < bound);
    205                 ++i;
    206             }
    207             assertTrue(i < NCALLS);
    208         }
    209     }
    210 
    211     /**
    212      * nextLong(least, bound) returns least <= value < bound;
    213      * repeated calls produce at least one different result
    214      */
    215     public void testNextLongBounded2() {
    216         for (long least = -86028121; least < MAX_LONG_BOUND; least += 982451653L) {
    217             for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
    218                 long f = ThreadLocalRandom.current().nextLong(least, bound);
    219                 assertTrue(least <= f && f < bound);
    220                 int i = 0;
    221                 long j;
    222                 while (i < NCALLS &&
    223                        (j = ThreadLocalRandom.current().nextLong(least, bound)) == f) {
    224                     assertTrue(least <= j && j < bound);
    225                     ++i;
    226                 }
    227                 assertTrue(i < NCALLS);
    228             }
    229         }
    230     }
    231 
    232     /**
    233      * nextDouble(least, bound) returns least <= value < bound;
    234      * repeated calls produce at least one different result
    235      */
    236     public void testNextDoubleBounded2() {
    237         for (double least = 0.0001; least < 1.0e20; least *= 8) {
    238             for (double bound = least * 1.001; bound < 1.0e20; bound *= 16) {
    239                 double f = ThreadLocalRandom.current().nextDouble(least, bound);
    240                 assertTrue(least <= f && f < bound);
    241                 int i = 0;
    242                 double j;
    243                 while (i < NCALLS &&
    244                        (j = ThreadLocalRandom.current().nextDouble(least, bound)) == f) {
    245                     assertTrue(least <= j && j < bound);
    246                     ++i;
    247                 }
    248                 assertTrue(i < NCALLS);
    249             }
    250         }
    251     }
    252 
    253     /**
    254      * Different threads produce different pseudo-random sequences
    255      */
    256     public void testDifferentSequences() {
    257         // Don't use main thread's ThreadLocalRandom - it is likely to
    258         // be polluted by previous tests.
    259         final AtomicReference<ThreadLocalRandom> threadLocalRandom =
    260             new AtomicReference<ThreadLocalRandom>();
    261         final AtomicLong rand = new AtomicLong();
    262 
    263         long firstRand = 0;
    264         ThreadLocalRandom firstThreadLocalRandom = null;
    265 
    266         final CheckedRunnable getRandomState = new CheckedRunnable() {
    267             public void realRun() {
    268                 ThreadLocalRandom current = ThreadLocalRandom.current();
    269                 assertSame(current, ThreadLocalRandom.current());
    270                 // test bug: the following is not guaranteed and not true in JDK8
    271                 //                assertNotSame(current, threadLocalRandom.get());
    272                 rand.set(current.nextLong());
    273                 threadLocalRandom.set(current);
    274             }};
    275 
    276         Thread first = newStartedThread(getRandomState);
    277         awaitTermination(first);
    278         firstRand = rand.get();
    279         firstThreadLocalRandom = threadLocalRandom.get();
    280 
    281         for (int i = 0; i < NCALLS; i++) {
    282             Thread t = newStartedThread(getRandomState);
    283             awaitTermination(t);
    284             if (firstRand != rand.get())
    285                 return;
    286         }
    287         fail("all threads generate the same pseudo-random sequence");
    288     }
    289 
    290 }
    291