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