/* * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ import java.math.BigInteger; import java.security.SecureRandom; import java.util.concurrent.ThreadLocalRandom; import java.util.random.RandomGenerator; import java.util.random.RandomGenerator.ArbitrarilyJumpableGenerator; import java.util.random.RandomGenerator.JumpableGenerator; import java.util.random.RandomGenerator.LeapableGenerator; import java.util.random.RandomGenerator.SplittableGenerator; import java.util.random.RandomGenerator.StreamableGenerator; import java.util.random.RandomGeneratorFactory; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; import java.util.stream.Stream; /** * @test * @summary Ensure that all implementations of RandomGenerator supply required methods. * @bug 8248862 * @run main RandomTestCoverage * @key randomness */ public class RandomTestCoverage { static void coverRandomGenerator(RandomGenerator rng) { boolean bool = rng.nextBoolean(); byte[] bytes = new byte[8]; rng.nextBytes(bytes); int i1 = rng.nextInt(); int i2 = rng.nextInt(10); int i3 = rng.nextInt(5, 10); long l1 = rng.nextLong(); long l2 = rng.nextLong(10L); long l3 = rng.nextLong(5L, 10L); float f1 = rng.nextFloat(); float f2 = rng.nextFloat(1.0f); float f3 = rng.nextFloat(0.5f, 1.0f); double d1 = rng.nextDouble(); double d2 = rng.nextDouble(1.0); double d3 = rng.nextDouble(0.5, 1.0); double exp = rng.nextExponential(); double gauss1 = rng.nextGaussian(); double gauss2 = rng.nextGaussian(0.5, 2.0); IntStream intStream1 = rng.ints(); IntStream intStream2 = rng.ints(5, 10); IntStream intStream3 = rng.ints(5L); IntStream intStream4 = rng.ints(5L, 5, 10); LongStream longStream1 = rng.longs(); LongStream longStream2 = rng.longs(5L, 10L); LongStream longStream3 = rng.longs(5L); LongStream longStream4 = rng.longs(5L, 5L, 10L); DoubleStream doubleStream1 = rng.doubles(); DoubleStream doubleStream2 = rng.doubles(0.5, 1.0); DoubleStream doubleStream3 = rng.doubles(5); DoubleStream doubleStream4 = rng.doubles(5, 0.5, 1.0); } static void checkPredicates(RandomGeneratorFactory factory) { RandomGenerator rng = factory.create(); if (rng instanceof ArbitrarilyJumpableGenerator != factory.isArbitrarilyJumpable()) { throw new RuntimeException("isArbitrarilyJumpable failing"); } if (rng instanceof JumpableGenerator != factory.isJumpable()) { throw new RuntimeException("isJumpable failing"); } if (rng instanceof LeapableGenerator != factory.isLeapable()) { throw new RuntimeException("isLeapable failing"); } if (rng instanceof SplittableGenerator != factory.isSplittable()) { throw new RuntimeException("isArbitrarilyJumpable failing"); } if (rng instanceof StreamableGenerator != factory.isStreamable()) { throw new RuntimeException("isArbitrarilyJumpable failing"); } } static void coverStreamable(StreamableGenerator rng) { Stream rngs1 = rng.rngs(); Stream rngs2 = rng.rngs(5L); } static void coverSplittable(SplittableGenerator rng) { SplittableGenerator s1 = rng.split(); SplittableGenerator s2 = rng.split(rng); Stream s3 = rng.splits(); Stream s4 = rng.splits(5L); Stream s5 = rng.splits(rng); Stream s6 = rng.splits(5L, rng); } static void coverJumpable(JumpableGenerator rng) { JumpableGenerator j1 = rng.copy(); rng.jump(); RandomGenerator j2 = rng.copyAndJump(); double d = rng.jumpDistance(); Stream j3 = rng.jumps(); Stream j4 = rng.jumps(5L); } static void coverLeapable(LeapableGenerator rng) { LeapableGenerator l1 = rng.copy(); rng.leap(); JumpableGenerator l2 = rng.copyAndLeap(); double d = rng.leapDistance(); Stream l3 = rng.leaps(); Stream l4 = rng.leaps(5L); } static void coverArbitrarilyJumpable(ArbitrarilyJumpableGenerator rng) { ArbitrarilyJumpableGenerator a1 = rng.copy(); rng.jump(); rng.leap(); rng.jump(1.2345); rng.jumpPowerOfTwo(4); RandomGenerator a2 = rng.copyAndJump(); RandomGenerator a3 = rng.copyAndJump(1.2345); Stream a4 = rng.jumps(1.2345); Stream a5 = rng.jumps(5L, 1.2345); } static void coverOf(String name) { coverRandomGenerator(RandomGenerator.of(name)); coverFactory(RandomGeneratorFactory.of(name)); } static void coverFactory(RandomGeneratorFactory factory) { String name = factory.name(); String group = factory.group(); int stateBits = factory.stateBits(); int equidistribution = factory.equidistribution(); BigInteger period = factory.period(); boolean isStatistical = factory.isStatistical(); boolean isStochastic = factory.isStochastic(); boolean isHardware = factory.isHardware(); boolean isArbitrarilyJumpable = factory.isArbitrarilyJumpable(); boolean isJumpable = factory.isJumpable(); boolean isLeapable = factory.isLeapable(); boolean isSplittable = factory.isSplittable(); coverRandomGenerator(factory.create()); // test create(long) switch (factory.name()) { // SecureRandom doesn't have long constructors so we expect // UnsupportedOperationException case "SecureRandom" -> { try { factory.create(12345L); throw new AssertionError("RandomGeneratorFactory.create(long) was expected" + "to throw UnsupportedOperationException for " + factory.name() + " but didn't"); } catch (UnsupportedOperationException ignored) { } } default -> coverRandomGenerator(factory.create(12345L)); } // test create(byte[]) switch (factory.name()) { // these don't have byte[] constructors so we expect UnsupportedOperationException case "Random", "SplittableRandom" -> { try { factory.create(new byte[] {1, 2, 3, 4, 5, 6, 7, 8}); throw new AssertionError("RandomGeneratorFactory.create(byte[]) was expected" + "to throw UnsupportedOperationException for " + factory.name() + " but didn't"); } catch (UnsupportedOperationException ignored) { } } default -> coverRandomGenerator(factory.create(new byte[] {1, 2, 3, 4, 5, 6, 7, 8})); } } static void coverDefaults() { RandomGeneratorFactory factory = RandomGeneratorFactory.getDefault(); RandomGenerator rng = RandomGenerator.getDefault(); } public static void main(String[] args) throws Throwable { RandomGeneratorFactory.all() .forEach(factory -> { coverFactory(factory); coverOf(factory.name()); }); RandomGeneratorFactory.all() .filter(RandomGeneratorFactory::isStreamable) .forEach(factory -> { coverStreamable((StreamableGenerator)factory.create()); }); RandomGeneratorFactory.all() .filter(RandomGeneratorFactory::isSplittable) .forEach(factory -> { coverSplittable((SplittableGenerator)factory.create()); }); RandomGeneratorFactory.all() .filter(RandomGeneratorFactory::isJumpable) .forEach(factory -> { coverJumpable((JumpableGenerator)factory.create()); }); RandomGeneratorFactory.all() .filter(RandomGeneratorFactory::isLeapable) .forEach(factory -> { coverLeapable((LeapableGenerator)factory.create()); }); RandomGeneratorFactory.all() .filter(RandomGeneratorFactory::isArbitrarilyJumpable) .forEach(factory -> { coverArbitrarilyJumpable((ArbitrarilyJumpableGenerator)factory.create()); }); RandomGeneratorFactory.all() .forEach(RandomTestCoverage::checkPredicates); coverRandomGenerator(new SecureRandom()); coverRandomGenerator(ThreadLocalRandom.current()); coverDefaults(); } }