diff --git a/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java b/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java index 7095c7b2c2acf..030f7f70a0a4b 100644 --- a/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java +++ b/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java @@ -126,6 +126,7 @@ private record RandomGeneratorProperties( int equidistribution, int flags) { + /* single bit masks composable with operator | */ private static final int INSTANTIABLE = 1 << 0; private static final int LONG_SEED = 1 << 1; private static final int BYTE_ARRAY_SEED = 1 << 2; @@ -139,11 +140,11 @@ private record RandomGeneratorProperties( /** * Returns the factory map, lazily constructing it on first use. - *

- * Although {@link ThreadLocalRandom} can only be accessed via + *

Although {@link ThreadLocalRandom} can only be accessed via * {@link ThreadLocalRandom#current()}, a map entry is added nevertheless * to record its properties that are otherwise not documented * anywhere else. + *

Currently, no algorithm is deprecated. * * @return Map of RandomGeneratorProperties. */ @@ -151,13 +152,13 @@ private static Map createFactoryMap() { return Map.ofEntries( entry(SecureRandom.class, "SecureRandom", "Legacy", 0, 0, 0, Integer.MAX_VALUE, - INSTANTIABLE | BYTE_ARRAY_SEED | STOCHASTIC), + INSTANTIABLE | BYTE_ARRAY_SEED | STOCHASTIC | deprecationBit(SecureRandom.class)), entry(Random.class, "Random", "Legacy", 48, 0, 0, 0, - INSTANTIABLE | LONG_SEED), + INSTANTIABLE | LONG_SEED | deprecationBit(Random.class)), entry(SplittableRandom.class, "SplittableRandom", "Legacy", 64, 0, 0, 1, - INSTANTIABLE | LONG_SEED), + INSTANTIABLE | LONG_SEED | deprecationBit(SplittableRandom.class)), entry(L32X64MixRandom.class, "L32X64MixRandom", "LXM", 64, 1, 32, 1, ALL_CONSTRUCTORS), @@ -190,7 +191,7 @@ private static Map createFactoryMap() { ALL_CONSTRUCTORS), entry(ThreadLocalRandom.class, "ThreadLocalRandom", "Legacy", 64, 0, 0, 1, - 0) + deprecationBit(ThreadLocalRandom.class)) ); } @@ -201,7 +202,11 @@ private static Map.Entry entry( return Map.entry(name, new RandomGeneratorProperties(rgClass, name, group, i, j, k, equidistribution, - flags | (rgClass.isAnnotationPresent(Deprecated.class) ? DEPRECATED : 0))); + flags)); + } + + private static int deprecationBit(Class rgClass) { + return rgClass.isAnnotationPresent(Deprecated.class) ? DEPRECATED : 0; } private RandomGenerator create() { diff --git a/test/jdk/java/util/Random/RandomTestCoverage.java b/test/jdk/java/util/Random/RandomTestCoverage.java index cc9fe01cf450e..a0e906fbbe2a1 100644 --- a/test/jdk/java/util/Random/RandomTestCoverage.java +++ b/test/jdk/java/util/Random/RandomTestCoverage.java @@ -87,7 +87,7 @@ static void coverRandomGenerator(RandomGenerator rng) { DoubleStream doubleStream4 = rng.doubles(5, 0.5, 1.0); } - static void checkPredicates(RandomGeneratorFactory factory) { + static void checkPredicates(RandomGeneratorFactory factory) { RandomGenerator rng = factory.create(); if (rng instanceof ArbitrarilyJumpableGenerator != factory.isArbitrarilyJumpable()) { throw new RuntimeException("isArbitrarilyJumpable failing"); @@ -156,7 +156,7 @@ static void coverOf(String name) { coverFactory(RandomGeneratorFactory.of(name)); } - static void coverFactory(RandomGeneratorFactory factory) { + static void coverFactory(RandomGeneratorFactory factory) { String name = factory.name(); String group = factory.group(); int stateBits = factory.stateBits(); @@ -171,24 +171,33 @@ static void coverFactory(RandomGeneratorFactory factory) { boolean isSplittable = factory.isSplittable(); coverRandomGenerator(factory.create()); - RandomGenerator rng; - - rng = null; - try { - rng = factory.create(12345L); - } catch (UnsupportedOperationException ignore) { - } - if (rng != null) { - coverRandomGenerator(rng); + // 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)); } - - rng = null; - try { - rng = factory.create(new byte[] {1, 2, 3, 4, 5, 6, 7, 8}); - } catch (UnsupportedOperationException ignore) { - } - if (rng != null) { - coverRandomGenerator(rng); + // 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})); } } @@ -205,32 +214,35 @@ public static void main(String[] args) throws Throwable { coverOf(factory.name()); }); RandomGeneratorFactory.all() - .filter(f -> f.isStreamable()) + .filter(RandomGeneratorFactory::isStreamable) .forEach(factory -> { coverStreamable((StreamableGenerator)factory.create()); }); RandomGeneratorFactory.all() - .filter(f -> f.isSplittable()) + .filter(RandomGeneratorFactory::isSplittable) .forEach(factory -> { coverSplittable((SplittableGenerator)factory.create()); }); RandomGeneratorFactory.all() - .filter(f -> f.isJumpable()) + .filter(RandomGeneratorFactory::isJumpable) .forEach(factory -> { coverJumpable((JumpableGenerator)factory.create()); }); RandomGeneratorFactory.all() - .filter(f -> f.isLeapable()) + .filter(RandomGeneratorFactory::isLeapable) .forEach(factory -> { coverLeapable((LeapableGenerator)factory.create()); }); RandomGeneratorFactory.all() - .filter(f -> f.isArbitrarilyJumpable()) + .filter(RandomGeneratorFactory::isArbitrarilyJumpable) .forEach(factory -> { coverArbitrarilyJumpable((ArbitrarilyJumpableGenerator)factory.create()); }); + RandomGeneratorFactory.all() + .forEach(RandomTestCoverage::checkPredicates); coverRandomGenerator(new SecureRandom()); coverRandomGenerator(ThreadLocalRandom.current()); + coverDefaults(); } }