diff --git a/test/net/sf/briar/transport/ConnectionReaderImplTest.java b/test/net/sf/briar/transport/ConnectionReaderImplTest.java index e975ce539eb7744c0d51d6ca8ed0db2d102847b8..f00b611ba90d7263ce420b6a55c81c963a68aaca 100644 --- a/test/net/sf/briar/transport/ConnectionReaderImplTest.java +++ b/test/net/sf/briar/transport/ConnectionReaderImplTest.java @@ -1,12 +1,103 @@ package net.sf.briar.transport; -import org.junit.Test; - +import static net.sf.briar.api.transport.TransportConstants.HEADER_LENGTH; +import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; import net.sf.briar.BriarTestCase; +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.junit.Test; + public class ConnectionReaderImplTest extends BriarTestCase { - // FIXME: Write tests + private static final int FRAME_LENGTH = 1024; + private static final int MAX_PAYLOAD_LENGTH = + FRAME_LENGTH - HEADER_LENGTH - MAC_LENGTH; + + @Test + public void testEmptyFramesAreSkipped() throws Exception { + Mockery context = new Mockery(); + final FrameReader reader = context.mock(FrameReader.class); + context.checking(new Expectations() {{ + oneOf(reader).readFrame(with(any(byte[].class))); + will(returnValue(0)); // Empty frame + oneOf(reader).readFrame(with(any(byte[].class))); + will(returnValue(2)); // Non-empty frame with two payload bytes + oneOf(reader).readFrame(with(any(byte[].class))); + will(returnValue(0)); // Empty frame + oneOf(reader).readFrame(with(any(byte[].class))); + will(returnValue(-1)); // No more frames + }}); + ConnectionReaderImpl c = new ConnectionReaderImpl(reader, FRAME_LENGTH); + assertEquals(0, c.read()); // Skip the first empty frame, read a byte + assertEquals(0, c.read()); // Read another byte + assertEquals(-1, c.read()); // Skip the second empty frame, reach EOF + assertEquals(-1, c.read()); // Still at EOF + } + + @Test + public void testEmptyFramesAreSkippedWithBuffer() throws Exception { + Mockery context = new Mockery(); + final FrameReader reader = context.mock(FrameReader.class); + context.checking(new Expectations() {{ + oneOf(reader).readFrame(with(any(byte[].class))); + will(returnValue(0)); // Empty frame + oneOf(reader).readFrame(with(any(byte[].class))); + will(returnValue(2)); // Non-empty frame with two payload bytes + oneOf(reader).readFrame(with(any(byte[].class))); + will(returnValue(0)); // Empty frame + oneOf(reader).readFrame(with(any(byte[].class))); + will(returnValue(-1)); // No more frames + }}); + ConnectionReaderImpl c = new ConnectionReaderImpl(reader, FRAME_LENGTH); + byte[] buf = new byte[MAX_PAYLOAD_LENGTH]; + // Skip the first empty frame, read the two payload bytes + assertEquals(2, c.read(buf)); + // Skip the second empty frame, reach EOF + assertEquals(-1, c.read(buf)); + // Still at EOF + assertEquals(-1, c.read(buf)); + } + + @Test + public void testMultipleReadsPerFrame() throws Exception { + Mockery context = new Mockery(); + final FrameReader reader = context.mock(FrameReader.class); + context.checking(new Expectations() {{ + oneOf(reader).readFrame(with(any(byte[].class))); + will(returnValue(MAX_PAYLOAD_LENGTH)); // Nice long frame + oneOf(reader).readFrame(with(any(byte[].class))); + will(returnValue(-1)); // No more frames + }}); + ConnectionReaderImpl c = new ConnectionReaderImpl(reader, FRAME_LENGTH); + byte[] buf = new byte[MAX_PAYLOAD_LENGTH / 2]; + // Read the first half of the payload + assertEquals(MAX_PAYLOAD_LENGTH / 2, c.read(buf)); + // Read the second half of the payload + assertEquals(MAX_PAYLOAD_LENGTH / 2, c.read(buf)); + // Reach EOF + assertEquals(-1, c.read(buf, 0, buf.length)); + } + @Test - public void testNothing() {} + public void testMultipleReadsPerFrameWithOffsets() throws Exception { + Mockery context = new Mockery(); + final FrameReader reader = context.mock(FrameReader.class); + context.checking(new Expectations() {{ + oneOf(reader).readFrame(with(any(byte[].class))); + will(returnValue(MAX_PAYLOAD_LENGTH)); // Nice long frame + oneOf(reader).readFrame(with(any(byte[].class))); + will(returnValue(-1)); // No more frames + }}); + ConnectionReaderImpl c = new ConnectionReaderImpl(reader, FRAME_LENGTH); + byte[] buf = new byte[MAX_PAYLOAD_LENGTH]; + // Read the first half of the payload + assertEquals(MAX_PAYLOAD_LENGTH / 2, c.read(buf, MAX_PAYLOAD_LENGTH / 2, + MAX_PAYLOAD_LENGTH / 2)); + // Read the second half of the payload + assertEquals(MAX_PAYLOAD_LENGTH / 2, c.read(buf, 123, + MAX_PAYLOAD_LENGTH / 2)); + // Reach EOF + assertEquals(-1, c.read(buf, 0, buf.length)); + } } diff --git a/test/net/sf/briar/transport/NullIncomingEncryptionLayer.java b/test/net/sf/briar/transport/NullIncomingEncryptionLayer.java deleted file mode 100644 index 96e4729fe17c17dbdbeed4ccb9161cae9de0cceb..0000000000000000000000000000000000000000 --- a/test/net/sf/briar/transport/NullIncomingEncryptionLayer.java +++ /dev/null @@ -1,45 +0,0 @@ -package net.sf.briar.transport; - -import static net.sf.briar.api.transport.TransportConstants.HEADER_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH; - -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; - -import net.sf.briar.api.FormatException; - -/** An encryption layer that performs no encryption. */ -class NullIncomingEncryptionLayer implements FrameReader { - - private final InputStream in; - - NullIncomingEncryptionLayer(InputStream in) { - this.in = in; - } - - public int readFrame(byte[] frame) throws IOException { - // Read the frame - int ciphertextLength = 0; - while(ciphertextLength < MAX_FRAME_LENGTH) { - int read = in.read(frame, ciphertextLength, - MAX_FRAME_LENGTH - ciphertextLength); - if(read == -1) break; // We'll check the length later - ciphertextLength += read; - } - int plaintextLength = ciphertextLength - MAC_LENGTH; - if(plaintextLength < HEADER_LENGTH) throw new EOFException(); - // Decode and validate the header - boolean lastFrame = FrameEncoder.isLastFrame(frame); - if(!lastFrame && ciphertextLength < MAX_FRAME_LENGTH) - throw new EOFException(); - int payloadLength = FrameEncoder.getPayloadLength(frame); - if(payloadLength > plaintextLength - HEADER_LENGTH) - throw new FormatException(); - // If there's any padding it must be all zeroes - for(int i = HEADER_LENGTH + payloadLength; i < plaintextLength; i++) - if(frame[i] != 0) throw new FormatException(); - return payloadLength; - } -} diff --git a/test/net/sf/briar/transport/NullOutgoingEncryptionLayer.java b/test/net/sf/briar/transport/NullOutgoingEncryptionLayer.java deleted file mode 100644 index a9dd1332a68079cef03235ef85bf9ea97b076da6..0000000000000000000000000000000000000000 --- a/test/net/sf/briar/transport/NullOutgoingEncryptionLayer.java +++ /dev/null @@ -1,47 +0,0 @@ -package net.sf.briar.transport; - -import static net.sf.briar.api.transport.TransportConstants.HEADER_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; - -import java.io.IOException; -import java.io.OutputStream; - -/** An encryption layer that performs no encryption. */ -class NullOutgoingEncryptionLayer implements FrameWriter { - - private final OutputStream out; - - private long capacity; - - NullOutgoingEncryptionLayer(OutputStream out) { - this.out = out; - capacity = Long.MAX_VALUE; - } - - NullOutgoingEncryptionLayer(OutputStream out, long capacity) { - this.out = out; - this.capacity = capacity; - } - - public void writeFrame(byte[] frame, int payloadLength, int paddingLength, - boolean lastFrame) throws IOException { - int plaintextLength = HEADER_LENGTH + payloadLength + paddingLength; - int ciphertextLength = plaintextLength + MAC_LENGTH; - // Encode the header - FrameEncoder.encodeHeader(frame, lastFrame, payloadLength); - // If there's any padding it must all be zeroes - for(int i = HEADER_LENGTH + payloadLength; i < plaintextLength; i++) - frame[i] = 0; - // Write the frame - out.write(frame, 0, ciphertextLength); - capacity -= ciphertextLength; - } - - public void flush() throws IOException { - out.flush(); - } - - public long getRemainingCapacity() { - return capacity; - } -}