From bd3bba6e8a7ae8977cbdc4102a4c85f254a59cce Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Wed, 16 Nov 2016 14:32:45 +0000
Subject: [PATCH] Unit tests for ForumPostValidator.

---
 .../forum/ForumPostValidatorTest.java         | 395 +++++++++++++++++-
 1 file changed, 390 insertions(+), 5 deletions(-)

diff --git a/briar-tests/src/org/briarproject/forum/ForumPostValidatorTest.java b/briar-tests/src/org/briarproject/forum/ForumPostValidatorTest.java
index 089cce54d9..a6707b526c 100644
--- a/briar-tests/src/org/briarproject/forum/ForumPostValidatorTest.java
+++ b/briar-tests/src/org/briarproject/forum/ForumPostValidatorTest.java
@@ -1,14 +1,399 @@
 package org.briarproject.forum;
 
-import org.briarproject.BriarTestCase;
+import org.briarproject.TestUtils;
+import org.briarproject.ValidatorTestCase;
+import org.briarproject.api.FormatException;
+import org.briarproject.api.UniqueId;
+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.identity.Author;
+import org.briarproject.api.identity.AuthorFactory;
+import org.briarproject.api.identity.AuthorId;
+import org.briarproject.api.sync.InvalidMessageException;
+import org.briarproject.api.sync.MessageId;
+import org.briarproject.api.system.Clock;
+import org.jmock.Expectations;
 import org.junit.Test;
 
-import static org.junit.Assert.fail;
+import java.security.GeneralSecurityException;
+import java.util.Collection;
 
-public class ForumPostValidatorTest extends BriarTestCase {
+import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
+import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+public class ForumPostValidatorTest extends ValidatorTestCase {
+
+	private final AuthorFactory authorFactory =
+			context.mock(AuthorFactory.class);
+	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 parentId = new MessageId(TestUtils.getRandomId());
+	private final String authorName =
+			TestUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH);
+	private final byte[] authorPublicKey =
+			TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
+	private final BdfList authorList = BdfList.of(authorName, authorPublicKey);
+	private final String content =
+			TestUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH);
+	private final byte[] signature =
+			TestUtils.getRandomBytes(MAX_SIGNATURE_LENGTH);
+	private final AuthorId authorId = new AuthorId(TestUtils.getRandomId());
+	private final Author author =
+			new Author(authorId, authorName, authorPublicKey);
+	private final BdfList signedWithParent = BdfList.of(groupId, timestamp,
+			parentId.getBytes(), authorList, content);
+	private final BdfList signedWithoutParent = BdfList.of(groupId, timestamp,
+			null, authorList, content);
+
+	@Test(expected = FormatException.class)
+	public void testRejectsTooShortBody() throws Exception {
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group, BdfList.of(1, 2, 3));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsTooLongBody() throws Exception {
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group, BdfList.of(1, 2, 3, 4, 5));
+	}
+
+	@Test
+	public void testAcceptsNullParentId() throws Exception {
+		context.checking(new Expectations() {{
+			oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
+			will(returnValue(author));
+			oneOf(clientHelper).verifySignature(signature, authorPublicKey,
+					signedWithoutParent);
+		}});
+
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		BdfMessageContext messageContext = v.validateMessage(message, group,
+				BdfList.of(null, authorList, content, signature));
+		assertExpectedContext(messageContext, false, authorName);
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsNonRawParentId() throws Exception {
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(123, authorList, content, signature));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsTooShortParentId() throws Exception {
+		byte[] invalidParentId = new byte[UniqueId.LENGTH - 1];
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(invalidParentId, authorList, content, signature));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsTooLongParentId() throws Exception {
+		byte[] invalidParentId = new byte[UniqueId.LENGTH + 1];
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(invalidParentId, authorList, content, signature));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsNullAuthorList() throws Exception {
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, null, content, signature));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsNonListAuthorList() throws Exception {
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, 123, content, signature));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsTooShortAuthorList() throws Exception {
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, new BdfList(), content, signature));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsTooLongAuthorList() throws Exception {
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, BdfList.of(1, 2, 3), content, signature));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsNullAuthorName() throws Exception {
+		BdfList invalidAuthorList = BdfList.of(null, authorPublicKey);
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, invalidAuthorList, content, signature));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsNonStringAuthorName() throws Exception {
+		BdfList invalidAuthorList = BdfList.of(123, authorPublicKey);
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, invalidAuthorList, content, signature));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsTooShortAuthorName() throws Exception {
+		BdfList invalidAuthorList = BdfList.of("", authorPublicKey);
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, invalidAuthorList, content, signature));
+	}
+
+	@Test
+	public void testAcceptsMinLengthAuthorName() throws Exception {
+		final String shortAuthorName = "a";
+		BdfList shortNameAuthorList =
+				BdfList.of(shortAuthorName, authorPublicKey);
+		final Author shortNameAuthor =
+				new Author(authorId, shortAuthorName, authorPublicKey);
+		final BdfList signedWithShortNameAuthor = BdfList.of(groupId, timestamp,
+				parentId.getBytes(), shortNameAuthorList, content);
+
+		context.checking(new Expectations() {{
+			oneOf(authorFactory).createAuthor(shortAuthorName, authorPublicKey);
+			will(returnValue(shortNameAuthor));
+			oneOf(clientHelper).verifySignature(signature, authorPublicKey,
+					signedWithShortNameAuthor);
+		}});
+
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		BdfMessageContext messageContext = v.validateMessage(message, group,
+				BdfList.of(parentId, shortNameAuthorList, content, signature));
+		assertExpectedContext(messageContext, true, shortAuthorName);
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsTooLongAuthorName() throws Exception {
+		String invalidAuthorName =
+				TestUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH + 1);
+		BdfList invalidAuthorList =
+				BdfList.of(invalidAuthorName, authorPublicKey);
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, invalidAuthorList, content, signature));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsNullAuthorPublicKey() throws Exception {
+		BdfList invalidAuthorList = BdfList.of(authorName, null);
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, invalidAuthorList, content, signature));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsNonRawAuthorPublicKey() throws Exception {
+		BdfList invalidAuthorList = BdfList.of(authorName, 123);
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, invalidAuthorList, content, signature));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsTooLongAuthorPublicKey() throws Exception {
+		byte[] invalidAuthorPublicKey =
+				TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH + 1);
+		BdfList invalidAuthorList =
+				BdfList.of(authorName, invalidAuthorPublicKey);
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, invalidAuthorList, content, signature));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsNullContent() throws Exception {
+		context.checking(new Expectations() {{
+			oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
+			will(returnValue(author));
+		}});
+
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, authorList, null, signature));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsNonStringContent() throws Exception {
+		context.checking(new Expectations() {{
+			oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
+			will(returnValue(author));
+		}});
+
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, authorList, 123, signature));
+	}
 
 	@Test
-	public void testUnitTestsExist() {
-		fail(); // FIXME: Write tests
+	public void testAcceptsMinLengthContent() throws Exception {
+		String shortContent = "";
+		final BdfList signedWithShortContent = BdfList.of(groupId, timestamp,
+				parentId.getBytes(), authorList, shortContent);
+
+		context.checking(new Expectations() {{
+			oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
+			will(returnValue(author));
+			oneOf(clientHelper).verifySignature(signature, authorPublicKey,
+					signedWithShortContent);
+		}});
+
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		BdfMessageContext messageContext = v.validateMessage(message, group,
+				BdfList.of(parentId, authorList, shortContent, signature));
+		assertExpectedContext(messageContext, true, authorName);
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsTooLongContent() throws Exception {
+		String invalidContent =
+				TestUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH + 1);
+
+		context.checking(new Expectations() {{
+			oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
+			will(returnValue(author));
+		}});
+
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, authorList, invalidContent, signature));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsNullSignature() throws Exception {
+		context.checking(new Expectations() {{
+			oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
+			will(returnValue(author));
+		}});
+
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, authorList, content, null));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsNonRawSignature() throws Exception {
+		context.checking(new Expectations() {{
+			oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
+			will(returnValue(author));
+		}});
+
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, authorList, content, 123));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsTooLongSignature() throws Exception {
+		byte[] invalidSignature =
+				TestUtils.getRandomBytes(MAX_SIGNATURE_LENGTH + 1);
+
+		context.checking(new Expectations() {{
+			oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
+			will(returnValue(author));
+		}});
+
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, authorList, content, invalidSignature));
+	}
+
+	@Test(expected = FormatException.class)
+	public void testRejectsIfVerifyingSignatureThrowsFormatException()
+			throws Exception {
+		context.checking(new Expectations() {{
+			oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
+			will(returnValue(author));
+			oneOf(clientHelper).verifySignature(signature, authorPublicKey,
+					signedWithParent);
+			will(throwException(new FormatException()));
+		}});
+
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, authorList, content, signature));
+	}
+
+	@Test(expected = InvalidMessageException.class)
+	public void testRejectsIfVerifyingSignatureThrowsGeneralSecurityException()
+			throws Exception {
+		context.checking(new Expectations() {{
+			oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
+			will(returnValue(author));
+			oneOf(clientHelper).verifySignature(signature, authorPublicKey,
+					signedWithParent);
+			will(throwException(new GeneralSecurityException()));
+		}});
+
+		ForumPostValidator v = new ForumPostValidator(authorFactory,
+				clientHelper, metadataEncoder, clock);
+		v.validateMessage(message, group,
+				BdfList.of(parentId, authorList, content, signature));
+	}
+
+	private void assertExpectedContext(BdfMessageContext messageContext,
+			boolean hasParent, String authorName) throws FormatException {
+		BdfDictionary meta = messageContext.getDictionary();
+		Collection<MessageId> dependencies = messageContext.getDependencies();
+		if (hasParent) {
+			assertEquals(4, meta.size());
+			assertArrayEquals(parentId.getBytes(), meta.getRaw("parent"));
+			assertEquals(1, dependencies.size());
+			assertEquals(parentId, dependencies.iterator().next());
+		} else {
+			assertEquals(3, meta.size());
+			assertEquals(0, dependencies.size());
+		}
+		assertEquals(Long.valueOf(timestamp), meta.getLong("timestamp"));
+		assertFalse(meta.getBoolean("read"));
+		BdfDictionary authorMeta = meta.getDictionary("author");
+		assertEquals(3, authorMeta.size());
+		assertArrayEquals(authorId.getBytes(), authorMeta.getRaw("id"));
+		assertEquals(authorName, authorMeta.getString("name"));
+		assertArrayEquals(authorPublicKey, authorMeta.getRaw("publicKey"));
 	}
 }
-- 
GitLab