mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-16 12:49:55 +01:00
Moved classes from messaging package to sync package.
This commit is contained in:
243
briar-tests/src/org/briarproject/sync/ConstantsTest.java
Normal file
243
briar-tests/src/org/briarproject/sync/ConstantsTest.java
Normal file
@@ -0,0 +1,243 @@
|
||||
package org.briarproject.sync;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
import org.briarproject.BriarTestCase;
|
||||
import org.briarproject.TestDatabaseModule;
|
||||
import org.briarproject.TestLifecycleModule;
|
||||
import org.briarproject.TestSystemModule;
|
||||
import org.briarproject.TestUtils;
|
||||
import org.briarproject.api.Author;
|
||||
import org.briarproject.api.AuthorFactory;
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.TransportProperties;
|
||||
import org.briarproject.api.UniqueId;
|
||||
import org.briarproject.api.crypto.CryptoComponent;
|
||||
import org.briarproject.api.crypto.KeyPair;
|
||||
import org.briarproject.api.crypto.PrivateKey;
|
||||
import org.briarproject.api.crypto.Signature;
|
||||
import org.briarproject.api.sync.Ack;
|
||||
import org.briarproject.api.sync.Group;
|
||||
import org.briarproject.api.sync.GroupFactory;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.sync.MessageFactory;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.briarproject.api.sync.Offer;
|
||||
import org.briarproject.api.sync.PacketWriter;
|
||||
import org.briarproject.api.sync.PacketWriterFactory;
|
||||
import org.briarproject.api.sync.Request;
|
||||
import org.briarproject.api.sync.SubscriptionUpdate;
|
||||
import org.briarproject.api.sync.TransportUpdate;
|
||||
import org.briarproject.crypto.CryptoModule;
|
||||
import org.briarproject.data.DataModule;
|
||||
import org.briarproject.db.DatabaseModule;
|
||||
import org.briarproject.event.EventModule;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Random;
|
||||
|
||||
import static org.briarproject.api.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
||||
import static org.briarproject.api.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||
import static org.briarproject.api.AuthorConstants.MAX_SIGNATURE_LENGTH;
|
||||
import static org.briarproject.api.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT;
|
||||
import static org.briarproject.api.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
|
||||
import static org.briarproject.api.TransportPropertyConstants.MAX_TRANSPORT_ID_LENGTH;
|
||||
import static org.briarproject.api.sync.MessagingConstants.MAX_BODY_LENGTH;
|
||||
import static org.briarproject.api.sync.MessagingConstants.MAX_CONTENT_TYPE_LENGTH;
|
||||
import static org.briarproject.api.sync.MessagingConstants.MAX_GROUP_NAME_LENGTH;
|
||||
import static org.briarproject.api.sync.MessagingConstants.MAX_PAYLOAD_LENGTH;
|
||||
import static org.briarproject.api.sync.MessagingConstants.MAX_SUBSCRIPTIONS;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ConstantsTest extends BriarTestCase {
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
private final GroupFactory groupFactory;
|
||||
private final AuthorFactory authorFactory;
|
||||
private final MessageFactory messageFactory;
|
||||
private final PacketWriterFactory packetWriterFactory;
|
||||
|
||||
public ConstantsTest() throws Exception {
|
||||
Injector i = Guice.createInjector(new TestDatabaseModule(),
|
||||
new TestLifecycleModule(), new TestSystemModule(),
|
||||
new CryptoModule(), new DatabaseModule(), new EventModule(),
|
||||
new org.briarproject.sync.MessagingModule(), new DataModule());
|
||||
crypto = i.getInstance(CryptoComponent.class);
|
||||
groupFactory = i.getInstance(GroupFactory.class);
|
||||
authorFactory = i.getInstance(AuthorFactory.class);
|
||||
messageFactory = i.getInstance(MessageFactory.class);
|
||||
packetWriterFactory = i.getInstance(PacketWriterFactory.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAgreementPublicKeys() throws Exception {
|
||||
// Generate 10 agreement key pairs
|
||||
for (int i = 0; i < 10; i++) {
|
||||
KeyPair keyPair = crypto.generateSignatureKeyPair();
|
||||
// Check the length of the public key
|
||||
byte[] publicKey = keyPair.getPublic().getEncoded();
|
||||
assertTrue(publicKey.length <= MAX_PUBLIC_KEY_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignaturePublicKeys() throws Exception {
|
||||
Random random = new Random();
|
||||
Signature sig = crypto.getSignature();
|
||||
// Generate 10 signature key pairs
|
||||
for (int i = 0; i < 10; i++) {
|
||||
KeyPair keyPair = crypto.generateSignatureKeyPair();
|
||||
// Check the length of the public key
|
||||
byte[] publicKey = keyPair.getPublic().getEncoded();
|
||||
assertTrue(publicKey.length <= MAX_PUBLIC_KEY_LENGTH);
|
||||
// Sign some random data and check the length of the signature
|
||||
byte[] toBeSigned = new byte[1234];
|
||||
random.nextBytes(toBeSigned);
|
||||
sig.initSign(keyPair.getPrivate());
|
||||
sig.update(toBeSigned);
|
||||
byte[] signature = sig.sign();
|
||||
assertTrue("Length " + signature.length,
|
||||
signature.length <= MAX_SIGNATURE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessageIdsFitIntoLargeAck() throws Exception {
|
||||
testMessageIdsFitIntoAck(MAX_PAYLOAD_LENGTH);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessageIdsFitIntoSmallAck() throws Exception {
|
||||
testMessageIdsFitIntoAck(1000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessageFitsIntoPacket() throws Exception {
|
||||
MessageId parent = new MessageId(TestUtils.getRandomId());
|
||||
// Create a maximum-length group
|
||||
String groupName = TestUtils.createRandomString(MAX_GROUP_NAME_LENGTH);
|
||||
Group group = groupFactory.createGroup(groupName);
|
||||
// Create a maximum-length author
|
||||
String authorName =
|
||||
TestUtils.createRandomString(MAX_AUTHOR_NAME_LENGTH);
|
||||
byte[] authorPublic = new byte[MAX_PUBLIC_KEY_LENGTH];
|
||||
Author author = authorFactory.createAuthor(authorName, authorPublic);
|
||||
// Create a maximum-length message
|
||||
PrivateKey privateKey = crypto.generateSignatureKeyPair().getPrivate();
|
||||
String contentType =
|
||||
TestUtils.createRandomString(MAX_CONTENT_TYPE_LENGTH);
|
||||
long timestamp = Long.MAX_VALUE;
|
||||
byte[] body = new byte[MAX_BODY_LENGTH];
|
||||
Message message = messageFactory.createPseudonymousMessage(parent,
|
||||
group, author, privateKey, contentType, timestamp, body);
|
||||
// Check the size of the serialised message
|
||||
int length = message.getSerialised().length;
|
||||
assertTrue(length > UniqueId.LENGTH + MAX_GROUP_NAME_LENGTH
|
||||
+ MAX_PUBLIC_KEY_LENGTH + MAX_AUTHOR_NAME_LENGTH
|
||||
+ MAX_PUBLIC_KEY_LENGTH + MAX_CONTENT_TYPE_LENGTH
|
||||
+ MAX_BODY_LENGTH);
|
||||
assertTrue(length <= MAX_PAYLOAD_LENGTH);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessageIdsFitIntoLargeOffer() throws Exception {
|
||||
testMessageIdsFitIntoOffer(MAX_PAYLOAD_LENGTH);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessageIdsFitIntoSmallOffer() throws Exception {
|
||||
testMessageIdsFitIntoOffer(1000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessageIdsFitIntoLargeRequest() throws Exception {
|
||||
testMessageIdsFitIntoRequest(MAX_PAYLOAD_LENGTH);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessageIdsFitIntoSmallRequest() throws Exception {
|
||||
testMessageIdsFitIntoRequest(1000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertiesFitIntoTransportUpdate() throws Exception {
|
||||
// Create the maximum number of properties with the maximum length
|
||||
TransportProperties p = new TransportProperties();
|
||||
for (int i = 0; i < MAX_PROPERTIES_PER_TRANSPORT; i++) {
|
||||
String key = TestUtils.createRandomString(MAX_PROPERTY_LENGTH);
|
||||
String value = TestUtils.createRandomString(MAX_PROPERTY_LENGTH);
|
||||
p.put(key, value);
|
||||
}
|
||||
// Create a maximum-length transport update
|
||||
String idString = TestUtils.createRandomString(MAX_TRANSPORT_ID_LENGTH);
|
||||
TransportId id = new TransportId(idString);
|
||||
TransportUpdate u = new TransportUpdate(id, p, Long.MAX_VALUE);
|
||||
// Serialise the update
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
PacketWriter writer = packetWriterFactory.createPacketWriter(out);
|
||||
writer.writeTransportUpdate(u);
|
||||
// Check the size of the serialised transport update
|
||||
assertTrue(out.size() <= MAX_PAYLOAD_LENGTH);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroupsFitIntoSubscriptionUpdate() throws Exception {
|
||||
// Create the maximum number of maximum-length groups
|
||||
Collection<Group> groups = new ArrayList<Group>();
|
||||
for (int i = 0; i < MAX_SUBSCRIPTIONS; i++) {
|
||||
String name = TestUtils.createRandomString(MAX_GROUP_NAME_LENGTH);
|
||||
groups.add(groupFactory.createGroup(name));
|
||||
}
|
||||
// Create a maximum-length subscription update
|
||||
SubscriptionUpdate u = new SubscriptionUpdate(groups, Long.MAX_VALUE);
|
||||
// Serialise the update
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
PacketWriter writer = packetWriterFactory.createPacketWriter(out);
|
||||
writer.writeSubscriptionUpdate(u);
|
||||
// Check the size of the serialised subscription update
|
||||
assertTrue(out.size() <= MAX_PAYLOAD_LENGTH);
|
||||
}
|
||||
|
||||
private void testMessageIdsFitIntoAck(int length) throws Exception {
|
||||
// Create an ack with as many message IDs as possible
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(length);
|
||||
PacketWriter writer = packetWriterFactory.createPacketWriter(out);
|
||||
int maxMessages = writer.getMaxMessagesForAck(length);
|
||||
Collection<MessageId> ids = new ArrayList<MessageId>();
|
||||
for (int i = 0; i < maxMessages; i++)
|
||||
ids.add(new MessageId(TestUtils.getRandomId()));
|
||||
writer.writeAck(new Ack(ids));
|
||||
// Check the size of the serialised ack
|
||||
assertTrue(out.size() <= length);
|
||||
}
|
||||
|
||||
private void testMessageIdsFitIntoRequest(int length) throws Exception {
|
||||
// Create a request with as many message IDs as possible
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(length);
|
||||
PacketWriter writer = packetWriterFactory.createPacketWriter(out);
|
||||
int maxMessages = writer.getMaxMessagesForRequest(length);
|
||||
Collection<MessageId> ids = new ArrayList<MessageId>();
|
||||
for (int i = 0; i < maxMessages; i++)
|
||||
ids.add(new MessageId(TestUtils.getRandomId()));
|
||||
writer.writeRequest(new Request(ids));
|
||||
// Check the size of the serialised request
|
||||
assertTrue(out.size() <= length);
|
||||
}
|
||||
|
||||
private void testMessageIdsFitIntoOffer(int length) throws Exception {
|
||||
// Create an offer with as many message IDs as possible
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(length);
|
||||
PacketWriter writer = packetWriterFactory.createPacketWriter(out);
|
||||
int maxMessages = writer.getMaxMessagesForOffer(length);
|
||||
Collection<MessageId> ids = new ArrayList<MessageId>();
|
||||
for (int i = 0; i < maxMessages; i++)
|
||||
ids.add(new MessageId(TestUtils.getRandomId()));
|
||||
writer.writeOffer(new Offer(ids));
|
||||
// Check the size of the serialised offer
|
||||
assertTrue(out.size() <= length);
|
||||
}
|
||||
}
|
||||
108
briar-tests/src/org/briarproject/sync/ConsumersTest.java
Normal file
108
briar-tests/src/org/briarproject/sync/ConsumersTest.java
Normal file
@@ -0,0 +1,108 @@
|
||||
package org.briarproject.sync;
|
||||
|
||||
import org.briarproject.BriarTestCase;
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.crypto.MessageDigest;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Random;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class ConsumersTest extends BriarTestCase {
|
||||
|
||||
@Test
|
||||
public void testDigestingConsumer() throws Exception {
|
||||
byte[] data = new byte[1234];
|
||||
// Generate some random data and digest it
|
||||
new Random().nextBytes(data);
|
||||
MessageDigest messageDigest = new TestMessageDigest();
|
||||
messageDigest.update(data);
|
||||
byte[] dig = messageDigest.digest();
|
||||
// Check that feeding a DigestingConsumer generates the same digest
|
||||
org.briarproject.sync.DigestingConsumer
|
||||
dc = new org.briarproject.sync.DigestingConsumer(messageDigest);
|
||||
dc.write(data[0]);
|
||||
dc.write(data, 1, data.length - 2);
|
||||
dc.write(data[data.length - 1]);
|
||||
byte[] dig1 = messageDigest.digest();
|
||||
assertArrayEquals(dig, dig1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountingConsumer() throws Exception {
|
||||
byte[] data = new byte[1234];
|
||||
org.briarproject.sync.CountingConsumer
|
||||
cc = new org.briarproject.sync.CountingConsumer(data.length);
|
||||
cc.write(data[0]);
|
||||
cc.write(data, 1, data.length - 2);
|
||||
cc.write(data[data.length - 1]);
|
||||
assertEquals(data.length, cc.getCount());
|
||||
try {
|
||||
cc.write((byte) 0);
|
||||
fail();
|
||||
} catch (FormatException expected) {
|
||||
// Expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopyingConsumer() throws Exception {
|
||||
byte[] data = new byte[1234];
|
||||
new Random().nextBytes(data);
|
||||
// Check that a CopyingConsumer creates a faithful copy
|
||||
org.briarproject.sync.CopyingConsumer
|
||||
cc = new org.briarproject.sync.CopyingConsumer();
|
||||
cc.write(data[0]);
|
||||
cc.write(data, 1, data.length - 2);
|
||||
cc.write(data[data.length - 1]);
|
||||
assertArrayEquals(data, cc.getCopy());
|
||||
}
|
||||
|
||||
private static class TestMessageDigest implements MessageDigest {
|
||||
|
||||
private final java.security.MessageDigest delegate;
|
||||
|
||||
private TestMessageDigest() throws GeneralSecurityException {
|
||||
delegate = java.security.MessageDigest.getInstance("SHA-256");
|
||||
}
|
||||
|
||||
public byte[] digest() {
|
||||
return delegate.digest();
|
||||
}
|
||||
|
||||
public byte[] digest(byte[] input) {
|
||||
return delegate.digest(input);
|
||||
}
|
||||
|
||||
public int digest(byte[] buf, int offset, int len) {
|
||||
byte[] digest = digest();
|
||||
len = Math.min(len, digest.length);
|
||||
System.arraycopy(digest, 0, buf, offset, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
public int getDigestLength() {
|
||||
return delegate.getDigestLength();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
delegate.reset();
|
||||
}
|
||||
|
||||
public void update(byte input) {
|
||||
delegate.update(input);
|
||||
}
|
||||
|
||||
public void update(byte[] input) {
|
||||
delegate.update(input);
|
||||
}
|
||||
|
||||
public void update(byte[] input, int offset, int len) {
|
||||
delegate.update(input, offset, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
263
briar-tests/src/org/briarproject/sync/PacketReaderImplTest.java
Normal file
263
briar-tests/src/org/briarproject/sync/PacketReaderImplTest.java
Normal file
@@ -0,0 +1,263 @@
|
||||
package org.briarproject.sync;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
import org.briarproject.BriarTestCase;
|
||||
import org.briarproject.TestUtils;
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.data.ReaderFactory;
|
||||
import org.briarproject.api.data.Writer;
|
||||
import org.briarproject.api.data.WriterFactory;
|
||||
import org.briarproject.data.DataModule;
|
||||
import org.briarproject.util.ByteUtils;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
import static org.briarproject.api.data.DataConstants.LIST_END_LENGTH;
|
||||
import static org.briarproject.api.data.DataConstants.UNIQUE_ID_LENGTH;
|
||||
import static org.briarproject.api.sync.MessagingConstants.HEADER_LENGTH;
|
||||
import static org.briarproject.api.sync.MessagingConstants.MAX_PAYLOAD_LENGTH;
|
||||
import static org.briarproject.api.sync.PacketTypes.ACK;
|
||||
import static org.briarproject.api.sync.PacketTypes.OFFER;
|
||||
import static org.briarproject.api.sync.PacketTypes.REQUEST;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class PacketReaderImplTest extends BriarTestCase {
|
||||
|
||||
// FIXME: This is an integration test, not a unit test
|
||||
|
||||
private final ReaderFactory readerFactory;
|
||||
private final WriterFactory writerFactory;
|
||||
|
||||
public PacketReaderImplTest() throws Exception {
|
||||
Injector i = Guice.createInjector(new DataModule());
|
||||
readerFactory = i.getInstance(ReaderFactory.class);
|
||||
writerFactory = i.getInstance(WriterFactory.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormatExceptionIfAckIsTooLarge() throws Exception {
|
||||
byte[] b = createAck(true);
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(b);
|
||||
org.briarproject.sync.PacketReaderImpl
|
||||
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null,
|
||||
null, in);
|
||||
try {
|
||||
reader.readAck();
|
||||
fail();
|
||||
} catch (FormatException expected) {
|
||||
// Expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoFormatExceptionIfAckIsMaximumSize() throws Exception {
|
||||
byte[] b = createAck(false);
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(b);
|
||||
org.briarproject.sync.PacketReaderImpl
|
||||
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null,
|
||||
null, in);
|
||||
reader.readAck();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyAck() throws Exception {
|
||||
byte[] b = createEmptyAck();
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(b);
|
||||
org.briarproject.sync.PacketReaderImpl
|
||||
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null,
|
||||
null, in);
|
||||
try {
|
||||
reader.readAck();
|
||||
fail();
|
||||
} catch (FormatException expected) {
|
||||
// Expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormatExceptionIfOfferIsTooLarge() throws Exception {
|
||||
byte[] b = createOffer(true);
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(b);
|
||||
org.briarproject.sync.PacketReaderImpl
|
||||
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null,
|
||||
null, in);
|
||||
try {
|
||||
reader.readOffer();
|
||||
fail();
|
||||
} catch (FormatException expected) {
|
||||
// Expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoFormatExceptionIfOfferIsMaximumSize() throws Exception {
|
||||
byte[] b = createOffer(false);
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(b);
|
||||
org.briarproject.sync.PacketReaderImpl
|
||||
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null,
|
||||
null, in);
|
||||
reader.readOffer();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyOffer() throws Exception {
|
||||
byte[] b = createEmptyOffer();
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(b);
|
||||
org.briarproject.sync.PacketReaderImpl
|
||||
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null,
|
||||
null, in);
|
||||
try {
|
||||
reader.readOffer();
|
||||
fail();
|
||||
} catch (FormatException expected) {
|
||||
// Expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormatExceptionIfRequestIsTooLarge() throws Exception {
|
||||
byte[] b = createRequest(true);
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(b);
|
||||
org.briarproject.sync.PacketReaderImpl
|
||||
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null,
|
||||
null, in);
|
||||
try {
|
||||
reader.readRequest();
|
||||
fail();
|
||||
} catch (FormatException expected) {
|
||||
// Expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoFormatExceptionIfRequestIsMaximumSize() throws Exception {
|
||||
byte[] b = createRequest(false);
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(b);
|
||||
org.briarproject.sync.PacketReaderImpl
|
||||
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null,
|
||||
null, in);
|
||||
reader.readRequest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyRequest() throws Exception {
|
||||
byte[] b = createEmptyRequest();
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(b);
|
||||
org.briarproject.sync.PacketReaderImpl
|
||||
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null,
|
||||
null, in);
|
||||
try {
|
||||
reader.readRequest();
|
||||
fail();
|
||||
} catch (FormatException expected) {
|
||||
// Expected
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] createAck(boolean tooBig) throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write(new byte[HEADER_LENGTH]);
|
||||
Writer w = writerFactory.createWriter(out);
|
||||
w.writeListStart();
|
||||
w.writeListStart();
|
||||
while (out.size() + UNIQUE_ID_LENGTH + LIST_END_LENGTH * 2
|
||||
< HEADER_LENGTH + MAX_PAYLOAD_LENGTH) {
|
||||
w.writeRaw(TestUtils.getRandomId());
|
||||
}
|
||||
if (tooBig) w.writeRaw(TestUtils.getRandomId());
|
||||
w.writeListEnd();
|
||||
w.writeListEnd();
|
||||
assertEquals(tooBig, out.size() > HEADER_LENGTH + MAX_PAYLOAD_LENGTH);
|
||||
byte[] packet = out.toByteArray();
|
||||
packet[1] = ACK;
|
||||
ByteUtils.writeUint16(packet.length - HEADER_LENGTH, packet, 2);
|
||||
return packet;
|
||||
}
|
||||
|
||||
private byte[] createEmptyAck() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write(new byte[HEADER_LENGTH]);
|
||||
Writer w = writerFactory.createWriter(out);
|
||||
w.writeListStart();
|
||||
w.writeListStart();
|
||||
w.writeListEnd();
|
||||
w.writeListEnd();
|
||||
byte[] packet = out.toByteArray();
|
||||
packet[1] = ACK;
|
||||
ByteUtils.writeUint16(packet.length - HEADER_LENGTH, packet, 2);
|
||||
return packet;
|
||||
}
|
||||
|
||||
private byte[] createOffer(boolean tooBig) throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write(new byte[HEADER_LENGTH]);
|
||||
Writer w = writerFactory.createWriter(out);
|
||||
w.writeListStart();
|
||||
w.writeListStart();
|
||||
while (out.size() + UNIQUE_ID_LENGTH + LIST_END_LENGTH * 2
|
||||
< HEADER_LENGTH + MAX_PAYLOAD_LENGTH) {
|
||||
w.writeRaw(TestUtils.getRandomId());
|
||||
}
|
||||
if (tooBig) w.writeRaw(TestUtils.getRandomId());
|
||||
w.writeListEnd();
|
||||
w.writeListEnd();
|
||||
assertEquals(tooBig, out.size() > HEADER_LENGTH + MAX_PAYLOAD_LENGTH);
|
||||
byte[] packet = out.toByteArray();
|
||||
packet[1] = OFFER;
|
||||
ByteUtils.writeUint16(packet.length - HEADER_LENGTH, packet, 2);
|
||||
return packet;
|
||||
}
|
||||
|
||||
private byte[] createEmptyOffer() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write(new byte[HEADER_LENGTH]);
|
||||
Writer w = writerFactory.createWriter(out);
|
||||
w.writeListStart();
|
||||
w.writeListStart();
|
||||
w.writeListEnd();
|
||||
w.writeListEnd();
|
||||
byte[] packet = out.toByteArray();
|
||||
packet[1] = OFFER;
|
||||
ByteUtils.writeUint16(packet.length - HEADER_LENGTH, packet, 2);
|
||||
return packet;
|
||||
}
|
||||
|
||||
private byte[] createRequest(boolean tooBig) throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write(new byte[HEADER_LENGTH]);
|
||||
Writer w = writerFactory.createWriter(out);
|
||||
w.writeListStart();
|
||||
w.writeListStart();
|
||||
while (out.size() + UNIQUE_ID_LENGTH + LIST_END_LENGTH * 2
|
||||
< HEADER_LENGTH + MAX_PAYLOAD_LENGTH) {
|
||||
w.writeRaw(TestUtils.getRandomId());
|
||||
}
|
||||
if (tooBig) w.writeRaw(TestUtils.getRandomId());
|
||||
w.writeListEnd();
|
||||
w.writeListEnd();
|
||||
assertEquals(tooBig, out.size() > HEADER_LENGTH + MAX_PAYLOAD_LENGTH);
|
||||
byte[] packet = out.toByteArray();
|
||||
packet[1] = REQUEST;
|
||||
ByteUtils.writeUint16(packet.length - HEADER_LENGTH, packet, 2);
|
||||
return packet;
|
||||
}
|
||||
|
||||
private byte[] createEmptyRequest() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write(new byte[HEADER_LENGTH]);
|
||||
Writer w = writerFactory.createWriter(out);
|
||||
w.writeListStart();
|
||||
w.writeListStart();
|
||||
w.writeListEnd();
|
||||
w.writeListEnd();
|
||||
byte[] packet = out.toByteArray();
|
||||
packet[1] = REQUEST;
|
||||
ByteUtils.writeUint16(packet.length - HEADER_LENGTH, packet, 2);
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
package org.briarproject.sync;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
import org.briarproject.BriarTestCase;
|
||||
import org.briarproject.TestDatabaseModule;
|
||||
import org.briarproject.TestLifecycleModule;
|
||||
import org.briarproject.TestSystemModule;
|
||||
import org.briarproject.TestUtils;
|
||||
import org.briarproject.api.Author;
|
||||
import org.briarproject.api.AuthorId;
|
||||
import org.briarproject.api.ContactId;
|
||||
import org.briarproject.api.LocalAuthor;
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.crypto.CryptoComponent;
|
||||
import org.briarproject.api.crypto.SecretKey;
|
||||
import org.briarproject.api.db.DatabaseComponent;
|
||||
import org.briarproject.api.event.Event;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.event.EventListener;
|
||||
import org.briarproject.api.event.MessageAddedEvent;
|
||||
import org.briarproject.api.sync.Group;
|
||||
import org.briarproject.api.sync.GroupFactory;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.sync.MessageFactory;
|
||||
import org.briarproject.api.sync.MessageVerifier;
|
||||
import org.briarproject.api.sync.MessagingSession;
|
||||
import org.briarproject.api.sync.PacketReader;
|
||||
import org.briarproject.api.sync.PacketReaderFactory;
|
||||
import org.briarproject.api.sync.PacketWriter;
|
||||
import org.briarproject.api.sync.PacketWriterFactory;
|
||||
import org.briarproject.api.transport.KeyManager;
|
||||
import org.briarproject.api.transport.StreamContext;
|
||||
import org.briarproject.api.transport.StreamReaderFactory;
|
||||
import org.briarproject.api.transport.StreamWriterFactory;
|
||||
import org.briarproject.api.transport.TransportKeys;
|
||||
import org.briarproject.crypto.CryptoModule;
|
||||
import org.briarproject.data.DataModule;
|
||||
import org.briarproject.db.DatabaseModule;
|
||||
import org.briarproject.event.EventModule;
|
||||
import org.briarproject.plugins.ImmediateExecutor;
|
||||
import org.briarproject.transport.TransportModule;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.briarproject.api.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||
import static org.briarproject.api.sync.MessagingConstants.GROUP_SALT_LENGTH;
|
||||
import static org.briarproject.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
|
||||
import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class SimplexMessagingIntegrationTest extends BriarTestCase {
|
||||
|
||||
private static final int MAX_LATENCY = 2 * 60 * 1000; // 2 minutes
|
||||
private static final long ROTATION_PERIOD_LENGTH =
|
||||
MAX_LATENCY + MAX_CLOCK_DIFFERENCE;
|
||||
|
||||
private final File testDir = TestUtils.getTestDirectory();
|
||||
private final File aliceDir = new File(testDir, "alice");
|
||||
private final File bobDir = new File(testDir, "bob");
|
||||
private final TransportId transportId = new TransportId("id");
|
||||
private final SecretKey master = TestUtils.createSecretKey();
|
||||
private final long timestamp = System.currentTimeMillis();
|
||||
|
||||
private Injector alice, bob;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
testDir.mkdirs();
|
||||
alice = createInjector(aliceDir);
|
||||
bob = createInjector(bobDir);
|
||||
}
|
||||
|
||||
private Injector createInjector(File dir) {
|
||||
return Guice.createInjector(new TestDatabaseModule(dir),
|
||||
new TestLifecycleModule(), new TestSystemModule(),
|
||||
new CryptoModule(), new DatabaseModule(), new EventModule(),
|
||||
new org.briarproject.sync.MessagingModule(), new DataModule(),
|
||||
new TransportModule());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteAndRead() throws Exception {
|
||||
read(write());
|
||||
}
|
||||
|
||||
private byte[] write() throws Exception {
|
||||
// Open Alice's database
|
||||
DatabaseComponent db = alice.getInstance(DatabaseComponent.class);
|
||||
assertFalse(db.open());
|
||||
// Start Alice's key manager
|
||||
KeyManager keyManager = alice.getInstance(KeyManager.class);
|
||||
keyManager.start();
|
||||
// Add a local pseudonym for Alice
|
||||
AuthorId aliceId = new AuthorId(TestUtils.getRandomId());
|
||||
LocalAuthor aliceAuthor = new LocalAuthor(aliceId, "Alice",
|
||||
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[100], 1234);
|
||||
db.addLocalAuthor(aliceAuthor);
|
||||
// Add Bob as a contact
|
||||
AuthorId bobId = new AuthorId(TestUtils.getRandomId());
|
||||
Author bobAuthor = new Author(bobId, "Bob",
|
||||
new byte[MAX_PUBLIC_KEY_LENGTH]);
|
||||
ContactId contactId = db.addContact(bobAuthor, aliceId);
|
||||
// Add the inbox group
|
||||
GroupFactory gf = alice.getInstance(GroupFactory.class);
|
||||
Group group = gf.createGroup("Group", new byte[GROUP_SALT_LENGTH]);
|
||||
db.addGroup(group);
|
||||
db.setInboxGroup(contactId, group);
|
||||
// Add the transport
|
||||
db.addTransport(transportId, MAX_LATENCY);
|
||||
// Derive and store the transport keys
|
||||
long rotationPeriod = timestamp / ROTATION_PERIOD_LENGTH;
|
||||
CryptoComponent crypto = alice.getInstance(CryptoComponent.class);
|
||||
TransportKeys keys = crypto.deriveTransportKeys(transportId, master,
|
||||
rotationPeriod, true);
|
||||
db.addTransportKeys(contactId, keys);
|
||||
keyManager.contactAdded(contactId, Collections.singletonList(keys));
|
||||
// Send Bob a message
|
||||
String contentType = "text/plain";
|
||||
byte[] body = "Hi Bob!".getBytes("UTF-8");
|
||||
MessageFactory messageFactory = alice.getInstance(MessageFactory.class);
|
||||
Message message = messageFactory.createAnonymousMessage(null, group,
|
||||
contentType, timestamp, body);
|
||||
db.addLocalMessage(message);
|
||||
// Get a stream context
|
||||
StreamContext ctx = keyManager.getStreamContext(contactId, transportId);
|
||||
assertNotNull(ctx);
|
||||
// Create a stream writer
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
StreamWriterFactory streamWriterFactory =
|
||||
alice.getInstance(StreamWriterFactory.class);
|
||||
OutputStream streamWriter =
|
||||
streamWriterFactory.createStreamWriter(out, ctx);
|
||||
// Create an outgoing messaging session
|
||||
EventBus eventBus = alice.getInstance(EventBus.class);
|
||||
PacketWriterFactory packetWriterFactory =
|
||||
alice.getInstance(PacketWriterFactory.class);
|
||||
PacketWriter packetWriter = packetWriterFactory.createPacketWriter(
|
||||
streamWriter);
|
||||
MessagingSession session = new org.briarproject.sync.SimplexOutgoingSession(db,
|
||||
new ImmediateExecutor(), eventBus, contactId, transportId,
|
||||
MAX_LATENCY, packetWriter);
|
||||
// Write whatever needs to be written
|
||||
session.run();
|
||||
streamWriter.close();
|
||||
// Clean up
|
||||
keyManager.stop();
|
||||
db.close();
|
||||
// Return the contents of the stream
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
private void read(byte[] stream) throws Exception {
|
||||
// Open Bob's database
|
||||
DatabaseComponent db = bob.getInstance(DatabaseComponent.class);
|
||||
assertFalse(db.open());
|
||||
// Start Bob's key manager
|
||||
KeyManager keyManager = bob.getInstance(KeyManager.class);
|
||||
keyManager.start();
|
||||
// Add a local pseudonym for Bob
|
||||
AuthorId bobId = new AuthorId(TestUtils.getRandomId());
|
||||
LocalAuthor bobAuthor = new LocalAuthor(bobId, "Bob",
|
||||
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[100], 1234);
|
||||
db.addLocalAuthor(bobAuthor);
|
||||
// Add Alice as a contact
|
||||
AuthorId aliceId = new AuthorId(TestUtils.getRandomId());
|
||||
Author aliceAuthor = new Author(aliceId, "Alice",
|
||||
new byte[MAX_PUBLIC_KEY_LENGTH]);
|
||||
ContactId contactId = db.addContact(aliceAuthor, bobId);
|
||||
// Add the inbox group
|
||||
GroupFactory gf = bob.getInstance(GroupFactory.class);
|
||||
Group group = gf.createGroup("Group", new byte[GROUP_SALT_LENGTH]);
|
||||
db.addGroup(group);
|
||||
db.setInboxGroup(contactId, group);
|
||||
// Add the transport
|
||||
db.addTransport(transportId, MAX_LATENCY);
|
||||
// Derive and store the transport keys
|
||||
long rotationPeriod = timestamp / ROTATION_PERIOD_LENGTH;
|
||||
CryptoComponent crypto = bob.getInstance(CryptoComponent.class);
|
||||
TransportKeys keys = crypto.deriveTransportKeys(transportId, master,
|
||||
rotationPeriod, false);
|
||||
db.addTransportKeys(contactId, keys);
|
||||
keyManager.contactAdded(contactId, Collections.singletonList(keys));
|
||||
// Set up an event listener
|
||||
MessageListener listener = new MessageListener();
|
||||
bob.getInstance(EventBus.class).addListener(listener);
|
||||
// Read and recognise the tag
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(stream);
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
int read = in.read(tag);
|
||||
assertEquals(tag.length, read);
|
||||
StreamContext ctx = keyManager.recogniseTag(transportId, tag);
|
||||
assertNotNull(ctx);
|
||||
// Create a stream reader
|
||||
StreamReaderFactory streamReaderFactory =
|
||||
bob.getInstance(StreamReaderFactory.class);
|
||||
InputStream streamReader =
|
||||
streamReaderFactory.createStreamReader(in, ctx);
|
||||
// Create an incoming messaging session
|
||||
EventBus eventBus = bob.getInstance(EventBus.class);
|
||||
MessageVerifier messageVerifier =
|
||||
bob.getInstance(MessageVerifier.class);
|
||||
PacketReaderFactory packetReaderFactory =
|
||||
bob.getInstance(PacketReaderFactory.class);
|
||||
PacketReader packetReader = packetReaderFactory.createPacketReader(
|
||||
streamReader);
|
||||
MessagingSession session = new org.briarproject.sync.IncomingSession(db,
|
||||
new ImmediateExecutor(), new ImmediateExecutor(), eventBus,
|
||||
messageVerifier, contactId, transportId, packetReader);
|
||||
// No messages should have been added yet
|
||||
assertFalse(listener.messageAdded);
|
||||
// Read whatever needs to be read
|
||||
session.run();
|
||||
streamReader.close();
|
||||
// The private message from Alice should have been added
|
||||
assertTrue(listener.messageAdded);
|
||||
// Clean up
|
||||
keyManager.stop();
|
||||
db.close();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
TestUtils.deleteTestDirectory(testDir);
|
||||
}
|
||||
|
||||
private static class MessageListener implements EventListener {
|
||||
|
||||
private volatile boolean messageAdded = false;
|
||||
|
||||
public void eventOccurred(Event e) {
|
||||
if (e instanceof MessageAddedEvent) messageAdded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package org.briarproject.sync;
|
||||
|
||||
import org.briarproject.BriarTestCase;
|
||||
import org.briarproject.TestUtils;
|
||||
import org.briarproject.api.ContactId;
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.db.DatabaseComponent;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.sync.Ack;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.briarproject.api.sync.PacketWriter;
|
||||
import org.briarproject.plugins.ImmediateExecutor;
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
public class SimplexOutgoingSessionTest extends BriarTestCase {
|
||||
|
||||
private static final int MAX_MESSAGES_PER_ACK = 10;
|
||||
|
||||
private final Mockery context;
|
||||
private final DatabaseComponent db;
|
||||
private final Executor dbExecutor;
|
||||
private final EventBus eventBus;
|
||||
private final ContactId contactId;
|
||||
private final TransportId transportId;
|
||||
private final MessageId messageId;
|
||||
private final int maxLatency;
|
||||
private final PacketWriter packetWriter;
|
||||
|
||||
public SimplexOutgoingSessionTest() {
|
||||
context = new Mockery();
|
||||
db = context.mock(DatabaseComponent.class);
|
||||
dbExecutor = new ImmediateExecutor();
|
||||
eventBus = context.mock(EventBus.class);
|
||||
packetWriter = context.mock(PacketWriter.class);
|
||||
contactId = new ContactId(234);
|
||||
transportId = new TransportId("id");
|
||||
messageId = new MessageId(TestUtils.getRandomId());
|
||||
maxLatency = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNothingToSend() throws Exception {
|
||||
final org.briarproject.sync.SimplexOutgoingSession
|
||||
session = new org.briarproject.sync.SimplexOutgoingSession(db,
|
||||
dbExecutor, eventBus, contactId, transportId, maxLatency,
|
||||
packetWriter);
|
||||
context.checking(new Expectations() {{
|
||||
// Add listener
|
||||
oneOf(eventBus).addListener(session);
|
||||
// No transport acks to send
|
||||
oneOf(db).generateTransportAcks(contactId);
|
||||
will(returnValue(null));
|
||||
// No transport updates to send
|
||||
oneOf(db).generateTransportUpdates(contactId, maxLatency);
|
||||
will(returnValue(null));
|
||||
// No subscription ack to send
|
||||
oneOf(db).generateSubscriptionAck(contactId);
|
||||
will(returnValue(null));
|
||||
// No subscription update to send
|
||||
oneOf(db).generateSubscriptionUpdate(contactId, maxLatency);
|
||||
will(returnValue(null));
|
||||
// No retention ack to send
|
||||
oneOf(db).generateRetentionAck(contactId);
|
||||
will(returnValue(null));
|
||||
// No retention update to send
|
||||
oneOf(db).generateRetentionUpdate(contactId, maxLatency);
|
||||
will(returnValue(null));
|
||||
// No acks to send
|
||||
oneOf(packetWriter).getMaxMessagesForAck(with(any(long.class)));
|
||||
will(returnValue(MAX_MESSAGES_PER_ACK));
|
||||
oneOf(db).generateAck(contactId, MAX_MESSAGES_PER_ACK);
|
||||
will(returnValue(null));
|
||||
// No messages to send
|
||||
oneOf(db).generateBatch(with(contactId), with(any(int.class)),
|
||||
with(maxLatency));
|
||||
will(returnValue(null));
|
||||
// Flush the output stream
|
||||
oneOf(packetWriter).flush();
|
||||
// Remove listener
|
||||
oneOf(eventBus).removeListener(session);
|
||||
}});
|
||||
session.run();
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSomethingToSend() throws Exception {
|
||||
final Ack ack = new Ack(Collections.singletonList(messageId));
|
||||
final byte[] raw = new byte[1234];
|
||||
final org.briarproject.sync.SimplexOutgoingSession
|
||||
session = new org.briarproject.sync.SimplexOutgoingSession(db,
|
||||
dbExecutor, eventBus, contactId, transportId, maxLatency,
|
||||
packetWriter);
|
||||
context.checking(new Expectations() {{
|
||||
// Add listener
|
||||
oneOf(eventBus).addListener(session);
|
||||
// No transport acks to send
|
||||
oneOf(db).generateTransportAcks(contactId);
|
||||
will(returnValue(null));
|
||||
// No transport updates to send
|
||||
oneOf(db).generateTransportUpdates(contactId, maxLatency);
|
||||
will(returnValue(null));
|
||||
// No subscription ack to send
|
||||
oneOf(db).generateSubscriptionAck(contactId);
|
||||
will(returnValue(null));
|
||||
// No subscription update to send
|
||||
oneOf(db).generateSubscriptionUpdate(contactId, maxLatency);
|
||||
will(returnValue(null));
|
||||
// No retention ack to send
|
||||
oneOf(db).generateRetentionAck(contactId);
|
||||
will(returnValue(null));
|
||||
// No retention update to send
|
||||
oneOf(db).generateRetentionUpdate(contactId, maxLatency);
|
||||
will(returnValue(null));
|
||||
// One ack to send
|
||||
oneOf(packetWriter).getMaxMessagesForAck(with(any(long.class)));
|
||||
will(returnValue(MAX_MESSAGES_PER_ACK));
|
||||
oneOf(db).generateAck(contactId, MAX_MESSAGES_PER_ACK);
|
||||
will(returnValue(ack));
|
||||
oneOf(packetWriter).writeAck(ack);
|
||||
// No more acks
|
||||
oneOf(packetWriter).getMaxMessagesForAck(with(any(long.class)));
|
||||
will(returnValue(MAX_MESSAGES_PER_ACK));
|
||||
oneOf(db).generateAck(contactId, MAX_MESSAGES_PER_ACK);
|
||||
will(returnValue(null));
|
||||
// One message to send
|
||||
oneOf(db).generateBatch(with(contactId), with(any(int.class)),
|
||||
with(maxLatency));
|
||||
will(returnValue(Arrays.asList(raw)));
|
||||
oneOf(packetWriter).writeMessage(raw);
|
||||
// No more messages
|
||||
oneOf(db).generateBatch(with(contactId), with(any(int.class)),
|
||||
with(maxLatency));
|
||||
will(returnValue(null));
|
||||
// Flush the output stream
|
||||
oneOf(packetWriter).flush();
|
||||
// Remove listener
|
||||
oneOf(eventBus).removeListener(session);
|
||||
}});
|
||||
session.run();
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user