package net.jxta.util; import static org.junit.Assert.*; import java.io.IOException; import java.io.OutputStream; import java.util.LinkedList; import java.util.List; import org.jmock.Expectations; import org.junit.Before; import org.junit.Test; public class CountingOutputStreamTest { private FakeOutputStream underlying; private CountingOutputStream stream; @Before public void setUp() throws Exception { underlying = new FakeOutputStream(); stream = new CountingOutputStream(underlying); } @Test public void testInitiallyZeroBytesWritten() { assertEquals(0L, stream.getBytesWritten()); } @Test public void testWriteSingleByte() throws Exception { stream.write(0); assertEquals(1L, stream.getBytesWritten()); } @Test public void testWriteMultipleBytes() throws Exception { stream.write(new byte[1024]); assertEquals(1024L, stream.getBytesWritten()); } @Test public void testMultipleConsecutiveWriteCalls() throws Exception { stream.write(0); stream.write(new byte[100]); stream.write(new byte[1]); assertEquals(102, stream.getBytesWritten()); } @Test public void testWriteMillionsOfBytes() throws Exception { byte[] megabyteArray = new byte[1024 * 1024]; long startTime = System.nanoTime(); for(int i=0; i < 1024; i++) { stream.write(megabyteArray); } long stopTime = System.nanoTime(); assertEquals(1024 * 1024 * 1024, stream.getBytesWritten()); long totalTimeTaken = stopTime - startTime; System.out.println("Time taken to write 1GB:" + (totalTimeTaken / 1000000.0) + "ms"); } /** * This test will fail in the pre-patch implementation of CountingOutputStream. * The original implementation was pushing all bytes through * OutputStream.write(int b) instead of the byte array methods where * that was appropriate. This was a significant and unnecessary performance * hit. */ @Test public void testWriteByteArray_usesWriteByteArrayInWrappedStream() throws Exception { final byte[] bytesToWrite = new byte[1024]; stream.write(bytesToWrite); // there should be a single byte array, of size 1024 assertEquals(1, underlying.writtenBytes.size()); assertEquals(1024, underlying.writtenBytes.get(0).length); } private class FakeOutputStream extends OutputStream { private List<byte[]> writtenBytes = new LinkedList<byte[]>(); @Override public void write(int b) throws IOException { writtenBytes.add(new byte[] { (byte)b }); } @Override public void write(byte[] b) throws IOException { writtenBytes.add(b); } @Override public void write(byte[] b, int off, int len) throws IOException { if(off == 0 && len == b.length) { write(b); } else { byte[] written = new byte[len]; System.arraycopy(b, off, written, 0, len); writtenBytes.add(written); } } } }