ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/SplittableRandomTest.java
Revision: 1.24
Committed: Fri Oct 13 16:14:40 2017 UTC (6 years, 7 months ago) by jsr166
Branch: MAIN
Changes since 1.23: +0 -1 lines
Log Message:
remove unused imports

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