diff --git a/components/net/sf/briar/transport/XorErasureDecoder.java b/components/net/sf/briar/transport/XorErasureDecoder.java index 5c44778bbff196a28a87cee181da0f1668cfaa8e..47093034edd670874fa4211cd6f83008194b9245 100644 --- a/components/net/sf/briar/transport/XorErasureDecoder.java +++ b/components/net/sf/briar/transport/XorErasureDecoder.java @@ -23,7 +23,7 @@ class XorErasureDecoder implements ErasureDecoder { // All the pieces must have the same length - take the minimum int length = MAX_FRAME_LENGTH; for(int i = 0; i < n; i++) { - if(set[i] == null) { + if(set[i] != null) { int len = set[i].getLength(); if(len < length) length = len; } diff --git a/test/build.xml b/test/build.xml index 6c64adbf5e35b55deeb81966a12873e214af1c9c..2f41b5e64e9f118f1c81d9ce4481405acb5fab46 100644 --- a/test/build.xml +++ b/test/build.xml @@ -61,6 +61,7 @@ <test name='net.sf.briar.transport.IncomingSegmentedEncryptionLayerTest'/> <test name='net.sf.briar.transport.OutgoingEncryptionLayerImplTest'/> <test name='net.sf.briar.transport.OutgoingSegmentedEncryptionLayerTest'/> + <test name='net.sf.briar.transport.XorErasureDecoderTest'/> <test name='net.sf.briar.transport.XorErasureEncoderTest'/> <test name='net.sf.briar.util.ByteUtilsTest'/> <test name='net.sf.briar.util.FileUtilsTest'/> diff --git a/test/net/sf/briar/transport/XorErasureDecoderTest.java b/test/net/sf/briar/transport/XorErasureDecoderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3b78f755b497a1a4dd0c2f19794f94dda368eb8f --- /dev/null +++ b/test/net/sf/briar/transport/XorErasureDecoderTest.java @@ -0,0 +1,67 @@ +package net.sf.briar.transport; + +import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH; +import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; +import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH; +import net.sf.briar.BriarTestCase; +import net.sf.briar.api.FormatException; +import net.sf.briar.api.transport.Segment; + +import static org.junit.Assert.assertArrayEquals; +import org.junit.Test; + +public class XorErasureDecoderTest extends BriarTestCase { + + @Test + public void testMaximumLength() throws Exception { + // A frame of the maximum length should be decoded successfully + Segment[] set = encodeEmptyFrame(MAX_FRAME_LENGTH / 4, 5); + XorErasureDecoder d = new XorErasureDecoder(5); + Frame f = new Frame(); + assertTrue(d.decodeFrame(f, set)); + // Check the header + byte[] b = f.getBuffer(); + assertEquals(0L, HeaderEncoder.getFrameNumber(b)); + int payload = MAX_FRAME_LENGTH - FRAME_HEADER_LENGTH - MAC_LENGTH; + assertEquals(payload, HeaderEncoder.getPayloadLength(b)); + assertEquals(0, HeaderEncoder.getPaddingLength(b)); + // Check the body + assertEquals(MAX_FRAME_LENGTH, f.getLength()); + for(int i = FRAME_HEADER_LENGTH; i < MAX_FRAME_LENGTH; i++) { + assertEquals(0, b[i]); + } + // A frame larger than the maximum length should not be decoded + set = encodeEmptyFrame(MAX_FRAME_LENGTH / 4 + 1, 5); + try { + d.decodeFrame(f, set); + } catch(FormatException expected) {} + } + + @Test + public void testMinimumLengthIsUsed() throws Exception { + Segment[] set = encodeEmptyFrame(250, 4); + // Replace one of the pieces with a longer piece + byte[] b = set[1].getBuffer(); + assertArrayEquals(new byte[250], b); + set[1] = new SegmentImpl(251); + set[1].setLength(251); + // The frame should be decoded successfully + XorErasureDecoder d = new XorErasureDecoder(4); + Frame f = new Frame(); + assertTrue(d.decodeFrame(f, set)); + // The minimum of the segments' lengths should have been used + assertEquals(750, f.getLength()); + } + + private Segment[] encodeEmptyFrame(int length, int n) { + Segment[] set = new Segment[n]; + for(int i = 0; i < n; i++) { + set[i] = new SegmentImpl(length); + set[i].setLength(length); + } + int payload = length * (n - 1) - FRAME_HEADER_LENGTH - MAC_LENGTH; + HeaderEncoder.encodeHeader(set[0].getBuffer(), 0L, payload, 0); + HeaderEncoder.encodeHeader(set[n - 1].getBuffer(), 0L, payload, 0); + return set; + } +}