package tc.oc.commons.random;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import com.google.common.collect.Range;
import org.junit.Test;
import tc.oc.commons.core.random.Entropy;
import tc.oc.commons.core.random.MutableEntropy;
import tc.oc.commons.core.util.Ranges;
import static org.junit.Assert.*;
import static tc.oc.test.Assert.*;
public class EntropyTest {
// Make the tests repeatable
private static final long SEED = 4512060816665834742L;
@Test
public void doubleRange() throws Exception {
Entropy e = new MutableEntropy(SEED);
double min = Double.POSITIVE_INFINITY, max = Double.NEGATIVE_INFINITY;
// Choose 10k values and track the min and max
for(int i = 0; i < 10000; i++) {
final double n = e.randomDouble();
min = Math.min(min, n);
max = Math.max(max, n);
e.advance();
}
// Assert that no value was outside the valid range
assertTrue(min >= 0);
assertTrue(max < 1);
// Assert that the min and max values pretty close to 0 and 1
assertEquals(0, min, 0.01);
assertEquals(1, max, 0.01);
}
@Test
public void intRange() throws Exception {
Entropy e = new MutableEntropy(SEED);
Range<Integer> range = Range.closedOpen(-5, 5);
Multiset<Integer> distribution = HashMultiset.create();
// Choose 1k values and check that they are in the range
for(int i = 0; i < 10000; i++) {
final int value = e.randomInt(range);
assertContains(range, value);
distribution.add(value);
e.advance();
}
// Assert that each of the 10 values was chosen ~1000 times
Ranges.forEach(range, value -> {
assertEquals(1000D, distribution.count(value), 50D);
});
}
@Test
public void advance() throws Exception {
Entropy e = new MutableEntropy();
final double d = e.randomDouble();
assertEquals(d, e.randomDouble(), 0);
e.advance();
assertNotEquals(d, e.randomDouble(), 0);
}
}