• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 package test.java.util.Random;
25 
26 import java.util.Random;
27 import java.util.concurrent.atomic.AtomicInteger;
28 import java.util.concurrent.atomic.LongAdder;
29 import java.util.function.BiConsumer;
30 import java.util.random.RandomGenerator;
31 import java.util.ArrayList;
32 import java.util.Collections;
33 
34 import org.testng.annotations.Test;
35 
36 import static org.testng.Assert.*;
37 
38 /**
39  * @test
40  * @run testng RandomTest
41  * @summary test methods on Random
42  * @bug 8288596
43  * @key randomness
44  */
45 @Test
46 public class RandomTest {
47 
48     // Note: this test was adapted from the 166 TCK ThreadLocalRandomTest test
49     // and modified to be a TestNG test
50 
51     /*
52      * Testing coverage notes:
53      *
54      * We don't test randomness properties, but only that repeated
55      * calls, up to NCALLS tries, produce at least one different
56      * result.  For bounded versions, we sample various intervals
57      * across multiples of primes.
58      */
59 
60     // max numbers of calls to detect getting stuck on one value
61     static final int NCALLS = 10000;
62 
63     // max sampled int bound
64     static final int MAX_INT_BOUND = (1 << 28);
65 
66     // max sampled long bound
67     static final long MAX_LONG_BOUND = (1L << 42);
68 
69     // Number of replications for other checks
70     // Android-changed: takes too much time to run on certain targets.
71     // static final int REPS = 20;
72     static final int REPS = 5;
73 
74     /**
75      * Repeated calls to nextInt produce at least two distinct results
76      */
testNextInt()77     public void testNextInt() {
78         Random r = new Random();
79         int f = r.nextInt();
80         int i = 0;
81         while (i < NCALLS && r.nextInt() == f)
82             ++i;
83         assertTrue(i < NCALLS);
84     }
85 
86     /**
87      * Repeated calls to nextLong produce at least two distinct results
88      */
89     public void testNextLong() {
90         Random r = new Random();
91         long f = r.nextLong();
92         int i = 0;
93         while (i < NCALLS && r.nextLong() == f)
94             ++i;
95         assertTrue(i < NCALLS);
96     }
97 
98     /**
99      * Repeated calls to nextBoolean produce at least two distinct results
100      */
101     public void testNextBoolean() {
102         Random r = new Random();
103         boolean f = r.nextBoolean();
104         int i = 0;
105         while (i < NCALLS && r.nextBoolean() == f)
106             ++i;
107         assertTrue(i < NCALLS);
108     }
109 
110     /**
111      * Repeated calls to nextFloat produce at least two distinct results
112      */
113     public void testNextFloat() {
114         Random r = new Random();
115         float f = r.nextFloat();
116         int i = 0;
117         while (i < NCALLS && r.nextFloat() == f)
118             ++i;
119         assertTrue(i < NCALLS);
120     }
121 
122     /**
123      * Repeated calls to nextDouble produce at least two distinct results
124      */
125     public void testNextDouble() {
126         Random r = new Random();
127         double f = r.nextDouble();
128         int i = 0;
129         while (i < NCALLS && r.nextDouble() == f)
130             ++i;
131         assertTrue(i < NCALLS);
132     }
133 
134     /**
135      * Repeated calls to nextGaussian produce at least two distinct results
136      */
137     public void testNextGaussian() {
138         Random r = new Random();
139         double f = r.nextGaussian();
140         int i = 0;
141         while (i < NCALLS && r.nextGaussian() == f)
142             ++i;
143         assertTrue(i < NCALLS);
144     }
145 
146     /**
147      * nextInt(negative) throws IllegalArgumentException
148      */
149     @Test(expectedExceptions = IllegalArgumentException.class)
150     public void testNextIntBoundedNeg() {
151         Random r = new Random();
152         int f = r.nextInt(-17);
153     }
154 
155     /**
156      * nextInt(bound) returns 0 <= value < bound; repeated calls produce at
157      * least two distinct results
158      */
159     public void testNextIntBounded() {
160         Random r = new Random();
161         // sample bound space across prime number increments
162         for (int bound = 2; bound < MAX_INT_BOUND; bound += 524959) {
163             int f = r.nextInt(bound);
164             assertTrue(0 <= f && f < bound);
165             int i = 0;
166             int j;
167             while (i < NCALLS &&
168                    (j = r.nextInt(bound)) == f) {
169                 assertTrue(0 <= j && j < bound);
170                 ++i;
171             }
172             assertTrue(i < NCALLS);
173         }
174     }
175 
176     /**
177      * Invoking sized ints, long, doubles, with negative sizes throws
178      * IllegalArgumentException
179      */
180     public void testBadStreamSize() {
181         Random r = new Random();
182         assertThrowsIAE(() -> r.ints(-1L));
183         assertThrowsIAE(() -> r.ints(-1L, 2, 3));
184         assertThrowsIAE(() -> r.longs(-1L));
185         assertThrowsIAE(() -> r.longs(-1L, -1L, 1L));
186         assertThrowsIAE(() -> r.doubles(-1L));
187         assertThrowsIAE(() -> r.doubles(-1L, .5, .6));
188     }
189 
190     /**
191      * Invoking bounded ints, long, doubles, with illegal bounds throws
192      * IllegalArgumentException
193      */
194     public void testBadStreamBounds() {
195         Random r = new Random();
196         assertThrowsIAE(() -> r.ints(2, 1));
197         assertThrowsIAE(() -> r.ints(10, 42, 42));
198         assertThrowsIAE(() -> r.longs(-1L, -1L));
199         assertThrowsIAE(() -> r.longs(10, 1L, -2L));
200 
201         testDoubleBadOriginBound((o, b) -> r.doubles(10, o, b));
202     }
203 
204     // An arbitrary finite double value
205     static final double FINITE = Math.PI;
206 
207     void testDoubleBadOriginBound(BiConsumer<Double, Double> bi) {
208         assertThrowsIAE(() -> bi.accept(17.0, 2.0));
209         assertThrowsIAE(() -> bi.accept(0.0, 0.0));
210         assertThrowsIAE(() -> bi.accept(Double.NaN, FINITE));
211         assertThrowsIAE(() -> bi.accept(FINITE, Double.NaN));
212         assertThrowsIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY));
213 
214         // Returns NaN
215 //        assertThrowsIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, FINITE));
216 //        assertThrowsIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
217 
218         assertThrowsIAE(() -> bi.accept(FINITE, Double.NEGATIVE_INFINITY));
219 
220         // Returns Double.MAX_VALUE
221 //        assertThrowsIAE(() -> bi.accept(FINITE, Double.POSITIVE_INFINITY));
222 
223         assertThrowsIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY));
224         assertThrowsIAE(() -> bi.accept(Double.POSITIVE_INFINITY, FINITE));
225         assertThrowsIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY));
226     }
227 
assertThrowsIAE(ThrowingRunnable r)228     private void assertThrowsIAE(ThrowingRunnable r) {
229         assertThrows(IllegalArgumentException.class, r);
230     }
231 
232     /**
233      * A sequential sized stream of ints generates the given number of values
234      */
testIntsCount()235     public void testIntsCount() {
236         LongAdder counter = new LongAdder();
237         Random r = new Random();
238         long size = 0;
239         for (int reps = 0; reps < REPS; ++reps) {
240             counter.reset();
241             r.ints(size).forEach(x -> {
242                 counter.increment();
243             });
244             assertEquals(counter.sum(), size);
245             size += 524959;
246         }
247     }
248 
249     /**
250      * A sequential sized stream of longs generates the given number of values
251      */
testLongsCount()252     public void testLongsCount() {
253         LongAdder counter = new LongAdder();
254         Random r = new Random();
255         long size = 0;
256         for (int reps = 0; reps < REPS; ++reps) {
257             counter.reset();
258             r.longs(size).forEach(x -> {
259                 counter.increment();
260             });
261             assertEquals(counter.sum(), size);
262             size += 524959;
263         }
264     }
265 
266     /**
267      * A sequential sized stream of doubles generates the given number of values
268      */
testDoublesCount()269     public void testDoublesCount() {
270         LongAdder counter = new LongAdder();
271         Random r = new Random();
272         long size = 0;
273         for (int reps = 0; reps < REPS; ++reps) {
274             counter.reset();
275             r.doubles(size).forEach(x -> {
276                 counter.increment();
277             });
278             assertEquals(counter.sum(), size);
279             size += 524959;
280         }
281     }
282 
283     /**
284      * Each of a sequential sized stream of bounded ints is within bounds
285      */
testBoundedInts()286     public void testBoundedInts() {
287         AtomicInteger fails = new AtomicInteger(0);
288         Random r = new Random();
289         long size = 12345L;
290         for (int least = -15485867; least < MAX_INT_BOUND; least += 524959) {
291             for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 67867967) {
292                 final int lo = least, hi = bound;
293                 r.ints(size, lo, hi).
294                         forEach(x -> {
295                             if (x < lo || x >= hi)
296                                 fails.getAndIncrement();
297                         });
298             }
299         }
300         assertEquals(fails.get(), 0);
301     }
302 
303     /**
304      * Each of a sequential sized stream of bounded longs is within bounds
305      */
testBoundedLongs()306     public void testBoundedLongs() {
307         AtomicInteger fails = new AtomicInteger(0);
308         Random r = new Random();
309         long size = 123L;
310         for (long least = -86028121; least < MAX_LONG_BOUND; least += 1982451653L) {
311             for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
312                 final long lo = least, hi = bound;
313                 r.longs(size, lo, hi).
314                         forEach(x -> {
315                             if (x < lo || x >= hi)
316                                 fails.getAndIncrement();
317                         });
318             }
319         }
320         assertEquals(fails.get(), 0);
321     }
322 
323     /**
324      * Each of a sequential sized stream of bounded doubles is within bounds
325      */
testBoundedDoubles()326     public void testBoundedDoubles() {
327         AtomicInteger fails = new AtomicInteger(0);
328         Random r = new Random();
329         long size = 456;
330         for (double least = 0.00011; least < 1.0e20; least *= 9) {
331             for (double bound = least * 1.0011; bound < 1.0e20; bound *= 17) {
332                 final double lo = least, hi = bound;
333                 r.doubles(size, lo, hi).
334                         forEach(x -> {
335                             if (x < lo || x >= hi)
336                                 fails.getAndIncrement();
337                         });
338             }
339         }
340         assertEquals(fails.get(), 0);
341     }
342 
343     /**
344      * A parallel unsized stream of ints generates at least 100 values
345      */
testUnsizedIntsCount()346     public void testUnsizedIntsCount() {
347         LongAdder counter = new LongAdder();
348         Random r = new Random();
349         long size = 100;
350         r.ints().limit(size).parallel().forEach(x -> {
351             counter.increment();
352         });
353         assertEquals(counter.sum(), size);
354     }
355 
356     /**
357      * A parallel unsized stream of longs generates at least 100 values
358      */
testUnsizedLongsCount()359     public void testUnsizedLongsCount() {
360         LongAdder counter = new LongAdder();
361         Random r = new Random();
362         long size = 100;
363         r.longs().limit(size).parallel().forEach(x -> {
364             counter.increment();
365         });
366         assertEquals(counter.sum(), size);
367     }
368 
369     /**
370      * A parallel unsized stream of doubles generates at least 100 values
371      */
testUnsizedDoublesCount()372     public void testUnsizedDoublesCount() {
373         LongAdder counter = new LongAdder();
374         Random r = new Random();
375         long size = 100;
376         r.doubles().limit(size).parallel().forEach(x -> {
377             counter.increment();
378         });
379         assertEquals(counter.sum(), size);
380     }
381 
382     /**
383      * A sequential unsized stream of ints generates at least 100 values
384      */
testUnsizedIntsCountSeq()385     public void testUnsizedIntsCountSeq() {
386         LongAdder counter = new LongAdder();
387         Random r = new Random();
388         long size = 100;
389         r.ints().limit(size).forEach(x -> {
390             counter.increment();
391         });
392         assertEquals(counter.sum(), size);
393     }
394 
395     /**
396      * A sequential unsized stream of longs generates at least 100 values
397      */
testUnsizedLongsCountSeq()398     public void testUnsizedLongsCountSeq() {
399         LongAdder counter = new LongAdder();
400         Random r = new Random();
401         long size = 100;
402         r.longs().limit(size).forEach(x -> {
403             counter.increment();
404         });
405         assertEquals(counter.sum(), size);
406     }
407 
408     /**
409      * A sequential unsized stream of doubles generates at least 100 values
410      */
testUnsizedDoublesCountSeq()411     public void testUnsizedDoublesCountSeq() {
412         LongAdder counter = new LongAdder();
413         Random r = new Random();
414         long size = 100;
415         r.doubles().limit(size).forEach(x -> {
416             counter.increment();
417         });
418         assertEquals(counter.sum(), size);
419     }
420 
421     /**
422      * Test shuffling a list with Random.from()
423      */
testShufflingList()424     public void testShufflingList() {
425         final var listTest = new ArrayList<Integer>();
426         final RandomGenerator randomGenerator = RandomGenerator.getDefault();
427         final Random random = Random.from(randomGenerator);
428 
429         for (int i = 0; i < 100; i++) {
430             listTest.add(i * 2);
431         }
432         final var listCopy = new ArrayList<Integer>(listTest);
433 
434         Collections.shuffle(listCopy, random);
435 
436         assertFalse(listCopy.equals(listTest));
437     }
438 
439     /**
440      * Test if Random.from returns this
441      */
testRandomFromInstance()442     public void testRandomFromInstance() {
443         final RandomGenerator randomGenerator = RandomGenerator.getDefault();
444 
445         final Random randomInstance = Random.from(randomGenerator);
446 
447         // we wrap the same instance again
448         final Random randomInstanceCopy = Random.from(randomInstance);
449 
450         assertSame(randomInstance, randomInstanceCopy);
451     }
452 
453     private int delegationCount;
454 
455     private class RandomGen implements RandomGenerator {
456 
457         @Override
isDeprecated()458         public boolean isDeprecated() {
459             delegationCount += 1;
460             return RandomGenerator.super.isDeprecated();
461         }
462 
463         @Override
nextFloat(float bound)464         public float nextFloat(float bound) {
465             delegationCount += 1;
466             return RandomGenerator.super.nextFloat(bound);
467         }
468 
469         @Override
nextDouble(double bound)470         public double nextDouble(double bound) {
471             delegationCount += 1;
472             return RandomGenerator.super.nextDouble(bound);
473         }
474 
475         @Override
nextLong()476         public long nextLong() {
477             return 0;
478         }
479 
480     }
481 
482     /*
483      * Test whether calls to methods inherited from RandomGenerator
484      * are delegated to the instance returned by from().
485      * This is not a complete coverage, but simulates the reproducer
486      * in issue JDK-8288596
487      */
testRandomFrom()488     public void testRandomFrom() {
489         delegationCount = 0;
490         var r = Random.from(new RandomGen());
491         r.isDeprecated();
492         r.nextFloat(1_000.0f);
493         r.nextFloat();  // not implemented in RandomGen, does not count
494         r.nextDouble(1_000.0);
495         r.nextDouble();  // not implemented in RandomGen, does not count
496         assertEquals(delegationCount, 3);
497     }
498 
499 }
500