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 }