package com.trilead.ssh2.channel;
import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
/**
* @author Kohsuke Kawaguchi
*/
public class FifoBufferTest {
final FifoBuffer rb = new FifoBuffer(9,115); // use strange number to make buffer mod op interesting
final byte[] buf = new byte[1024];
@Test
public void basic() throws InterruptedException {
rb.write(new byte[]{1,2,3},0,3);
rb.close();
int d = rb.read(buf, 0, 999);
assertThat(d, is(3));
assertThat((int)buf[0],is(1));
assertThat((int)buf[1],is(2));
assertThat((int)buf[2],is(3));
assertThat(rb.read(buf, 0, 1), is(-1));
}
/**
* Read/write ops that go around the buffer.
*
* Read are smaller so that we leave more stuff in the buffer
*/
@Test
public void wrapAround() throws Exception {
for (int i=0; i<10; i++)
buf[i] = (byte)(i+1);
int total=0;
for (int j=0; j<100; j++) {
rb.write(buf,0,10);
byte[] d = new byte[9];
int dat = rb.read(d, 0, 9);
assertThat(dat,is(9));
for (int i=0; i<9; i++) {
assertThat((int)d[i],is(total+1));
total = (total+1)%10;
}
}
}
/**
* Read/write operation whose buffer is bigger than what the ring buffer holds.
* This tests the thread notification.
*/
@Test
public void bigAccess() throws Exception {
ExecutorService es = Executors.newFixedThreadPool(1);
Future<byte[]> reader = es.submit(new Callable<byte[]>() {
public byte[] call() throws Exception {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
while (true) {
int len = rb.read(buf, 0, buf.length);
if (len < 0) return baos.toByteArray();
assertTrue(len > 0);
baos.write(buf, 0, len);
}
}
});
byte[] data = new byte[10*1024];
new Random().nextBytes(data);
rb.write(data,0,data.length);
rb.close();
byte[] copy = reader.get();
assertArrayEquals(data, copy);
es.shutdown();
}
}