ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ThreadLocalRandomTest.java
Revision: 1.15
Committed: Wed Aug 14 12:41:18 2013 UTC (10 years, 9 months ago) by dl
Branch: MAIN
Changes since 1.14: +234 -0 lines
Log Message:
Add stream tests

File Contents

# Content
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 import junit.framework.*;
7 import java.util.*;
8 import java.util.concurrent.ThreadLocalRandom;
9 import java.util.concurrent.atomic.AtomicLong;
10 import java.util.concurrent.atomic.AtomicInteger;
11 import java.util.concurrent.atomic.AtomicReference;
12 import java.util.concurrent.atomic.LongAdder;
13
14 public class ThreadLocalRandomTest extends JSR166TestCase {
15
16 public static void main(String[] args) {
17 junit.textui.TestRunner.run(suite());
18 }
19 public static Test suite() {
20 return new TestSuite(ThreadLocalRandomTest.class);
21 }
22
23 /*
24 * Testing coverage notes:
25 *
26 * 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 // max numbers of calls to detect getting stuck on one value
33 static final int NCALLS = 10000;
34
35 // max sampled int bound
36 static final int MAX_INT_BOUND = (1 << 28);
37
38 // max sampled long bound
39 static final long MAX_LONG_BOUND = (1L << 42);
40
41 // Number of replications for other checks
42 static final int REPS = 20;
43
44 /**
45 * setSeed throws UnsupportedOperationException
46 */
47 public void testSetSeed() {
48 try {
49 ThreadLocalRandom.current().setSeed(17);
50 shouldThrow();
51 } catch (UnsupportedOperationException success) {}
52 }
53
54 /**
55 * Repeated calls to nextInt produce at least two distinct results
56 */
57 public void testNextInt() {
58 int f = ThreadLocalRandom.current().nextInt();
59 int i = 0;
60 while (i < NCALLS && ThreadLocalRandom.current().nextInt() == f)
61 ++i;
62 assertTrue(i < NCALLS);
63 }
64
65 /**
66 * Repeated calls to nextLong produce at least two distinct results
67 */
68 public void testNextLong() {
69 long f = ThreadLocalRandom.current().nextLong();
70 int i = 0;
71 while (i < NCALLS && ThreadLocalRandom.current().nextLong() == f)
72 ++i;
73 assertTrue(i < NCALLS);
74 }
75
76 /**
77 * Repeated calls to nextBoolean produce at least two distinct results
78 */
79 public void testNextBoolean() {
80 boolean f = ThreadLocalRandom.current().nextBoolean();
81 int i = 0;
82 while (i < NCALLS && ThreadLocalRandom.current().nextBoolean() == f)
83 ++i;
84 assertTrue(i < NCALLS);
85 }
86
87 /**
88 * Repeated calls to nextFloat produce at least two distinct results
89 */
90 public void testNextFloat() {
91 float f = ThreadLocalRandom.current().nextFloat();
92 int i = 0;
93 while (i < NCALLS && ThreadLocalRandom.current().nextFloat() == f)
94 ++i;
95 assertTrue(i < NCALLS);
96 }
97
98 /**
99 * Repeated calls to nextDouble produce at least two distinct results
100 */
101 public void testNextDouble() {
102 double f = ThreadLocalRandom.current().nextDouble();
103 int i = 0;
104 while (i < NCALLS && ThreadLocalRandom.current().nextDouble() == f)
105 ++i;
106 assertTrue(i < NCALLS);
107 }
108
109 /**
110 * Repeated calls to nextGaussian produce at least two distinct results
111 */
112 public void testNextGaussian() {
113 double f = ThreadLocalRandom.current().nextGaussian();
114 int i = 0;
115 while (i < NCALLS && ThreadLocalRandom.current().nextGaussian() == f)
116 ++i;
117 assertTrue(i < NCALLS);
118 }
119
120 /**
121 * nextInt(negative) throws IllegalArgumentException
122 */
123 public void testNextIntBoundedNeg() {
124 try {
125 int f = ThreadLocalRandom.current().nextInt(-17);
126 shouldThrow();
127 } catch (IllegalArgumentException success) {}
128 }
129
130 /**
131 * nextInt(least >= bound) throws IllegalArgumentException
132 */
133 public void testNextIntBadBounds() {
134 try {
135 int f = ThreadLocalRandom.current().nextInt(17, 2);
136 shouldThrow();
137 } catch (IllegalArgumentException success) {}
138 }
139
140 /**
141 * nextInt(bound) returns 0 <= value < bound;
142 * repeated calls produce at least two distinct results
143 */
144 public void testNextIntBounded() {
145 // sample bound space across prime number increments
146 for (int bound = 2; bound < MAX_INT_BOUND; bound += 524959) {
147 int f = ThreadLocalRandom.current().nextInt(bound);
148 assertTrue(0 <= f && f < bound);
149 int i = 0;
150 int j;
151 while (i < NCALLS &&
152 (j = ThreadLocalRandom.current().nextInt(bound)) == f) {
153 assertTrue(0 <= j && j < bound);
154 ++i;
155 }
156 assertTrue(i < NCALLS);
157 }
158 }
159
160 /**
161 * nextInt(least, bound) returns least <= value < bound;
162 * repeated calls produce at least two distinct results
163 */
164 public void testNextIntBounded2() {
165 for (int least = -15485863; least < MAX_INT_BOUND; least += 524959) {
166 for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 49979687) {
167 int f = ThreadLocalRandom.current().nextInt(least, bound);
168 assertTrue(least <= f && f < bound);
169 int i = 0;
170 int j;
171 while (i < NCALLS &&
172 (j = ThreadLocalRandom.current().nextInt(least, bound)) == f) {
173 assertTrue(least <= j && j < bound);
174 ++i;
175 }
176 assertTrue(i < NCALLS);
177 }
178 }
179 }
180
181 /**
182 * nextLong(negative) throws IllegalArgumentException
183 */
184 public void testNextLongBoundedNeg() {
185 try {
186 long f = ThreadLocalRandom.current().nextLong(-17);
187 shouldThrow();
188 } catch (IllegalArgumentException success) {}
189 }
190
191 /**
192 * nextLong(least >= bound) throws IllegalArgumentException
193 */
194 public void testNextLongBadBounds() {
195 try {
196 long f = ThreadLocalRandom.current().nextLong(17, 2);
197 shouldThrow();
198 } catch (IllegalArgumentException success) {}
199 }
200
201 /**
202 * nextLong(bound) returns 0 <= value < bound;
203 * repeated calls produce at least two distinct results
204 */
205 public void testNextLongBounded() {
206 for (long bound = 2; bound < MAX_LONG_BOUND; bound += 15485863) {
207 long f = ThreadLocalRandom.current().nextLong(bound);
208 assertTrue(0 <= f && f < bound);
209 int i = 0;
210 long j;
211 while (i < NCALLS &&
212 (j = ThreadLocalRandom.current().nextLong(bound)) == f) {
213 assertTrue(0 <= j && j < bound);
214 ++i;
215 }
216 assertTrue(i < NCALLS);
217 }
218 }
219
220 /**
221 * nextLong(least, bound) returns least <= value < bound;
222 * repeated calls produce at least two distinct results
223 */
224 public void testNextLongBounded2() {
225 for (long least = -86028121; least < MAX_LONG_BOUND; least += 982451653L) {
226 for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
227 long f = ThreadLocalRandom.current().nextLong(least, bound);
228 assertTrue(least <= f && f < bound);
229 int i = 0;
230 long j;
231 while (i < NCALLS &&
232 (j = ThreadLocalRandom.current().nextLong(least, bound)) == f) {
233 assertTrue(least <= j && j < bound);
234 ++i;
235 }
236 assertTrue(i < NCALLS);
237 }
238 }
239 }
240
241 /**
242 * nextDouble(least, bound) returns least <= value < bound;
243 * repeated calls produce at least two distinct results
244 */
245 public void testNextDoubleBounded2() {
246 for (double least = 0.0001; least < 1.0e20; least *= 8) {
247 for (double bound = least * 1.001; bound < 1.0e20; bound *= 16) {
248 double f = ThreadLocalRandom.current().nextDouble(least, bound);
249 assertTrue(least <= f && f < bound);
250 int i = 0;
251 double j;
252 while (i < NCALLS &&
253 (j = ThreadLocalRandom.current().nextDouble(least, bound)) == f) {
254 assertTrue(least <= j && j < bound);
255 ++i;
256 }
257 assertTrue(i < NCALLS);
258 }
259 }
260 }
261
262 /**
263 * Different threads produce different pseudo-random sequences
264 */
265 public void testDifferentSequences() {
266 // Don't use main thread's ThreadLocalRandom - it is likely to
267 // be polluted by previous tests.
268 final AtomicReference<ThreadLocalRandom> threadLocalRandom =
269 new AtomicReference<ThreadLocalRandom>();
270 final AtomicLong rand = new AtomicLong();
271
272 long firstRand = 0;
273 ThreadLocalRandom firstThreadLocalRandom = null;
274
275 final CheckedRunnable getRandomState = new CheckedRunnable() {
276 public void realRun() {
277 ThreadLocalRandom current = ThreadLocalRandom.current();
278 assertSame(current, ThreadLocalRandom.current());
279 // test bug: the following is not guaranteed and not true in JDK8
280 // assertNotSame(current, threadLocalRandom.get());
281 rand.set(current.nextLong());
282 threadLocalRandom.set(current);
283 }};
284
285 Thread first = newStartedThread(getRandomState);
286 awaitTermination(first);
287 firstRand = rand.get();
288 firstThreadLocalRandom = threadLocalRandom.get();
289
290 for (int i = 0; i < NCALLS; i++) {
291 Thread t = newStartedThread(getRandomState);
292 awaitTermination(t);
293 if (firstRand != rand.get())
294 return;
295 }
296 fail("all threads generate the same pseudo-random sequence");
297 }
298
299 /**
300 * Invoking sized ints, long, doubles, with negative sizes throws
301 * IllegalArgumentException
302 */
303 public void testBadStreamSize() {
304 ThreadLocalRandom r = ThreadLocalRandom.current();
305 try {
306 java.util.stream.IntStream x = r.ints(-1L);
307 shouldThrow();
308 } catch (IllegalArgumentException success) {}
309 try {
310 java.util.stream.IntStream x = r.ints(-1L, 2, 3);
311 shouldThrow();
312 } catch (IllegalArgumentException success) {}
313 try {
314 java.util.stream.LongStream x = r.longs(-1L);
315 shouldThrow();
316 } catch (IllegalArgumentException success) {}
317 try {
318 java.util.stream.LongStream x = r.longs(-1L, -1L, 1L);
319 shouldThrow();
320 } catch (IllegalArgumentException success) {}
321 try {
322 java.util.stream.DoubleStream x = r.doubles(-1L);
323 shouldThrow();
324 } catch (IllegalArgumentException success) {}
325 try {
326 java.util.stream.DoubleStream x = r.doubles(-1L, .5, .6);
327 shouldThrow();
328 } catch (IllegalArgumentException success) {}
329 }
330
331 /**
332 * Invoking bounded ints, long, doubles, with illegal bounds throws
333 * IllegalArgumentException
334 */
335 public void testBadStreamBounds() {
336 ThreadLocalRandom r = ThreadLocalRandom.current();
337 try {
338 java.util.stream.IntStream x = r.ints(2, 1);
339 shouldThrow();
340 } catch (IllegalArgumentException success) {}
341 try {
342 java.util.stream.IntStream x = r.ints(10, 42, 42);
343 shouldThrow();
344 } catch (IllegalArgumentException success) {}
345 try {
346 java.util.stream.LongStream x = r.longs(-1L, -1L);
347 shouldThrow();
348 } catch (IllegalArgumentException success) {}
349 try {
350 java.util.stream.LongStream x = r.longs(10, 1L, -2L);
351 shouldThrow();
352 } catch (IllegalArgumentException success) {}
353 try {
354 java.util.stream.DoubleStream x = r.doubles(0.0, 0.0);
355 shouldThrow();
356 } catch (IllegalArgumentException success) {}
357 try {
358 java.util.stream.DoubleStream x = r.doubles(10, .5, .4);
359 shouldThrow();
360 } catch (IllegalArgumentException success) {}
361 }
362
363 /**
364 * A parallel sized stream of ints generates the given number of values
365 */
366 public void testIntsCount() {
367 LongAdder counter = new LongAdder();
368 ThreadLocalRandom r = ThreadLocalRandom.current();
369 long size = 0;
370 for (int reps = 0; reps < REPS; ++reps) {
371 counter.reset();
372 r.ints(size).parallel().forEach(x -> {counter.increment();});
373 assertEquals(size, counter.sum());
374 size += 524959;
375 }
376 }
377
378 /**
379 * A parallel sized stream of longs generates the given number of values
380 */
381 public void testLongsCount() {
382 LongAdder counter = new LongAdder();
383 ThreadLocalRandom r = ThreadLocalRandom.current();
384 long size = 0;
385 for (int reps = 0; reps < REPS; ++reps) {
386 counter.reset();
387 r.longs(size).parallel().forEach(x -> {counter.increment();});
388 assertEquals(size, counter.sum());
389 size += 524959;
390 }
391 }
392
393 /**
394 * A parallel sized stream of doubles generates the given number of values
395 */
396 public void testDoublesCount() {
397 LongAdder counter = new LongAdder();
398 ThreadLocalRandom r = ThreadLocalRandom.current();
399 long size = 0;
400 for (int reps = 0; reps < REPS; ++reps) {
401 counter.reset();
402 r.doubles(size).parallel().forEach(x -> {counter.increment();});
403 assertEquals(size, counter.sum());
404 size += 524959;
405 }
406 }
407
408 /**
409 * Each of a parallel sized stream of bounded ints is within bounds
410 */
411 public void testBoundedInts() {
412 AtomicInteger fails = new AtomicInteger(0);
413 ThreadLocalRandom r = ThreadLocalRandom.current();
414 long size = 12345L;
415 for (int least = -15485867; least < MAX_INT_BOUND; least += 524959) {
416 for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 67867967) {
417 final int lo = least, hi = bound;
418 r.ints(size, lo, hi).parallel().
419 forEach(x -> {if (x < lo || x >= hi)
420 fails.getAndIncrement(); });
421 }
422 }
423 assertEquals(0, fails.get());
424 }
425
426 /**
427 * Each of a parallel sized stream of bounded longs is within bounds
428 */
429 public void testBoundedLongs() {
430 AtomicInteger fails = new AtomicInteger(0);
431 ThreadLocalRandom r = ThreadLocalRandom.current();
432 long size = 123L;
433 for (long least = -86028121; least < MAX_LONG_BOUND; least += 1982451653L) {
434 for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
435 final long lo = least, hi = bound;
436 r.longs(size, lo, hi).parallel().
437 forEach(x -> {if (x < lo || x >= hi)
438 fails.getAndIncrement(); });
439 }
440 }
441 assertEquals(0, fails.get());
442 }
443
444 /**
445 * Each of a parallel sized stream of bounded doubles is within bounds
446 */
447 public void testBoundedDoubles() {
448 AtomicInteger fails = new AtomicInteger(0);
449 ThreadLocalRandom r = ThreadLocalRandom.current();
450 long size = 456;
451 for (double least = 0.00011; least < 1.0e20; least *= 9) {
452 for (double bound = least * 1.0011; bound < 1.0e20; bound *= 17) {
453 final double lo = least, hi = bound;
454 r.doubles(size, lo, hi).parallel().
455 forEach(x -> {if (x < lo || x >= hi)
456 fails.getAndIncrement(); });
457 }
458 }
459 assertEquals(0, fails.get());
460 }
461
462 /**
463 * A parallel unsized stream of ints generates at least 100 values
464 */
465 public void testUnsizedIntsCount() {
466 LongAdder counter = new LongAdder();
467 ThreadLocalRandom r = ThreadLocalRandom.current();
468 long size = 100;
469 r.ints().limit(size).parallel().forEach(x -> {counter.increment();});
470 assertEquals(size, counter.sum());
471 }
472
473 /**
474 * A parallel unsized stream of longs generates at least 100 values
475 */
476 public void testUnsizedLongsCount() {
477 LongAdder counter = new LongAdder();
478 ThreadLocalRandom r = ThreadLocalRandom.current();
479 long size = 100;
480 r.longs().limit(size).parallel().forEach(x -> {counter.increment();});
481 assertEquals(size, counter.sum());
482 }
483
484 /**
485 * A parallel unsized stream of doubles generates at least 100 values
486 */
487 public void testUnsizedDoublesCount() {
488 LongAdder counter = new LongAdder();
489 ThreadLocalRandom r = ThreadLocalRandom.current();
490 long size = 100;
491 r.doubles().limit(size).parallel().forEach(x -> {counter.increment();});
492 assertEquals(size, counter.sum());
493 }
494
495 /**
496 * A sequential unsized stream of ints generates at least 100 values
497 */
498 public void testUnsizedIntsCountSeq() {
499 LongAdder counter = new LongAdder();
500 ThreadLocalRandom r = ThreadLocalRandom.current();
501 long size = 100;
502 r.ints().limit(size).forEach(x -> {counter.increment();});
503 assertEquals(size, counter.sum());
504 }
505
506 /**
507 * A sequential unsized stream of longs generates at least 100 values
508 */
509 public void testUnsizedLongsCountSeq() {
510 LongAdder counter = new LongAdder();
511 ThreadLocalRandom r = ThreadLocalRandom.current();
512 long size = 100;
513 r.longs().limit(size).forEach(x -> {counter.increment();});
514 assertEquals(size, counter.sum());
515 }
516
517 /**
518 * A sequential unsized stream of doubles generates at least 100 values
519 */
520 public void testUnsizedDoublesCountSeq() {
521 LongAdder counter = new LongAdder();
522 ThreadLocalRandom r = ThreadLocalRandom.current();
523 long size = 100;
524 r.doubles().limit(size).forEach(x -> {counter.increment();});
525 assertEquals(size, counter.sum());
526 }
527
528 }