package com.comphenix.xp;
import static org.junit.Assert.*;
import java.util.Random;
import org.junit.BeforeClass;
import org.junit.Test;
public class RangeTest {
private static final int REPEAT_COUNT = 1000000;
private static Random rnd;
@BeforeClass
public static void oneTimeSetUp() {
// Initialize random source
rnd = new Random();
}
@Test
public void testRandom() {
// Generate a random range
int start = rnd.nextInt(10);
int stop = start + 1 + rnd.nextInt(20);
SampleRange range = new SampleRange(start, stop);
int[] results = SampleValues(range, REPEAT_COUNT);
double average = getAverage(results);
double std = getStandardDeviation(average, results) / average;
if (std > 0.1) {
fail(String.format("Standard deviation (%f) is greater than 10 procent.", std));
}
}
@Test
public void testSpecific() {
SampleRange range = new SampleRange(0.1, 0.1);
int[] results = SampleValues(range, REPEAT_COUNT);
// "0" should occur approximately 90%.
double rate = results[0] / (double) REPEAT_COUNT;
if (Math.abs(rate - 0.9) > 0.1)
fail("The number 0 didn't occur 90% in the range 0 - 0.1");
}
@Test
public void testUnbiased() {
SampleRange range = new SampleRange(0.1, 0.5);
int[] counts = SampleValues(range, REPEAT_COUNT);
// The expected value (average)
double expected = (range.getStart() + range.getEnd()) / 2.0;
double average = counts[1] / (double) REPEAT_COUNT; // results[0] * 0
if (Math.abs(expected - average) > 0.1) {
fail("Expected value differs too much.");
}
}
@Test
public void testSmallRange() {
SampleRange range = new SampleRange(0.9, 3.1);
int[] counts = SampleValues(range, REPEAT_COUNT);
double expected = 0.1 / (3.1 - 0.9);
double actual = counts[0] / (double) REPEAT_COUNT;
if (Math.abs(expected - actual) > 0.1) {
fail("Small range value differs too much.");
}
}
private int[] SampleValues(SampleRange range, int count) {
int start = range.getMinimum();
int stop = range.getMaximum();
// Storage of results (stop is inclusive)
int[] results = new int[stop - start + 1];
for (int i = 0; i < count; i++) {
int value = range.sampleInt(rnd);
if (value >= start && value <= stop)
results[value - start]++;
else
fail(String.format("Outside of range [%d, %d] with value %d", start, stop, value));
}
return results;
}
private double getAverage(int[] numbers) {
double sum = 0;
// Find total sum
for (int i = 0; i < numbers.length; i++) {
sum += numbers[i];
}
return sum / (double)numbers.length;
}
private double getStandardDeviation(double average, int[] numbers) {
double sum = 0;
// Sum of squares
for (int i = 0; i < numbers.length; i++) {
sum += (numbers[i] - average) * (numbers[i] - average);
}
return Math.sqrt(sum / numbers.length);
}
}