/*
* Copyright 2015-2016 Cel Skeggs
*
* This file is part of the CCRE, the Common Chicken Runtime Engine.
*
* The CCRE is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* The CCRE 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 Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the CCRE. If not, see <http://www.gnu.org/licenses/>.
*/
package ccre.util;
import java.util.Random;
/**
* A class that provides useful sets of values and methods for generating them,
* which may be used in unit tests.
*
* Some of these may be random, and some may be pregenerated sequences that hit
* all of the major edge cases.
*
* @author skeggsc
*/
public class Values {
private static final Random random = new Random();
/**
* Creates and return a random string of up to length 9.
*
* Characters are chosen to be weighted towards ASCII characters, especially
* control characters.
*
* @return the generated String.
*/
public static String getRandomString() {
char[] chrs = new char[random.nextInt(10)];
for (int i = 0; i < chrs.length; i++) {
chrs[i] = (char) (random.nextBoolean() ? random.nextBoolean() ? random.nextInt(0xAFFF) : random.nextInt(256) : random.nextInt(33));
}
return new String(chrs);
}
/**
* Creates and returns an array of <code>n</code> random strings of up to
* length 9.
*
* @param n the number of strings to generate.
* @see #getRandomString() for how these strings are generated.
* @return the generated strings.
*/
public static String[] getRandomStrings(int n) {
String[] strs = new String[n];
for (int i = 0; i < n; i++) {
strs[i] = getRandomString();
}
return strs;
}
/**
* Generates a random array of <code>length</code> bytes, mostly evenly
* distributed.
*
* @param length the number of bytes to generate.
* @return the generated bytes.
*/
public static byte[] getRandomBytes(int length) {
byte[] bytes = new byte[length];
random.nextBytes(bytes);
return bytes;
}
/**
* Generates a random array of bytes, somewhere from length
* <code>minlen</code> to length <code>maxlen</code>, inclusive.
*
* @see #getRandomBytes(int) for details on how random bytes are generated.
* @param minlen the minimum number of bytes to generate.
* @param maxlen the maximum number of bytes to generate.
* @return the generated bytes.
*/
public static byte[] getRandomBytes(int minlen, int maxlen) {
return getRandomBytes(random.nextInt(maxlen - minlen + 1) + minlen);
}
/**
* Generates an array of random random arrays of bytes, somewhere from
* length <code>minlen</code> to length <code>maxlen</code>, inclusive.
* <code>count</code> is the count of the number of arrays generated.
*
* @see #getRandomBytes(int, int) for details on how random byte arrays are
* generated.
* @param count the number of byte arrays to generate.
* @param minlen the minimum number of bytes to generate.
* @param maxlen the maximum number of bytes to generate.
* @return the generated bytes.
*/
public static byte[][] getRandomByteses(int count, int minlen, int maxlen) {
byte[][] byteses = new byte[count][];
for (int i = 0; i < count; i++) {
byteses[i] = getRandomBytes(minlen, maxlen);
}
return byteses;
}
/**
* Generates a random boolean.
*
* @return the random boolean.
*/
public static boolean getRandomBoolean() {
return random.nextBoolean();
}
/**
* Generates a random integer, no less than zero and smaller than
* <code>bound</code>.
*
* @param bound the upper bound, exclusive.
* @return the random boolean.
*/
public static int getRandomInt(int bound) {
return random.nextInt(bound);
}
/**
* Generates a random float. May include numbers like NaN, infinity,
* MAX_VALUE, or 0.
*
* @return the random float.
*/
public static float getRandomFloat() {
return (float) (interestingFloats[random.nextInt(interestingFloats.length)] * random.nextGaussian() * 1.5f);
}
/**
* A sequence of interesting floats for testing edge cases: things like
* negative infinity, NaN, MAX_VALUE, -MAX_VALUE, 0, 1, -1, etc.
*
* @see Values#shorterInterestingFloats
* @see Values#lessInterestingFloats
* @see Values#interestingBooleans
*/
public static final float[] interestingFloats = new float[] { Float.NEGATIVE_INFINITY, -Float.MAX_VALUE, -1024.7f, -32f, -6.3f, -1.1f, -1f, -0.7f, -0.3f, -0.1f, -0.001f, -Float.MIN_VALUE, -0.0f, +0.0f, Float.NaN, Float.MIN_VALUE, 0.001f, 0.1f, 0.3f, 0.7f, 1.0f, 1.1f, 6.3f, 32f, 1024.7f, Float.MAX_VALUE, Float.POSITIVE_INFINITY };
/**
* A shorter sequence of interesting floats for testing edge cases: things
* like negative infinity, NaN, MAX_VALUE, -MAX_VALUE, 0, 1, -1, etc.
*
* @see Values#interestingFloats
* @see Values#lessInterestingFloats
* @see Values#interestingBooleans
*/
public static final float[] shorterInterestingFloats = new float[] { Float.NEGATIVE_INFINITY, -Float.MAX_VALUE, -32f, -1.1f, -1f, -0.1f, -Float.MIN_VALUE, -0.0f, +0.0f, Float.NaN, Float.MIN_VALUE, 0.1f, 1.0f, 1.1f, 32f, Float.MAX_VALUE, Float.POSITIVE_INFINITY };
/**
* A sequence of slightly less interesting floats for testing edge cases:
* this is like {@link #interestingFloats}, but with only finite values not
* near MAX_VALUE in magnitude.
*
* @see Values#interestingFloats
* @see Values#shorterInterestingFloats
*/
public static final float[] lessInterestingFloats = new float[] { -1024.7f, -32f, -6.3f, -1.1f, -1f, -0.7f, -0.5f, -0.3f, -0.1f, -0.001f, -Float.MIN_VALUE, 0, Float.NaN, Float.MIN_VALUE, 0.001f, 0.1f, 0.3f, 0.5f, 0.7f, 1.0f, 1.1f, 6.3f, 32f, 1024.7f };
/**
* A sequence of booleans in an interesting sequence: mostly, toggling and
* longer periods of toggling.
*
* @see Values#interestingFloats
*/
public static final boolean[] interestingBooleans = new boolean[] { false, true, true, false, false, true, false, true, false, true, true, true, false, true, false, false, false, true };
}