Files
briar/briar-tests/src/org/briarproject/introduction/IntroductionValidatorTest.java
Torsten Grote 9f9a216305 Prepare for new Forum Sharing Client
Methods for creating, adding and removing forums have been moved to the
`ForumManager`. In order to still handle removing forums properly, a
`RemoveForumHook` has been introduced.

Methods for sharing forums with all current and future contacts have
been removed along with the localGroup where this information was saved.

The `ShareForumActivity` now has the proper label.

The `SessionId` and the `ProtocolEngine` have been moved to the
`clients` package.

This addresses part of #322 and part of what has been discussed in #320.
2016-05-03 11:48:45 -03:00

358 lines
12 KiB
Java

package org.briarproject.introduction;
import org.briarproject.BriarTestCase;
import org.briarproject.TestUtils;
import org.briarproject.api.FormatException;
import org.briarproject.api.TransportId;
import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfEntry;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.clients.SessionId;
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.briarproject.system.SystemClock;
import org.jmock.Mockery;
import org.junit.Test;
import java.io.IOException;
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.introduction.IntroductionConstants.ACCEPT;
import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
import static org.briarproject.api.introduction.IntroductionConstants.MSG;
import static org.briarproject.api.introduction.IntroductionConstants.NAME;
import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
import static org.briarproject.api.introduction.IntroductionConstants.TIME;
import static org.briarproject.api.introduction.IntroductionConstants.TRANSPORT;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ABORT;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
public class IntroductionValidatorTest extends BriarTestCase {
private final Mockery context = new Mockery();
private final Group group;
private final Message message;
private final IntroductionValidator validator;
private final Clock clock = new SystemClock();
public IntroductionValidatorTest() {
GroupId groupId = new GroupId(TestUtils.getRandomId());
ClientId clientId = new ClientId(TestUtils.getRandomId());
byte[] descriptor = TestUtils.getRandomBytes(12);
group = new Group(groupId, clientId, descriptor);
MessageId messageId = new MessageId(TestUtils.getRandomId());
long timestamp = System.currentTimeMillis();
byte[] raw = TestUtils.getRandomBytes(123);
message = new Message(messageId, group.getId(), timestamp, raw);
ClientHelper clientHelper = context.mock(ClientHelper.class);
MetadataEncoder metadataEncoder = context.mock(MetadataEncoder.class);
validator = new IntroductionValidator(clientHelper, metadataEncoder,
clock);
context.assertIsSatisfied();
}
//
// Introduction Requests
//
@Test
public void testValidateProperIntroductionRequest() throws IOException {
final byte[] sessionId = TestUtils.getRandomId();
final String name = TestUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH);
final byte[] publicKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
final String text = TestUtils.getRandomString(MAX_MESSAGE_BODY_LENGTH);
BdfList body = BdfList.of(TYPE_REQUEST, sessionId,
name, publicKey, text);
final BdfDictionary result =
validator.validateMessage(message, group, body);
assertEquals(Long.valueOf(TYPE_REQUEST), result.getLong(TYPE));
assertEquals(sessionId, result.getRaw(SESSION_ID));
assertEquals(name, result.getString(NAME));
assertEquals(publicKey, result.getRaw(PUBLIC_KEY));
assertEquals(text, result.getString(MSG));
context.assertIsSatisfied();
}
@Test(expected = FormatException.class)
public void testValidateIntroductionRequestWithNoName() throws IOException {
BdfDictionary msg = getValidIntroductionRequest();
// no NAME is message
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
msg.getRaw(PUBLIC_KEY));
if (msg.containsKey(MSG)) body.add(msg.getString(MSG));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testValidateIntroductionRequestWithLongName() throws IOException {
// too long NAME in message
BdfDictionary msg = getValidIntroductionRequest();
msg.put(NAME, msg.get(NAME) + "x");
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
msg.getString(NAME), msg.getRaw(PUBLIC_KEY));
if (msg.containsKey(MSG)) body.add(msg.getString(MSG));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testValidateIntroductionRequestWithWrongType()
throws IOException {
// wrong message type
BdfDictionary msg = getValidIntroductionRequest();
msg.put(TYPE, 324234);
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
msg.getString(NAME), msg.getRaw(PUBLIC_KEY));
if (msg.containsKey(MSG)) body.add(msg.getString(MSG));
validator.validateMessage(message, group, body);
}
private BdfDictionary getValidIntroductionRequest() throws FormatException {
byte[] sessionId = TestUtils.getRandomId();
String name = TestUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH);
byte[] publicKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
String text = TestUtils.getRandomString(MAX_MESSAGE_BODY_LENGTH);
BdfDictionary msg = new BdfDictionary();
msg.put(TYPE, TYPE_REQUEST);
msg.put(SESSION_ID, sessionId);
msg.put(NAME, name);
msg.put(PUBLIC_KEY, publicKey);
msg.put(MSG, text);
return msg;
}
//
// Introduction Responses
//
@Test
public void testValidateIntroductionAcceptResponse() throws IOException {
byte[] groupId = TestUtils.getRandomId();
byte[] sessionId = TestUtils.getRandomId();
long time = clock.currentTimeMillis();
byte[] publicKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
String transportId = TestUtils
.getRandomString(TransportId.MAX_TRANSPORT_ID_LENGTH);
BdfDictionary tProps = BdfDictionary.of(
new BdfEntry(TestUtils.getRandomString(MAX_PROPERTY_LENGTH),
TestUtils.getRandomString(MAX_PROPERTY_LENGTH))
);
BdfDictionary tp = BdfDictionary.of(
new BdfEntry(transportId, tProps)
);
BdfDictionary msg = new BdfDictionary();
msg.put(TYPE, TYPE_RESPONSE);
msg.put(GROUP_ID, groupId);
msg.put(SESSION_ID, sessionId);
msg.put(ACCEPT, true);
msg.put(TIME, time);
msg.put(E_PUBLIC_KEY, publicKey);
msg.put(TRANSPORT, tp);
BdfList body = BdfList.of(TYPE_RESPONSE, msg.getRaw(SESSION_ID),
msg.getBoolean(ACCEPT), msg.getLong(TIME),
msg.getRaw(E_PUBLIC_KEY), msg.getDictionary(TRANSPORT));
final BdfDictionary result =
validator.validateMessage(message, group, body);
assertEquals(Long.valueOf(TYPE_RESPONSE), result.getLong(TYPE));
assertEquals(sessionId, result.getRaw(SESSION_ID));
assertEquals(true, result.getBoolean(ACCEPT));
assertEquals(publicKey, result.getRaw(E_PUBLIC_KEY));
assertEquals(tp, result.getDictionary(TRANSPORT));
context.assertIsSatisfied();
}
@Test
public void testValidateIntroductionDeclineResponse()
throws IOException {
BdfDictionary msg = getValidIntroductionResponse(false);
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
msg.getBoolean(ACCEPT));
BdfDictionary result = validator.validateMessage(message, group, body);
assertFalse(result.getBoolean(ACCEPT));
context.assertIsSatisfied();
}
@Test(expected = FormatException.class)
public void testValidateIntroductionResponseWithoutAccept()
throws IOException {
BdfDictionary msg = getValidIntroductionResponse(false);
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testValidateIntroductionResponseWithBrokenTp()
throws IOException {
BdfDictionary msg = getValidIntroductionResponse(true);
BdfDictionary tp = msg.getDictionary(TRANSPORT);
tp.put(TestUtils
.getRandomString(TransportId.MAX_TRANSPORT_ID_LENGTH), "X");
msg.put(TRANSPORT, tp);
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
msg.getBoolean(ACCEPT), msg.getLong(TIME),
msg.getRaw(E_PUBLIC_KEY), msg.getDictionary(TRANSPORT));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testValidateIntroductionResponseWithoutPublicKey()
throws IOException {
BdfDictionary msg = getValidIntroductionResponse(true);
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
msg.getBoolean(ACCEPT), msg.getLong(TIME),
msg.getDictionary(TRANSPORT));
validator.validateMessage(message, group, body);
}
private BdfDictionary getValidIntroductionResponse(boolean accept)
throws FormatException {
byte[] groupId = TestUtils.getRandomId();
byte[] sessionId = TestUtils.getRandomId();
long time = clock.currentTimeMillis();
byte[] publicKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
String transportId = TestUtils
.getRandomString(TransportId.MAX_TRANSPORT_ID_LENGTH);
BdfDictionary tProps = BdfDictionary.of(
new BdfEntry(TestUtils.getRandomString(MAX_PROPERTY_LENGTH),
TestUtils.getRandomString(MAX_PROPERTY_LENGTH))
);
BdfDictionary tp = BdfDictionary.of(
new BdfEntry(transportId, tProps)
);
BdfDictionary msg = new BdfDictionary();
msg.put(TYPE, TYPE_RESPONSE);
msg.put(GROUP_ID, groupId);
msg.put(SESSION_ID, sessionId);
msg.put(ACCEPT, accept);
if (accept) {
msg.put(TIME, time);
msg.put(E_PUBLIC_KEY, publicKey);
msg.put(TRANSPORT, tp);
}
return msg;
}
//
// Introduction ACK
//
@Test
public void testValidateProperIntroductionAck() throws IOException {
final byte[] sessionId = TestUtils.getRandomId();
BdfDictionary msg = new BdfDictionary();
msg.put(TYPE, TYPE_ACK);
msg.put(SESSION_ID, sessionId);
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID));
BdfDictionary result =
validator.validateMessage(message, group, body);
assertEquals(Long.valueOf(TYPE_ACK), result.getLong(TYPE));
assertEquals(sessionId, result.getRaw(SESSION_ID));
context.assertIsSatisfied();
}
@Test(expected = FormatException.class)
public void testValidateTooLongIntroductionAck() throws IOException {
BdfDictionary msg = BdfDictionary.of(
new BdfEntry(TYPE, TYPE_ACK),
new BdfEntry(SESSION_ID, TestUtils.getRandomId()),
new BdfEntry("garbage", TestUtils.getRandomString(255))
);
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
msg.getString("garbage"));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testValidateIntroductionAckWithLongSessionId() throws IOException {
BdfDictionary msg = BdfDictionary.of(
new BdfEntry(TYPE, TYPE_ACK),
new BdfEntry(SESSION_ID, new byte[SessionId.LENGTH + 1])
);
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID));
validator.validateMessage(message, group, body);
}
//
// Introduction Abort
//
@Test
public void testValidateProperIntroductionAbort() throws IOException {
byte[] sessionId = TestUtils.getRandomId();
BdfDictionary msg = new BdfDictionary();
msg.put(TYPE, TYPE_ABORT);
msg.put(SESSION_ID, sessionId);
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID));
BdfDictionary result =
validator.validateMessage(message, group, body);
assertEquals(Long.valueOf(TYPE_ABORT), result.getLong(TYPE));
assertEquals(sessionId, result.getRaw(SESSION_ID));
context.assertIsSatisfied();
}
@Test(expected = FormatException.class)
public void testValidateTooLongIntroductionAbort() throws IOException {
BdfDictionary msg = BdfDictionary.of(
new BdfEntry(TYPE, TYPE_ABORT),
new BdfEntry(SESSION_ID, TestUtils.getRandomId()),
new BdfEntry("garbage", TestUtils.getRandomString(255))
);
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
msg.getString("garbage"));
validator.validateMessage(message, group, body);
}
}