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  */
  39 @Test
  40 public 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         executeAndCatchIAE(() -> r.ints(-1L));
 175         executeAndCatchIAE(() -> r.ints(-1L, 2, 3));
 176         executeAndCatchIAE(() -> r.longs(-1L));
 177         executeAndCatchIAE(() -> r.longs(-1L, -1L, 1L));
 178         executeAndCatchIAE(() -> r.doubles(-1L));
 179         executeAndCatchIAE(() -> 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         executeAndCatchIAE(() -> r.ints(2, 1));
 189         executeAndCatchIAE(() -> r.ints(10, 42, 42));
 190         executeAndCatchIAE(() -> r.longs(-1L, -1L));
 191         executeAndCatchIAE(() -> 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         executeAndCatchIAE(() -> bi.accept(17.0, 2.0));
 201         executeAndCatchIAE(() -> bi.accept(0.0, 0.0));
 202         executeAndCatchIAE(() -> bi.accept(Double.NaN, FINITE));
 203         executeAndCatchIAE(() -> bi.accept(FINITE, Double.NaN));
 204         executeAndCatchIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY));
 205 
 206         // Returns NaN
 207 //        executeAndCatchIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, FINITE));
 208 //        executeAndCatchIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
 209 
 210         executeAndCatchIAE(() -> bi.accept(FINITE, Double.NEGATIVE_INFINITY));
 211 
 212         // Returns Double.MAX_VALUE
 213 //        executeAndCatchIAE(() -> bi.accept(FINITE, Double.POSITIVE_INFINITY));
 214 
 215         executeAndCatchIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY));
 216         executeAndCatchIAE(() -> bi.accept(Double.POSITIVE_INFINITY, FINITE));
 217         executeAndCatchIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY));
 218     }
 219 
 220     private void executeAndCatchIAE(Runnable r) {
 221         executeAndCatch(IllegalArgumentException.class, r);
 222     }
 223 
 224     private void executeAndCatch(Class<? extends Exception> expected, Runnable r) {
 225         Exception caught = null;
 226         try {
 227             r.run();
 228         }
 229         catch (Exception e) {
 230             caught = e;
 231         }
 232 
 233         assertNotNull(caught,
 234                       String.format("No Exception was thrown, expected an Exception of %s to be thrown",
 235                                     expected.getName()));
 236         Assert.assertTrue(expected.isInstance(caught),
 237                           String.format("Exception thrown %s not an instance of %s",
 238                                         caught.getClass().getName(), expected.getName()));
 239     }
 240 
 241     /**
 242      * A sequential sized stream of ints generates the given number of values
 243      */
 244     public void testIntsCount() {
 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.ints(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 longs generates the given number of values
 260      */
 261     public void testLongsCount() {
 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.longs(size).forEach(x -> {
 268                 counter.increment();
 269             });
 270             assertEquals(counter.sum(), size);
 271             size += 524959;
 272         }
 273     }
 274 
 275     /**
 276      * A sequential sized stream of doubles generates the given number of values
 277      */
 278     public void testDoublesCount() {
 279         LongAdder counter = new LongAdder();
 280         Random r = new Random();
 281         long size = 0;
 282         for (int reps = 0; reps < REPS; ++reps) {
 283             counter.reset();
 284             r.doubles(size).forEach(x -> {
 285                 counter.increment();
 286             });
 287             assertEquals(counter.sum(), size);
 288             size += 524959;
 289         }
 290     }
 291 
 292     /**
 293      * Each of a sequential sized stream of bounded ints is within bounds
 294      */
 295     public void testBoundedInts() {
 296         AtomicInteger fails = new AtomicInteger(0);
 297         Random r = new Random();
 298         long size = 12345L;
 299         for (int least = -15485867; least < MAX_INT_BOUND; least += 524959) {
 300             for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 67867967) {
 301                 final int lo = least, hi = bound;
 302                 r.ints(size, lo, hi).
 303                         forEach(x -> {
 304                             if (x < lo || x >= hi)
 305                                 fails.getAndIncrement();
 306                         });
 307             }
 308         }
 309         assertEquals(fails.get(), 0);
 310     }
 311 
 312     /**
 313      * Each of a sequential sized stream of bounded longs is within bounds
 314      */
 315     public void testBoundedLongs() {
 316         AtomicInteger fails = new AtomicInteger(0);
 317         Random r = new Random();
 318         long size = 123L;
 319         for (long least = -86028121; least < MAX_LONG_BOUND; least += 1982451653L) {
 320             for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
 321                 final long lo = least, hi = bound;
 322                 r.longs(size, lo, hi).
 323                         forEach(x -> {
 324                             if (x < lo || x >= hi)
 325                                 fails.getAndIncrement();
 326                         });
 327             }
 328         }
 329         assertEquals(fails.get(), 0);
 330     }
 331 
 332     /**
 333      * Each of a sequential sized stream of bounded doubles is within bounds
 334      */
 335     public void testBoundedDoubles() {
 336         AtomicInteger fails = new AtomicInteger(0);
 337         Random r = new Random();
 338         long size = 456;
 339         for (double least = 0.00011; least < 1.0e20; least *= 9) {
 340             for (double bound = least * 1.0011; bound < 1.0e20; bound *= 17) {
 341                 final double lo = least, hi = bound;
 342                 r.doubles(size, lo, hi).
 343                         forEach(x -> {
 344                             if (x < lo || x >= hi)
 345                                 fails.getAndIncrement();
 346                         });
 347             }
 348         }
 349         assertEquals(fails.get(), 0);
 350     }
 351 
 352     /**
 353      * A parallel unsized stream of ints generates at least 100 values
 354      */
 355     public void testUnsizedIntsCount() {
 356         LongAdder counter = new LongAdder();
 357         Random r = new Random();
 358         long size = 100;
 359         r.ints().limit(size).parallel().forEach(x -> {
 360             counter.increment();
 361         });
 362         assertEquals(counter.sum(), size);
 363     }
 364 
 365     /**
 366      * A parallel unsized stream of longs generates at least 100 values
 367      */
 368     public void testUnsizedLongsCount() {
 369         LongAdder counter = new LongAdder();
 370         Random r = new Random();
 371         long size = 100;
 372         r.longs().limit(size).parallel().forEach(x -> {
 373             counter.increment();
 374         });
 375         assertEquals(counter.sum(), size);
 376     }
 377 
 378     /**
 379      * A parallel unsized stream of doubles generates at least 100 values
 380      */
 381     public void testUnsizedDoublesCount() {
 382         LongAdder counter = new LongAdder();
 383         Random r = new Random();
 384         long size = 100;
 385         r.doubles().limit(size).parallel().forEach(x -> {
 386             counter.increment();
 387         });
 388         assertEquals(counter.sum(), size);
 389     }
 390 
 391     /**
 392      * A sequential unsized stream of ints generates at least 100 values
 393      */
 394     public void testUnsizedIntsCountSeq() {
 395         LongAdder counter = new LongAdder();
 396         Random r = new Random();
 397         long size = 100;
 398         r.ints().limit(size).forEach(x -> {
 399             counter.increment();
 400         });
 401         assertEquals(counter.sum(), size);
 402     }
 403 
 404     /**
 405      * A sequential unsized stream of longs generates at least 100 values
 406      */
 407     public void testUnsizedLongsCountSeq() {
 408         LongAdder counter = new LongAdder();
 409         Random r = new Random();
 410         long size = 100;
 411         r.longs().limit(size).forEach(x -> {
 412             counter.increment();
 413         });
 414         assertEquals(counter.sum(), size);
 415     }
 416 
 417     /**
 418      * A sequential unsized stream of doubles generates at least 100 values
 419      */
 420     public void testUnsizedDoublesCountSeq() {
 421         LongAdder counter = new LongAdder();
 422         Random r = new Random();
 423         long size = 100;
 424         r.doubles().limit(size).forEach(x -> {
 425             counter.increment();
 426         });
 427         assertEquals(counter.sum(), size);
 428     }
 429 
 430 }