RandomTest.java revision 17091:88379fba79d3
1/*
2 * Copyright (c) 2012, 2017, 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
24import java.util.Random;
25import java.util.concurrent.atomic.AtomicInteger;
26import java.util.concurrent.atomic.LongAdder;
27import java.util.function.BiConsumer;
28
29import org.testng.annotations.Test;
30
31import static org.testng.Assert.*;
32
33/**
34 * @test
35 * @run testng RandomTest
36 * @summary test methods on Random
37 * @key randomness
38 */
39@Test
40public class RandomTest {
41
42    // Note: this test was adapted from the 166 TCK ThreadLocalRandomTest test
43    // and modified to be a TestNG test
44
45    /*
46     * Testing coverage notes:
47     *
48     * We don't test randomness properties, but only that repeated
49     * calls, up to NCALLS tries, produce at least one different
50     * result.  For bounded versions, we sample various intervals
51     * across multiples of primes.
52     */
53
54    // max numbers of calls to detect getting stuck on one value
55    static final int NCALLS = 10000;
56
57    // max sampled int bound
58    static final int MAX_INT_BOUND = (1 << 28);
59
60    // max sampled long bound
61    static final long MAX_LONG_BOUND = (1L << 42);
62
63    // Number of replications for other checks
64    static final int REPS = 20;
65
66    /**
67     * Repeated calls to nextInt produce at least two distinct results
68     */
69    public void testNextInt() {
70        Random r = new Random();
71        int f = r.nextInt();
72        int i = 0;
73        while (i < NCALLS && r.nextInt() == f)
74            ++i;
75        assertTrue(i < NCALLS);
76    }
77
78    /**
79     * Repeated calls to nextLong produce at least two distinct results
80     */
81    public void testNextLong() {
82        Random r = new Random();
83        long f = r.nextLong();
84        int i = 0;
85        while (i < NCALLS && r.nextLong() == f)
86            ++i;
87        assertTrue(i < NCALLS);
88    }
89
90    /**
91     * Repeated calls to nextBoolean produce at least two distinct results
92     */
93    public void testNextBoolean() {
94        Random r = new Random();
95        boolean f = r.nextBoolean();
96        int i = 0;
97        while (i < NCALLS && r.nextBoolean() == f)
98            ++i;
99        assertTrue(i < NCALLS);
100    }
101
102    /**
103     * Repeated calls to nextFloat produce at least two distinct results
104     */
105    public void testNextFloat() {
106        Random r = new Random();
107        float f = r.nextFloat();
108        int i = 0;
109        while (i < NCALLS && r.nextFloat() == f)
110            ++i;
111        assertTrue(i < NCALLS);
112    }
113
114    /**
115     * Repeated calls to nextDouble produce at least two distinct results
116     */
117    public void testNextDouble() {
118        Random r = new Random();
119        double f = r.nextDouble();
120        int i = 0;
121        while (i < NCALLS && r.nextDouble() == f)
122            ++i;
123        assertTrue(i < NCALLS);
124    }
125
126    /**
127     * Repeated calls to nextGaussian produce at least two distinct results
128     */
129    public void testNextGaussian() {
130        Random r = new Random();
131        double f = r.nextGaussian();
132        int i = 0;
133        while (i < NCALLS && r.nextGaussian() == f)
134            ++i;
135        assertTrue(i < NCALLS);
136    }
137
138    /**
139     * nextInt(negative) throws IllegalArgumentException
140     */
141    @Test(expectedExceptions = IllegalArgumentException.class)
142    public void testNextIntBoundedNeg() {
143        Random r = new Random();
144        int f = r.nextInt(-17);
145    }
146
147    /**
148     * nextInt(bound) returns 0 <= value < bound; repeated calls produce at
149     * least two distinct results
150     */
151    public void testNextIntBounded() {
152        Random r = new Random();
153        // sample bound space across prime number increments
154        for (int bound = 2; bound < MAX_INT_BOUND; bound += 524959) {
155            int f = r.nextInt(bound);
156            assertTrue(0 <= f && f < bound);
157            int i = 0;
158            int j;
159            while (i < NCALLS &&
160                   (j = r.nextInt(bound)) == f) {
161                assertTrue(0 <= j && j < bound);
162                ++i;
163            }
164            assertTrue(i < NCALLS);
165        }
166    }
167
168    /**
169     * Invoking sized ints, long, doubles, with negative sizes throws
170     * IllegalArgumentException
171     */
172    public void testBadStreamSize() {
173        Random r = new Random();
174        assertThrowsIAE(() -> r.ints(-1L));
175        assertThrowsIAE(() -> r.ints(-1L, 2, 3));
176        assertThrowsIAE(() -> r.longs(-1L));
177        assertThrowsIAE(() -> r.longs(-1L, -1L, 1L));
178        assertThrowsIAE(() -> r.doubles(-1L));
179        assertThrowsIAE(() -> r.doubles(-1L, .5, .6));
180    }
181
182    /**
183     * Invoking bounded ints, long, doubles, with illegal bounds throws
184     * IllegalArgumentException
185     */
186    public void testBadStreamBounds() {
187        Random r = new Random();
188        assertThrowsIAE(() -> r.ints(2, 1));
189        assertThrowsIAE(() -> r.ints(10, 42, 42));
190        assertThrowsIAE(() -> r.longs(-1L, -1L));
191        assertThrowsIAE(() -> r.longs(10, 1L, -2L));
192
193        testDoubleBadOriginBound((o, b) -> r.doubles(10, o, b));
194    }
195
196    // An arbitrary finite double value
197    static final double FINITE = Math.PI;
198
199    void testDoubleBadOriginBound(BiConsumer<Double, Double> bi) {
200        assertThrowsIAE(() -> bi.accept(17.0, 2.0));
201        assertThrowsIAE(() -> bi.accept(0.0, 0.0));
202        assertThrowsIAE(() -> bi.accept(Double.NaN, FINITE));
203        assertThrowsIAE(() -> bi.accept(FINITE, Double.NaN));
204        assertThrowsIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY));
205
206        // Returns NaN
207//        assertThrowsIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, FINITE));
208//        assertThrowsIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
209
210        assertThrowsIAE(() -> bi.accept(FINITE, Double.NEGATIVE_INFINITY));
211
212        // Returns Double.MAX_VALUE
213//        assertThrowsIAE(() -> bi.accept(FINITE, Double.POSITIVE_INFINITY));
214
215        assertThrowsIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY));
216        assertThrowsIAE(() -> bi.accept(Double.POSITIVE_INFINITY, FINITE));
217        assertThrowsIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY));
218    }
219
220    private void assertThrowsIAE(ThrowingRunnable r) {
221        assertThrows(IllegalArgumentException.class, r);
222    }
223
224    /**
225     * A sequential sized stream of ints generates the given number of values
226     */
227    public void testIntsCount() {
228        LongAdder counter = new LongAdder();
229        Random r = new Random();
230        long size = 0;
231        for (int reps = 0; reps < REPS; ++reps) {
232            counter.reset();
233            r.ints(size).forEach(x -> {
234                counter.increment();
235            });
236            assertEquals(counter.sum(), size);
237            size += 524959;
238        }
239    }
240
241    /**
242     * A sequential sized stream of longs generates the given number of values
243     */
244    public void testLongsCount() {
245        LongAdder counter = new LongAdder();
246        Random r = new Random();
247        long size = 0;
248        for (int reps = 0; reps < REPS; ++reps) {
249            counter.reset();
250            r.longs(size).forEach(x -> {
251                counter.increment();
252            });
253            assertEquals(counter.sum(), size);
254            size += 524959;
255        }
256    }
257
258    /**
259     * A sequential sized stream of doubles generates the given number of values
260     */
261    public void testDoublesCount() {
262        LongAdder counter = new LongAdder();
263        Random r = new Random();
264        long size = 0;
265        for (int reps = 0; reps < REPS; ++reps) {
266            counter.reset();
267            r.doubles(size).forEach(x -> {
268                counter.increment();
269            });
270            assertEquals(counter.sum(), size);
271            size += 524959;
272        }
273    }
274
275    /**
276     * Each of a sequential sized stream of bounded ints is within bounds
277     */
278    public void testBoundedInts() {
279        AtomicInteger fails = new AtomicInteger(0);
280        Random r = new Random();
281        long size = 12345L;
282        for (int least = -15485867; least < MAX_INT_BOUND; least += 524959) {
283            for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 67867967) {
284                final int lo = least, hi = bound;
285                r.ints(size, lo, hi).
286                        forEach(x -> {
287                            if (x < lo || x >= hi)
288                                fails.getAndIncrement();
289                        });
290            }
291        }
292        assertEquals(fails.get(), 0);
293    }
294
295    /**
296     * Each of a sequential sized stream of bounded longs is within bounds
297     */
298    public void testBoundedLongs() {
299        AtomicInteger fails = new AtomicInteger(0);
300        Random r = new Random();
301        long size = 123L;
302        for (long least = -86028121; least < MAX_LONG_BOUND; least += 1982451653L) {
303            for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
304                final long lo = least, hi = bound;
305                r.longs(size, lo, hi).
306                        forEach(x -> {
307                            if (x < lo || x >= hi)
308                                fails.getAndIncrement();
309                        });
310            }
311        }
312        assertEquals(fails.get(), 0);
313    }
314
315    /**
316     * Each of a sequential sized stream of bounded doubles is within bounds
317     */
318    public void testBoundedDoubles() {
319        AtomicInteger fails = new AtomicInteger(0);
320        Random r = new Random();
321        long size = 456;
322        for (double least = 0.00011; least < 1.0e20; least *= 9) {
323            for (double bound = least * 1.0011; bound < 1.0e20; bound *= 17) {
324                final double lo = least, hi = bound;
325                r.doubles(size, lo, hi).
326                        forEach(x -> {
327                            if (x < lo || x >= hi)
328                                fails.getAndIncrement();
329                        });
330            }
331        }
332        assertEquals(fails.get(), 0);
333    }
334
335    /**
336     * A parallel unsized stream of ints generates at least 100 values
337     */
338    public void testUnsizedIntsCount() {
339        LongAdder counter = new LongAdder();
340        Random r = new Random();
341        long size = 100;
342        r.ints().limit(size).parallel().forEach(x -> {
343            counter.increment();
344        });
345        assertEquals(counter.sum(), size);
346    }
347
348    /**
349     * A parallel unsized stream of longs generates at least 100 values
350     */
351    public void testUnsizedLongsCount() {
352        LongAdder counter = new LongAdder();
353        Random r = new Random();
354        long size = 100;
355        r.longs().limit(size).parallel().forEach(x -> {
356            counter.increment();
357        });
358        assertEquals(counter.sum(), size);
359    }
360
361    /**
362     * A parallel unsized stream of doubles generates at least 100 values
363     */
364    public void testUnsizedDoublesCount() {
365        LongAdder counter = new LongAdder();
366        Random r = new Random();
367        long size = 100;
368        r.doubles().limit(size).parallel().forEach(x -> {
369            counter.increment();
370        });
371        assertEquals(counter.sum(), size);
372    }
373
374    /**
375     * A sequential unsized stream of ints generates at least 100 values
376     */
377    public void testUnsizedIntsCountSeq() {
378        LongAdder counter = new LongAdder();
379        Random r = new Random();
380        long size = 100;
381        r.ints().limit(size).forEach(x -> {
382            counter.increment();
383        });
384        assertEquals(counter.sum(), size);
385    }
386
387    /**
388     * A sequential unsized stream of longs generates at least 100 values
389     */
390    public void testUnsizedLongsCountSeq() {
391        LongAdder counter = new LongAdder();
392        Random r = new Random();
393        long size = 100;
394        r.longs().limit(size).forEach(x -> {
395            counter.increment();
396        });
397        assertEquals(counter.sum(), size);
398    }
399
400    /**
401     * A sequential unsized stream of doubles generates at least 100 values
402     */
403    public void testUnsizedDoublesCountSeq() {
404        LongAdder counter = new LongAdder();
405        Random r = new Random();
406        long size = 100;
407        r.doubles().limit(size).forEach(x -> {
408            counter.increment();
409        });
410        assertEquals(counter.sum(), size);
411    }
412
413}
414