ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/SplittableRandomTest.java
Revision: 1.20
Committed: Sun Nov 13 03:36:50 2016 UTC (7 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.19: +35 -0 lines
Log Message:
revise (uselessly inaccessible) next(int) method javadoc, implementation and 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
7 import java.util.SplittableRandom;
8 import java.util.concurrent.atomic.AtomicInteger;
9 import java.util.concurrent.atomic.LongAdder;
10
11 import junit.framework.Test;
12 import junit.framework.TestSuite;
13
14 public class SplittableRandomTest extends JSR166TestCase {
15
16 public static void main(String[] args) {
17 main(suite(), args);
18 }
19 public static Test suite() {
20 return new TestSuite(SplittableRandomTest.class);
21 }
22
23 /*
24 * Testing coverage notes:
25 *
26 * 1. Many of the test methods are adapted from ThreadLocalRandomTest.
27 *
28 * 2. These tests do not check for random number generator quality.
29 * But we check for minimal API compliance by requiring that
30 * repeated calls to nextX methods, up to NCALLS tries, produce at
31 * least two distinct results. (In some possible universe, a
32 * "correct" implementation might fail, but the odds are vastly
33 * less than that of encountering a hardware failure while running
34 * the test.) For bounded nextX methods, we sample various
35 * intervals across multiples of primes. In other tests, we repeat
36 * under REPS different values.
37 */
38
39 // max numbers of calls to detect getting stuck on one value
40 static final int NCALLS = 10000;
41
42 // max sampled int bound
43 static final int MAX_INT_BOUND = (1 << 26);
44
45 // max sampled long bound
46 static final long MAX_LONG_BOUND = (1L << 40);
47
48 // Number of replications for other checks
49 static final int REPS =
50 Integer.getInteger("SplittableRandomTest.reps", 4);
51
52 /**
53 * Repeated calls to next (only accessible via reflection) produce
54 * at least two distinct results, and repeated calls produce all
55 * possible values.
56 */
57 public void testNext() throws ReflectiveOperationException {
58 SplittableRandom rnd = new SplittableRandom();
59 try {
60 java.lang.reflect.Method m
61 = SplittableRandom.class.getDeclaredMethod(
62 "next", new Class[] { int.class });
63 m.setAccessible(true);
64
65 int i;
66 {
67 int val = new java.util.Random().nextInt(4);
68 for (i = 0; i < NCALLS; i++) {
69 int q = (int) m.invoke(rnd, new Object[] { 2 });
70 if (val == q) break;
71 }
72 assertTrue(i < NCALLS);
73 }
74
75 {
76 int r = (int) m.invoke(rnd, new Object[] { 3 });
77 for (i = 0; i < NCALLS; i++) {
78 int q = (int) m.invoke(rnd, new Object[] { 3 });
79 assertTrue(q < (1<<3));
80 if (r != q) break;
81 }
82 assertTrue(i < NCALLS);
83 }
84 } catch (SecurityException acceptable) {}
85 }
86
87 /**
88 * Repeated calls to nextInt produce at least two distinct results
89 */
90 public void testNextInt() {
91 SplittableRandom sr = new SplittableRandom();
92 int f = sr.nextInt();
93 int i = 0;
94 while (i < NCALLS && sr.nextInt() == f)
95 ++i;
96 assertTrue(i < NCALLS);
97 }
98
99 /**
100 * Repeated calls to nextLong produce at least two distinct results
101 */
102 public void testNextLong() {
103 SplittableRandom sr = new SplittableRandom();
104 long f = sr.nextLong();
105 int i = 0;
106 while (i < NCALLS && sr.nextLong() == f)
107 ++i;
108 assertTrue(i < NCALLS);
109 }
110
111 /**
112 * Repeated calls to nextDouble produce at least two distinct results
113 */
114 public void testNextDouble() {
115 SplittableRandom sr = new SplittableRandom();
116 double f = sr.nextDouble();
117 int i = 0;
118 while (i < NCALLS && sr.nextDouble() == f)
119 ++i;
120 assertTrue(i < NCALLS);
121 }
122
123 /**
124 * Two SplittableRandoms created with the same seed produce the
125 * same values for nextLong.
126 */
127 public void testSeedConstructor() {
128 for (long seed = 2; seed < MAX_LONG_BOUND; seed += 15485863) {
129 SplittableRandom sr1 = new SplittableRandom(seed);
130 SplittableRandom sr2 = new SplittableRandom(seed);
131 for (int i = 0; i < REPS; ++i)
132 assertEquals(sr1.nextLong(), sr2.nextLong());
133 }
134 }
135
136 /**
137 * A SplittableRandom produced by split() of a default-constructed
138 * SplittableRandom generates a different sequence
139 */
140 public void testSplit1() {
141 SplittableRandom sr = new SplittableRandom();
142 for (int reps = 0; reps < REPS; ++reps) {
143 SplittableRandom sc = sr.split();
144 int i = 0;
145 while (i < NCALLS && sr.nextLong() == sc.nextLong())
146 ++i;
147 assertTrue(i < NCALLS);
148 }
149 }
150
151 /**
152 * A SplittableRandom produced by split() of a seeded-constructed
153 * SplittableRandom generates a different sequence
154 */
155 public void testSplit2() {
156 SplittableRandom sr = new SplittableRandom(12345);
157 for (int reps = 0; reps < REPS; ++reps) {
158 SplittableRandom sc = sr.split();
159 int i = 0;
160 while (i < NCALLS && sr.nextLong() == sc.nextLong())
161 ++i;
162 assertTrue(i < NCALLS);
163 }
164 }
165
166 /**
167 * nextInt(non-positive) throws IllegalArgumentException
168 */
169 public void testNextIntBoundNonPositive() {
170 SplittableRandom sr = new SplittableRandom();
171 Runnable[] throwingActions = {
172 () -> sr.nextInt(-17),
173 () -> sr.nextInt(0),
174 () -> sr.nextInt(Integer.MIN_VALUE),
175 };
176 assertThrows(IllegalArgumentException.class, throwingActions);
177 }
178
179 /**
180 * nextInt(least >= bound) throws IllegalArgumentException
181 */
182 public void testNextIntBadBounds() {
183 SplittableRandom sr = new SplittableRandom();
184 Runnable[] throwingActions = {
185 () -> sr.nextInt(17, 2),
186 () -> sr.nextInt(-42, -42),
187 () -> sr.nextInt(Integer.MAX_VALUE, Integer.MIN_VALUE),
188 };
189 assertThrows(IllegalArgumentException.class, throwingActions);
190 }
191
192 /**
193 * nextInt(bound) returns 0 <= value < bound;
194 * repeated calls produce at least two distinct results
195 */
196 public void testNextIntBounded() {
197 SplittableRandom sr = new SplittableRandom();
198 for (int i = 0; i < 2; i++) assertEquals(0, sr.nextInt(1));
199 // sample bound space across prime number increments
200 for (int bound = 2; bound < MAX_INT_BOUND; bound += 524959) {
201 int f = sr.nextInt(bound);
202 assertTrue(0 <= f && f < bound);
203 int i = 0;
204 int j;
205 while (i < NCALLS &&
206 (j = sr.nextInt(bound)) == f) {
207 assertTrue(0 <= j && j < bound);
208 ++i;
209 }
210 assertTrue(i < NCALLS);
211 }
212 }
213
214 /**
215 * nextInt(least, bound) returns least <= value < bound;
216 * repeated calls produce at least two distinct results
217 */
218 public void testNextIntBounded2() {
219 SplittableRandom sr = new SplittableRandom();
220 for (int least = -15485863; least < MAX_INT_BOUND; least += 524959) {
221 for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 49979687) {
222 int f = sr.nextInt(least, bound);
223 assertTrue(least <= f && f < bound);
224 int i = 0;
225 int j;
226 while (i < NCALLS &&
227 (j = sr.nextInt(least, bound)) == f) {
228 assertTrue(least <= j && j < bound);
229 ++i;
230 }
231 assertTrue(i < NCALLS);
232 }
233 }
234 }
235
236 /**
237 * nextLong(non-positive) throws IllegalArgumentException
238 */
239 public void testNextLongBoundNonPositive() {
240 SplittableRandom sr = new SplittableRandom();
241 Runnable[] throwingActions = {
242 () -> sr.nextLong(-17L),
243 () -> sr.nextLong(0L),
244 () -> sr.nextLong(Long.MIN_VALUE),
245 };
246 assertThrows(IllegalArgumentException.class, throwingActions);
247 }
248
249 /**
250 * nextLong(least >= bound) throws IllegalArgumentException
251 */
252 public void testNextLongBadBounds() {
253 SplittableRandom sr = new SplittableRandom();
254 Runnable[] throwingActions = {
255 () -> sr.nextLong(17L, 2L),
256 () -> sr.nextLong(-42L, -42L),
257 () -> sr.nextLong(Long.MAX_VALUE, Long.MIN_VALUE),
258 };
259 assertThrows(IllegalArgumentException.class, throwingActions);
260 }
261
262 /**
263 * nextLong(bound) returns 0 <= value < bound;
264 * repeated calls produce at least two distinct results
265 */
266 public void testNextLongBounded() {
267 SplittableRandom sr = new SplittableRandom();
268 for (int i = 0; i < 2; i++) assertEquals(0L, sr.nextLong(1L));
269 for (long bound = 2; bound < MAX_LONG_BOUND; bound += 15485863) {
270 long f = sr.nextLong(bound);
271 assertTrue(0 <= f && f < bound);
272 int i = 0;
273 long j;
274 while (i < NCALLS &&
275 (j = sr.nextLong(bound)) == f) {
276 assertTrue(0 <= j && j < bound);
277 ++i;
278 }
279 assertTrue(i < NCALLS);
280 }
281 }
282
283 /**
284 * nextLong(least, bound) returns least <= value < bound;
285 * repeated calls produce at least two distinct results
286 */
287 public void testNextLongBounded2() {
288 SplittableRandom sr = new SplittableRandom();
289 for (long least = -86028121; least < MAX_LONG_BOUND; least += 982451653L) {
290 for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
291 long f = sr.nextLong(least, bound);
292 assertTrue(least <= f && f < bound);
293 int i = 0;
294 long j;
295 while (i < NCALLS &&
296 (j = sr.nextLong(least, bound)) == f) {
297 assertTrue(least <= j && j < bound);
298 ++i;
299 }
300 assertTrue(i < NCALLS);
301 }
302 }
303 }
304
305 /**
306 * nextDouble(non-positive) throws IllegalArgumentException
307 */
308 public void testNextDoubleBoundNonPositive() {
309 SplittableRandom sr = new SplittableRandom();
310 Runnable[] throwingActions = {
311 () -> sr.nextDouble(-17.0d),
312 () -> sr.nextDouble(0.0d),
313 () -> sr.nextDouble(-Double.MIN_VALUE),
314 () -> sr.nextDouble(Double.NEGATIVE_INFINITY),
315 () -> sr.nextDouble(Double.NaN),
316 };
317 assertThrows(IllegalArgumentException.class, throwingActions);
318 }
319
320 /**
321 * nextDouble(! (least < bound)) throws IllegalArgumentException
322 */
323 public void testNextDoubleBadBounds() {
324 SplittableRandom sr = new SplittableRandom();
325 Runnable[] throwingActions = {
326 () -> sr.nextDouble(17.0d, 2.0d),
327 () -> sr.nextDouble(-42.0d, -42.0d),
328 () -> sr.nextDouble(Double.MAX_VALUE, Double.MIN_VALUE),
329 () -> sr.nextDouble(Double.NaN, 0.0d),
330 () -> sr.nextDouble(0.0d, Double.NaN),
331 };
332 assertThrows(IllegalArgumentException.class, throwingActions);
333 }
334
335 // TODO: Test infinite bounds!
336 //() -> sr.nextDouble(Double.NEGATIVE_INFINITY, 0.0d),
337 //() -> sr.nextDouble(0.0d, Double.POSITIVE_INFINITY),
338
339 /**
340 * nextDouble(least, bound) returns least <= value < bound;
341 * repeated calls produce at least two distinct results
342 */
343 public void testNextDoubleBounded2() {
344 SplittableRandom sr = new SplittableRandom();
345 for (double least = 0.0001; least < 1.0e20; least *= 8) {
346 for (double bound = least * 1.001; bound < 1.0e20; bound *= 16) {
347 double f = sr.nextDouble(least, bound);
348 assertTrue(least <= f && f < bound);
349 int i = 0;
350 double j;
351 while (i < NCALLS &&
352 (j = sr.nextDouble(least, bound)) == f) {
353 assertTrue(least <= j && j < bound);
354 ++i;
355 }
356 assertTrue(i < NCALLS);
357 }
358 }
359 }
360
361 /**
362 * Invoking sized ints, long, doubles, with negative sizes throws
363 * IllegalArgumentException
364 */
365 public void testBadStreamSize() {
366 SplittableRandom r = new SplittableRandom();
367 Runnable[] throwingActions = {
368 () -> { java.util.stream.IntStream x = r.ints(-1L); },
369 () -> { java.util.stream.IntStream x = r.ints(-1L, 2, 3); },
370 () -> { java.util.stream.LongStream x = r.longs(-1L); },
371 () -> { java.util.stream.LongStream x = r.longs(-1L, -1L, 1L); },
372 () -> { java.util.stream.DoubleStream x = r.doubles(-1L); },
373 () -> { java.util.stream.DoubleStream x = r.doubles(-1L, .5, .6); },
374 };
375 assertThrows(IllegalArgumentException.class, throwingActions);
376 }
377
378 /**
379 * Invoking bounded ints, long, doubles, with illegal bounds throws
380 * IllegalArgumentException
381 */
382 public void testBadStreamBounds() {
383 SplittableRandom r = new SplittableRandom();
384 Runnable[] throwingActions = {
385 () -> { java.util.stream.IntStream x = r.ints(2, 1); },
386 () -> { java.util.stream.IntStream x = r.ints(10, 42, 42); },
387 () -> { java.util.stream.LongStream x = r.longs(-1L, -1L); },
388 () -> { java.util.stream.LongStream x = r.longs(10, 1L, -2L); },
389 () -> { java.util.stream.DoubleStream x = r.doubles(0.0, 0.0); },
390 () -> { java.util.stream.DoubleStream x = r.doubles(10, .5, .4); },
391 };
392 assertThrows(IllegalArgumentException.class, throwingActions);
393 }
394
395 /**
396 * A parallel sized stream of ints generates the given number of values
397 */
398 public void testIntsCount() {
399 LongAdder counter = new LongAdder();
400 SplittableRandom r = new SplittableRandom();
401 long size = 0;
402 for (int reps = 0; reps < REPS; ++reps) {
403 counter.reset();
404 r.ints(size).parallel().forEach(x -> counter.increment());
405 assertEquals(size, counter.sum());
406 size += 524959;
407 }
408 }
409
410 /**
411 * A parallel sized stream of longs generates the given number of values
412 */
413 public void testLongsCount() {
414 LongAdder counter = new LongAdder();
415 SplittableRandom r = new SplittableRandom();
416 long size = 0;
417 for (int reps = 0; reps < REPS; ++reps) {
418 counter.reset();
419 r.longs(size).parallel().forEach(x -> counter.increment());
420 assertEquals(size, counter.sum());
421 size += 524959;
422 }
423 }
424
425 /**
426 * A parallel sized stream of doubles generates the given number of values
427 */
428 public void testDoublesCount() {
429 LongAdder counter = new LongAdder();
430 SplittableRandom r = new SplittableRandom();
431 long size = 0;
432 for (int reps = 0; reps < REPS; ++reps) {
433 counter.reset();
434 r.doubles(size).parallel().forEach(x -> counter.increment());
435 assertEquals(size, counter.sum());
436 size += 524959;
437 }
438 }
439
440 /**
441 * Each of a parallel sized stream of bounded ints is within bounds
442 */
443 public void testBoundedInts() {
444 AtomicInteger fails = new AtomicInteger(0);
445 SplittableRandom r = new SplittableRandom();
446 long size = 12345L;
447 for (int least = -15485867; least < MAX_INT_BOUND; least += 524959) {
448 for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 67867967) {
449 final int lo = least, hi = bound;
450 r.ints(size, lo, hi).parallel().forEach(
451 x -> {
452 if (x < lo || x >= hi)
453 fails.getAndIncrement(); });
454 }
455 }
456 assertEquals(0, fails.get());
457 }
458
459 /**
460 * Each of a parallel sized stream of bounded longs is within bounds
461 */
462 public void testBoundedLongs() {
463 AtomicInteger fails = new AtomicInteger(0);
464 SplittableRandom r = new SplittableRandom();
465 long size = 123L;
466 for (long least = -86028121; least < MAX_LONG_BOUND; least += 1982451653L) {
467 for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
468 final long lo = least, hi = bound;
469 r.longs(size, lo, hi).parallel().forEach(
470 x -> {
471 if (x < lo || x >= hi)
472 fails.getAndIncrement(); });
473 }
474 }
475 assertEquals(0, fails.get());
476 }
477
478 /**
479 * Each of a parallel sized stream of bounded doubles is within bounds
480 */
481 public void testBoundedDoubles() {
482 AtomicInteger fails = new AtomicInteger(0);
483 SplittableRandom r = new SplittableRandom();
484 long size = 456;
485 for (double least = 0.00011; least < 1.0e20; least *= 9) {
486 for (double bound = least * 1.0011; bound < 1.0e20; bound *= 17) {
487 final double lo = least, hi = bound;
488 r.doubles(size, lo, hi).parallel().forEach(
489 x -> {
490 if (x < lo || x >= hi)
491 fails.getAndIncrement(); });
492 }
493 }
494 assertEquals(0, fails.get());
495 }
496
497 /**
498 * A parallel unsized stream of ints generates at least 100 values
499 */
500 public void testUnsizedIntsCount() {
501 LongAdder counter = new LongAdder();
502 SplittableRandom r = new SplittableRandom();
503 long size = 100;
504 r.ints().limit(size).parallel().forEach(x -> counter.increment());
505 assertEquals(size, counter.sum());
506 }
507
508 /**
509 * A parallel unsized stream of longs generates at least 100 values
510 */
511 public void testUnsizedLongsCount() {
512 LongAdder counter = new LongAdder();
513 SplittableRandom r = new SplittableRandom();
514 long size = 100;
515 r.longs().limit(size).parallel().forEach(x -> counter.increment());
516 assertEquals(size, counter.sum());
517 }
518
519 /**
520 * A parallel unsized stream of doubles generates at least 100 values
521 */
522 public void testUnsizedDoublesCount() {
523 LongAdder counter = new LongAdder();
524 SplittableRandom r = new SplittableRandom();
525 long size = 100;
526 r.doubles().limit(size).parallel().forEach(x -> counter.increment());
527 assertEquals(size, counter.sum());
528 }
529
530 /**
531 * A sequential unsized stream of ints generates at least 100 values
532 */
533 public void testUnsizedIntsCountSeq() {
534 LongAdder counter = new LongAdder();
535 SplittableRandom r = new SplittableRandom();
536 long size = 100;
537 r.ints().limit(size).forEach(x -> counter.increment());
538 assertEquals(size, counter.sum());
539 }
540
541 /**
542 * A sequential unsized stream of longs generates at least 100 values
543 */
544 public void testUnsizedLongsCountSeq() {
545 LongAdder counter = new LongAdder();
546 SplittableRandom r = new SplittableRandom();
547 long size = 100;
548 r.longs().limit(size).forEach(x -> counter.increment());
549 assertEquals(size, counter.sum());
550 }
551
552 /**
553 * A sequential unsized stream of doubles generates at least 100 values
554 */
555 public void testUnsizedDoublesCountSeq() {
556 LongAdder counter = new LongAdder();
557 SplittableRandom r = new SplittableRandom();
558 long size = 100;
559 r.doubles().limit(size).forEach(x -> counter.increment());
560 assertEquals(size, counter.sum());
561 }
562
563 }