package com.yahoo.dtf.junit;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Random;
import junit.framework.JUnit4TestAdapter;
import junit.framework.TestCase;
import org.junit.BeforeClass;
import org.junit.Test;
import com.yahoo.dtf.DTFNode;
import com.yahoo.dtf.exception.DTFException;
import com.yahoo.dtf.exception.ParseException;
import com.yahoo.dtf.exception.PropertyException;
import com.yahoo.dtf.util.DTFRandom;
/**
*
* @author rlgomes
*/
public class RandomGenSuite extends DTFJUnitTest {
private NumberFormat percentage = new DecimalFormat("##.00");
private long seed = System.nanoTime();
private Random[] gens = new Random[]{ new Random(seed),
new DTFRandom(seed),
};
@BeforeClass
public static void setup() {
try {
DTFNode.init();
} catch (PropertyException e) {
e.printStackTrace();
TestCase.fail("Unable to retrieve proprety.");
} catch (ParseException e) {
e.printStackTrace();
TestCase.fail("Unable to retrieve proprety.");
} catch (DTFException e) {
e.printStackTrace();
TestCase.fail("Unable to init DTF.");
}
}
@Test(timeout=600000)
public void distributionTestForSmallDataset() throws PropertyException, ParseException {
getLogger().info("Small Dataset Distribution");
int samplesize = 10;
long iterations = getConfig().getPropertyAsInt("iterations",1000);
for (int r = 0; r < gens.length; r++) {
int[] occurences = new int[samplesize];
Random rand = gens[r];
String rname = rand.getClass().getSimpleName();
for (int i = 0; i < iterations; i++) {
occurences[rand.nextInt(samplesize)]++;
}
double max = Float.MIN_VALUE;
double ideal = (double)iterations/samplesize;
for (int i = 0; i < samplesize; i++) {
double diff = 0;
if ( ideal > occurences[i] )
diff = ideal - occurences[i];
else
diff = occurences[i] - ideal;
if ( diff > max )
max = diff;
}
getLogger().info(rname + " offby " +
percentage.format((max/ideal)*100.0f) + "%");
}
}
@Test(timeout=600000)
public void distributionTestForLargeDataset() throws PropertyException, ParseException {
getLogger().info("Large Dataset Distribution");
int samplesize = 10;
long iterations = getConfig().getPropertyAsInt("iterations",10000000);
for (int r = 0; r < gens.length; r++) {
int[] occurences = new int[samplesize];
Random rand = gens[r];
String rname = rand.getClass().getSimpleName();
for (int i = 0; i < iterations; i++) {
occurences[rand.nextInt(samplesize)]++;
}
double max = Float.MIN_VALUE;
double ideal = (float)iterations/samplesize;
for (int i = 0; i < samplesize; i++) {
double diff = 0;
if ( ideal > occurences[i] )
diff = ideal - occurences[i];
else
diff = occurences[i] - ideal;
if ( diff > max )
max = diff;
}
getLogger().info(rname + " offby " +
percentage.format((max/ideal)*100.0f) + "%");
}
}
@Test(timeout=600000)
public void nextIntPerformanceTest() throws PropertyException, ParseException {
long iterations = getConfig().getPropertyAsInt("iterations",10000000);
for (int r = 0; r < gens.length; r++) {
Random rand = gens[r];
String rname = rand.getClass().getSimpleName();
long start = System.currentTimeMillis();
for (long i = 0; i < iterations; i++) {
rand.nextInt();
}
long stop = System.currentTimeMillis();
double duration = (stop-start)/1000.0f;
getLogger().info(rname + " ops/sec: " + (int)(iterations/duration));
}
}
@Test(timeout=600000)
public void nextLongPerformanceTest() throws PropertyException, ParseException {
long iterations = getConfig().getPropertyAsInt("iterations",10000000);
for (int r = 0; r < gens.length; r++) {
Random rand = gens[r];
String rname = rand.getClass().getSimpleName();
long start = System.currentTimeMillis();
for (long i = 0; i < iterations; i++) {
rand.nextLong();
}
long stop = System.currentTimeMillis();
double duration = (stop-start)/1000.0f;
getLogger().info(rname + " ops/sec: " + (int)(iterations/duration));
}
}
@Test(timeout=600000)
public void nextBytesThroughputPerformanceTest() throws PropertyException, ParseException {
long iterations = getConfig().getPropertyAsInt("iterations",4096);
int size = 32*1024;
for (int r = 0; r < gens.length; r++) {
Random rand = gens[r];
String rname = rand.getClass().getSimpleName();
byte[] bytes = new byte[size];
long start = System.currentTimeMillis();
for (long i = 0; i < iterations; i++) {
rand.nextBytes(bytes);
}
long stop = System.currentTimeMillis();
double duration = (stop-start)/1000.0f;
getLogger().info(rname + " bytes/sec: " + (int)((iterations*size)/duration));
}
}
@Test(timeout=600000)
public void validateDataTest() throws DTFException {
long iterations = getConfig().getPropertyAsInt("iterations",20*1024);
int size = 32*1024;
// we only validate DTFRandom because the other Random always had this
// issue
DTFRandom rand = new DTFRandom();
getLogger().info("Validating data for DTFRandom.");
byte[] bytes = new byte[size];
for (long i = 0; i < iterations; i++) {
rand.nextBytes(bytes);
for (int b = 0; b < bytes.length-1; b++) {
if ( bytes[b] == '$' && bytes[b+1] == '{')
throw new DTFException("Found a property within the randomly generated data.");
}
}
}
@Test(timeout=600000)
public void simpleTest() {
DTFRandom rand = new DTFRandom(1234567890);
getLogger().info("Generating nextInt() sequence from seed 1234567890");
StringBuffer results = new StringBuffer();
for (int i = 0; i < 10; i++)
results.append(rand.nextInt() + ",");
getLogger().info(results.toString());
byte[] bytes = new byte[16];
rand.nextBytes(bytes);
getLogger().info("randomString [" + new String(bytes) + "]");
}
public static junit.framework.Test suite() {
return new JUnit4TestAdapter(RandomGenSuite.class);
}
}