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 }