Skip to content

Commit

Permalink
Rely on Deprecated annotation only for legacy generators.
Browse files Browse the repository at this point in the history
  • Loading branch information
rgiulietti committed May 16, 2024
1 parent 920655a commit a77146f
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -139,25 +140,25 @@ private record RandomGeneratorProperties(

/**
* Returns the factory map, lazily constructing it on first use.
* <p>
* Although {@link ThreadLocalRandom} can only be accessed via
* <p> 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.
* <p> Currently, no algorithm is deprecated.
*
* @return Map of RandomGeneratorProperties.
*/
private static Map<String, RandomGeneratorProperties> 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),
Expand Down Expand Up @@ -190,7 +191,7 @@ private static Map<String, RandomGeneratorProperties> createFactoryMap() {
ALL_CONSTRUCTORS),
entry(ThreadLocalRandom.class, "ThreadLocalRandom", "Legacy",
64, 0, 0, 1,
0)
deprecationBit(ThreadLocalRandom.class))
);
}

Expand All @@ -201,7 +202,11 @@ private static Map.Entry<String, RandomGeneratorProperties> 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<? extends RandomGenerator> rgClass) {
return rgClass.isAnnotationPresent(Deprecated.class) ? DEPRECATED : 0;
}

private RandomGenerator create() {
Expand Down
60 changes: 36 additions & 24 deletions test/jdk/java/util/Random/RandomTestCoverage.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<RandomGenerator> factory) {
RandomGenerator rng = factory.create();
if (rng instanceof ArbitrarilyJumpableGenerator != factory.isArbitrarilyJumpable()) {
throw new RuntimeException("isArbitrarilyJumpable failing");
Expand Down Expand Up @@ -156,7 +156,7 @@ static void coverOf(String name) {
coverFactory(RandomGeneratorFactory.of(name));
}

static void coverFactory(RandomGeneratorFactory factory) {
static void coverFactory(RandomGeneratorFactory<RandomGenerator> factory) {
String name = factory.name();
String group = factory.group();
int stateBits = factory.stateBits();
Expand All @@ -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}));
}
}

Expand All @@ -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();
}
}

0 comments on commit a77146f

Please sign in to comment.