Skip to content
Snippets Groups Projects
Commit 156bafb8 authored by akwizgran's avatar akwizgran
Browse files

Unit tests for ConnectionReaderImpl.

parent a59ad23e
No related branches found
No related tags found
No related merge requests found
package net.sf.briar.transport; package net.sf.briar.transport;
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
...@@ -10,6 +12,7 @@ import javax.crypto.Mac; ...@@ -10,6 +12,7 @@ import javax.crypto.Mac;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.briar.TestUtils; import net.sf.briar.TestUtils;
import net.sf.briar.api.FormatException;
import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.transport.ConnectionReader; import net.sf.briar.api.transport.ConnectionReader;
import net.sf.briar.crypto.CryptoModule; import net.sf.briar.crypto.CryptoModule;
...@@ -33,13 +36,28 @@ public class ConnectionReaderImplTest extends TestCase { ...@@ -33,13 +36,28 @@ public class ConnectionReaderImplTest extends TestCase {
mac.init(crypto.generateSecretKey()); mac.init(crypto.generateSecretKey());
} }
// FIXME: Test corner cases and corrupt frames @Test
public void testLengthZero() throws Exception {
// Six bytes for the header, none for the payload
byte[] frame = new byte[6 + mac.getMacLength()];
// Calculate the MAC
mac.update(frame, 0, 6);
mac.doFinal(frame, 6);
// Read the frame
ByteArrayInputStream in = new ByteArrayInputStream(frame);
ConnectionDecrypter d = new NullConnectionDecrypter(in);
ConnectionReader r = new ConnectionReaderImpl(d, mac);
try {
r.getInputStream().read();
fail();
} catch(FormatException expected) {}
}
@Test @Test
public void testSingleByteFrame() throws Exception { public void testLengthOne() throws Exception {
// Six bytes for the header, one for the payload // Six bytes for the header, one for the payload
byte[] frame = new byte[6 + 1 + mac.getMacLength()]; byte[] frame = new byte[6 + 1 + mac.getMacLength()];
ByteUtils.writeUint16(1, frame, 4); // Payload length = 1 ByteUtils.writeUint16(1, frame, 4); // Frame number 0, length 1
// Calculate the MAC // Calculate the MAC
mac.update(frame, 0, 6 + 1); mac.update(frame, 0, 6 + 1);
mac.doFinal(frame, 6 + 1); mac.doFinal(frame, 6 + 1);
...@@ -52,17 +70,49 @@ public class ConnectionReaderImplTest extends TestCase { ...@@ -52,17 +70,49 @@ public class ConnectionReaderImplTest extends TestCase {
assertEquals(-1, r.getInputStream().read()); assertEquals(-1, r.getInputStream().read());
} }
@Test
public void testMaxLength() throws Exception {
int maxPayloadLength = MAX_FRAME_LENGTH - 6 - mac.getMacLength();
// First frame: max payload length
byte[] frame = new byte[6 + maxPayloadLength + mac.getMacLength()];
ByteUtils.writeUint16(maxPayloadLength, frame, 4);
mac.update(frame, 0, 6 + maxPayloadLength);
mac.doFinal(frame, 6 + maxPayloadLength);
// Second frame: max payload length plus one
byte[] frame1 = new byte[6 + maxPayloadLength + 1 + mac.getMacLength()];
ByteUtils.writeUint32(1, frame1, 0);
ByteUtils.writeUint16(maxPayloadLength + 1, frame1, 4);
mac.update(frame1, 0, 6 + maxPayloadLength + 1);
mac.doFinal(frame1, 6 + maxPayloadLength + 1);
// Concatenate the frames
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(frame);
out.write(frame1);
// Read the first frame
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
ConnectionDecrypter d = new NullConnectionDecrypter(in);
ConnectionReader r = new ConnectionReaderImpl(d, mac);
byte[] read = new byte[maxPayloadLength];
TestUtils.readFully(r.getInputStream(), read);
// Try to read the second frame
byte[] read1 = new byte[maxPayloadLength + 1];
try {
TestUtils.readFully(r.getInputStream(), read1);
fail();
} catch(FormatException expected) {}
}
@Test @Test
public void testMultipleFrames() throws Exception { public void testMultipleFrames() throws Exception {
// First frame: 123-byte payload // First frame: 123-byte payload
byte[] frame = new byte[6 + 123 + mac.getMacLength()]; byte[] frame = new byte[6 + 123 + mac.getMacLength()];
ByteUtils.writeUint16(123, frame, 4); ByteUtils.writeUint16(123, frame, 4); // Frame number 0, length 123
mac.update(frame, 0, 6 + 123); mac.update(frame, 0, 6 + 123);
mac.doFinal(frame, 6 + 123); mac.doFinal(frame, 6 + 123);
// Second frame: 1234-byte payload // Second frame: 1234-byte payload
byte[] frame1 = new byte[6 + 1234 + mac.getMacLength()]; byte[] frame1 = new byte[6 + 1234 + mac.getMacLength()];
ByteUtils.writeUint32(1, frame1, 0); ByteUtils.writeUint32(1, frame1, 0); // Frame number 1
ByteUtils.writeUint16(1234, frame1, 4); ByteUtils.writeUint16(1234, frame1, 4); // Length 1234
mac.update(frame1, 0, 6 + 1234); mac.update(frame1, 0, 6 + 1234);
mac.doFinal(frame1, 6 + 1234); mac.doFinal(frame1, 6 + 1234);
// Concatenate the frames // Concatenate the frames
...@@ -81,6 +131,46 @@ public class ConnectionReaderImplTest extends TestCase { ...@@ -81,6 +131,46 @@ public class ConnectionReaderImplTest extends TestCase {
assertTrue(Arrays.equals(new byte[1234], read1)); assertTrue(Arrays.equals(new byte[1234], read1));
} }
@Test
public void testCorruptPayload() throws Exception {
// Six bytes for the header, eight for the payload
byte[] frame = new byte[6 + 8 + mac.getMacLength()];
ByteUtils.writeUint16(8, frame, 4); // Frame number 0, length 8
// Calculate the MAC
mac.update(frame, 0, 6 + 8);
mac.doFinal(frame, 6 + 8);
// Modify the payload
frame[12] ^= 1;
// Try to read the frame - not a single byte should be read
ByteArrayInputStream in = new ByteArrayInputStream(frame);
ConnectionDecrypter d = new NullConnectionDecrypter(in);
ConnectionReader r = new ConnectionReaderImpl(d, mac);
try {
r.getInputStream().read();
fail();
} catch(FormatException expected) {}
}
@Test
public void testCorruptMac() throws Exception {
// Six bytes for the header, eight for the payload
byte[] frame = new byte[6 + 8 + mac.getMacLength()];
ByteUtils.writeUint16(8, frame, 4); // Frame number 0, length 8
// Calculate the MAC
mac.update(frame, 0, 6 + 8);
mac.doFinal(frame, 6 + 8);
// Modify the MAC
frame[17] ^= 1;
// Try to read the frame - not a single byte should be read
ByteArrayInputStream in = new ByteArrayInputStream(frame);
ConnectionDecrypter d = new NullConnectionDecrypter(in);
ConnectionReader r = new ConnectionReaderImpl(d, mac);
try {
r.getInputStream().read();
fail();
} catch(FormatException expected) {}
}
/** A ConnectionDecrypter that performs no decryption. */ /** A ConnectionDecrypter that performs no decryption. */
private static class NullConnectionDecrypter private static class NullConnectionDecrypter
implements ConnectionDecrypter { implements ConnectionDecrypter {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment