package com.onionnetworks.io;
import java.io.*;
import java.util.Random;
/**
* This InputStream is designed to simulate real-world network IO conditions
* where less bytes may be returned or skipped than specified. This is
* designed for testing for edge-conditions or incorrect assumptions about IO
* semantics.
*
* @author Justin F. Chapweske
*/
public class UnpredictableInputStream extends FilterInputStream {
Random rand = new Random();
public UnpredictableInputStream(InputStream is) {
super(is);
}
public long skip(long n) throws IOException {
// We use nextInt rather than nextLong to ensure equal distribution
// across the possible bytes so that we're consistantly skipping
// less than n bytes.
// (int) cast is safe due to min(int,long)
if (rand.nextInt(5) == 0) {
// Return 0 length skips quite often for testing implementations.
return super.skip(0);
}
System.out.println("skip!");
return super.skip(rand.nextInt((int)Math.min(Integer.MAX_VALUE,n+1)));
}
public int read(byte[] b) throws IOException {
// This method must block until data is available, thus we will
// keep reading on a 0 byte result.
if (b.length == 0) {
return 0;
}
int c;
while ((c = read(b,0,b.length)) == 0) {}
return c;
}
public int read(byte[] b, int off, int len) throws IOException {
// Even though FilterInputStream's JavaDoc claims that this method
// must block until data is available, the current FilterInputStream
// implementation doesn't even enforce that.
if (rand.nextInt(5) == 0) {
// Return 0 length reads quite often for testing implementations.
return super.read(b,off,0);
}
return super.read(b,off,rand.nextInt(len+1));
}
}