ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ThreadLocalRandomTest.java
Revision: 1.23
Committed: Fri Dec 9 06:56:30 2016 UTC (7 years, 5 months ago) by jsr166
Branch: MAIN
Changes since 1.22: +23 -19 lines
Log Message:
testNext: tolerate InaccessibleObjectException

File Contents

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