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