MATH-1608: Remove random string generator.
Functionality is out-of-scope (cf. "Commons Codec").
This commit is contained in:
parent
bdc4a527fb
commit
24b1d86ffb
|
@ -62,120 +62,6 @@ public class RandomUtils {
|
|||
this.rng = rng;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random string of hex characters of length {@code len}.
|
||||
*
|
||||
* <strong>Algorithm Description:</strong> how hexadecimal strings are
|
||||
* generated depends on the value of the {@code useSha1} argument.
|
||||
*
|
||||
* <ul>
|
||||
* <li>If {@code useSha1 == false}, a 2-step process is used:
|
||||
* <ol>
|
||||
* <li>
|
||||
* {@code len / 2 + 1} binary bytes are generated using the underlying
|
||||
* generator.
|
||||
* </li>
|
||||
* <li>
|
||||
* Each binary byte is translated into 2 hex digits.
|
||||
* </li>
|
||||
* </ol>
|
||||
* </li>
|
||||
* <li>
|
||||
* If {@code useSha1 == true}, hex strings are generated in 40-byte
|
||||
* segments using a 3-step process:
|
||||
* <ol>
|
||||
* <li>
|
||||
* 20 random bytes are generated using the underlying generator.
|
||||
* </li>
|
||||
* <li>
|
||||
* SHA-1 hash is applied to yield a 20-byte binary digest.
|
||||
* </li>
|
||||
* <li>
|
||||
* Each byte of the binary digest is converted to 2 hex digits.
|
||||
* </li>
|
||||
* </ol>
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @param len Length of the generated string.
|
||||
* @param useSha1 Whether to use a digest.
|
||||
* If {@code true} (resp. {@code false}), the 3-step (resp. 2-step)
|
||||
* process will be used.
|
||||
* @return the random string.
|
||||
* @throws NotStrictlyPositiveException if {@code len <= 0}.
|
||||
*/
|
||||
public String nextHexString(int len,
|
||||
boolean useSha1) {
|
||||
if (len <= 0) {
|
||||
throw new NotStrictlyPositiveException(LocalizedFormats.LENGTH, len);
|
||||
}
|
||||
|
||||
// Initialize output buffer.
|
||||
final StringBuilder outBuffer = new StringBuilder();
|
||||
|
||||
if (!useSha1) {
|
||||
// Generate int(len/2)+1 random bytes.
|
||||
final byte[] randomBytes = new byte[(len / 2) + 1];
|
||||
rng.nextBytes(randomBytes);
|
||||
|
||||
// Convert each byte to 2 hex digits.
|
||||
for (int i = 0; i < randomBytes.length; i++) {
|
||||
final Integer c = Integer.valueOf(randomBytes[i]);
|
||||
|
||||
// Add 128 to byte value to make interval 0-255 before
|
||||
// conversion to hex.
|
||||
// This guarantees <= 2 hex digits from "toHexString".
|
||||
// "toHexString" would otherwise add 2^32 to negative arguments.
|
||||
String hex = Integer.toHexString(c.intValue() + 128);
|
||||
|
||||
// Make sure we add 2 hex digits for each byte.
|
||||
if (hex.length() == 1) {
|
||||
hex = "0" + hex;
|
||||
}
|
||||
outBuffer.append(hex);
|
||||
}
|
||||
} else {
|
||||
MessageDigest alg = null;
|
||||
try {
|
||||
alg = MessageDigest.getInstance("SHA-1");
|
||||
} catch (NoSuchAlgorithmException ex) {
|
||||
// Should never happen.
|
||||
throw new MathInternalError(ex);
|
||||
}
|
||||
alg.reset();
|
||||
|
||||
// Compute number of iterations required (40 bytes each).
|
||||
final int numIter = (len / 40) + 1;
|
||||
|
||||
for (int iter = 1; iter < numIter + 1; iter++) {
|
||||
final byte[] randomBytes = new byte[40];
|
||||
rng.nextBytes(randomBytes);
|
||||
alg.update(randomBytes);
|
||||
|
||||
// Create 20-byte binary hash.
|
||||
final byte[] hash = alg.digest();
|
||||
|
||||
// Loop over the hash, converting each byte to 2 hex digits
|
||||
for (int i = 0; i < hash.length; i++) {
|
||||
final Integer c = Integer.valueOf(hash[i]);
|
||||
|
||||
// Add 128 to byte value to make interval 0-255.
|
||||
// This guarantees <= 2 hex digits from "toHexString".
|
||||
// "toHexString" would otherwise add 2^32 to negative arguments.
|
||||
String hex = Integer.toHexString(c.intValue() + 128);
|
||||
|
||||
// Keep strings uniform length: guarantees 40 bytes.
|
||||
if (hex.length() == 1) {
|
||||
hex = "0" + hex;
|
||||
}
|
||||
outBuffer.append(hex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outBuffer.toString().substring(0, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a uniformly distributed random long integer between {@code lower}
|
||||
* and {@code upper} (endpoints included).
|
||||
|
|
|
@ -136,65 +136,6 @@ public abstract class RandomUtilsDataGeneratorAbstractTest {
|
|||
(((double) upper) - ((double) lower));
|
||||
Assert.assertTrue(ratio > 0.99999);
|
||||
}
|
||||
|
||||
/** Test dispersion and failure modes for "nextHex". */
|
||||
@Test
|
||||
public void testNextHexWithoutSha1() {
|
||||
checkNextHex(false);
|
||||
}
|
||||
@Test
|
||||
public void testNextHexWithSha1() {
|
||||
checkNextHex(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param useSha1 Alternative.
|
||||
*/
|
||||
private void checkNextHex(boolean useSha1) {
|
||||
try {
|
||||
randomData.nextHexString(-1, useSha1);
|
||||
Assert.fail("negative length supplied -- MathIllegalArgumentException expected");
|
||||
} catch (MathIllegalArgumentException ex) {
|
||||
// ignored
|
||||
}
|
||||
try {
|
||||
randomData.nextHexString(0, useSha1);
|
||||
Assert.fail("zero length supplied -- MathIllegalArgumentException expected");
|
||||
} catch (MathIllegalArgumentException ex) {
|
||||
// ignored
|
||||
}
|
||||
String hexString = randomData.nextHexString(3, useSha1);
|
||||
if (hexString.length() != 3) {
|
||||
Assert.fail("incorrect length for generated string");
|
||||
}
|
||||
hexString = randomData.nextHexString(1, useSha1);
|
||||
if (hexString.length() != 1) {
|
||||
Assert.fail("incorrect length for generated string");
|
||||
}
|
||||
try {
|
||||
hexString = randomData.nextHexString(0, useSha1);
|
||||
Assert.fail("zero length requested -- expecting MathIllegalArgumentException");
|
||||
} catch (MathIllegalArgumentException ex) {
|
||||
// ignored
|
||||
}
|
||||
Frequency<String> f = new Frequency<>();
|
||||
for (int i = 0; i < smallSampleSize; i++) {
|
||||
hexString = randomData.nextHexString(100, useSha1);
|
||||
if (hexString.length() != 100) {
|
||||
Assert.fail("incorrect length for generated string");
|
||||
}
|
||||
for (int j = 0; j < hexString.length(); j++) {
|
||||
f.addValue(hexString.substring(j, j + 1));
|
||||
}
|
||||
}
|
||||
double[] expected = new double[16];
|
||||
long[] observed = new long[16];
|
||||
for (int i = 0; i < 16; i++) {
|
||||
expected[i] = (double) smallSampleSize * 100 / 16;
|
||||
observed[i] = f.getCount(hex[i]);
|
||||
}
|
||||
TestUtils.assertChiSquareAccept(expected, observed, 0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNextUniformIAE() {
|
||||
|
|
Loading…
Reference in New Issue