ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/SplittableRandomTest.java
Revision: 1.19
Committed: Sun Sep 20 21:16:08 2015 UTC (8 years, 7 months ago) by jsr166
Branch: MAIN
Changes since 1.18: +2 -0 lines
Log Message:
more assertions for testNextIntBounded, testNextLongBounded

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 nextInt produce at least two distinct results
54 */
55 public void testNextInt() {
56 SplittableRandom sr = new SplittableRandom();
57 int f = sr.nextInt();
58 int i = 0;
59 while (i < NCALLS && sr.nextInt() == f)
60 ++i;
61 assertTrue(i < NCALLS);
62 }
63
64 /**
65 * Repeated calls to nextLong produce at least two distinct results
66 */
67 public void testNextLong() {
68 SplittableRandom sr = new SplittableRandom();
69 long f = sr.nextLong();
70 int i = 0;
71 while (i < NCALLS && sr.nextLong() == f)
72 ++i;
73 assertTrue(i < NCALLS);
74 }
75
76 /**
77 * Repeated calls to nextDouble produce at least two distinct results
78 */
79 public void testNextDouble() {
80 SplittableRandom sr = new SplittableRandom();
81 double f = sr.nextDouble();
82 int i = 0;
83 while (i < NCALLS && sr.nextDouble() == f)
84 ++i;
85 assertTrue(i < NCALLS);
86 }
87
88 /**
89 * Two SplittableRandoms created with the same seed produce the
90 * same values for nextLong.
91 */
92 public void testSeedConstructor() {
93 for (long seed = 2; seed < MAX_LONG_BOUND; seed += 15485863) {
94 SplittableRandom sr1 = new SplittableRandom(seed);
95 SplittableRandom sr2 = new SplittableRandom(seed);
96 for (int i = 0; i < REPS; ++i)
97 assertEquals(sr1.nextLong(), sr2.nextLong());
98 }
99 }
100
101 /**
102 * A SplittableRandom produced by split() of a default-constructed
103 * SplittableRandom generates a different sequence
104 */
105 public void testSplit1() {
106 SplittableRandom sr = new SplittableRandom();
107 for (int reps = 0; reps < REPS; ++reps) {
108 SplittableRandom sc = sr.split();
109 int i = 0;
110 while (i < NCALLS && sr.nextLong() == sc.nextLong())
111 ++i;
112 assertTrue(i < NCALLS);
113 }
114 }
115
116 /**
117 * A SplittableRandom produced by split() of a seeded-constructed
118 * SplittableRandom generates a different sequence
119 */
120 public void testSplit2() {
121 SplittableRandom sr = new SplittableRandom(12345);
122 for (int reps = 0; reps < REPS; ++reps) {
123 SplittableRandom sc = sr.split();
124 int i = 0;
125 while (i < NCALLS && sr.nextLong() == sc.nextLong())
126 ++i;
127 assertTrue(i < NCALLS);
128 }
129 }
130
131 /**
132 * nextInt(non-positive) throws IllegalArgumentException
133 */
134 public void testNextIntBoundNonPositive() {
135 SplittableRandom sr = new SplittableRandom();
136 Runnable[] throwingActions = {
137 () -> sr.nextInt(-17),
138 () -> sr.nextInt(0),
139 () -> sr.nextInt(Integer.MIN_VALUE),
140 };
141 assertThrows(IllegalArgumentException.class, throwingActions);
142 }
143
144 /**
145 * nextInt(least >= bound) throws IllegalArgumentException
146 */
147 public void testNextIntBadBounds() {
148 SplittableRandom sr = new SplittableRandom();
149 Runnable[] throwingActions = {
150 () -> sr.nextInt(17, 2),
151 () -> sr.nextInt(-42, -42),
152 () -> sr.nextInt(Integer.MAX_VALUE, Integer.MIN_VALUE),
153 };
154 assertThrows(IllegalArgumentException.class, throwingActions);
155 }
156
157 /**
158 * nextInt(bound) returns 0 <= value < bound;
159 * repeated calls produce at least two distinct results
160 */
161 public void testNextIntBounded() {
162 SplittableRandom sr = new SplittableRandom();
163 for (int i = 0; i < 2; i++) assertEquals(0, sr.nextInt(1));
164 // sample bound space across prime number increments
165 for (int bound = 2; bound < MAX_INT_BOUND; bound += 524959) {
166 int f = sr.nextInt(bound);
167 assertTrue(0 <= f && f < bound);
168 int i = 0;
169 int j;
170 while (i < NCALLS &&
171 (j = sr.nextInt(bound)) == f) {
172 assertTrue(0 <= j && j < bound);
173 ++i;
174 }
175 assertTrue(i < NCALLS);
176 }
177 }
178
179 /**
180 * nextInt(least, bound) returns least <= value < bound;
181 * repeated calls produce at least two distinct results
182 */
183 public void testNextIntBounded2() {
184 SplittableRandom sr = new SplittableRandom();
185 for (int least = -15485863; least < MAX_INT_BOUND; least += 524959) {
186 for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 49979687) {
187 int f = sr.nextInt(least, bound);
188 assertTrue(least <= f && f < bound);
189 int i = 0;
190 int j;
191 while (i < NCALLS &&
192 (j = sr.nextInt(least, bound)) == f) {
193 assertTrue(least <= j && j < bound);
194 ++i;
195 }
196 assertTrue(i < NCALLS);
197 }
198 }
199 }
200
201 /**
202 * nextLong(non-positive) throws IllegalArgumentException
203 */
204 public void testNextLongBoundNonPositive() {
205 SplittableRandom sr = new SplittableRandom();
206 Runnable[] throwingActions = {
207 () -> sr.nextLong(-17L),
208 () -> sr.nextLong(0L),
209 () -> sr.nextLong(Long.MIN_VALUE),
210 };
211 assertThrows(IllegalArgumentException.class, throwingActions);
212 }
213
214 /**
215 * nextLong(least >= bound) throws IllegalArgumentException
216 */
217 public void testNextLongBadBounds() {
218 SplittableRandom sr = new SplittableRandom();
219 Runnable[] throwingActions = {
220 () -> sr.nextLong(17L, 2L),
221 () -> sr.nextLong(-42L, -42L),
222 () -> sr.nextLong(Long.MAX_VALUE, Long.MIN_VALUE),
223 };
224 assertThrows(IllegalArgumentException.class, throwingActions);
225 }
226
227 /**
228 * nextLong(bound) returns 0 <= value < bound;
229 * repeated calls produce at least two distinct results
230 */
231 public void testNextLongBounded() {
232 SplittableRandom sr = new SplittableRandom();
233 for (int i = 0; i < 2; i++) assertEquals(0L, sr.nextLong(1L));
234 for (long bound = 2; bound < MAX_LONG_BOUND; bound += 15485863) {
235 long f = sr.nextLong(bound);
236 assertTrue(0 <= f && f < bound);
237 int i = 0;
238 long j;
239 while (i < NCALLS &&
240 (j = sr.nextLong(bound)) == f) {
241 assertTrue(0 <= j && j < bound);
242 ++i;
243 }
244 assertTrue(i < NCALLS);
245 }
246 }
247
248 /**
249 * nextLong(least, bound) returns least <= value < bound;
250 * repeated calls produce at least two distinct results
251 */
252 public void testNextLongBounded2() {
253 SplittableRandom sr = new SplittableRandom();
254 for (long least = -86028121; least < MAX_LONG_BOUND; least += 982451653L) {
255 for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
256 long f = sr.nextLong(least, bound);
257 assertTrue(least <= f && f < bound);
258 int i = 0;
259 long j;
260 while (i < NCALLS &&
261 (j = sr.nextLong(least, bound)) == f) {
262 assertTrue(least <= j && j < bound);
263 ++i;
264 }
265 assertTrue(i < NCALLS);
266 }
267 }
268 }
269
270 /**
271 * nextDouble(non-positive) throws IllegalArgumentException
272 */
273 public void testNextDoubleBoundNonPositive() {
274 SplittableRandom sr = new SplittableRandom();
275 Runnable[] throwingActions = {
276 () -> sr.nextDouble(-17.0d),
277 () -> sr.nextDouble(0.0d),
278 () -> sr.nextDouble(-Double.MIN_VALUE),
279 () -> sr.nextDouble(Double.NEGATIVE_INFINITY),
280 () -> sr.nextDouble(Double.NaN),
281 };
282 assertThrows(IllegalArgumentException.class, throwingActions);
283 }
284
285 /**
286 * nextDouble(! (least < bound)) throws IllegalArgumentException
287 */
288 public void testNextDoubleBadBounds() {
289 SplittableRandom sr = new SplittableRandom();
290 Runnable[] throwingActions = {
291 () -> sr.nextDouble(17.0d, 2.0d),
292 () -> sr.nextDouble(-42.0d, -42.0d),
293 () -> sr.nextDouble(Double.MAX_VALUE, Double.MIN_VALUE),
294 () -> sr.nextDouble(Double.NaN, 0.0d),
295 () -> sr.nextDouble(0.0d, Double.NaN),
296 };
297 assertThrows(IllegalArgumentException.class, throwingActions);
298 }
299
300 // TODO: Test infinite bounds!
301 //() -> sr.nextDouble(Double.NEGATIVE_INFINITY, 0.0d),
302 //() -> sr.nextDouble(0.0d, Double.POSITIVE_INFINITY),
303
304 /**
305 * nextDouble(least, bound) returns least <= value < bound;
306 * repeated calls produce at least two distinct results
307 */
308 public void testNextDoubleBounded2() {
309 SplittableRandom sr = new SplittableRandom();
310 for (double least = 0.0001; least < 1.0e20; least *= 8) {
311 for (double bound = least * 1.001; bound < 1.0e20; bound *= 16) {
312 double f = sr.nextDouble(least, bound);
313 assertTrue(least <= f && f < bound);
314 int i = 0;
315 double j;
316 while (i < NCALLS &&
317 (j = sr.nextDouble(least, bound)) == f) {
318 assertTrue(least <= j && j < bound);
319 ++i;
320 }
321 assertTrue(i < NCALLS);
322 }
323 }
324 }
325
326 /**
327 * Invoking sized ints, long, doubles, with negative sizes throws
328 * IllegalArgumentException
329 */
330 public void testBadStreamSize() {
331 SplittableRandom r = new SplittableRandom();
332 Runnable[] throwingActions = {
333 () -> { java.util.stream.IntStream x = r.ints(-1L); },
334 () -> { java.util.stream.IntStream x = r.ints(-1L, 2, 3); },
335 () -> { java.util.stream.LongStream x = r.longs(-1L); },
336 () -> { java.util.stream.LongStream x = r.longs(-1L, -1L, 1L); },
337 () -> { java.util.stream.DoubleStream x = r.doubles(-1L); },
338 () -> { java.util.stream.DoubleStream x = r.doubles(-1L, .5, .6); },
339 };
340 assertThrows(IllegalArgumentException.class, throwingActions);
341 }
342
343 /**
344 * Invoking bounded ints, long, doubles, with illegal bounds throws
345 * IllegalArgumentException
346 */
347 public void testBadStreamBounds() {
348 SplittableRandom r = new SplittableRandom();
349 Runnable[] throwingActions = {
350 () -> { java.util.stream.IntStream x = r.ints(2, 1); },
351 () -> { java.util.stream.IntStream x = r.ints(10, 42, 42); },
352 () -> { java.util.stream.LongStream x = r.longs(-1L, -1L); },
353 () -> { java.util.stream.LongStream x = r.longs(10, 1L, -2L); },
354 () -> { java.util.stream.DoubleStream x = r.doubles(0.0, 0.0); },
355 () -> { java.util.stream.DoubleStream x = r.doubles(10, .5, .4); },
356 };
357 assertThrows(IllegalArgumentException.class, throwingActions);
358 }
359
360 /**
361 * A parallel sized stream of ints generates the given number of values
362 */
363 public void testIntsCount() {
364 LongAdder counter = new LongAdder();
365 SplittableRandom r = new SplittableRandom();
366 long size = 0;
367 for (int reps = 0; reps < REPS; ++reps) {
368 counter.reset();
369 r.ints(size).parallel().forEach(x -> counter.increment());
370 assertEquals(size, counter.sum());
371 size += 524959;
372 }
373 }
374
375 /**
376 * A parallel sized stream of longs generates the given number of values
377 */
378 public void testLongsCount() {
379 LongAdder counter = new LongAdder();
380 SplittableRandom r = new SplittableRandom();
381 long size = 0;
382 for (int reps = 0; reps < REPS; ++reps) {
383 counter.reset();
384 r.longs(size).parallel().forEach(x -> counter.increment());
385 assertEquals(size, counter.sum());
386 size += 524959;
387 }
388 }
389
390 /**
391 * A parallel sized stream of doubles generates the given number of values
392 */
393 public void testDoublesCount() {
394 LongAdder counter = new LongAdder();
395 SplittableRandom r = new SplittableRandom();
396 long size = 0;
397 for (int reps = 0; reps < REPS; ++reps) {
398 counter.reset();
399 r.doubles(size).parallel().forEach(x -> counter.increment());
400 assertEquals(size, counter.sum());
401 size += 524959;
402 }
403 }
404
405 /**
406 * Each of a parallel sized stream of bounded ints is within bounds
407 */
408 public void testBoundedInts() {
409 AtomicInteger fails = new AtomicInteger(0);
410 SplittableRandom r = new SplittableRandom();
411 long size = 12345L;
412 for (int least = -15485867; least < MAX_INT_BOUND; least += 524959) {
413 for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 67867967) {
414 final int lo = least, hi = bound;
415 r.ints(size, lo, hi).parallel().forEach(
416 x -> {
417 if (x < lo || x >= hi)
418 fails.getAndIncrement(); });
419 }
420 }
421 assertEquals(0, fails.get());
422 }
423
424 /**
425 * Each of a parallel sized stream of bounded longs is within bounds
426 */
427 public void testBoundedLongs() {
428 AtomicInteger fails = new AtomicInteger(0);
429 SplittableRandom r = new SplittableRandom();
430 long size = 123L;
431 for (long least = -86028121; least < MAX_LONG_BOUND; least += 1982451653L) {
432 for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
433 final long lo = least, hi = bound;
434 r.longs(size, lo, hi).parallel().forEach(
435 x -> {
436 if (x < lo || x >= hi)
437 fails.getAndIncrement(); });
438 }
439 }
440 assertEquals(0, fails.get());
441 }
442
443 /**
444 * Each of a parallel sized stream of bounded doubles is within bounds
445 */
446 public void testBoundedDoubles() {
447 AtomicInteger fails = new AtomicInteger(0);
448 SplittableRandom r = new SplittableRandom();
449 long size = 456;
450 for (double least = 0.00011; least < 1.0e20; least *= 9) {
451 for (double bound = least * 1.0011; bound < 1.0e20; bound *= 17) {
452 final double lo = least, hi = bound;
453 r.doubles(size, lo, hi).parallel().forEach(
454 x -> {
455 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 SplittableRandom r = new SplittableRandom();
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 SplittableRandom r = new SplittableRandom();
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 SplittableRandom r = new SplittableRandom();
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 SplittableRandom r = new SplittableRandom();
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 SplittableRandom r = new SplittableRandom();
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 SplittableRandom r = new SplittableRandom();
523 long size = 100;
524 r.doubles().limit(size).forEach(x -> counter.increment());
525 assertEquals(size, counter.sum());
526 }
527
528 }