undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
87
test/jdk/java/util/Random/DistinctSeeds.java
Normal file
87
test/jdk/java/util/Random/DistinctSeeds.java
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4949279 6937857
|
||||
* @summary Independent instantiations of Random() have distinct seeds.
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class DistinctSeeds {
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Strictly speaking, it is possible for these to randomly fail,
|
||||
// but the probability should be small (approximately 2**-48).
|
||||
if (new Random().nextLong() == new Random().nextLong() ||
|
||||
new Random().nextLong() == new Random().nextLong())
|
||||
throw new RuntimeException("Random() seeds not unique.");
|
||||
|
||||
// Now try generating seeds concurrently
|
||||
class RandomCollector implements Runnable {
|
||||
long[] randoms = new long[1<<17];
|
||||
public void run() {
|
||||
for (int i = 0; i < randoms.length; i++)
|
||||
randoms[i] = new Random().nextLong();
|
||||
}
|
||||
}
|
||||
final int threadCount = 2;
|
||||
List<RandomCollector> collectors = new ArrayList<>();
|
||||
List<Thread> threads = new ArrayList<>();
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
RandomCollector r = new RandomCollector();
|
||||
collectors.add(r);
|
||||
threads.add(new Thread(r));
|
||||
}
|
||||
for (Thread thread : threads)
|
||||
thread.start();
|
||||
for (Thread thread : threads)
|
||||
thread.join();
|
||||
int collisions = 0;
|
||||
HashSet<Long> s = new HashSet<>();
|
||||
for (RandomCollector r : collectors) {
|
||||
for (long x : r.randoms) {
|
||||
if (s.contains(x))
|
||||
collisions++;
|
||||
s.add(x);
|
||||
}
|
||||
}
|
||||
System.out.printf("collisions=%d%n", collisions);
|
||||
if (collisions > 10)
|
||||
throw new Error("too many collisions");
|
||||
}
|
||||
}
|
||||
349
test/jdk/java/util/Random/EquiDoublesTest.java
Normal file
349
test/jdk/java/util/Random/EquiDoublesTest.java
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
/*
|
||||
* Copyright (c) 2023, 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 jdk.test.lib.RandomFactory;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeSet;
|
||||
import java.util.random.RandomGenerator;
|
||||
import java.util.stream.DoubleStream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8302987
|
||||
* @key randomness
|
||||
*
|
||||
* @summary Check consistency of RandomGenerator::equiDoubles
|
||||
* @library /test/lib
|
||||
* @run junit EquiDoublesTest
|
||||
*
|
||||
*/
|
||||
|
||||
public class EquiDoublesTest {
|
||||
|
||||
private static final int SAMPLES = 100_000;
|
||||
|
||||
/*
|
||||
* A factor to use in the tight*() tests to make sure that
|
||||
* all equidistant doubles are generated.
|
||||
*/
|
||||
private static final long SAFETY_FACTOR = 100L;
|
||||
private static final RandomGenerator rnd = RandomFactory.getRandom();
|
||||
|
||||
private static double nextUp(double d, int steps) {
|
||||
for (int i = 0; i < steps; ++i) {
|
||||
d = Math.nextUp(d);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
private static double nextDown(double d, int steps) {
|
||||
for (int i = 0; i < steps; ++i) {
|
||||
d = Math.nextDown(d);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
static Arguments[] equi() {
|
||||
return new Arguments[] {
|
||||
arguments(0.0, 1e-9),
|
||||
arguments(1.0, 1.1),
|
||||
arguments(1.0e23, 1.1e23),
|
||||
arguments(1.0e300, 1.1e300),
|
||||
arguments(-1.2, 1.1),
|
||||
arguments(-1.2e-30, 1.1e6),
|
||||
arguments(-Double.MIN_VALUE, Double.MIN_VALUE),
|
||||
arguments(-Double.MAX_VALUE, Double.MAX_VALUE),
|
||||
};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource
|
||||
void equi(double l, double r) {
|
||||
double[] minmax = new double[2];
|
||||
|
||||
resetMinmax(minmax);
|
||||
DoubleStream equi = rnd.equiDoubles(l, r, true, false);
|
||||
equi.limit(SAMPLES).forEach(d -> updateMinmax(minmax, d));
|
||||
assertTrue(l <= minmax[0]);
|
||||
assertTrue(minmax[1] < r);
|
||||
|
||||
resetMinmax(minmax);
|
||||
equi = rnd.equiDoubles(l, r, true, true);
|
||||
equi.limit(SAMPLES).forEach(d -> updateMinmax(minmax, d));
|
||||
assertTrue(l <= minmax[0]);
|
||||
assertTrue(minmax[1] <= r);
|
||||
|
||||
resetMinmax(minmax);
|
||||
equi = rnd.equiDoubles(l, r, false, true);
|
||||
equi.limit(SAMPLES).forEach(d -> updateMinmax(minmax, d));
|
||||
assertTrue(l < minmax[0]);
|
||||
assertTrue(minmax[1] <= r);
|
||||
|
||||
resetMinmax(minmax);
|
||||
equi = rnd.equiDoubles(l, r, false, false);
|
||||
equi.limit(SAMPLES).forEach(d -> updateMinmax(minmax, d));
|
||||
assertTrue(l < minmax[0]);
|
||||
assertTrue(minmax[1] < r);
|
||||
|
||||
/* with negated intervals */
|
||||
resetMinmax(minmax);
|
||||
equi = rnd.equiDoubles(-r, -l, true, false);
|
||||
equi.limit(SAMPLES).forEach(d -> updateMinmax(minmax, d));
|
||||
assertTrue(-r <= minmax[0]);
|
||||
assertTrue(minmax[1] < -l);
|
||||
|
||||
resetMinmax(minmax);
|
||||
equi = rnd.equiDoubles(-r, -l, true, true);
|
||||
equi.limit(SAMPLES).forEach(d -> updateMinmax(minmax, d));
|
||||
assertTrue(-r <= minmax[0]);
|
||||
assertTrue(minmax[1] <= -l);
|
||||
|
||||
resetMinmax(minmax);
|
||||
equi = rnd.equiDoubles(-r, -l, false, true);
|
||||
equi.limit(SAMPLES).forEach(d -> updateMinmax(minmax, d));
|
||||
assertTrue(-r < minmax[0]);
|
||||
assertTrue(minmax[1] <= -l);
|
||||
|
||||
resetMinmax(minmax);
|
||||
equi = rnd.equiDoubles(-r, -l, false, false);
|
||||
equi.limit(SAMPLES).forEach(d -> updateMinmax(minmax, d));
|
||||
assertTrue(-r < minmax[0]);
|
||||
assertTrue(minmax[1] < -l);
|
||||
}
|
||||
|
||||
private void resetMinmax(double[] minmax) {
|
||||
minmax[0] = Double.POSITIVE_INFINITY;
|
||||
minmax[1] = Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
||||
private void updateMinmax(double[] minmax, double d) {
|
||||
if (d < minmax[0]) {
|
||||
minmax[0] = d;
|
||||
}
|
||||
if (d > minmax[1]) {
|
||||
minmax[1] = d;
|
||||
}
|
||||
}
|
||||
|
||||
static Arguments[] tight() {
|
||||
return new Arguments[] {
|
||||
arguments(0.0, (short) 100),
|
||||
arguments(1.0, (short) 100),
|
||||
arguments(1.1, (short) 100),
|
||||
arguments(1.0e23, (short) 100),
|
||||
arguments(1.0e300, (short) 100),
|
||||
arguments(-1.2, (short) 100),
|
||||
arguments(-1.2e-30, (short) 100),
|
||||
arguments(-Double.MIN_VALUE, (short) 100),
|
||||
|
||||
arguments(-Double.MIN_VALUE, (short) 2),
|
||||
arguments(-Double.MAX_VALUE, (short) 2),
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* All equidistant doubles in a tight range are expected to be generated.
|
||||
* The arguments must be chosen as to not overlap a value with irregular
|
||||
* spacing around it.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource
|
||||
void tight(double l, short steps) {
|
||||
double r = nextUp(l, steps);
|
||||
|
||||
TreeSet<Double> set = new TreeSet<>();
|
||||
DoubleStream equi = rnd.equiDoubles(l, r, true, false);
|
||||
equi.limit(SAFETY_FACTOR * steps).forEach(set::add);
|
||||
assertEquals(steps, set.size());
|
||||
checkEquidistance(set);
|
||||
|
||||
set.clear();
|
||||
equi = rnd.equiDoubles(l, r, true, true);
|
||||
equi.limit(SAFETY_FACTOR * steps).forEach(set::add);
|
||||
assertEquals(steps + 1, set.size());
|
||||
checkEquidistance(set);
|
||||
|
||||
set.clear();
|
||||
equi = rnd.equiDoubles(l, r, false, true);
|
||||
equi.limit(SAFETY_FACTOR * steps).forEach(set::add);
|
||||
assertEquals(steps, set.size());
|
||||
checkEquidistance(set);
|
||||
|
||||
set.clear();
|
||||
equi = rnd.equiDoubles(l, r, false, false);
|
||||
equi.limit(SAFETY_FACTOR * steps).forEach(set::add);
|
||||
assertEquals(steps - 1, set.size());
|
||||
checkEquidistance(set);
|
||||
|
||||
/* with negated intervals */
|
||||
set.clear();
|
||||
equi = rnd.equiDoubles(-r, -l, true, true);
|
||||
equi.limit(SAFETY_FACTOR * steps).forEach(set::add);
|
||||
assertEquals(steps + 1, set.size());
|
||||
checkEquidistance(set);
|
||||
|
||||
set.clear();
|
||||
equi = rnd.equiDoubles(-r, -l, true, true);
|
||||
equi.limit(SAFETY_FACTOR * steps).forEach(set::add);
|
||||
assertEquals(steps + 1, set.size());
|
||||
checkEquidistance(set);
|
||||
|
||||
set.clear();
|
||||
equi = rnd.equiDoubles(-r, -l, false, true);
|
||||
equi.limit(SAFETY_FACTOR * steps).forEach(set::add);
|
||||
assertEquals(steps, set.size());
|
||||
checkEquidistance(set);
|
||||
|
||||
set.clear();
|
||||
equi = rnd.equiDoubles(-r, -l, false, false);
|
||||
equi.limit(SAFETY_FACTOR * steps).forEach(set::add);
|
||||
assertEquals(steps - 1, set.size());
|
||||
checkEquidistance(set);
|
||||
}
|
||||
|
||||
static Arguments[] tightWithIrregularSpacing() {
|
||||
return new Arguments[] {
|
||||
arguments(0x1p-1, (short) 15, (short) 23),
|
||||
arguments(0x1p0, (short) 17, (short) 5),
|
||||
arguments(0x1p1, (short) 7, (short) 8),
|
||||
arguments(0x1p-600, (short) 28, (short) 33),
|
||||
arguments(0x1p600, (short) 9, (short) 19),
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* m must be a power of 2 greater than Double.MIN_NORMAL
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource
|
||||
void tightWithIrregularSpacing(double m, short lSteps, short rSteps) {
|
||||
double l = nextDown(m, 2 * lSteps);
|
||||
double r = nextUp(m, rSteps);
|
||||
int steps = lSteps + rSteps;
|
||||
|
||||
TreeSet<Double> set = new TreeSet<>();
|
||||
DoubleStream equi = rnd.equiDoubles(l, r, true, false);
|
||||
equi.limit(SAFETY_FACTOR * steps).forEach(set::add);
|
||||
assertEquals(steps, set.size());
|
||||
checkEquidistance(set);
|
||||
|
||||
set.clear();
|
||||
equi = rnd.equiDoubles(l, r, true, true);
|
||||
equi.limit(SAFETY_FACTOR * steps).forEach(set::add);
|
||||
assertEquals(steps + 1, set.size());
|
||||
checkEquidistance(set);
|
||||
|
||||
set.clear();
|
||||
equi = rnd.equiDoubles(l, r, false, true);
|
||||
equi.limit(SAFETY_FACTOR * steps).forEach(set::add);
|
||||
assertEquals(steps, set.size());
|
||||
checkEquidistance(set);
|
||||
|
||||
set.clear();
|
||||
equi = rnd.equiDoubles(l, r, false, false);
|
||||
equi.limit(SAFETY_FACTOR * steps).forEach(set::add);
|
||||
assertEquals(steps - 1, set.size());
|
||||
checkEquidistance(set);
|
||||
|
||||
/* with negated intervals */
|
||||
set.clear();
|
||||
equi = rnd.equiDoubles(-r, -l, true, true);
|
||||
equi.limit(SAFETY_FACTOR * steps).forEach(set::add);
|
||||
assertEquals(steps + 1, set.size());
|
||||
checkEquidistance(set);
|
||||
|
||||
set.clear();
|
||||
equi = rnd.equiDoubles(-r, -l, true, true);
|
||||
equi.limit(SAFETY_FACTOR * steps).forEach(set::add);
|
||||
assertEquals(steps + 1, set.size());
|
||||
checkEquidistance(set);
|
||||
|
||||
set.clear();
|
||||
equi = rnd.equiDoubles(-r, -l, false, true);
|
||||
equi.limit(SAFETY_FACTOR * steps).forEach(set::add);
|
||||
assertEquals(steps, set.size());
|
||||
checkEquidistance(set);
|
||||
|
||||
set.clear();
|
||||
equi = rnd.equiDoubles(-r, -l, false, false);
|
||||
equi.limit(SAFETY_FACTOR * steps).forEach(set::add);
|
||||
assertEquals(steps - 1, set.size());
|
||||
checkEquidistance(set);
|
||||
}
|
||||
|
||||
private void checkEquidistance(TreeSet<Double> set) {
|
||||
if (set.size() < 3) {
|
||||
return;
|
||||
}
|
||||
Iterator<Double> iter = set.iterator();
|
||||
double prev = iter.next();
|
||||
double curr = iter.next();
|
||||
double delta = curr - prev;
|
||||
while (iter.hasNext()) {
|
||||
prev = curr;
|
||||
curr = iter.next();
|
||||
assertEquals(delta, curr - prev);
|
||||
}
|
||||
}
|
||||
|
||||
static Arguments[] empty() {
|
||||
return new Arguments[] {
|
||||
arguments(1.0),
|
||||
arguments(-1.0),
|
||||
arguments(0.0),
|
||||
arguments(nextDown(Double.MAX_VALUE, 1)),
|
||||
arguments(nextUp(-Double.MAX_VALUE, 1)),
|
||||
};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource
|
||||
void empty(double l) {
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> rnd.equiDoubles(l, l, true, false)
|
||||
);
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> rnd.equiDoubles(l, nextUp(l, 1), false, false)
|
||||
);
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> rnd.equiDoubles(nextDown(l, 1), l, false, false)
|
||||
);
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> rnd.equiDoubles(l, l, false, true)
|
||||
);
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> rnd.equiDoubles(l, nextDown(l, 1), true, true)
|
||||
);
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> rnd.equiDoubles(nextUp(l, 1), l, true, true)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
51
test/jdk/java/util/Random/LXMRandomWithSeed.java
Normal file
51
test/jdk/java/util/Random/LXMRandomWithSeed.java
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2022, 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.util.random.RandomGeneratorFactory;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Check that the (byte[]) constructors do not throw (see bug report)
|
||||
* @bug 8283083
|
||||
*/
|
||||
|
||||
public class LXMRandomWithSeed {
|
||||
|
||||
public static void main(String[] args) {
|
||||
byte[] seed = new byte[0x100];
|
||||
for (var i = 0; i < seed.length; ++i) {
|
||||
seed[i] = (byte) i;
|
||||
}
|
||||
var lxmFactories = RandomGeneratorFactory.all()
|
||||
.filter(factory -> factory.group().equals("LXM"))
|
||||
.toList();
|
||||
for (var lxmFactory : lxmFactories) {
|
||||
var lxmGen0 = lxmFactory.create(seed);
|
||||
var lxmGen1 = lxmFactory.create(seed);
|
||||
if (lxmGen0.nextLong() != lxmGen1.nextLong()) {
|
||||
throw new RuntimeException("%s(byte[]) is incorrect".formatted(lxmFactory.name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
62
test/jdk/java/util/Random/NextBytes.java
Normal file
62
test/jdk/java/util/Random/NextBytes.java
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4261170
|
||||
* @summary Tests for Random.nextBytes
|
||||
* @author Martin Buchholz
|
||||
*/
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
public class NextBytes {
|
||||
private static void realMain(String[] args) throws Throwable {
|
||||
byte[] expected = new byte[]
|
||||
{27, -105, -24, 83, -77, -29, 119, -74, -106, 68, 54};
|
||||
Random r = new java.util.Random(2398579034L);
|
||||
for (int i = 0; i <= expected.length; i++) {
|
||||
r.setSeed(2398579034L);
|
||||
byte[] actual = new byte[i];
|
||||
r.nextBytes(actual);
|
||||
//System.out.println(Arrays.toString(actual));
|
||||
check(Arrays.equals(actual, Arrays.copyOf(expected,i)));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
static volatile int passed = 0, failed = 0;
|
||||
static void pass() {passed++;}
|
||||
static void fail() {failed++; Thread.dumpStack();}
|
||||
static void fail(String msg) {System.out.println(msg); fail();}
|
||||
static void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
static void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
static void equal(Object x, Object y) {
|
||||
if (x == null ? y == null : x.equals(y)) pass();
|
||||
else fail(x + " not equal to " + y);}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
try {realMain(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
}
|
||||
42
test/jdk/java/util/Random/NextIntPowerOfTwoMod.java
Normal file
42
test/jdk/java/util/Random/NextIntPowerOfTwoMod.java
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4187412
|
||||
* @summary The FCS release of 1.2 did not special case the Random.nextInt
|
||||
* calculation for a power of two modulus, as mandated by the spec.
|
||||
*/
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class NextIntPowerOfTwoMod {
|
||||
public static void main(String[] args) throws Exception {
|
||||
Random r = new Random(69);
|
||||
int total = 0;
|
||||
for (int i=0; i<1000; i++)
|
||||
total += r.nextInt(16);
|
||||
if (total != 7639)
|
||||
throw new RuntimeException("Not using correct algorithm.");
|
||||
}
|
||||
}
|
||||
79
test/jdk/java/util/Random/RandomCanaryPi.java
Normal file
79
test/jdk/java/util/Random/RandomCanaryPi.java
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 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.util.Comparator;
|
||||
import java.util.random.RandomGenerator;
|
||||
import java.util.random.RandomGenerator.*;
|
||||
import java.util.random.RandomGeneratorFactory;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary test bit sequences produced by clases that implement interface RandomGenerator
|
||||
* @bug 8248862
|
||||
* @run main RandomCanaryPi
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
public class RandomCanaryPi {
|
||||
static double pi(RandomGenerator rng) {
|
||||
int N = 10000000;
|
||||
int k = 0;
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
double x = rng.nextDouble();
|
||||
double y = rng.nextDouble();
|
||||
|
||||
if (x * x + y * y <= 1.0) {
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
return 4.0 * (double)k / (double)N;
|
||||
}
|
||||
|
||||
static int failed = 0;
|
||||
|
||||
public static void main(String[] args) {
|
||||
RandomGeneratorFactory.all()
|
||||
.sorted(Comparator.comparing(RandomGeneratorFactory::name))
|
||||
.forEach(factory -> {
|
||||
RandomGenerator rng = factory.create();
|
||||
double pi = pi(rng);
|
||||
double delta = Math.abs(Math.PI - pi);
|
||||
boolean pass = delta < 1E-2;
|
||||
|
||||
if (!pass) {
|
||||
System.err.println("Algorithm = " + factory.name() + " failed");
|
||||
System.err.println("Actual = " + Math.PI);
|
||||
System.err.println("Monte Carlo = " + pi);
|
||||
System.err.println("Delta = " + delta);
|
||||
System.err.println();
|
||||
|
||||
failed++;
|
||||
}
|
||||
});
|
||||
if (failed != 0) {
|
||||
throw new RuntimeException(failed + " tests failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
58
test/jdk/java/util/Random/RandomExponentialTest.java
Normal file
58
test/jdk/java/util/Random/RandomExponentialTest.java
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2022, 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 jdk.test.lib.RandomFactory;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Check that nextExponential() returns non-negative outcomes
|
||||
* @bug 8284866
|
||||
*
|
||||
* @key randomness
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.RandomFactory
|
||||
* @run main RandomExponentialTest
|
||||
*/
|
||||
|
||||
public class RandomExponentialTest {
|
||||
|
||||
private static final int SAMPLES = 1_000_000_000;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
var errCount = 0;
|
||||
var errSample = Double.NaN;
|
||||
var random = RandomFactory.getRandom();
|
||||
for (int i = 0; i < SAMPLES; i++) {
|
||||
var expVal = random.nextExponential();
|
||||
if (!(expVal >= 0.0)) {
|
||||
errCount += 1;
|
||||
errSample = expVal;
|
||||
}
|
||||
}
|
||||
if (errCount > 0) {
|
||||
throw new RuntimeException("%d errors out of %d samples: e.g., %f"
|
||||
.formatted(errCount, SAMPLES, errSample));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
124
test/jdk/java/util/Random/RandomNextDoubleBoundary.java
Normal file
124
test/jdk/java/util/Random/RandomNextDoubleBoundary.java
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (c) 2022, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Verify nextDouble stays within range
|
||||
* @bug 8280550 8280950 8281183 8202449
|
||||
*
|
||||
* @key randomness
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.RandomFactory
|
||||
* @run main RandomNextDoubleBoundary
|
||||
|
||||
*/
|
||||
|
||||
import java.util.SplittableRandom;
|
||||
import java.util.random.RandomGenerator;
|
||||
import jdk.test.lib.RandomFactory;
|
||||
|
||||
public class RandomNextDoubleBoundary {
|
||||
public static void main(String... args) {
|
||||
negativeBounds();
|
||||
positiveBounds();
|
||||
nextDoubleHugeRange();
|
||||
}
|
||||
|
||||
private static void negativeBounds() {
|
||||
// Both bounds are negative
|
||||
double lowerBound = -1.0000000000000002;
|
||||
double upperBound = -1.0;
|
||||
var sr = new SplittableRandom(42L);
|
||||
var r = sr.nextDouble(lowerBound, upperBound);
|
||||
|
||||
if (r >= upperBound) {
|
||||
System.err.println("r = " + r + "\t" + Double.toHexString(r));
|
||||
System.err.println("ub = " + upperBound + "\t" + Double.toHexString(upperBound));
|
||||
throw new RuntimeException("Greater than upper bound");
|
||||
}
|
||||
|
||||
if (r < lowerBound) {
|
||||
System.err.println("r = " + r + "\t" + Double.toHexString(r));
|
||||
System.err.println("lb = " + lowerBound + "\t" + Double.toHexString(lowerBound));
|
||||
throw new RuntimeException("Less than lower bound");
|
||||
}
|
||||
}
|
||||
|
||||
private static void positiveBounds() {
|
||||
double[][] originAndBounds = {{10, 100},
|
||||
{12345, 123456},
|
||||
{5432167.234, 54321678.1238}};
|
||||
for (double[] originAndBound : originAndBounds) {
|
||||
nextDoublesWithRange(originAndBound[0], originAndBound[1]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void nextDoublesWithRange(double origin, double bound) {
|
||||
RandomGenerator rg = new RandomGenerator() {
|
||||
@Override
|
||||
public double nextDouble() {
|
||||
return Double.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long nextLong() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
double value = rg.nextDouble(origin, bound);
|
||||
|
||||
if (bound > 0) {
|
||||
value = rg.nextDouble(bound); // Equivalent to nextDouble(0.0, bound)
|
||||
assertTrue(value >= 0.0);
|
||||
assertTrue(value < bound);
|
||||
}
|
||||
}
|
||||
|
||||
public static void nextDoubleHugeRange() {
|
||||
var random = RandomFactory.getRandom();
|
||||
var n = 100_000;
|
||||
|
||||
var origin = -(3.0 / 4.0) * Double.MAX_VALUE;
|
||||
var bound = (3.0 / 4.0) * Double.MAX_VALUE;
|
||||
assertTrue(bound - origin == Double.POSITIVE_INFINITY);
|
||||
|
||||
/* all are within [origin, bound) */
|
||||
assertTrue(random.doubles(n, origin, bound)
|
||||
.allMatch(d -> origin <= d && d < bound));
|
||||
|
||||
/* some are near the origin */
|
||||
assertTrue(random.doubles(n, origin, bound)
|
||||
.anyMatch(d -> d < (15.0 / 16.0) * origin));
|
||||
|
||||
/* some are near the bound */
|
||||
assertTrue(random.doubles(n, origin, bound)
|
||||
.anyMatch(d -> d > (15.0 / 16.0) * bound));
|
||||
}
|
||||
|
||||
public static void assertTrue(boolean condition) {
|
||||
if (!condition) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
162
test/jdk/java/util/Random/RandomStreamTest.java
Normal file
162
test/jdk/java/util/Random/RandomStreamTest.java
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, 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 org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @run testng RandomStreamTest
|
||||
* @summary test stream methods on Random
|
||||
* @author Brian Goetz
|
||||
* @key randomness
|
||||
*/
|
||||
public class RandomStreamTest {
|
||||
|
||||
private static final int SIZE = 1000;
|
||||
|
||||
@DataProvider(name = "suppliers")
|
||||
public Object[][] randomSuppliers() {
|
||||
return new Object[][] {
|
||||
{new Random(), SIZE},
|
||||
{new SecureRandom(), SIZE}
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "suppliers")
|
||||
public void testRandomIntStream(final Random random, final int count) {
|
||||
final List<Integer> destination = new ArrayList<>(count);
|
||||
random.ints().limit(count).forEach(destination::add);
|
||||
assertEquals(destination.size(), count);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "suppliers")
|
||||
public void testRandomLongStream(final Random random, final int count) {
|
||||
final List<Long> destination = new ArrayList<>(count);
|
||||
random.longs().limit(count).forEach(destination::add);
|
||||
assertEquals(destination.size(), count);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "suppliers")
|
||||
public void testRandomDoubleStream(final Random random, final int count) {
|
||||
final List<Double> destination = new ArrayList<>(count);
|
||||
random.doubles().limit(count).forEach(destination::add);
|
||||
random.doubles().limit(count).forEach(d -> assertTrue(d >= 0.0 && d < 1.0));
|
||||
assertEquals(destination.size(), count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntStream() {
|
||||
final long seed = System.currentTimeMillis();
|
||||
final Random r1 = new Random(seed);
|
||||
final int[] a = new int[SIZE];
|
||||
for (int i=0; i < SIZE; i++) {
|
||||
a[i] = r1.nextInt();
|
||||
}
|
||||
|
||||
final Random r2 = new Random(seed); // same seed
|
||||
final int[] b = r2.ints().limit(SIZE).toArray();
|
||||
assertEquals(a, b);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongStream() {
|
||||
final long seed = System.currentTimeMillis();
|
||||
final Random r1 = new Random(seed);
|
||||
final long[] a = new long[SIZE];
|
||||
for (int i=0; i < SIZE; i++) {
|
||||
a[i] = r1.nextLong();
|
||||
}
|
||||
|
||||
final Random r2 = new Random(seed); // same seed
|
||||
final long[] b = r2.longs().limit(SIZE).toArray();
|
||||
assertEquals(a, b);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoubleStream() {
|
||||
final long seed = System.currentTimeMillis();
|
||||
final Random r1 = new Random(seed);
|
||||
final double[] a = new double[SIZE];
|
||||
for (int i=0; i < SIZE; i++) {
|
||||
a[i] = r1.nextDouble();
|
||||
}
|
||||
|
||||
final Random r2 = new Random(seed); // same seed
|
||||
final double[] b = r2.doubles().limit(SIZE).toArray();
|
||||
assertEquals(a, b);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThreadLocalIntStream() throws InterruptedException, ExecutionException, TimeoutException {
|
||||
ThreadLocalRandom tlr = ThreadLocalRandom.current();
|
||||
testRandomResultSupplierConcurrently(() -> tlr.ints().limit(SIZE).boxed().collect(toList()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThreadLocalLongStream() throws InterruptedException, ExecutionException, TimeoutException {
|
||||
ThreadLocalRandom tlr = ThreadLocalRandom.current();
|
||||
testRandomResultSupplierConcurrently(() -> tlr.longs().limit(SIZE).boxed().collect(toList()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThreadLocalDoubleStream() throws InterruptedException, ExecutionException, TimeoutException {
|
||||
ThreadLocalRandom tlr = ThreadLocalRandom.current();
|
||||
testRandomResultSupplierConcurrently(() -> tlr.doubles().limit(SIZE).boxed().collect(toList()));
|
||||
}
|
||||
|
||||
<T> void testRandomResultSupplierConcurrently(Supplier<T> s) throws InterruptedException, ExecutionException, TimeoutException {
|
||||
// Produce 10 completable future tasks
|
||||
final int tasks = 10;
|
||||
List<CompletableFuture<T>> cfs = Stream.generate(() -> CompletableFuture.supplyAsync(s)).
|
||||
limit(tasks).collect(toList());
|
||||
|
||||
// Wait for all tasks to complete
|
||||
// Timeout is beyond reasonable doubt that completion should
|
||||
// have occurred unless there is an issue
|
||||
CompletableFuture<Void> all = CompletableFuture.allOf(cfs.stream().toArray(CompletableFuture[]::new));
|
||||
all.get(1, TimeUnit.MINUTES);
|
||||
|
||||
// Count the distinct results, which should equal the number of tasks
|
||||
long rc = cfs.stream().map(CompletableFuture::join).distinct().count();
|
||||
assertEquals(rc, tasks);
|
||||
}
|
||||
}
|
||||
495
test/jdk/java/util/Random/RandomTest.java
Normal file
495
test/jdk/java/util/Random/RandomTest.java
Normal file
|
|
@ -0,0 +1,495 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2022, 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.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.random.RandomGenerator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @run testng RandomTest
|
||||
* @summary test methods on Random
|
||||
* @bug 8288596
|
||||
* @key randomness
|
||||
*/
|
||||
@Test
|
||||
public class RandomTest {
|
||||
|
||||
// Note: this test was adapted from the 166 TCK ThreadLocalRandomTest test
|
||||
// and modified to be a TestNG test
|
||||
|
||||
/*
|
||||
* Testing coverage notes:
|
||||
*
|
||||
* We don't test randomness properties, but only that repeated
|
||||
* calls, up to NCALLS tries, produce at least one different
|
||||
* result. For bounded versions, we sample various intervals
|
||||
* across multiples of primes.
|
||||
*/
|
||||
|
||||
// max numbers of calls to detect getting stuck on one value
|
||||
static final int NCALLS = 10000;
|
||||
|
||||
// max sampled int bound
|
||||
static final int MAX_INT_BOUND = (1 << 28);
|
||||
|
||||
// max sampled long bound
|
||||
static final long MAX_LONG_BOUND = (1L << 42);
|
||||
|
||||
// Number of replications for other checks
|
||||
static final int REPS = 20;
|
||||
|
||||
/**
|
||||
* Repeated calls to nextInt produce at least two distinct results
|
||||
*/
|
||||
public void testNextInt() {
|
||||
Random r = new Random();
|
||||
int f = r.nextInt();
|
||||
int i = 0;
|
||||
while (i < NCALLS && r.nextInt() == f)
|
||||
++i;
|
||||
assertTrue(i < NCALLS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeated calls to nextLong produce at least two distinct results
|
||||
*/
|
||||
public void testNextLong() {
|
||||
Random r = new Random();
|
||||
long f = r.nextLong();
|
||||
int i = 0;
|
||||
while (i < NCALLS && r.nextLong() == f)
|
||||
++i;
|
||||
assertTrue(i < NCALLS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeated calls to nextBoolean produce at least two distinct results
|
||||
*/
|
||||
public void testNextBoolean() {
|
||||
Random r = new Random();
|
||||
boolean f = r.nextBoolean();
|
||||
int i = 0;
|
||||
while (i < NCALLS && r.nextBoolean() == f)
|
||||
++i;
|
||||
assertTrue(i < NCALLS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeated calls to nextFloat produce at least two distinct results
|
||||
*/
|
||||
public void testNextFloat() {
|
||||
Random r = new Random();
|
||||
float f = r.nextFloat();
|
||||
int i = 0;
|
||||
while (i < NCALLS && r.nextFloat() == f)
|
||||
++i;
|
||||
assertTrue(i < NCALLS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeated calls to nextDouble produce at least two distinct results
|
||||
*/
|
||||
public void testNextDouble() {
|
||||
Random r = new Random();
|
||||
double f = r.nextDouble();
|
||||
int i = 0;
|
||||
while (i < NCALLS && r.nextDouble() == f)
|
||||
++i;
|
||||
assertTrue(i < NCALLS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeated calls to nextGaussian produce at least two distinct results
|
||||
*/
|
||||
public void testNextGaussian() {
|
||||
Random r = new Random();
|
||||
double f = r.nextGaussian();
|
||||
int i = 0;
|
||||
while (i < NCALLS && r.nextGaussian() == f)
|
||||
++i;
|
||||
assertTrue(i < NCALLS);
|
||||
}
|
||||
|
||||
/**
|
||||
* nextInt(negative) throws IllegalArgumentException
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testNextIntBoundedNeg() {
|
||||
Random r = new Random();
|
||||
int f = r.nextInt(-17);
|
||||
}
|
||||
|
||||
/**
|
||||
* nextInt(bound) returns 0 <= value < bound; repeated calls produce at
|
||||
* least two distinct results
|
||||
*/
|
||||
public void testNextIntBounded() {
|
||||
Random r = new Random();
|
||||
// sample bound space across prime number increments
|
||||
for (int bound = 2; bound < MAX_INT_BOUND; bound += 524959) {
|
||||
int f = r.nextInt(bound);
|
||||
assertTrue(0 <= f && f < bound);
|
||||
int i = 0;
|
||||
int j;
|
||||
while (i < NCALLS &&
|
||||
(j = r.nextInt(bound)) == f) {
|
||||
assertTrue(0 <= j && j < bound);
|
||||
++i;
|
||||
}
|
||||
assertTrue(i < NCALLS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoking sized ints, long, doubles, with negative sizes throws
|
||||
* IllegalArgumentException
|
||||
*/
|
||||
public void testBadStreamSize() {
|
||||
Random r = new Random();
|
||||
assertThrowsIAE(() -> r.ints(-1L));
|
||||
assertThrowsIAE(() -> r.ints(-1L, 2, 3));
|
||||
assertThrowsIAE(() -> r.longs(-1L));
|
||||
assertThrowsIAE(() -> r.longs(-1L, -1L, 1L));
|
||||
assertThrowsIAE(() -> r.doubles(-1L));
|
||||
assertThrowsIAE(() -> r.doubles(-1L, .5, .6));
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoking bounded ints, long, doubles, with illegal bounds throws
|
||||
* IllegalArgumentException
|
||||
*/
|
||||
public void testBadStreamBounds() {
|
||||
Random r = new Random();
|
||||
assertThrowsIAE(() -> r.ints(2, 1));
|
||||
assertThrowsIAE(() -> r.ints(10, 42, 42));
|
||||
assertThrowsIAE(() -> r.longs(-1L, -1L));
|
||||
assertThrowsIAE(() -> r.longs(10, 1L, -2L));
|
||||
|
||||
testDoubleBadOriginBound((o, b) -> r.doubles(10, o, b));
|
||||
}
|
||||
|
||||
// An arbitrary finite double value
|
||||
static final double FINITE = Math.PI;
|
||||
|
||||
void testDoubleBadOriginBound(BiConsumer<Double, Double> bi) {
|
||||
assertThrowsIAE(() -> bi.accept(17.0, 2.0));
|
||||
assertThrowsIAE(() -> bi.accept(0.0, 0.0));
|
||||
assertThrowsIAE(() -> bi.accept(Double.NaN, FINITE));
|
||||
assertThrowsIAE(() -> bi.accept(FINITE, Double.NaN));
|
||||
assertThrowsIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY));
|
||||
|
||||
// Returns NaN
|
||||
// assertThrowsIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, FINITE));
|
||||
// assertThrowsIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
|
||||
|
||||
assertThrowsIAE(() -> bi.accept(FINITE, Double.NEGATIVE_INFINITY));
|
||||
|
||||
// Returns Double.MAX_VALUE
|
||||
// assertThrowsIAE(() -> bi.accept(FINITE, Double.POSITIVE_INFINITY));
|
||||
|
||||
assertThrowsIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY));
|
||||
assertThrowsIAE(() -> bi.accept(Double.POSITIVE_INFINITY, FINITE));
|
||||
assertThrowsIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY));
|
||||
}
|
||||
|
||||
private void assertThrowsIAE(ThrowingRunnable r) {
|
||||
assertThrows(IllegalArgumentException.class, r);
|
||||
}
|
||||
|
||||
/**
|
||||
* A sequential sized stream of ints generates the given number of values
|
||||
*/
|
||||
public void testIntsCount() {
|
||||
LongAdder counter = new LongAdder();
|
||||
Random r = new Random();
|
||||
long size = 0;
|
||||
for (int reps = 0; reps < REPS; ++reps) {
|
||||
counter.reset();
|
||||
r.ints(size).forEach(x -> {
|
||||
counter.increment();
|
||||
});
|
||||
assertEquals(counter.sum(), size);
|
||||
size += 524959;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sequential sized stream of longs generates the given number of values
|
||||
*/
|
||||
public void testLongsCount() {
|
||||
LongAdder counter = new LongAdder();
|
||||
Random r = new Random();
|
||||
long size = 0;
|
||||
for (int reps = 0; reps < REPS; ++reps) {
|
||||
counter.reset();
|
||||
r.longs(size).forEach(x -> {
|
||||
counter.increment();
|
||||
});
|
||||
assertEquals(counter.sum(), size);
|
||||
size += 524959;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sequential sized stream of doubles generates the given number of values
|
||||
*/
|
||||
public void testDoublesCount() {
|
||||
LongAdder counter = new LongAdder();
|
||||
Random r = new Random();
|
||||
long size = 0;
|
||||
for (int reps = 0; reps < REPS; ++reps) {
|
||||
counter.reset();
|
||||
r.doubles(size).forEach(x -> {
|
||||
counter.increment();
|
||||
});
|
||||
assertEquals(counter.sum(), size);
|
||||
size += 524959;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Each of a sequential sized stream of bounded ints is within bounds
|
||||
*/
|
||||
public void testBoundedInts() {
|
||||
AtomicInteger fails = new AtomicInteger(0);
|
||||
Random r = new Random();
|
||||
long size = 12345L;
|
||||
for (int least = -15485867; least < MAX_INT_BOUND; least += 524959) {
|
||||
for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 67867967) {
|
||||
final int lo = least, hi = bound;
|
||||
r.ints(size, lo, hi).
|
||||
forEach(x -> {
|
||||
if (x < lo || x >= hi)
|
||||
fails.getAndIncrement();
|
||||
});
|
||||
}
|
||||
}
|
||||
assertEquals(fails.get(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Each of a sequential sized stream of bounded longs is within bounds
|
||||
*/
|
||||
public void testBoundedLongs() {
|
||||
AtomicInteger fails = new AtomicInteger(0);
|
||||
Random r = new Random();
|
||||
long size = 123L;
|
||||
for (long least = -86028121; least < MAX_LONG_BOUND; least += 1982451653L) {
|
||||
for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
|
||||
final long lo = least, hi = bound;
|
||||
r.longs(size, lo, hi).
|
||||
forEach(x -> {
|
||||
if (x < lo || x >= hi)
|
||||
fails.getAndIncrement();
|
||||
});
|
||||
}
|
||||
}
|
||||
assertEquals(fails.get(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Each of a sequential sized stream of bounded doubles is within bounds
|
||||
*/
|
||||
public void testBoundedDoubles() {
|
||||
AtomicInteger fails = new AtomicInteger(0);
|
||||
Random r = new Random();
|
||||
long size = 456;
|
||||
for (double least = 0.00011; least < 1.0e20; least *= 9) {
|
||||
for (double bound = least * 1.0011; bound < 1.0e20; bound *= 17) {
|
||||
final double lo = least, hi = bound;
|
||||
r.doubles(size, lo, hi).
|
||||
forEach(x -> {
|
||||
if (x < lo || x >= hi)
|
||||
fails.getAndIncrement();
|
||||
});
|
||||
}
|
||||
}
|
||||
assertEquals(fails.get(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* A parallel unsized stream of ints generates at least 100 values
|
||||
*/
|
||||
public void testUnsizedIntsCount() {
|
||||
LongAdder counter = new LongAdder();
|
||||
Random r = new Random();
|
||||
long size = 100;
|
||||
r.ints().limit(size).parallel().forEach(x -> {
|
||||
counter.increment();
|
||||
});
|
||||
assertEquals(counter.sum(), size);
|
||||
}
|
||||
|
||||
/**
|
||||
* A parallel unsized stream of longs generates at least 100 values
|
||||
*/
|
||||
public void testUnsizedLongsCount() {
|
||||
LongAdder counter = new LongAdder();
|
||||
Random r = new Random();
|
||||
long size = 100;
|
||||
r.longs().limit(size).parallel().forEach(x -> {
|
||||
counter.increment();
|
||||
});
|
||||
assertEquals(counter.sum(), size);
|
||||
}
|
||||
|
||||
/**
|
||||
* A parallel unsized stream of doubles generates at least 100 values
|
||||
*/
|
||||
public void testUnsizedDoublesCount() {
|
||||
LongAdder counter = new LongAdder();
|
||||
Random r = new Random();
|
||||
long size = 100;
|
||||
r.doubles().limit(size).parallel().forEach(x -> {
|
||||
counter.increment();
|
||||
});
|
||||
assertEquals(counter.sum(), size);
|
||||
}
|
||||
|
||||
/**
|
||||
* A sequential unsized stream of ints generates at least 100 values
|
||||
*/
|
||||
public void testUnsizedIntsCountSeq() {
|
||||
LongAdder counter = new LongAdder();
|
||||
Random r = new Random();
|
||||
long size = 100;
|
||||
r.ints().limit(size).forEach(x -> {
|
||||
counter.increment();
|
||||
});
|
||||
assertEquals(counter.sum(), size);
|
||||
}
|
||||
|
||||
/**
|
||||
* A sequential unsized stream of longs generates at least 100 values
|
||||
*/
|
||||
public void testUnsizedLongsCountSeq() {
|
||||
LongAdder counter = new LongAdder();
|
||||
Random r = new Random();
|
||||
long size = 100;
|
||||
r.longs().limit(size).forEach(x -> {
|
||||
counter.increment();
|
||||
});
|
||||
assertEquals(counter.sum(), size);
|
||||
}
|
||||
|
||||
/**
|
||||
* A sequential unsized stream of doubles generates at least 100 values
|
||||
*/
|
||||
public void testUnsizedDoublesCountSeq() {
|
||||
LongAdder counter = new LongAdder();
|
||||
Random r = new Random();
|
||||
long size = 100;
|
||||
r.doubles().limit(size).forEach(x -> {
|
||||
counter.increment();
|
||||
});
|
||||
assertEquals(counter.sum(), size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test shuffling a list with Random.from()
|
||||
*/
|
||||
public void testShufflingList() {
|
||||
final var listTest = new ArrayList<Integer>();
|
||||
final RandomGenerator randomGenerator = RandomGenerator.getDefault();
|
||||
final Random random = Random.from(randomGenerator);
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
listTest.add(i * 2);
|
||||
}
|
||||
final var listCopy = new ArrayList<Integer>(listTest);
|
||||
|
||||
Collections.shuffle(listCopy, random);
|
||||
|
||||
assertFalse(listCopy.equals(listTest));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if Random.from returns this
|
||||
*/
|
||||
public void testRandomFromInstance() {
|
||||
final RandomGenerator randomGenerator = RandomGenerator.getDefault();
|
||||
|
||||
final Random randomInstance = Random.from(randomGenerator);
|
||||
|
||||
// we wrap the same instance again
|
||||
final Random randomInstanceCopy = Random.from(randomInstance);
|
||||
|
||||
assertSame(randomInstance, randomInstanceCopy);
|
||||
}
|
||||
|
||||
private int delegationCount;
|
||||
|
||||
private class RandomGen implements RandomGenerator {
|
||||
|
||||
@Override
|
||||
public boolean isDeprecated() {
|
||||
delegationCount += 1;
|
||||
return RandomGenerator.super.isDeprecated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float nextFloat(float bound) {
|
||||
delegationCount += 1;
|
||||
return RandomGenerator.super.nextFloat(bound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double nextDouble(double bound) {
|
||||
delegationCount += 1;
|
||||
return RandomGenerator.super.nextDouble(bound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long nextLong() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether calls to methods inherited from RandomGenerator
|
||||
* are delegated to the instance returned by from().
|
||||
* This is not a complete coverage, but simulates the reproducer
|
||||
* in issue JDK-8288596
|
||||
*/
|
||||
public void testRandomFrom() {
|
||||
delegationCount = 0;
|
||||
var r = Random.from(new RandomGen());
|
||||
r.isDeprecated();
|
||||
r.nextFloat(1_000.0f);
|
||||
r.nextFloat(); // not implemented in RandomGen, does not count
|
||||
r.nextDouble(1_000.0);
|
||||
r.nextDouble(); // not implemented in RandomGen, does not count
|
||||
assertEquals(delegationCount, 3);
|
||||
}
|
||||
|
||||
}
|
||||
456
test/jdk/java/util/Random/RandomTestBsi1999.java
Normal file
456
test/jdk/java/util/Random/RandomTestBsi1999.java
Normal file
|
|
@ -0,0 +1,456 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2021, 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.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.PrimitiveIterator;
|
||||
|
||||
import java.util.random.*;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.function.LongSupplier;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary test bit sequences produced by classes that implement interface RandomGenerator
|
||||
* @bug 8248862
|
||||
* @run main/othervm/timeout=400 RandomTestBsi1999
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
public class RandomTestBsi1999 {
|
||||
|
||||
/* A set of tests for pseudorandom number generators inspired by this report:
|
||||
*
|
||||
* Werner Schindler. Functionality Classes and Evaluation Methodology for
|
||||
* Deterministic Random Number Generators, Version 2.0.
|
||||
* Bundesamt fur Sicherheit in der Informationstechnik (BSI). December 2, 1999.
|
||||
* https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Zertifizierung/Interpretationen/AIS_20_Functionality_Classes_Evaluation_Methodology_DRNG_e.pdf
|
||||
*
|
||||
* Section F of this report (pp. 19-20) recommends the use of five tests to evaluate a
|
||||
* sequence of bits:
|
||||
*
|
||||
* Monobit test
|
||||
* Poker test
|
||||
* Run test
|
||||
* Long run test
|
||||
* Autocorrelation test
|
||||
*
|
||||
* The first four of these tests are in turn taken from this report:
|
||||
*
|
||||
* National Institute of Standards and Technology (NIST),
|
||||
* U.S. Department of Commerce. Security Requirements for
|
||||
* Cryptographic Modules. Federal Information Processing
|
||||
* Standard (FIPS) 140-1, January 11, 1994.
|
||||
* https://csrc.nist.gov/csrc/media/publications/fips/140/1/archive/1994-01-11/documents/fips1401.pdf
|
||||
*
|
||||
* The BSI report appears to contain a few typos in transcribing the FIPS 140-1
|
||||
* requirements (pp. 44-45); specifically, the last three intervals for the runs test
|
||||
* (for lengths 4, 5, and 6+) are given as "223 - 402, 90 - 223, 90 - 223" in the FIPS
|
||||
* standard but as "233-402, 90-223, 90-233" in the BSI publication. A quick
|
||||
* mathematical check indicates that the FIPS 140-1 values are correct; therefore we
|
||||
* use those values here. In addition, the BSI report specifies a test interval of
|
||||
* 2326-2674 for the autocorrelation test, which provides an appropriately small
|
||||
* rejection rate if the test were done for only a single value of tau; but because we
|
||||
* wish to perform 5000 distinct tests, one for each value of tau in the range 1-5000,
|
||||
* that test interval produces too many false positives. Some calculation shows that
|
||||
* the interval 2267-2733 used by the FIPS 140-1 run test for runs of length 1 is
|
||||
* appropriate, so we use that interval here for each of the 5000 individual
|
||||
* autocorrelation tests.
|
||||
*
|
||||
* Each of the four FIPS 140-1 tests examines a sequence of 20000 bits. The
|
||||
* autocorrelation test examines a sequence of 10000 bits. It is convenient to
|
||||
* generate a sequence of 20000 bits (which we represent as an array of 20000 bytes)
|
||||
* and then apply all five tests, knowing that the autocorrelation test will examine
|
||||
* only the first half of the byte array.
|
||||
*
|
||||
* The descriptions of the tests are quoted from the FIPS 140-1 and BSI reports
|
||||
* (with some adjustments of punctuation and mathematical symbols, as well as
|
||||
* for our specific choices of test intervals).
|
||||
*/
|
||||
|
||||
static String currentRNG = "";
|
||||
static int failCount = 0;
|
||||
|
||||
static void exceptionOnFail() {
|
||||
if (failCount != 0) {
|
||||
throw new RuntimeException(failCount + " fails detected");
|
||||
}
|
||||
}
|
||||
|
||||
static void setRNG(String rng) {
|
||||
currentRNG = rng;
|
||||
}
|
||||
|
||||
static void fail(String format, Object... args) {
|
||||
if (currentRNG.length() != 0) {
|
||||
System.err.println(currentRNG);
|
||||
currentRNG = "";
|
||||
}
|
||||
|
||||
System.err.format(" " + format, args);
|
||||
failCount++;
|
||||
}
|
||||
|
||||
private static final int SEQUENCE_SIZE = 20000;
|
||||
|
||||
/* The Monobit Test
|
||||
*
|
||||
* 1. Count the number of ones in the 20,000 bit stream. Denote this quantity by X.
|
||||
*
|
||||
* 2. The test is passed if 9,654 < X < 10,346.
|
||||
*/
|
||||
static int monobitTest(String id, byte[] s) {
|
||||
// System.out.println("monobit test");
|
||||
int count = 0;
|
||||
for (int j = 0; j < s.length; j++) {
|
||||
count += s[j];
|
||||
}
|
||||
int monobitFailure = ((9654 < count) && (count < 10346)) ? 0 : 1;
|
||||
if (monobitFailure != 0) fail("monobit test failure for %s: count=%d (should be in [9654,10346])\n", id, count);
|
||||
return monobitFailure;
|
||||
}
|
||||
|
||||
/* The Poker Test
|
||||
*
|
||||
* 1. Divide the 20,000 bit stream into 5,000 contiguous 4-bit segments. Count and
|
||||
* store the number of occurrences of each of the 16 possible 4-bit values. Denote
|
||||
* f(i) as the number of each 4-bit value i where 0 <= i <= 15.
|
||||
*
|
||||
* 2. Evaluate the following: X = (16/5000)(sum[i=0,15] (f(i))**2) - 5000
|
||||
*
|
||||
* 3. The test is passed if 1.03 < X < 57.4.
|
||||
*/
|
||||
|
||||
static int pokerTest(String id, byte[] s) {
|
||||
// System.out.println("poker test");
|
||||
// Divide the bit sequence into 4-bit chunks, and count the number of times each 4-bit value appears.
|
||||
int[] stats = new int[16];
|
||||
int v = 0;
|
||||
for (int j = 0; j < s.length; j++) {
|
||||
v = (v << 1) | s[j];
|
||||
if ((j & 3) == 3) {
|
||||
++stats[v];
|
||||
v = 0;
|
||||
}
|
||||
}
|
||||
int z = 0;
|
||||
for (int k = 0; k < stats.length; k++) {
|
||||
z += stats[k]*stats[k];
|
||||
}
|
||||
double x = (16.0 / (s.length / 4)) * z - (s.length / 4);
|
||||
int pokerFailure = ((1.03 < x) && (x < 57.4)) ? 0 : 1;
|
||||
if (pokerFailure != 0) fail("poker test failure for %s: x=%g (should be in [1.03,57.4])\n", id, x);
|
||||
return pokerFailure;
|
||||
}
|
||||
|
||||
/* The Runs Test
|
||||
*
|
||||
* 1. A run is defined as a maximal sequence of consecutive bits of either all ones
|
||||
* or all zeros, which is part of the 20,000 bit sample stream. The incidences of
|
||||
* runs (for both consecutive zeros and consecutive ones) of all lengths (>= 1) in
|
||||
* the sample stream should be counted and stored.
|
||||
*
|
||||
* 2. The test is passed if the number of runs that occur (of lengths 1 through 6)
|
||||
* is each within the corresponding interval specified below. This must hold for
|
||||
* both the zeros and ones; that is, all 12 counts must lie in the specified
|
||||
* interval. For the purpose of this test, runs of greater than 6 are considered to
|
||||
* be of length 6.
|
||||
*
|
||||
* Length of run Required Interval
|
||||
* 1 2,267 - 2,733
|
||||
* 2 1,079 - 1,421
|
||||
* 3 502 - 748
|
||||
* 4 223 - 402
|
||||
* 5 90 - 223
|
||||
* 6+ 90 - 223
|
||||
*
|
||||
* The Long Run Test
|
||||
*
|
||||
* 1 . A long run is defined to be a run of length 34 or more (of either zeros or ones).
|
||||
*
|
||||
* 2. On the sample of 20,000 bits, the test is passed if there are NO long runs.
|
||||
*/
|
||||
static int runTestAndLongRunTest(String id, byte[] s) {
|
||||
// System.out.println("run test");
|
||||
int[][] stats = new int[2][8];
|
||||
int count = 0;
|
||||
for (int j = 0; j < s.length; j++) {
|
||||
++count;
|
||||
if ((j == (s.length - 1)) || (s[j+1] != s[j])) {
|
||||
++stats[s[j]][(count < 6) ? count : (count < 34) ? 6 : 7];
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
stats[0][6] += stats[0][7];
|
||||
stats[1][6] += stats[1][7];
|
||||
int runFailure = checkRunStats(stats[0]) | checkRunStats(stats[1]);
|
||||
if (runFailure != 0) fail("run test failure for %s\n", id);
|
||||
int longRunFailure = ((stats[0][7] == 0) && (stats[1][7] == 0)) ? 0 : 1;
|
||||
if (longRunFailure != 0) fail("long run test failure for %s\n", id);
|
||||
return (runFailure + longRunFailure);
|
||||
}
|
||||
|
||||
static int checkRunStats(int[] stats) {
|
||||
int runFailure = 0;
|
||||
runFailure |= ((2267 <= stats[1]) && (stats[1] <= 2733)) ? 0 : 1;
|
||||
runFailure |= ((1079 <= stats[2]) && (stats[2] <= 1421)) ? 0 : 1;
|
||||
runFailure |= (( 502 <= stats[3]) && (stats[3] <= 748)) ? 0 : 1;
|
||||
runFailure |= (( 223 <= stats[4]) && (stats[4] <= 402)) ? 0 : 1;
|
||||
runFailure |= (( 90 <= stats[5]) && (stats[5] <= 223)) ? 0 : 1;
|
||||
runFailure |= (( 90 <= stats[6]) && (stats[6] <= 223)) ? 0 : 1;
|
||||
return runFailure;
|
||||
}
|
||||
|
||||
/* Autocorrelation Test
|
||||
*
|
||||
* For tau in {1, ..., 5000}, Z[tau] := sum[j=1,5000] (b[j] ^ b[j+tau]).
|
||||
*
|
||||
* The sequence passes the autocorrelation test if every Z[tau] lies within the
|
||||
* interval 2267-2733.
|
||||
*/
|
||||
static int autocorrelationTest(String id, byte[] s) {
|
||||
// System.out.println("autocorrelation test");
|
||||
int autocorrelationFailure = 0;
|
||||
int N = s.length / 4;
|
||||
for (int tau = 1; tau <= N; tau++) {
|
||||
int count = 0;
|
||||
for (int j = 0; j < N; j++) {
|
||||
count += (s[j] ^ s[j+tau]);
|
||||
}
|
||||
// We intentionally use bounds [2267, 2733], which are wider than
|
||||
// the bounds [2326, 2674] specified by BSI for this test.
|
||||
// The latter bounds produce way too many false positives.
|
||||
int singleAutocorrelationFailure = ((2267 < count) && (count < 2733)) ? 0 : 1;
|
||||
if (singleAutocorrelationFailure != 0) {
|
||||
if (autocorrelationFailure < 8) {
|
||||
fail("autocorrelation failure for %s: count=%d (should be in [2267,2733]), tau=%d\n", id, count, tau);
|
||||
if (count < 100 || count > 4900) {
|
||||
System.out.print(" ");
|
||||
for (int q = 0; q < 50; q++) System.out.print(s[q]);
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
autocorrelationFailure += singleAutocorrelationFailure;
|
||||
}
|
||||
return (autocorrelationFailure == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
static int entireBsi1999Test(String id, byte[] s) {
|
||||
return (monobitTest(id, s) +
|
||||
pokerTest(id, s) +
|
||||
runTestAndLongRunTest(id, s) +
|
||||
autocorrelationTest(id, s)
|
||||
);
|
||||
}
|
||||
|
||||
/* To test a sequence of boolean values from a BooleanSupplier,
|
||||
* sequentially extract 20000 boolean values, convert to an array
|
||||
* of bytes, and feed them to method {@code entireBsi1999Test}.
|
||||
*/
|
||||
|
||||
static int testRngBsi1999BooleanOnce(String id, BooleanSupplier theSupplier) {
|
||||
int failureCount = 0;
|
||||
byte[] s = new byte[SEQUENCE_SIZE];
|
||||
// Take the next SEQUENCE_SIZE booleans and test them
|
||||
for (int j = 0; j < s.length; j++) {
|
||||
s[j] = (theSupplier.getAsBoolean() ? (byte)1 : (byte)0);
|
||||
}
|
||||
failureCount += entireBsi1999Test(id + " consecutive", s);
|
||||
return failureCount;
|
||||
}
|
||||
|
||||
/* To test a sequence of long values from a LongSupplier,
|
||||
* two kinds of tests are performed.
|
||||
*
|
||||
* The first kind of test extracts 313=ceiling(20000/64) long
|
||||
* values and concatenates all their bits; the first 20000 bits
|
||||
* are converted to a byte array of bits to be tested. This test is
|
||||
* repeated 64 times.
|
||||
*
|
||||
* The second kind of test focuses on one bit position m (0 <= m < 64);
|
||||
* it extracts 20000 long values and uses just bit m from each value
|
||||
* to produce an array of bytes to be tested. This test is performed
|
||||
* once for each possible value of m (64 times in all).
|
||||
*/
|
||||
static int testRngBsi1999LongOnce(String id, LongSupplier theSupplier) {
|
||||
int failureCount = 0;
|
||||
byte[] s = new byte[SEQUENCE_SIZE];
|
||||
// Part 1: 64 times, take the next SEQUENCE_SIZE bits and test them
|
||||
for (int m = 0; m < 64; m++) {
|
||||
long bits = 0;
|
||||
int bitCount = 0;
|
||||
for (int j = 0; j < s.length; j++) {
|
||||
if ((j & 0x3f) == 0) {
|
||||
bits = theSupplier.getAsLong();
|
||||
// System.out.printf("0x%016x\n", bits);
|
||||
bitCount += Long.bitCount((j == (20000 - 32)) ? ((bits << 32) >>> 32) : bits);
|
||||
}
|
||||
s[j] = (byte)(bits & 1);
|
||||
bits >>>= 1;
|
||||
}
|
||||
// System.out.println(m + ": " + bitCount + " 1-bits");
|
||||
failureCount += entireBsi1999Test(id + " consecutive (" + bitCount + " 1-bits)", s);
|
||||
}
|
||||
// Part 2: for 0 <= m < 64, use bit m from each of the next SEQUENCE_SIZE longs
|
||||
for (int m = 0; m < 64; m++) {
|
||||
for (int j = 0; j < s.length; j++) {
|
||||
s[j] = (byte)((theSupplier.getAsLong() >>> m) & 1);
|
||||
}
|
||||
failureCount += entireBsi1999Test(id + " bit " + m, s);
|
||||
}
|
||||
return failureCount;
|
||||
}
|
||||
|
||||
/* To test a sequence of ing values from an IntSupplier,
|
||||
* two kinds of tests are performed.
|
||||
*
|
||||
* The first kind of test extracts 625=20000/32 int values and
|
||||
* concatenates all their bits; these 20000 bits are converted to
|
||||
* a byte array of bits to be tested. This test is repeated 64
|
||||
* times.
|
||||
*
|
||||
* The second kind of test focuses on one bit position m (0 <= m < 32);
|
||||
* it extracts 20000 int values and uses just bit m from each value
|
||||
* to produce an array of bytes to be tested. This test is performed
|
||||
* once for each possible value of m (32 times in all).
|
||||
*/
|
||||
static int testRngBsi1999IntOnce(String id, IntSupplier theSupplier) {
|
||||
int failureCount = 0;
|
||||
byte[] s = new byte[SEQUENCE_SIZE];
|
||||
// Part 1: 64 times, take the next SEQUENCE_SIZE bits and test them
|
||||
for (int m = 0; m < 64; m++) {
|
||||
int bits = 0;
|
||||
int bitCount = 0;
|
||||
for (int j = 0; j < s.length; j++) {
|
||||
if ((j & 0x1f) == 0) {
|
||||
bits = theSupplier.getAsInt();
|
||||
bitCount += Integer.bitCount(bits);
|
||||
}
|
||||
s[j] = (byte)(bits & 1);
|
||||
bits >>>= 1;
|
||||
}
|
||||
// System.out.println(m + ": " + bitCount + " 1-bits");
|
||||
failureCount += entireBsi1999Test(id + " consecutive (" + bitCount + " 1-bits)", s);
|
||||
}
|
||||
// Part 2: for 0 <= m < 32, use bit m from each of the next SEQUENCE_SIZE ints
|
||||
for (int m = 0; m < 32; m++) {
|
||||
for (int j = 0; j < s.length; j++) {
|
||||
s[j] = (byte)((theSupplier.getAsInt() >>> m) & 1);
|
||||
}
|
||||
failureCount += entireBsi1999Test(id + " bit " + m, s);
|
||||
}
|
||||
return failureCount;
|
||||
}
|
||||
|
||||
/* A call to {@code entireBsi1999Test} may report failure even if the source of random
|
||||
* bits is quite good, because the test is statistical in nature. To make the testing
|
||||
* procedure more robust, if the first call to {@code entireBsi1999Test} fails, then
|
||||
* the failure is ignored if two more calls to {@code entireBsi1999Test} both succeed.
|
||||
*/
|
||||
|
||||
static boolean testRngBsi1999Boolean(String id, BooleanSupplier theSupplier, int failureTolerance) {
|
||||
if (testRngBsi1999BooleanOnce(id, theSupplier) <= failureTolerance) return true;
|
||||
fail("testRngBsi1999Boolean glitch");
|
||||
return ((testRngBsi1999BooleanOnce(id, theSupplier) <= failureTolerance) &&
|
||||
(testRngBsi1999BooleanOnce(id, theSupplier) <= failureTolerance));
|
||||
}
|
||||
|
||||
static boolean testRngBsi1999Long(String id, LongSupplier theSupplier, int failureTolerance) {
|
||||
if (testRngBsi1999LongOnce(id, theSupplier) <= failureTolerance) return true;
|
||||
fail("testRngBsi1999Long glitch");
|
||||
return ((testRngBsi1999LongOnce(id, theSupplier) <= failureTolerance) &&
|
||||
(testRngBsi1999LongOnce(id, theSupplier) <= failureTolerance));
|
||||
}
|
||||
|
||||
static boolean testRngBsi1999Int(String id, IntSupplier theSupplier, int failureTolerance) {
|
||||
if (testRngBsi1999IntOnce(id, theSupplier) <= failureTolerance) return true;
|
||||
fail("testRngBsi1999Int glitch");
|
||||
return ((testRngBsi1999IntOnce(id, theSupplier) <= failureTolerance) &&
|
||||
(testRngBsi1999IntOnce(id, theSupplier) <= failureTolerance));
|
||||
}
|
||||
|
||||
static void tryIt(RandomGenerator rng, String id, BooleanSupplier theSupplier) {
|
||||
System.out.printf("Testing %s %s\n", rng.getClass().getName(), id);
|
||||
boolean success = theSupplier.getAsBoolean();
|
||||
if (!success) {
|
||||
fail("*** Failure of %s %s\n", rng.getClass().getName(), id);
|
||||
}
|
||||
}
|
||||
|
||||
static void testOneRng(RandomGenerator rng, int failureTolerance) {
|
||||
String name = rng.getClass().getName();
|
||||
tryIt(rng, "nextInt", () -> testRngBsi1999Int(name + " nextInt", rng::nextInt, failureTolerance));
|
||||
tryIt(rng, "nextLong", () -> testRngBsi1999Long(name + " nextLong", rng::nextLong, failureTolerance));
|
||||
tryIt(rng, "nextBoolean", () -> testRngBsi1999Boolean(name + " nextBoolean", rng::nextBoolean, failureTolerance));
|
||||
tryIt(rng, "ints", () -> testRngBsi1999Int(name + " ints", rng.ints().iterator()::next, failureTolerance));
|
||||
tryIt(rng, "longs", () -> testRngBsi1999Long(name + " longs", rng.longs().iterator()::next, failureTolerance));
|
||||
{
|
||||
PrimitiveIterator.OfDouble iter = rng.doubles().iterator();
|
||||
tryIt(rng, "doubles",
|
||||
() -> testRngBsi1999Int(name + " doubles",
|
||||
() -> (int)(long)Math.floor(iter.next() * 0x1.0p32),
|
||||
failureTolerance));
|
||||
}
|
||||
tryIt(rng, "nextDouble",
|
||||
() -> testRngBsi1999Int(name + " nextDouble",
|
||||
() -> (int)(long)Math.floor(rng.nextDouble() * 0x1.0p32),
|
||||
failureTolerance));
|
||||
tryIt(rng, "nextFloat",
|
||||
() -> testRngBsi1999Int(name + " nextFloat",
|
||||
() -> (((int)(long)Math.floor(rng.nextFloat() * 0x1.0p16f) << 16)
|
||||
| (int)(long)Math.floor(rng.nextFloat() * 0x1.0p16f)),
|
||||
failureTolerance));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
RandomGeneratorFactory.all().forEach(factory -> {
|
||||
setRNG(factory.name());
|
||||
|
||||
if (currentRNG.equals("SecureRandom")) {
|
||||
// skip because stochastic
|
||||
} else if (currentRNG.equals("Random")) {
|
||||
// testOneRng(factory.create(59), 1);
|
||||
// autocorrelation failure for java.util.Random longs bit 0: count=2207 (should be in [2267,2733]), tau=2819
|
||||
|
||||
} else {
|
||||
testOneRng(factory.create(59), 0);
|
||||
}
|
||||
});
|
||||
|
||||
exceptionOnFail();
|
||||
}
|
||||
}
|
||||
|
||||
243
test/jdk/java/util/Random/RandomTestChiSquared.java
Normal file
243
test/jdk/java/util/Random/RandomTestChiSquared.java
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2021, 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.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.PrimitiveIterator;
|
||||
|
||||
import java.util.random.*;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.function.LongSupplier;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary test bit sequences produced by clases that implement interface RandomGenerator
|
||||
* @bug 8248862
|
||||
* @run main RandomTestChiSquared
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
public class RandomTestChiSquared {
|
||||
|
||||
static String currentRNG = "";
|
||||
static int failCount = 0;
|
||||
|
||||
static void exceptionOnFail() {
|
||||
if (failCount != 0) {
|
||||
throw new RuntimeException(failCount + " fails detected");
|
||||
}
|
||||
}
|
||||
|
||||
static void setRNG(String rng) {
|
||||
currentRNG = rng;
|
||||
}
|
||||
|
||||
static void fail(String format, Object... args) {
|
||||
if (currentRNG.length() != 0) {
|
||||
System.err.println(currentRNG);
|
||||
currentRNG = "";
|
||||
}
|
||||
|
||||
System.err.format(" " + format, args);
|
||||
failCount++;
|
||||
}
|
||||
|
||||
// Some simple chi-squared tests similar to that used for the FIPS 140 poker test,
|
||||
// but intended primarily to test production of random values from ranges.
|
||||
|
||||
private static final int SEQUENCE_SIZE = 20000;
|
||||
|
||||
// Entry k of this table was computed in Microsoft Excel using the formulae
|
||||
// =CHISQ.INV(0.0000000777517,k) and =CHISQ.INV.RT(0.00000142611,k)
|
||||
// (except that entry 0 is a dummy and should never be used).
|
||||
static final double[][] chiSquaredBounds = {
|
||||
{ 0.0, 0.0 },
|
||||
{ 9.49598E-15, 23.24513154 },
|
||||
{ 1.55503E-07, 26.92112020 },
|
||||
{ 4.40485E-05, 29.93222467 },
|
||||
{ 0.000788782, 32.62391510 },
|
||||
{ 0.004636947, 35.11665045 },
|
||||
{ 0.015541535, 37.46947634 },
|
||||
{ 0.037678318, 39.71667636 },
|
||||
{ 0.074471919, 41.88031518 },
|
||||
{ 0.128297057, 43.97561646 },
|
||||
{ 0.200566433, 46.01362542 },
|
||||
{ 0.291944952, 48.00266676 },
|
||||
{ 0.402564694, 49.94920504 },
|
||||
{ 0.532199236, 51.85838271 },
|
||||
{ 0.680392565, 53.73437242 },
|
||||
{ 0.846549931, 55.58061674 },
|
||||
{ 1.030000010, 57.39999630 },
|
||||
{ 1.230036580, 59.19495111 },
|
||||
{ 1.445945898, 60.96756998 },
|
||||
{ 1.677024296, 62.71965780 },
|
||||
{ 1.922589129, 64.45278706 },
|
||||
{ 2.181985238, 66.16833789 },
|
||||
{ 2.454588423, 67.86752964 },
|
||||
{ 2.739806923, 69.55144602 },
|
||||
{ 3.037081611, 71.22105544 },
|
||||
{ 3.345885349, 72.87722754 },
|
||||
{ 3.665721841, 74.52074682 },
|
||||
{ 3.996124178, 76.15232388 },
|
||||
{ 4.336653242, 77.77260487 },
|
||||
{ 4.686896041, 79.38217943 },
|
||||
{ 5.046464051, 80.98158736 },
|
||||
{ 5.414991603, 82.57132439 }
|
||||
};
|
||||
|
||||
|
||||
|
||||
// N is the number of categories; every element of s ought to be in [0,N).
|
||||
// N must be in [1,31].
|
||||
static boolean chiSquaredTest(String id, int N, IntSupplier theSupplier) {
|
||||
int[] stats = new int[N];
|
||||
for (int j = 0; j < SEQUENCE_SIZE; j++) {
|
||||
int v = theSupplier.getAsInt();
|
||||
// assert((0 <= v) && (v < N));
|
||||
++stats[v];
|
||||
}
|
||||
int z = 0;
|
||||
for (int k = 0; k < stats.length; k++) {
|
||||
z += stats[k]*stats[k];
|
||||
}
|
||||
double x = ((double)N / (double)SEQUENCE_SIZE) * (double)z - (double)SEQUENCE_SIZE;
|
||||
double lo = chiSquaredBounds[N][0];
|
||||
double hi = chiSquaredBounds[N][1];
|
||||
boolean chiSquaredSuccess = ((lo < x) && (x < hi));
|
||||
if (!chiSquaredSuccess) fail("chi-squared test failure for %s: x=%g (should be in [%g,%g])\n", id, x, lo, hi);
|
||||
return chiSquaredSuccess;
|
||||
}
|
||||
|
||||
static boolean testRngChiSquared(String id, int N, IntSupplier theSupplier) {
|
||||
if (chiSquaredTest(id, N, theSupplier)) return true;
|
||||
fail("testRngChiSquared glitch");
|
||||
return chiSquaredTest(id, N, theSupplier) && chiSquaredTest(id, N, theSupplier);
|
||||
}
|
||||
|
||||
static void tryIt(RandomGenerator rng, String kind, Function<String,BooleanSupplier> f) {
|
||||
String id = rng.getClass().getName() + " " + kind;
|
||||
// System.out.printf("Testing %s\n", id);
|
||||
boolean success = f.apply(id).getAsBoolean();
|
||||
if (!success) {
|
||||
fail("*** Failure of %s\n", id);
|
||||
}
|
||||
}
|
||||
|
||||
// To test one instance of an RandomGenerator with the BSI test suite, we test:
|
||||
// nextInt()
|
||||
// nextLong()
|
||||
// nextBoolean()
|
||||
// ints()
|
||||
// longs()
|
||||
// doubles()
|
||||
// nextDouble()
|
||||
// nextFloat()
|
||||
|
||||
static final int[] testSizes = { 11, 13, 16, 17, 19, 23, 24 };
|
||||
|
||||
static void testOneRng(RandomGenerator rng, int failureTolerance) {
|
||||
String name = rng.getClass().getName();
|
||||
for (int j = 0; j < testSizes.length; j++) {
|
||||
int N = testSizes[j];
|
||||
tryIt(rng, "nextInt(" + N + ")", (String id) -> () -> testRngChiSquared(id, N, () -> rng.nextInt(N)));
|
||||
tryIt(rng, "nextInt(43, " + (N+43) + ")", (String id) -> () -> testRngChiSquared(id, N, () -> rng.nextInt(43, N+43) - 43));
|
||||
tryIt(rng, "nextInt(-59, " + (N-59) + ")", (String id) -> () -> testRngChiSquared(id, N, () -> rng.nextInt(-59, N-59) + 59));
|
||||
}
|
||||
for (int j = 0; j < testSizes.length; j++) {
|
||||
int N = testSizes[j];
|
||||
tryIt(rng, "nextLong(" + N + ")", (String id) -> () -> testRngChiSquared(id, N, () -> (int)(rng.nextLong(N))));
|
||||
tryIt(rng, "nextLong(43, " + (N+43) + ")", (String id) -> () -> testRngChiSquared(id, N, () -> (int)(rng.nextLong(43, N+43) - 43)));
|
||||
tryIt(rng, "nextLong(-59, " + (N-59) + ")", (String id) -> () -> testRngChiSquared(id, N, () -> (int)(rng.nextLong(-59, N-59) + 59)));
|
||||
}
|
||||
for (int j = 0; j < testSizes.length; j++) {
|
||||
int N = testSizes[j];
|
||||
tryIt(rng, "nextFloat(" + N + ")", (String id) -> () -> testRngChiSquared(id, N, () -> (int)(rng.nextFloat(N)) % N));
|
||||
tryIt(rng, "nextFloat(43, " + (N+43) + ")", (String id) -> () -> testRngChiSquared(id, N, () -> (int)(rng.nextFloat(43, N+43) - 43) % N));
|
||||
tryIt(rng, "nextFloat(-59, " + (N-59) + ")", (String id) -> () -> testRngChiSquared(id, N, () -> (int)(rng.nextFloat(-59, N-59) + 59) % N));
|
||||
}
|
||||
for (int j = 0; j < testSizes.length; j++) {
|
||||
int N = testSizes[j];
|
||||
tryIt(rng, "nextDouble(" + N + ")", (String id) -> () -> testRngChiSquared(id, N, () -> (int)(rng.nextDouble(N)) % N));
|
||||
tryIt(rng, "nextDouble(43, " + (N+43) + ")", (String id) -> () -> testRngChiSquared(id, N, () -> (int)(rng.nextDouble(43, N+43) - 43) % N));
|
||||
tryIt(rng, "nextDouble(-59, " + (N-59) + ")", (String id) -> () -> testRngChiSquared(id, N, () -> (int)(rng.nextDouble(-59, N-59) + 59) % N));
|
||||
}
|
||||
for (int j = 0; j < testSizes.length; j++) {
|
||||
int N = testSizes[j];
|
||||
PrimitiveIterator.OfInt iter1 = rng.ints(0, N).iterator();
|
||||
tryIt(rng, "ints(0, " + N + ")", (String id) -> () -> testRngChiSquared(id, N, iter1::next));
|
||||
PrimitiveIterator.OfInt iter2 = rng.ints(43, N+43).iterator();
|
||||
tryIt(rng, "ints(43, " + (N+43) + ")", (String id) -> () -> testRngChiSquared(id, N, () -> iter2.next() - 43));
|
||||
PrimitiveIterator.OfInt iter3 = rng.ints(-59, N-59).iterator();
|
||||
tryIt(rng, "ints(-59, " + (N-59) + ")", (String id) -> () -> testRngChiSquared(id, N, () -> iter3.next() + 59));
|
||||
}
|
||||
for (int j = 0; j < testSizes.length; j++) {
|
||||
int N = testSizes[j];
|
||||
PrimitiveIterator.OfLong iter1 = rng.longs(0, N).iterator();
|
||||
tryIt(rng, "longs(0, " + N + ")", (String id) -> () -> testRngChiSquared(id, N, () -> (int)(iter1.next() + 0)));
|
||||
PrimitiveIterator.OfLong iter2 = rng.longs(43, N+43).iterator();
|
||||
tryIt(rng, "longs(43, " + (N+43) + ")", (String id) -> () -> testRngChiSquared(id, N, () -> (int)(iter2.next() - 43)));
|
||||
PrimitiveIterator.OfLong iter3 = rng.longs(-59, N-59).iterator();
|
||||
tryIt(rng, "longs(-59, " + (N-59) + ")", (String id) -> () -> testRngChiSquared(id, N, () -> (int)(iter3.next() + 59)));
|
||||
}
|
||||
for (int j = 0; j < testSizes.length; j++) {
|
||||
int N = testSizes[j];
|
||||
PrimitiveIterator.OfDouble iter1 = rng.doubles(0, N).iterator();
|
||||
tryIt(rng, "doubles(0, " + N + ")", (String id) -> () -> testRngChiSquared(id, N, () -> (int)(iter1.next() + 0) % N));
|
||||
PrimitiveIterator.OfDouble iter2 = rng.doubles(43, N+43).iterator();
|
||||
tryIt(rng, "doubles(43, " + (N+43) + ")", (String id) -> () -> testRngChiSquared(id, N, () -> (int)(iter2.next() - 43) % N));
|
||||
PrimitiveIterator.OfDouble iter3 = rng.doubles(-59, N-59).iterator();
|
||||
tryIt(rng, "doubles(-59, " + (N-59) + ")", (String id) -> () -> testRngChiSquared(id, N, () -> (int)(iter3.next() + 59) % N));
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
RandomGeneratorFactory.all()
|
||||
.filter(f -> !f.name().equals("SecureRandom"))
|
||||
.forEach(factory -> {
|
||||
setRNG(factory.name());
|
||||
|
||||
if (factory.name().equals("Random")) {
|
||||
testOneRng(factory.create(417), 1);
|
||||
} else {
|
||||
testOneRng(factory.create(417), 0);
|
||||
}
|
||||
});
|
||||
|
||||
exceptionOnFail();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
248
test/jdk/java/util/Random/RandomTestCoverage.java
Normal file
248
test/jdk/java/util/Random/RandomTestCoverage.java
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* 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<RandomGenerator> 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<RandomGenerator> rngs1 = rng.rngs();
|
||||
Stream<RandomGenerator> rngs2 = rng.rngs(5L);
|
||||
}
|
||||
|
||||
static void coverSplittable(SplittableGenerator rng) {
|
||||
SplittableGenerator s1 = rng.split();
|
||||
SplittableGenerator s2 = rng.split(rng);
|
||||
Stream<SplittableGenerator> s3 = rng.splits();
|
||||
Stream<SplittableGenerator> s4 = rng.splits(5L);
|
||||
Stream<SplittableGenerator> s5 = rng.splits(rng);
|
||||
Stream<SplittableGenerator> 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<RandomGenerator> j3 = rng.jumps();
|
||||
Stream<RandomGenerator> j4 = rng.jumps(5L);
|
||||
}
|
||||
|
||||
static void coverLeapable(LeapableGenerator rng) {
|
||||
LeapableGenerator l1 = rng.copy();
|
||||
rng.leap();
|
||||
JumpableGenerator l2 = rng.copyAndLeap();
|
||||
double d = rng.leapDistance();
|
||||
Stream<JumpableGenerator> l3 = rng.leaps();
|
||||
Stream<JumpableGenerator> 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<ArbitrarilyJumpableGenerator> a4 = rng.jumps(1.2345);
|
||||
Stream<ArbitrarilyJumpableGenerator> a5 = rng.jumps(5L, 1.2345);
|
||||
|
||||
}
|
||||
|
||||
static void coverOf(String name) {
|
||||
coverRandomGenerator(RandomGenerator.of(name));
|
||||
coverFactory(RandomGeneratorFactory.of(name));
|
||||
}
|
||||
|
||||
static void coverFactory(RandomGeneratorFactory<RandomGenerator> 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<RandomGenerator> 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();
|
||||
}
|
||||
}
|
||||
206
test/jdk/java/util/Random/RandomTestMoments.java
Normal file
206
test/jdk/java/util/Random/RandomTestMoments.java
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2021, 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.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import java.util.random.*;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.DoubleSupplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary test bit sequences produced by clases that implement interface RandomGenerator
|
||||
* @bug 8248862
|
||||
* @run main RandomTestMoments
|
||||
* @author Guy Steele
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
public class RandomTestMoments {
|
||||
|
||||
static String currentRNG = "";
|
||||
static int failCount = 0;
|
||||
|
||||
static void exceptionOnFail() {
|
||||
if (failCount != 0) {
|
||||
throw new RuntimeException(failCount + " fails detected");
|
||||
}
|
||||
}
|
||||
|
||||
static void setRNG(String rng) {
|
||||
currentRNG = rng;
|
||||
}
|
||||
|
||||
static void fail(String format, Object... args) {
|
||||
if (currentRNG.length() != 0) {
|
||||
System.err.println(currentRNG);
|
||||
currentRNG = "";
|
||||
}
|
||||
|
||||
System.err.format(" " + format, args);
|
||||
failCount++;
|
||||
}
|
||||
|
||||
static final int SEQUENCE_SIZE = 50000;
|
||||
|
||||
// Moment k of uniform distribution over [0.0,1.0) is 1.0/(1+k).
|
||||
|
||||
static double[][] momentsUniform = {
|
||||
{ 1.00000, 1.00000, 0.01000 },
|
||||
{ 0.500000, 0.500000, 0.0266265 },
|
||||
{ 0.333333, 0.333333, 0.0391128 },
|
||||
{ 0.250000, 0.250000, 0.0477151 },
|
||||
{ 0.200000, 0.200000, 0.0540496 },
|
||||
{ 0.166667, 0.166667, 0.0589355 },
|
||||
{ 0.142857, 0.142857, 0.0628462 },
|
||||
{ 0.125000, 0.125000, 0.0660693 },
|
||||
{ 0.111111, 0.111111, 0.0688036 },
|
||||
{ 0.100000, 0.100000, 0.0712002 },
|
||||
{ 0.0909091, 0.0909091, 0.0733755 },
|
||||
{ 0.0833333, 0.0833333, 0.0754172 },
|
||||
{ 0.0769231, 0.0769231, 0.0773868 },
|
||||
{ 0.0714286, 0.0714286, 0.0793244 },
|
||||
{ 0.0666667, 0.0666667, 0.0812526 },
|
||||
{ 0.0625000, 0.0625000, 0.0831806 },
|
||||
};
|
||||
|
||||
// Moment k of exponential distribution with mean 1 is k!.
|
||||
|
||||
static double[][] momentsExponential = {
|
||||
{ 1.00000, 1.00000, 0.01000 },
|
||||
{ 1.00000, 1.00000, 0.0718997 },
|
||||
{ 2.00000, 2.00000, 0.153241 },
|
||||
{ 6.00000, 6.00000, 0.282813 },
|
||||
{ 24.0000, 24.0000, 0.503707 },
|
||||
};
|
||||
|
||||
|
||||
// Absolute moment k of Gaussian distribution with mean 0 and stddev 1 is
|
||||
// pow(2.0,k/2.0)*gamma((k+1)/2.0)/sqrt(PI)
|
||||
// https://arxiv.org/pdf/1209.4340.pdf, equation (18)
|
||||
|
||||
static double[][] absoluteMomentsGaussian = {
|
||||
{ 1.00000, 1.00000, 0.01 },
|
||||
{ 0.797885, 0.797885, 0.1 },
|
||||
{ 1.00000, 1.00000, 0.1 },
|
||||
{ 1.59577, 1.59577, 0.2 },
|
||||
{ 3.00000, 3.00000, 0.2 },
|
||||
{ 6.38308, 6.38308, 0.2 },
|
||||
{ 15.0000, 15.0000, 0.2 },
|
||||
{ 38.2985, 38.2985, 0.2 },
|
||||
{ 105.000, 105.000, 0.4 },
|
||||
};
|
||||
|
||||
static void checkMoments(String test, double[] measurements, double[][] standard) {
|
||||
for (int j = 0; j < measurements.length; j++) {
|
||||
double actual = measurements[j];
|
||||
double expected = standard[j][0];
|
||||
double basis = standard[j][1];
|
||||
double tolerance = standard[j][2];
|
||||
if (!(Math.abs(actual - expected)/basis < tolerance)) {
|
||||
fail("%s fail: actual=%f, expected=%f, basis=%f, tolerance=%f\n",
|
||||
test, actual, expected, basis, tolerance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testMomentsGaussian(DoubleSupplier theSupplier) {
|
||||
int m = absoluteMomentsGaussian.length;
|
||||
double[] absoluteMoments = new double[m];
|
||||
for (int j = 0; j < SEQUENCE_SIZE; j++) {
|
||||
double v = theSupplier.getAsDouble();
|
||||
double z = 1.0;
|
||||
for (int k = 0; k < m; k++) {
|
||||
absoluteMoments[k] += Math.abs(z);
|
||||
z *= v;
|
||||
}
|
||||
}
|
||||
for (int k = 0; k < m; k++) {
|
||||
absoluteMoments[k] /= SEQUENCE_SIZE;
|
||||
}
|
||||
checkMoments("Gaussian", absoluteMoments, absoluteMomentsGaussian);
|
||||
}
|
||||
|
||||
static void testMomentsExponential(DoubleSupplier theSupplier) {
|
||||
int m = momentsExponential.length;
|
||||
double[] moments = new double[m];
|
||||
for (int j = 0; j < SEQUENCE_SIZE; j++) {
|
||||
double v = theSupplier.getAsDouble();
|
||||
double z = 1.0;
|
||||
for (int k = 0; k < m; k++) {
|
||||
moments[k] += z;
|
||||
z *= v;
|
||||
}
|
||||
}
|
||||
for (int k = 0; k < m; k++) {
|
||||
moments[k] /= SEQUENCE_SIZE;
|
||||
}
|
||||
checkMoments("Exponential", moments, momentsExponential);
|
||||
}
|
||||
|
||||
static void testMomentsUniform(DoubleSupplier theSupplier) {
|
||||
int m = momentsUniform.length;
|
||||
double[] moments = new double[m];
|
||||
for (int j = 0; j < SEQUENCE_SIZE; j++) {
|
||||
double v = theSupplier.getAsDouble();
|
||||
double z = 1.0;
|
||||
for (int k = 0; k < m; k++) {
|
||||
moments[k] += z;
|
||||
z *= v;
|
||||
}
|
||||
}
|
||||
for (int k = 0; k < m; k++) {
|
||||
moments[k] /= SEQUENCE_SIZE;
|
||||
}
|
||||
checkMoments("Uniform", moments, momentsUniform);
|
||||
}
|
||||
|
||||
static void testOneRng(RandomGenerator rng) {
|
||||
testMomentsGaussian(rng::nextGaussian);
|
||||
testMomentsExponential(rng::nextExponential);
|
||||
testMomentsUniform(rng::nextDouble);
|
||||
testMomentsUniform(rng.doubles().iterator()::next);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
RandomGeneratorFactory.all()
|
||||
.filter(f -> !f.name().equals("SecureRandom"))
|
||||
.forEach(factory -> {
|
||||
setRNG(factory.name());
|
||||
testOneRng(factory.create(325) );
|
||||
});
|
||||
|
||||
exceptionOnFail();
|
||||
}
|
||||
|
||||
}
|
||||
110
test/jdk/java/util/Random/T8282144.java
Normal file
110
test/jdk/java/util/Random/T8282144.java
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (c) 2022, 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.util.random.*;
|
||||
import jdk.internal.util.random.RandomSupport;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary RandomSupport.convertSeedBytesToLongs sign extension overwrites previous bytes.
|
||||
* @bug 8282144 8294509
|
||||
* @modules java.base/jdk.internal.util.random
|
||||
* @run main T8282144
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
|
||||
public class T8282144 {
|
||||
public static void main(String[] args) {
|
||||
testLongs();
|
||||
testInts();
|
||||
}
|
||||
|
||||
private static void testLongs() {
|
||||
RandomGenerator rng = RandomGeneratorFactory.of("L64X128MixRandom").create(42);
|
||||
|
||||
for (int i = 1; i < 8; i++) {
|
||||
byte[] seed = new byte[i];
|
||||
|
||||
for (int j = 0; j < 10; j++) {
|
||||
rng.nextBytes(seed);
|
||||
|
||||
long[] existing = RandomSupport.convertSeedBytesToLongs(seed, 1, 1);
|
||||
long[] testing = convertSeedBytesToLongsFixed(seed, 1, 1);
|
||||
|
||||
for (int k = 0; k < existing.length; k++) {
|
||||
if (existing[k] != testing[k]) {
|
||||
throw new RuntimeException("convertSeedBytesToLongs incorrect");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testInts() {
|
||||
RandomGenerator rng = RandomGeneratorFactory.of("L64X128MixRandom").create(42);
|
||||
|
||||
for (int i = 1; i < 8; i++) {
|
||||
byte[] seed = new byte[i];
|
||||
|
||||
for (int j = 0; j < 10; j++) {
|
||||
rng.nextBytes(seed);
|
||||
|
||||
int[] existing = RandomSupport.convertSeedBytesToInts(seed, 1, 1);
|
||||
int[] testing = convertSeedBytesToIntsFixed(seed, 1, 1);
|
||||
|
||||
for (int k = 0; k < existing.length; k++) {
|
||||
if (existing[k] != testing[k]) {
|
||||
throw new RuntimeException("convertSeedBytesToInts incorrect");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static long[] convertSeedBytesToLongsFixed(byte[] seed, int n, int z) {
|
||||
final long[] result = new long[n];
|
||||
final int m = Math.min(seed.length, n << 3);
|
||||
|
||||
// Distribute seed bytes into the words to be formed.
|
||||
for (int j = 0; j < m; j++) {
|
||||
result[j >> 3] = (result[j >> 3] << 8) | (seed[j] & 0xff);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int[] convertSeedBytesToIntsFixed(byte[] seed, int n, int z) {
|
||||
final int[] result = new int[n];
|
||||
final int m = Math.min(seed.length, n << 2);
|
||||
|
||||
// Distribute seed bytes into the words to be formed.
|
||||
for (int j = 0; j < m; j++) {
|
||||
result[j >> 2] = (result[j >> 2] << 8) | (seed[j] & 0xff);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue