diff --git a/briar-tests/src/org/briarproject/BriarMockTestCase.java b/briar-tests/src/org/briarproject/BriarMockTestCase.java new file mode 100644 index 0000000000000000000000000000000000000000..45b662013b6050e1c12b554f1437c674aa13a4e5 --- /dev/null +++ b/briar-tests/src/org/briarproject/BriarMockTestCase.java @@ -0,0 +1,14 @@ +package org.briarproject; + +import org.jmock.Mockery; +import org.junit.After; + +public abstract class BriarMockTestCase extends BriarTestCase { + + protected final Mockery context = new Mockery(); + + @After + public void checkExpectations() { + context.assertIsSatisfied(); + } +} diff --git a/briar-tests/src/org/briarproject/ValidatorTestCase.java b/briar-tests/src/org/briarproject/ValidatorTestCase.java new file mode 100644 index 0000000000000000000000000000000000000000..a340994ed9371986352fb3a72fb845cd0c155422 --- /dev/null +++ b/briar-tests/src/org/briarproject/ValidatorTestCase.java @@ -0,0 +1,23 @@ +package org.briarproject; + +import org.briarproject.api.sync.ClientId; +import org.briarproject.api.sync.Group; +import org.briarproject.api.sync.GroupId; +import org.briarproject.api.sync.Message; +import org.briarproject.api.sync.MessageId; + +public abstract class ValidatorTestCase extends BriarMockTestCase { + + protected final MessageId messageId = + new MessageId(TestUtils.getRandomId()); + protected final GroupId groupId = new GroupId(TestUtils.getRandomId()); + protected final long timestamp = 1234567890 * 1000L; + protected final byte[] raw = TestUtils.getRandomBytes(123); + protected final Message message = + new Message(messageId, groupId, timestamp, raw); + protected final ClientId clientId = + new ClientId(TestUtils.getRandomString(123)); + protected final byte[] descriptor = TestUtils.getRandomBytes(123); + protected final Group group = new Group(groupId, clientId, descriptor); + +} diff --git a/briar-tests/src/org/briarproject/clients/BdfMessageValidatorTest.java b/briar-tests/src/org/briarproject/clients/BdfMessageValidatorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8c567e295ec6b21d08c22ab89371214e46e1a3a2 --- /dev/null +++ b/briar-tests/src/org/briarproject/clients/BdfMessageValidatorTest.java @@ -0,0 +1,189 @@ +package org.briarproject.clients; + +import org.briarproject.ValidatorTestCase; +import org.briarproject.api.FormatException; +import org.briarproject.api.clients.BdfMessageContext; +import org.briarproject.api.clients.ClientHelper; +import org.briarproject.api.data.BdfDictionary; +import org.briarproject.api.data.BdfList; +import org.briarproject.api.data.MetadataEncoder; +import org.briarproject.api.db.Metadata; +import org.briarproject.api.sync.Group; +import org.briarproject.api.sync.InvalidMessageException; +import org.briarproject.api.sync.Message; +import org.briarproject.api.sync.MessageContext; +import org.briarproject.api.system.Clock; +import org.jmock.Expectations; +import org.jmock.lib.legacy.ClassImposteriser; +import org.junit.Test; + +import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; +import static org.briarproject.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; + +public class BdfMessageValidatorTest extends ValidatorTestCase { + + private final ClientHelper clientHelper = context.mock(ClientHelper.class); + private final MetadataEncoder metadataEncoder = + context.mock(MetadataEncoder.class); + private final Clock clock = context.mock(Clock.class); + + private final BdfList body = BdfList.of(123, 456); + private final BdfDictionary dictionary = new BdfDictionary(); + private final Metadata meta = new Metadata(); + + public BdfMessageValidatorTest() { + context.setImposteriser(ClassImposteriser.INSTANCE); + } + + @Test(expected = InvalidMessageException.class) + public void testRejectsFarFutureTimestamp() throws Exception { + context.checking(new Expectations() {{ + oneOf(clock).currentTimeMillis(); + will(returnValue(timestamp - MAX_CLOCK_DIFFERENCE - 1)); + }}); + + BdfMessageValidator v = new BdfMessageValidator(clientHelper, + metadataEncoder, clock) { + @Override + protected BdfMessageContext validateMessage(Message m, Group g, + BdfList b) throws InvalidMessageException, FormatException { + fail(); + return null; + } + }; + v.validateMessage(message, group); + } + + @Test + public void testAcceptsMaxTimestamp() throws Exception { + context.checking(new Expectations() {{ + oneOf(clock).currentTimeMillis(); + will(returnValue(timestamp - MAX_CLOCK_DIFFERENCE)); + oneOf(clientHelper).toList(raw, MESSAGE_HEADER_LENGTH, + raw.length - MESSAGE_HEADER_LENGTH); + will(returnValue(body)); + oneOf(metadataEncoder).encode(dictionary); + will(returnValue(meta)); + }}); + + BdfMessageValidator v = new BdfMessageValidator(clientHelper, + metadataEncoder, clock) { + @Override + protected BdfMessageContext validateMessage(Message m, Group g, + BdfList b) throws InvalidMessageException, FormatException { + assertSame(message, m); + assertSame(group, g); + assertSame(body, b); + return new BdfMessageContext(dictionary); + } + }; + MessageContext messageContext = v.validateMessage(message, group); + assertEquals(0, messageContext.getDependencies().size()); + assertSame(meta, messageContext.getMetadata()); + } + + @Test(expected = InvalidMessageException.class) + public void testRejectsTooShortMessage() throws Exception { + final byte[] invalidRaw = new byte[MESSAGE_HEADER_LENGTH]; + // Use a mock message so the length of the raw message can be invalid + final Message invalidMessage = context.mock(Message.class); + + context.checking(new Expectations() {{ + oneOf(invalidMessage).getTimestamp(); + will(returnValue(timestamp)); + oneOf(clock).currentTimeMillis(); + will(returnValue(timestamp)); + oneOf(invalidMessage).getRaw(); + will(returnValue(invalidRaw)); + }}); + + BdfMessageValidator v = new BdfMessageValidator(clientHelper, + metadataEncoder, clock) { + @Override + protected BdfMessageContext validateMessage(Message m, Group g, + BdfList b) throws InvalidMessageException, FormatException { + fail(); + return null; + } + }; + v.validateMessage(invalidMessage, group); + } + + @Test + public void testAcceptsMinLengthMessage() throws Exception { + final byte[] shortRaw = new byte[MESSAGE_HEADER_LENGTH + 1]; + final Message shortMessage = + new Message(messageId, groupId, timestamp, shortRaw); + + context.checking(new Expectations() {{ + oneOf(clock).currentTimeMillis(); + will(returnValue(timestamp)); + oneOf(clientHelper).toList(shortRaw, MESSAGE_HEADER_LENGTH, + shortRaw.length - MESSAGE_HEADER_LENGTH); + will(returnValue(body)); + oneOf(metadataEncoder).encode(dictionary); + will(returnValue(meta)); + }}); + + BdfMessageValidator v = new BdfMessageValidator(clientHelper, + metadataEncoder, clock) { + @Override + protected BdfMessageContext validateMessage(Message m, Group g, + BdfList b) throws InvalidMessageException, FormatException { + assertSame(shortMessage, m); + assertSame(group, g); + assertSame(body, b); + return new BdfMessageContext(dictionary); + } + }; + MessageContext messageContext = v.validateMessage(shortMessage, group); + assertEquals(0, messageContext.getDependencies().size()); + assertSame(meta, messageContext.getMetadata()); + } + + @Test(expected = InvalidMessageException.class) + public void testRejectsInvalidBdfList() throws Exception { + context.checking(new Expectations() {{ + oneOf(clock).currentTimeMillis(); + will(returnValue(timestamp)); + oneOf(clientHelper).toList(raw, MESSAGE_HEADER_LENGTH, + raw.length - MESSAGE_HEADER_LENGTH); + will(throwException(new FormatException())); + }}); + + BdfMessageValidator v = new BdfMessageValidator(clientHelper, + metadataEncoder, clock) { + @Override + protected BdfMessageContext validateMessage(Message m, Group g, + BdfList b) throws InvalidMessageException, FormatException { + fail(); + return null; + } + }; + v.validateMessage(message, group); + } + + @Test(expected = InvalidMessageException.class) + public void testRethrowsFormatExceptionFromSubclass() throws Exception { + context.checking(new Expectations() {{ + oneOf(clock).currentTimeMillis(); + will(returnValue(timestamp)); + oneOf(clientHelper).toList(raw, MESSAGE_HEADER_LENGTH, + raw.length - MESSAGE_HEADER_LENGTH); + will(returnValue(body)); + }}); + + BdfMessageValidator v = new BdfMessageValidator(clientHelper, + metadataEncoder, clock) { + @Override + protected BdfMessageContext validateMessage(Message m, Group g, + BdfList b) throws InvalidMessageException, FormatException { + throw new FormatException(); + } + }; + v.validateMessage(message, group); + } +} diff --git a/briar-tests/src/org/briarproject/messaging/PrivateMessageValidatorTest.java b/briar-tests/src/org/briarproject/messaging/PrivateMessageValidatorTest.java index f73d02f966ec80524cad7d18c97d45448b85d7e8..d9b62b5a333e2475099331faefb9c03ef7cb9653 100644 --- a/briar-tests/src/org/briarproject/messaging/PrivateMessageValidatorTest.java +++ b/briar-tests/src/org/briarproject/messaging/PrivateMessageValidatorTest.java @@ -1,21 +1,14 @@ package org.briarproject.messaging; -import org.briarproject.BriarTestCase; import org.briarproject.TestUtils; +import org.briarproject.ValidatorTestCase; import org.briarproject.api.FormatException; import org.briarproject.api.clients.BdfMessageContext; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfList; import org.briarproject.api.data.MetadataEncoder; -import org.briarproject.api.sync.ClientId; -import org.briarproject.api.sync.Group; -import org.briarproject.api.sync.GroupId; -import org.briarproject.api.sync.Message; -import org.briarproject.api.sync.MessageId; import org.briarproject.api.system.Clock; -import org.jmock.Mockery; -import org.junit.After; import org.junit.Test; import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH; @@ -23,32 +16,15 @@ import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -public class PrivateMessageValidatorTest extends BriarTestCase { +public class PrivateMessageValidatorTest extends ValidatorTestCase { - private final Mockery context = new Mockery(); private final ClientHelper clientHelper = context.mock(ClientHelper.class); private final MetadataEncoder metadataEncoder = context.mock(MetadataEncoder.class); private final Clock clock = context.mock(Clock.class); - private final MessageId messageId = new MessageId(TestUtils.getRandomId()); - private final GroupId groupId = new GroupId(TestUtils.getRandomId()); - private final long timestamp = 1234567890 * 1000L; - private final byte[] raw = TestUtils.getRandomBytes(123); - private final Message message = - new Message(messageId, groupId, timestamp, raw); - private final ClientId clientId = - new ClientId(TestUtils.getRandomString(123)); - private final byte[] descriptor = TestUtils.getRandomBytes(123); - private final Group group = new Group(groupId, clientId, descriptor); - - @After - public void checkExpectations() { - context.assertIsSatisfied(); - } - @Test(expected = FormatException.class) - public void testRejectsEmptyBody() throws Exception { + public void testRejectsTooShortBody() throws Exception { PrivateMessageValidator v = new PrivateMessageValidator(clientHelper, metadataEncoder, clock); v.validateMessage(message, group, new BdfList()); @@ -58,7 +34,7 @@ public class PrivateMessageValidatorTest extends BriarTestCase { public void testRejectsTooLongBody() throws Exception { PrivateMessageValidator v = new PrivateMessageValidator(clientHelper, metadataEncoder, clock); - v.validateMessage(message, group, BdfList.of("", "")); + v.validateMessage(message, group, BdfList.of(1, 2)); } @Test(expected = FormatException.class) @@ -79,9 +55,9 @@ public class PrivateMessageValidatorTest extends BriarTestCase { public void testRejectsTooLongContent() throws Exception { PrivateMessageValidator v = new PrivateMessageValidator(clientHelper, metadataEncoder, clock); - String content = + String invalidContent = TestUtils.getRandomString(MAX_PRIVATE_MESSAGE_BODY_LENGTH + 1); - v.validateMessage(message, group, BdfList.of(content)); + v.validateMessage(message, group, BdfList.of(invalidContent)); } @Test @@ -90,27 +66,27 @@ public class PrivateMessageValidatorTest extends BriarTestCase { metadataEncoder, clock); String content = TestUtils.getRandomString(MAX_PRIVATE_MESSAGE_BODY_LENGTH); - BdfMessageContext context = + BdfMessageContext messageContext = v.validateMessage(message, group, BdfList.of(content)); - assertExpectedContext(context); + assertExpectedContext(messageContext); } @Test - public void testAcceptsEmptyContent() throws Exception { + public void testAcceptsMinLengthContent() throws Exception { PrivateMessageValidator v = new PrivateMessageValidator(clientHelper, metadataEncoder, clock); - BdfMessageContext context = + BdfMessageContext messageContext = v.validateMessage(message, group, BdfList.of("")); - assertExpectedContext(context); + assertExpectedContext(messageContext); } - private void assertExpectedContext(BdfMessageContext context) + private void assertExpectedContext(BdfMessageContext messageContext) throws FormatException { - assertEquals(0, context.getDependencies().size()); - BdfDictionary meta = context.getDictionary(); + BdfDictionary meta = messageContext.getDictionary(); assertEquals(3, meta.size()); assertEquals(Long.valueOf(timestamp), meta.getLong("timestamp")); assertFalse(meta.getBoolean("local")); assertFalse(meta.getBoolean(MSG_KEY_READ)); + assertEquals(0, messageContext.getDependencies().size()); } }