package org.nanopub.extra.server;

import java.io.IOException;
import java.io.InputStream;
import java.util.Random;

/**
 * For testing purposes.
 */
public class UnreliableInputStream extends InputStream {

	private static final double errorProbability = 0.01;
	private static Random random = new Random();

	private InputStream wrappedInputStream;

	public UnreliableInputStream(InputStream wrappedInputStream) {
		this.wrappedInputStream = wrappedInputStream;
	}

	@Override
	public int read() throws IOException {
		if (random.nextDouble() < errorProbability) {
			return random.nextInt(256);
		}
		return wrappedInputStream.read();
	}

	@Override
	public int read(byte[] b) throws IOException {
		int r = wrappedInputStream.read(b);
		if (random.nextDouble() < errorProbability) {
			b[random.nextInt(b.length)] = (byte) random.nextInt(256);
		}
		return r;
	}

	@Override
	public int read(byte[] b, int off, int len) throws IOException {
		int r = wrappedInputStream.read(b, off, len);
		if (random.nextDouble() < errorProbability && r > 0) {
			b[off + random.nextInt(r)] = (byte) random.nextInt(256);
		}
		return r;
	}

	@Override
	public int available() throws IOException {
		return wrappedInputStream.available();
	}

	@Override
	public void close() throws IOException {
		wrappedInputStream.close();
	}

	@Override
	public synchronized void mark(int readlimit) {
		wrappedInputStream.mark(readlimit);
	}

	@Override
	public boolean markSupported() {
		return wrappedInputStream.markSupported();
	}

	@Override
	public synchronized void reset() throws IOException {
		wrappedInputStream.reset();
	}

	@Override
	public long skip(long n) throws IOException {
		return wrappedInputStream.skip(n);
	}

}

@@ -513,20 +513,28 @@
 ion %7B%0A%09%09
-if (
+double rd = 
 random.n
@@ -536,32 +536,42 @@
 dom.nextDouble()
+;%0A%09%09if (rd
  %3C errorProbabil
@@ -569,24 +569,28 @@
 rProbability
+ / 2
 ) %7B%0A%09%09%09retur
@@ -604,32 +604,193 @@
 m.nextInt(256);%0A
+%09%09%7D else if (rd %3C errorProbability) %7B%0A%09%09%09try %7B%0A%09%09%09%09Thread.sleep(5000);%0A%09%09%09%7D catch (InterruptedException ex) %7B%7D%0A%09%09%09throw new IOException(%22Simulated IO Problem%22);%0A
 %09%09%7D%0A%09%09return wra
@@ -868,32 +868,67 @@
 s IOException %7B%0A
+%09%09double rd = random.nextDouble();%0A
 %09%09int r = wrappe
@@ -956,34 +956,17 @@
 %0A%09%09if (r
-andom.nextDouble()
+d
  %3C error
@@ -972,24 +972,28 @@
 rProbability
+ / 2
 ) %7B%0A%09%09%09b%5Bran
@@ -1037,32 +1037,193 @@
 m.nextInt(256);%0A
+%09%09%7D else if (rd %3C errorProbability) %7B%0A%09%09%09try %7B%0A%09%09%09%09Thread.sleep(5000);%0A%09%09%09%7D catch (InterruptedException ex) %7B%7D%0A%09%09%09throw new IOException(%22Simulated IO Problem%22);%0A
 %09%09%7D%0A%09%09return r;%0A
@@ -1303,16 +1303,51 @@
 ption %7B%0A
+%09%09double rd = random.nextDouble();%0A
 %09%09int r 
@@ -1393,34 +1393,17 @@
 %0A%09%09if (r
-andom.nextDouble()
+d
  %3C error
@@ -1418,11 +1418,22 @@
 ity 
-&& 
+/ 2) %7B%0A%09%09%09if (
 r %3E 
@@ -1433,24 +1433,25 @@
 f (r %3E 0) %7B%0A
+%09
 %09%09%09b%5Boff + r
@@ -1498,16 +1498,182 @@
 t(256);%0A
+%09%09%09%7D%0A%09%09%7D else if (rd %3C errorProbability) %7B%0A%09%09%09try %7B%0A%09%09%09%09Thread.sleep(5000);%0A%09%09%09%7D catch (InterruptedException ex) %7B%7D%0A%09%09%09throw new IOException(%22Simulated IO Problem%22);%0A
 %09%09%7D%0A%09%09re

Include timeout failure for UnreliableInputStream