mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 19:29:06 +01:00
Rewrote the bundle reading and writing code to eliminate copying. Signatures and digests are now calculated on the fly as the data is read or written. This is a little bit tricky in the case of reading because ReaderImpl uses a lookahead byte, so the signature and message digest need to lag one byte behind.
This commit is contained in:
@@ -6,8 +6,6 @@ import static net.sf.briar.api.db.DatabaseComponent.MIN_FREE_SPACE;
|
||||
import java.util.Collections;
|
||||
|
||||
import net.sf.briar.api.db.DbException;
|
||||
import net.sf.briar.api.protocol.BatchBuilder;
|
||||
import net.sf.briar.api.protocol.HeaderBuilder;
|
||||
import net.sf.briar.api.protocol.MessageId;
|
||||
import net.sf.briar.db.DatabaseCleaner.Callback;
|
||||
|
||||
@@ -15,8 +13,6 @@ import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.inject.Provider;
|
||||
|
||||
/**
|
||||
* Tests that use the DatabaseCleaner.Callback interface of
|
||||
* DatabaseComponentImpl.
|
||||
@@ -24,9 +20,7 @@ import com.google.inject.Provider;
|
||||
public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
|
||||
|
||||
protected abstract <T> DatabaseComponentImpl<T> createDatabaseComponentImpl(
|
||||
Database<T> database, DatabaseCleaner cleaner,
|
||||
Provider<HeaderBuilder> headerBuilderProvider,
|
||||
Provider<BatchBuilder> batchBuilderProvider);
|
||||
Database<T> database, DatabaseCleaner cleaner);
|
||||
|
||||
@Test
|
||||
public void testNotCleanedIfEnoughFreeSpace() throws DbException {
|
||||
@@ -34,18 +28,11 @@ public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(database).getFreeSpace();
|
||||
will(returnValue(MIN_FREE_SPACE));
|
||||
}});
|
||||
Callback db = createDatabaseComponentImpl(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
Callback db = createDatabaseComponentImpl(database, cleaner);
|
||||
|
||||
db.checkFreeSpaceAndClean();
|
||||
|
||||
@@ -58,12 +45,6 @@ public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(database).getFreeSpace();
|
||||
will(returnValue(MIN_FREE_SPACE - 1));
|
||||
@@ -76,8 +57,7 @@ public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
|
||||
oneOf(database).getFreeSpace();
|
||||
will(returnValue(MIN_FREE_SPACE));
|
||||
}});
|
||||
Callback db = createDatabaseComponentImpl(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
Callback db = createDatabaseComponentImpl(database, cleaner);
|
||||
|
||||
db.checkFreeSpaceAndClean();
|
||||
|
||||
@@ -91,12 +71,6 @@ public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(database).getFreeSpace();
|
||||
will(returnValue(MIN_FREE_SPACE - 1));
|
||||
@@ -111,8 +85,7 @@ public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
|
||||
oneOf(database).getFreeSpace();
|
||||
will(returnValue(MIN_FREE_SPACE));
|
||||
}});
|
||||
Callback db = createDatabaseComponentImpl(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
Callback db = createDatabaseComponentImpl(database, cleaner);
|
||||
|
||||
db.checkFreeSpaceAndClean();
|
||||
|
||||
@@ -126,12 +99,6 @@ public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(database).getFreeSpace();
|
||||
will(returnValue(MIN_FREE_SPACE - 1));
|
||||
@@ -148,8 +115,7 @@ public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
|
||||
oneOf(database).getFreeSpace();
|
||||
will(returnValue(MIN_FREE_SPACE));
|
||||
}});
|
||||
Callback db = createDatabaseComponentImpl(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
Callback db = createDatabaseComponentImpl(database, cleaner);
|
||||
|
||||
db.checkFreeSpaceAndClean();
|
||||
|
||||
|
||||
@@ -14,14 +14,12 @@ import net.sf.briar.api.db.NoSuchContactException;
|
||||
import net.sf.briar.api.db.Status;
|
||||
import net.sf.briar.api.protocol.AuthorId;
|
||||
import net.sf.briar.api.protocol.Batch;
|
||||
import net.sf.briar.api.protocol.BatchBuilder;
|
||||
import net.sf.briar.api.protocol.BatchId;
|
||||
import net.sf.briar.api.protocol.BundleId;
|
||||
import net.sf.briar.api.protocol.BundleReader;
|
||||
import net.sf.briar.api.protocol.BundleWriter;
|
||||
import net.sf.briar.api.protocol.GroupId;
|
||||
import net.sf.briar.api.protocol.Header;
|
||||
import net.sf.briar.api.protocol.HeaderBuilder;
|
||||
import net.sf.briar.api.protocol.Message;
|
||||
import net.sf.briar.api.protocol.MessageId;
|
||||
import net.sf.briar.protocol.MessageImpl;
|
||||
@@ -30,8 +28,6 @@ import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.inject.Provider;
|
||||
|
||||
public abstract class DatabaseComponentTest extends TestCase {
|
||||
|
||||
protected final Object txn = new Object();
|
||||
@@ -73,9 +69,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
}
|
||||
|
||||
protected abstract <T> DatabaseComponent createDatabaseComponent(
|
||||
Database<T> database, DatabaseCleaner cleaner,
|
||||
Provider<HeaderBuilder> headerBuilderProvider,
|
||||
Provider<BatchBuilder> batchBuilderProvider);
|
||||
Database<T> database, DatabaseCleaner cleaner);
|
||||
|
||||
@Test
|
||||
public void testSimpleCalls() throws DbException {
|
||||
@@ -85,12 +79,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
context.checking(new Expectations() {{
|
||||
allowing(database).startTransaction();
|
||||
will(returnValue(txn));
|
||||
@@ -129,8 +117,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
oneOf(cleaner).stopCleaning();
|
||||
oneOf(database).close();
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner);
|
||||
|
||||
db.open(false);
|
||||
assertEquals(Rating.UNRATED, db.getRating(authorId));
|
||||
@@ -153,12 +140,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
context.checking(new Expectations() {{
|
||||
// setRating(Rating.GOOD)
|
||||
allowing(database).startTransaction();
|
||||
@@ -175,8 +156,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
will(returnValue(MessageId.NONE));
|
||||
oneOf(database).commitTransaction(txn);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner);
|
||||
|
||||
db.setRating(authorId, Rating.GOOD);
|
||||
|
||||
@@ -189,12 +169,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
context.checking(new Expectations() {{
|
||||
// setRating(Rating.GOOD)
|
||||
oneOf(database).startTransaction();
|
||||
@@ -214,8 +188,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
will(returnValue(false));
|
||||
oneOf(database).commitTransaction(txn);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner);
|
||||
|
||||
db.setRating(authorId, Rating.GOOD);
|
||||
|
||||
@@ -229,12 +202,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
context.checking(new Expectations() {{
|
||||
// setRating(Rating.GOOD)
|
||||
oneOf(database).startTransaction();
|
||||
@@ -258,8 +225,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
will(returnValue(groupId1));
|
||||
oneOf(database).commitTransaction(txn);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner);
|
||||
|
||||
db.setRating(authorId, Rating.GOOD);
|
||||
|
||||
@@ -273,12 +239,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
context.checking(new Expectations() {{
|
||||
// setRating(Rating.GOOD)
|
||||
oneOf(database).startTransaction();
|
||||
@@ -305,8 +265,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
oneOf(database).setSendability(txn, parentId, 2);
|
||||
oneOf(database).commitTransaction(txn);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner);
|
||||
|
||||
db.setRating(authorId, Rating.GOOD);
|
||||
|
||||
@@ -320,12 +279,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
context.checking(new Expectations() {{
|
||||
// setRating(Rating.GOOD)
|
||||
oneOf(database).startTransaction();
|
||||
@@ -354,8 +307,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
will(returnValue(MessageId.NONE));
|
||||
oneOf(database).commitTransaction(txn);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner);
|
||||
|
||||
db.setRating(authorId, Rating.GOOD);
|
||||
|
||||
@@ -369,12 +321,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
context.checking(new Expectations() {{
|
||||
// addLocallyGeneratedMessage(message)
|
||||
oneOf(database).startTransaction();
|
||||
@@ -383,8 +329,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
will(returnValue(false));
|
||||
oneOf(database).commitTransaction(txn);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner);
|
||||
|
||||
db.addLocallyGeneratedMessage(message);
|
||||
|
||||
@@ -397,12 +342,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
context.checking(new Expectations() {{
|
||||
// addLocallyGeneratedMessage(message)
|
||||
oneOf(database).startTransaction();
|
||||
@@ -413,8 +352,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
will(returnValue(false));
|
||||
oneOf(database).commitTransaction(txn);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner);
|
||||
|
||||
db.addLocallyGeneratedMessage(message);
|
||||
|
||||
@@ -427,12 +365,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
context.checking(new Expectations() {{
|
||||
// addLocallyGeneratedMessage(message)
|
||||
oneOf(database).startTransaction();
|
||||
@@ -452,8 +384,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
oneOf(database).setSendability(txn, messageId, 0);
|
||||
oneOf(database).commitTransaction(txn);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner);
|
||||
|
||||
db.addLocallyGeneratedMessage(message);
|
||||
|
||||
@@ -467,12 +398,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
context.checking(new Expectations() {{
|
||||
// addLocallyGeneratedMessage(message)
|
||||
oneOf(database).startTransaction();
|
||||
@@ -495,8 +420,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
will(returnValue(MessageId.NONE));
|
||||
oneOf(database).commitTransaction(txn);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner);
|
||||
|
||||
db.addLocallyGeneratedMessage(message);
|
||||
|
||||
@@ -510,12 +434,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
final BundleWriter bundleBuilder = context.mock(BundleWriter.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Check that the contact is still in the DB
|
||||
@@ -525,8 +443,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
will(returnValue(false));
|
||||
oneOf(database).commitTransaction(txn);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner);
|
||||
|
||||
try {
|
||||
db.generateBundle(contactId, bundleBuilder);
|
||||
@@ -543,72 +460,43 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
final BundleWriter bundleWriter = context.mock(BundleWriter.class);
|
||||
final HeaderBuilder headerBuilder = context.mock(HeaderBuilder.class);
|
||||
final Header header = context.mock(Header.class);
|
||||
final BatchBuilder batchBuilder = context.mock(BatchBuilder.class);
|
||||
final Batch batch = context.mock(Batch.class);
|
||||
context.checking(new Expectations() {{
|
||||
allowing(database).startTransaction();
|
||||
will(returnValue(txn));
|
||||
allowing(database).commitTransaction(txn);
|
||||
allowing(database).containsContact(txn, contactId);
|
||||
will(returnValue(true));
|
||||
// Build the header
|
||||
oneOf(headerBuilderProvider).get();
|
||||
will(returnValue(headerBuilder));
|
||||
// Add acks to the header
|
||||
oneOf(database).removeBatchesToAck(txn, contactId);
|
||||
will(returnValue(acks));
|
||||
oneOf(headerBuilder).addAcks(acks);
|
||||
// Add subscriptions to the header
|
||||
oneOf(database).getSubscriptions(txn);
|
||||
will(returnValue(subs));
|
||||
oneOf(headerBuilder).addSubscriptions(subs);
|
||||
// Add transports to the header
|
||||
oneOf(database).getTransports(txn);
|
||||
will(returnValue(transports));
|
||||
oneOf(headerBuilder).addTransports(transports);
|
||||
// Build the header
|
||||
oneOf(headerBuilder).build();
|
||||
will(returnValue(header));
|
||||
oneOf(bundleWriter).getCapacity();
|
||||
will(returnValue(1024L * 1024L));
|
||||
oneOf(header).getSize();
|
||||
will(returnValue(headerSize));
|
||||
oneOf(bundleWriter).addHeader(header);
|
||||
oneOf(bundleWriter).addHeader(acks, subs, transports);
|
||||
will(returnValue(bundleId));
|
||||
// Add a batch to the bundle
|
||||
oneOf(bundleWriter).getRemainingCapacity();
|
||||
will(returnValue(1024L * 1024L - headerSize));
|
||||
oneOf(database).getSendableMessages(txn, contactId,
|
||||
Batch.MAX_SIZE - headerSize);
|
||||
will(returnValue(messages));
|
||||
oneOf(batchBuilderProvider).get();
|
||||
will(returnValue(batchBuilder));
|
||||
oneOf(database).getMessage(txn, messageId);
|
||||
will(returnValue(message));
|
||||
oneOf(batchBuilder).addMessage(message);
|
||||
oneOf(batchBuilder).build();
|
||||
will(returnValue(batch));
|
||||
// Record the batch as outstanding
|
||||
oneOf(batch).getId();
|
||||
// Add the batch to the bundle
|
||||
oneOf(bundleWriter).addBatch(Collections.singletonList(message));
|
||||
will(returnValue(batchId));
|
||||
// Record the outstanding batch
|
||||
oneOf(database).addOutstandingBatch(
|
||||
txn, contactId, batchId, messages);
|
||||
// Add the batch to the bundle
|
||||
oneOf(bundleWriter).addBatch(batch);
|
||||
// Check whether to add another batch
|
||||
oneOf(batch).getSize();
|
||||
will(returnValue((long) message.getSize()));
|
||||
// No, just send the bundle
|
||||
oneOf(bundleWriter).close();
|
||||
// Send the bundle
|
||||
oneOf(bundleWriter).finish();
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner);
|
||||
|
||||
db.generateBundle(contactId, bundleWriter);
|
||||
|
||||
@@ -622,12 +510,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
final BundleReader bundleReader = context.mock(BundleReader.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Check that the contact is still in the DB
|
||||
@@ -637,8 +519,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
will(returnValue(false));
|
||||
oneOf(database).commitTransaction(txn);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner);
|
||||
|
||||
try {
|
||||
db.receiveBundle(contactId, bundleReader);
|
||||
@@ -654,12 +535,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Database<Object> database = context.mock(Database.class);
|
||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
final BundleReader bundleReader = context.mock(BundleReader.class);
|
||||
final Header header = context.mock(Header.class);
|
||||
final Batch batch = context.mock(Batch.class);
|
||||
@@ -702,7 +577,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
// Any more batches? Nope
|
||||
oneOf(bundleReader).getNextBatch();
|
||||
will(returnValue(null));
|
||||
oneOf(bundleReader).close();
|
||||
oneOf(bundleReader).finish();
|
||||
// Lost batches
|
||||
oneOf(header).getId();
|
||||
will(returnValue(bundleId));
|
||||
@@ -710,8 +585,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
||||
will(returnValue(Collections.singleton(batchId)));
|
||||
oneOf(database).removeLostBatch(txn, contactId, batchId);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner);
|
||||
|
||||
db.receiveBundle(contactId, bundleReader);
|
||||
|
||||
|
||||
@@ -815,8 +815,8 @@ public class H2DatabaseTest extends TestCase {
|
||||
private static class TestMessageFactory implements MessageFactory {
|
||||
|
||||
public Message createMessage(MessageId id, MessageId parent,
|
||||
GroupId group, AuthorId author, long timestamp, byte[] body) {
|
||||
return new MessageImpl(id, parent, group, author, timestamp, body);
|
||||
GroupId group, AuthorId author, long timestamp, byte[] raw) {
|
||||
return new MessageImpl(id, parent, group, author, timestamp, raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,19 @@
|
||||
package net.sf.briar.db;
|
||||
|
||||
import net.sf.briar.api.db.DatabaseComponent;
|
||||
import net.sf.briar.api.protocol.BatchBuilder;
|
||||
import net.sf.briar.api.protocol.HeaderBuilder;
|
||||
|
||||
import com.google.inject.Provider;
|
||||
|
||||
public class ReadWriteLockDatabaseComponentTest
|
||||
extends DatabaseComponentImplTest {
|
||||
|
||||
@Override
|
||||
protected <T> DatabaseComponent createDatabaseComponent(
|
||||
Database<T> database, DatabaseCleaner cleaner,
|
||||
Provider<HeaderBuilder> headerBuilderProvider,
|
||||
Provider<BatchBuilder> batchBuilderProvider) {
|
||||
return createDatabaseComponentImpl(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
Database<T> database, DatabaseCleaner cleaner) {
|
||||
return createDatabaseComponentImpl(database, cleaner);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> DatabaseComponentImpl<T> createDatabaseComponentImpl(
|
||||
Database<T> database, DatabaseCleaner cleaner,
|
||||
Provider<HeaderBuilder> headerBuilderProvider,
|
||||
Provider<BatchBuilder> batchBuilderProvider) {
|
||||
return new ReadWriteLockDatabaseComponent<T>(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
Database<T> database, DatabaseCleaner cleaner) {
|
||||
return new ReadWriteLockDatabaseComponent<T>(database, cleaner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,19 @@
|
||||
package net.sf.briar.db;
|
||||
|
||||
import net.sf.briar.api.db.DatabaseComponent;
|
||||
import net.sf.briar.api.protocol.BatchBuilder;
|
||||
import net.sf.briar.api.protocol.HeaderBuilder;
|
||||
|
||||
import com.google.inject.Provider;
|
||||
|
||||
public class SynchronizedDatabaseComponentTest
|
||||
extends DatabaseComponentImplTest {
|
||||
|
||||
@Override
|
||||
protected <T> DatabaseComponent createDatabaseComponent(
|
||||
Database<T> database, DatabaseCleaner cleaner,
|
||||
Provider<HeaderBuilder> headerBuilderProvider,
|
||||
Provider<BatchBuilder> batchBuilderProvider) {
|
||||
return createDatabaseComponentImpl(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
Database<T> database, DatabaseCleaner cleaner) {
|
||||
return createDatabaseComponentImpl(database, cleaner);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> DatabaseComponentImpl<T> createDatabaseComponentImpl(
|
||||
Database<T> database, DatabaseCleaner cleaner,
|
||||
Provider<HeaderBuilder> headerBuilderProvider,
|
||||
Provider<BatchBuilder> batchBuilderProvider) {
|
||||
return new SynchronizedDatabaseComponent<T>(database, cleaner,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
Database<T> database, DatabaseCleaner cleaner) {
|
||||
return new SynchronizedDatabaseComponent<T>(database, cleaner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,21 +24,17 @@ import junit.framework.TestCase;
|
||||
import net.sf.briar.TestUtils;
|
||||
import net.sf.briar.api.crypto.KeyParser;
|
||||
import net.sf.briar.api.protocol.Batch;
|
||||
import net.sf.briar.api.protocol.BatchBuilder;
|
||||
import net.sf.briar.api.protocol.BatchId;
|
||||
import net.sf.briar.api.protocol.BundleReader;
|
||||
import net.sf.briar.api.protocol.BundleWriter;
|
||||
import net.sf.briar.api.protocol.GroupId;
|
||||
import net.sf.briar.api.protocol.Header;
|
||||
import net.sf.briar.api.protocol.HeaderBuilder;
|
||||
import net.sf.briar.api.protocol.Message;
|
||||
import net.sf.briar.api.protocol.MessageEncoder;
|
||||
import net.sf.briar.api.protocol.MessageId;
|
||||
import net.sf.briar.api.protocol.MessageParser;
|
||||
import net.sf.briar.api.protocol.UniqueId;
|
||||
import net.sf.briar.api.serial.Reader;
|
||||
import net.sf.briar.api.serial.ReaderFactory;
|
||||
import net.sf.briar.api.serial.Writer;
|
||||
import net.sf.briar.api.serial.WriterFactory;
|
||||
import net.sf.briar.serial.ReaderFactoryImpl;
|
||||
import net.sf.briar.serial.WriterFactoryImpl;
|
||||
@@ -47,8 +43,6 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.inject.Provider;
|
||||
|
||||
public class BundleReadWriteTest extends TestCase {
|
||||
|
||||
private static final String SIGNATURE_ALGO = "SHA256withRSA";
|
||||
@@ -74,7 +68,7 @@ public class BundleReadWriteTest extends TestCase {
|
||||
|
||||
private final KeyPair keyPair;
|
||||
private final Signature sig;
|
||||
private final MessageDigest digest;
|
||||
private final MessageDigest dig;
|
||||
private final KeyParser keyParser;
|
||||
private final Message message;
|
||||
|
||||
@@ -82,7 +76,7 @@ public class BundleReadWriteTest extends TestCase {
|
||||
super();
|
||||
keyPair = KeyPairGenerator.getInstance(KEY_PAIR_ALGO).generateKeyPair();
|
||||
sig = Signature.getInstance(SIGNATURE_ALGO);
|
||||
digest = MessageDigest.getInstance(DIGEST_ALGO);
|
||||
dig = MessageDigest.getInstance(DIGEST_ALGO);
|
||||
final KeyFactory keyFactory = KeyFactory.getInstance(KEY_PAIR_ALGO);
|
||||
keyParser = new KeyParser() {
|
||||
public PublicKey parsePublicKey(byte[] encodedKey)
|
||||
@@ -91,8 +85,8 @@ public class BundleReadWriteTest extends TestCase {
|
||||
return keyFactory.generatePublic(e);
|
||||
}
|
||||
};
|
||||
assertEquals(digest.getDigestLength(), UniqueId.LENGTH);
|
||||
MessageEncoder messageEncoder = new MessageEncoderImpl(sig, digest, wf);
|
||||
assertEquals(dig.getDigestLength(), UniqueId.LENGTH);
|
||||
MessageEncoder messageEncoder = new MessageEncoderImpl(sig, dig, wf);
|
||||
message = messageEncoder.encodeMessage(MessageId.NONE, sub, nick,
|
||||
keyPair, messageBody.getBytes("UTF-8"));
|
||||
}
|
||||
@@ -104,23 +98,13 @@ public class BundleReadWriteTest extends TestCase {
|
||||
|
||||
@Test
|
||||
public void testWriteBundle() throws Exception {
|
||||
HeaderBuilder h = new OutgoingHeaderBuilder(keyPair, sig, digest, wf);
|
||||
h.addAcks(acks);
|
||||
h.addSubscriptions(subs);
|
||||
h.addTransports(transports);
|
||||
Header header = h.build();
|
||||
|
||||
BatchBuilder b = new OutgoingBatchBuilder(keyPair, sig, digest, wf);
|
||||
b.addMessage(message);
|
||||
Batch batch = b.build();
|
||||
|
||||
FileOutputStream out = new FileOutputStream(bundle);
|
||||
Writer writer = new WriterFactoryImpl().createWriter(out);
|
||||
BundleWriter w = new BundleWriterImpl(writer, capacity);
|
||||
BundleWriter w = new BundleWriterImpl(out, wf, keyPair.getPrivate(),
|
||||
sig, dig, capacity);
|
||||
|
||||
w.addHeader(header);
|
||||
w.addBatch(batch);
|
||||
w.close();
|
||||
w.addHeader(acks, subs, transports);
|
||||
w.addBatch(Collections.singleton(message));
|
||||
w.finish();
|
||||
|
||||
assertTrue(bundle.exists());
|
||||
assertTrue(bundle.length() > message.getSize());
|
||||
@@ -132,24 +116,11 @@ public class BundleReadWriteTest extends TestCase {
|
||||
testWriteBundle();
|
||||
|
||||
MessageParser messageParser =
|
||||
new MessageParserImpl(keyParser, sig, digest, rf);
|
||||
Provider<HeaderBuilder> headerBuilderProvider =
|
||||
new Provider<HeaderBuilder>() {
|
||||
public HeaderBuilder get() {
|
||||
return new IncomingHeaderBuilder(keyPair, sig, digest, wf);
|
||||
}
|
||||
};
|
||||
Provider<BatchBuilder> batchBuilderProvider =
|
||||
new Provider<BatchBuilder>() {
|
||||
public BatchBuilder get() {
|
||||
return new IncomingBatchBuilder(keyPair, sig, digest, wf);
|
||||
}
|
||||
};
|
||||
|
||||
new MessageParserImpl(keyParser, sig, dig, rf);
|
||||
FileInputStream in = new FileInputStream(bundle);
|
||||
Reader reader = new ReaderFactoryImpl().createReader(in);
|
||||
BundleReader r = new BundleReaderImpl(reader, bundle.length(),
|
||||
messageParser, headerBuilderProvider, batchBuilderProvider);
|
||||
BundleReader r = new BundleReaderImpl(in, rf, keyPair.getPublic(), sig,
|
||||
dig, messageParser, new HeaderFactoryImpl(),
|
||||
new BatchFactoryImpl());
|
||||
|
||||
Header h = r.getHeader();
|
||||
assertEquals(acks, h.getAcks());
|
||||
@@ -167,7 +138,7 @@ public class BundleReadWriteTest extends TestCase {
|
||||
assertTrue(Arrays.equals(message.getBytes(), m.getBytes()));
|
||||
assertFalse(i.hasNext());
|
||||
assertNull(r.getNextBatch());
|
||||
r.close();
|
||||
r.finish();
|
||||
}
|
||||
|
||||
|
||||
@@ -184,24 +155,11 @@ public class BundleReadWriteTest extends TestCase {
|
||||
f.close();
|
||||
|
||||
MessageParser messageParser =
|
||||
new MessageParserImpl(keyParser, sig, digest, rf);
|
||||
Provider<HeaderBuilder> headerBuilderProvider =
|
||||
new Provider<HeaderBuilder>() {
|
||||
public HeaderBuilder get() {
|
||||
return new IncomingHeaderBuilder(keyPair, sig, digest, wf);
|
||||
}
|
||||
};
|
||||
Provider<BatchBuilder> batchBuilderProvider =
|
||||
new Provider<BatchBuilder>() {
|
||||
public BatchBuilder get() {
|
||||
return new IncomingBatchBuilder(keyPair, sig, digest, wf);
|
||||
}
|
||||
};
|
||||
|
||||
new MessageParserImpl(keyParser, sig, dig, rf);
|
||||
FileInputStream in = new FileInputStream(bundle);
|
||||
Reader reader = new ReaderFactoryImpl().createReader(in);
|
||||
BundleReader r = new BundleReaderImpl(reader, bundle.length(),
|
||||
messageParser, headerBuilderProvider, batchBuilderProvider);
|
||||
BundleReader r = new BundleReaderImpl(in, rf, keyPair.getPublic(), sig,
|
||||
dig, messageParser, new HeaderFactoryImpl(),
|
||||
new BatchFactoryImpl());
|
||||
|
||||
Header h = r.getHeader();
|
||||
assertEquals(acks, h.getAcks());
|
||||
@@ -211,7 +169,7 @@ public class BundleReadWriteTest extends TestCase {
|
||||
r.getNextBatch();
|
||||
assertTrue(false);
|
||||
} catch(GeneralSecurityException expected) {}
|
||||
r.close();
|
||||
r.finish();
|
||||
}
|
||||
|
||||
@After
|
||||
|
||||
@@ -1,266 +0,0 @@
|
||||
package net.sf.briar.protocol;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.SignatureException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import net.sf.briar.TestUtils;
|
||||
import net.sf.briar.api.protocol.Batch;
|
||||
import net.sf.briar.api.protocol.BatchBuilder;
|
||||
import net.sf.briar.api.protocol.BatchId;
|
||||
import net.sf.briar.api.protocol.BundleReader;
|
||||
import net.sf.briar.api.protocol.GroupId;
|
||||
import net.sf.briar.api.protocol.Header;
|
||||
import net.sf.briar.api.protocol.HeaderBuilder;
|
||||
import net.sf.briar.api.protocol.Message;
|
||||
import net.sf.briar.api.protocol.MessageParser;
|
||||
import net.sf.briar.api.serial.Raw;
|
||||
import net.sf.briar.api.serial.Reader;
|
||||
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.inject.Provider;
|
||||
|
||||
public class BundleReaderTest extends TestCase {
|
||||
|
||||
private final long size = 1024L * 1024L;
|
||||
private final BatchId ack = new BatchId(TestUtils.getRandomId());
|
||||
private final List<Raw> rawAcks =
|
||||
Collections.<Raw>singletonList(new TestRaw(ack.getBytes()));
|
||||
private final Set<BatchId> acks = Collections.singleton(ack);
|
||||
private final GroupId sub = new GroupId(TestUtils.getRandomId());
|
||||
private final List<Raw> rawSubs =
|
||||
Collections.<Raw>singletonList(new TestRaw(sub.getBytes()));
|
||||
private final Set<GroupId> subs = Collections.singleton(sub);
|
||||
private final Map<String, String> transports =
|
||||
Collections.singletonMap("foo", "bar");
|
||||
private final byte[] headerSig = TestUtils.getRandomId();
|
||||
private final byte[] messageBody = new byte[123];
|
||||
private final List<Raw> rawMessages =
|
||||
Collections.<Raw>singletonList(new TestRaw(messageBody));
|
||||
private final byte[] batchSig = TestUtils.getRandomId();
|
||||
|
||||
@Test
|
||||
public void testGetHeader() throws Exception {
|
||||
Mockery context = new Mockery();
|
||||
final Reader reader = context.mock(Reader.class);
|
||||
final MessageParser messageParser = context.mock(MessageParser.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
final HeaderBuilder headerBuilder = context.mock(HeaderBuilder.class);
|
||||
final Header header = context.mock(Header.class);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(reader).setReadLimit(Header.MAX_SIZE);
|
||||
oneOf(headerBuilderProvider).get();
|
||||
will(returnValue(headerBuilder));
|
||||
// Acks
|
||||
oneOf(reader).readList(Raw.class);
|
||||
will(returnValue(rawAcks));
|
||||
oneOf(headerBuilder).addAcks(acks);
|
||||
// Subs
|
||||
oneOf(reader).readList(Raw.class);
|
||||
will(returnValue(rawSubs));
|
||||
oneOf(headerBuilder).addSubscriptions(subs);
|
||||
// Transports
|
||||
oneOf(reader).readMap(String.class, String.class);
|
||||
will(returnValue(transports));
|
||||
oneOf(headerBuilder).addTransports(transports);
|
||||
// Signature
|
||||
oneOf(reader).readRaw();
|
||||
will(returnValue(headerSig));
|
||||
oneOf(headerBuilder).setSignature(headerSig);
|
||||
// Build the header
|
||||
oneOf(headerBuilder).build();
|
||||
will(returnValue(header));
|
||||
}});
|
||||
BundleReader r = new BundleReaderImpl(reader, size, messageParser,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
|
||||
assertEquals(header, r.getHeader());
|
||||
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBatchBeforeHeaderThrowsException() throws Exception {
|
||||
Mockery context = new Mockery();
|
||||
final Reader reader = context.mock(Reader.class);
|
||||
final MessageParser messageParser = context.mock(MessageParser.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
BundleReader r = new BundleReaderImpl(reader, size, messageParser,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
|
||||
try {
|
||||
r.getNextBatch();
|
||||
assertTrue(false);
|
||||
} catch(IllegalStateException expected) {}
|
||||
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseBeforeHeaderDoesNotThrowException() throws IOException,
|
||||
SignatureException {
|
||||
Mockery context = new Mockery();
|
||||
final Reader reader = context.mock(Reader.class);
|
||||
final MessageParser messageParser = context.mock(MessageParser.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(reader).close();
|
||||
}});
|
||||
BundleReader r = new BundleReaderImpl(reader, size, messageParser,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
|
||||
r.close();
|
||||
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetHeaderNoBatches() throws Exception {
|
||||
Mockery context = new Mockery();
|
||||
final Reader reader = context.mock(Reader.class);
|
||||
final MessageParser messageParser = context.mock(MessageParser.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
final HeaderBuilder headerBuilder = context.mock(HeaderBuilder.class);
|
||||
final Header header = context.mock(Header.class);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(reader).setReadLimit(Header.MAX_SIZE);
|
||||
oneOf(headerBuilderProvider).get();
|
||||
will(returnValue(headerBuilder));
|
||||
// Acks
|
||||
oneOf(reader).readList(Raw.class);
|
||||
will(returnValue(rawAcks));
|
||||
oneOf(headerBuilder).addAcks(acks);
|
||||
// Subs
|
||||
oneOf(reader).readList(Raw.class);
|
||||
will(returnValue(rawSubs));
|
||||
oneOf(headerBuilder).addSubscriptions(subs);
|
||||
// Transports
|
||||
oneOf(reader).readMap(String.class, String.class);
|
||||
will(returnValue(transports));
|
||||
oneOf(headerBuilder).addTransports(transports);
|
||||
// Signature
|
||||
oneOf(reader).readRaw();
|
||||
will(returnValue(headerSig));
|
||||
oneOf(headerBuilder).setSignature(headerSig);
|
||||
// Build the header
|
||||
oneOf(headerBuilder).build();
|
||||
will(returnValue(header));
|
||||
// No batches
|
||||
oneOf(reader).readListStart();
|
||||
oneOf(reader).hasListEnd();
|
||||
will(returnValue(true));
|
||||
oneOf(reader).readListEnd();
|
||||
// Close
|
||||
oneOf(reader).close();
|
||||
}});
|
||||
BundleReader r = new BundleReaderImpl(reader, size, messageParser,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
|
||||
assertEquals(header, r.getHeader());
|
||||
assertNull(r.getNextBatch());
|
||||
r.close();
|
||||
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetHeaderOneBatch() throws Exception {
|
||||
Mockery context = new Mockery();
|
||||
final Reader reader = context.mock(Reader.class);
|
||||
final MessageParser messageParser = context.mock(MessageParser.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||
context.mock(Provider.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Provider<BatchBuilder> batchBuilderProvider =
|
||||
context.mock(Provider.class, "batchBuilderProvider");
|
||||
final HeaderBuilder headerBuilder = context.mock(HeaderBuilder.class);
|
||||
final Header header = context.mock(Header.class);
|
||||
final BatchBuilder batchBuilder = context.mock(BatchBuilder.class);
|
||||
final Batch batch = context.mock(Batch.class);
|
||||
final Message message = context.mock(Message.class);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(reader).setReadLimit(Header.MAX_SIZE);
|
||||
oneOf(headerBuilderProvider).get();
|
||||
will(returnValue(headerBuilder));
|
||||
// Acks
|
||||
oneOf(reader).readList(Raw.class);
|
||||
will(returnValue(rawAcks));
|
||||
oneOf(headerBuilder).addAcks(acks);
|
||||
// Subs
|
||||
oneOf(reader).readList(Raw.class);
|
||||
will(returnValue(rawSubs));
|
||||
oneOf(headerBuilder).addSubscriptions(subs);
|
||||
// Transports
|
||||
oneOf(reader).readMap(String.class, String.class);
|
||||
will(returnValue(transports));
|
||||
oneOf(headerBuilder).addTransports(transports);
|
||||
// Signature
|
||||
oneOf(reader).readRaw();
|
||||
will(returnValue(headerSig));
|
||||
oneOf(headerBuilder).setSignature(headerSig);
|
||||
// Build the header
|
||||
oneOf(headerBuilder).build();
|
||||
will(returnValue(header));
|
||||
// First batch
|
||||
oneOf(reader).readListStart();
|
||||
oneOf(reader).hasListEnd();
|
||||
will(returnValue(false));
|
||||
oneOf(reader).setReadLimit(Batch.MAX_SIZE);
|
||||
oneOf(batchBuilderProvider).get();
|
||||
will(returnValue(batchBuilder));
|
||||
oneOf(reader).readList(Raw.class);
|
||||
will(returnValue(rawMessages));
|
||||
oneOf(messageParser).parseMessage(messageBody);
|
||||
will(returnValue(message));
|
||||
oneOf(batchBuilder).addMessage(message);
|
||||
oneOf(reader).readRaw();
|
||||
will(returnValue(batchSig));
|
||||
oneOf(batchBuilder).setSignature(batchSig);
|
||||
oneOf(batchBuilder).build();
|
||||
will(returnValue(batch));
|
||||
// No more batches
|
||||
oneOf(reader).hasListEnd();
|
||||
will(returnValue(true));
|
||||
oneOf(reader).readListEnd();
|
||||
// Close
|
||||
oneOf(reader).close();
|
||||
}});
|
||||
BundleReader r = new BundleReaderImpl(reader, size, messageParser,
|
||||
headerBuilderProvider, batchBuilderProvider);
|
||||
|
||||
assertEquals(header, r.getHeader());
|
||||
assertEquals(batch, r.getNextBatch());
|
||||
assertNull(r.getNextBatch());
|
||||
r.close();
|
||||
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
package net.sf.briar.protocol;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import net.sf.briar.TestUtils;
|
||||
import net.sf.briar.api.protocol.Batch;
|
||||
import net.sf.briar.api.protocol.BatchId;
|
||||
import net.sf.briar.api.protocol.BundleWriter;
|
||||
import net.sf.briar.api.protocol.GroupId;
|
||||
import net.sf.briar.api.protocol.Header;
|
||||
import net.sf.briar.api.protocol.Message;
|
||||
import net.sf.briar.api.serial.Writer;
|
||||
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.junit.Test;
|
||||
|
||||
public class BundleWriterTest extends TestCase {
|
||||
|
||||
private final long capacity = 1024L * 1024L;
|
||||
private final BatchId ack = new BatchId(TestUtils.getRandomId());
|
||||
private final Set<BatchId> acks = Collections.singleton(ack);
|
||||
private final GroupId sub = new GroupId(TestUtils.getRandomId());
|
||||
private final Set<GroupId> subs = Collections.singleton(sub);
|
||||
private final Map<String, String> transports =
|
||||
Collections.singletonMap("foo", "bar");
|
||||
private final byte[] headerSig = TestUtils.getRandomId();
|
||||
private final byte[] messageBody = new byte[123];
|
||||
private final byte[] batchSig = TestUtils.getRandomId();
|
||||
|
||||
@Test
|
||||
public void testAddHeader() throws IOException {
|
||||
Mockery context = new Mockery();
|
||||
final Writer writer = context.mock(Writer.class);
|
||||
final Header header = context.mock(Header.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Acks
|
||||
oneOf(writer).writeListStart();
|
||||
oneOf(header).getAcks();
|
||||
will(returnValue(acks));
|
||||
oneOf(writer).writeRaw(ack);
|
||||
oneOf(writer).writeListEnd();
|
||||
// Subs
|
||||
oneOf(writer).writeListStart();
|
||||
oneOf(header).getSubscriptions();
|
||||
will(returnValue(subs));
|
||||
oneOf(writer).writeRaw(sub);
|
||||
oneOf(writer).writeListEnd();
|
||||
// Transports
|
||||
oneOf(header).getTransports();
|
||||
will(returnValue(transports));
|
||||
oneOf(writer).writeMap(transports);
|
||||
// Signature
|
||||
oneOf(header).getSignature();
|
||||
will(returnValue(headerSig));
|
||||
oneOf(writer).writeRaw(headerSig);
|
||||
}});
|
||||
BundleWriter w = new BundleWriterImpl(writer, capacity);
|
||||
|
||||
w.addHeader(header);
|
||||
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddHeaderEmptyLists() throws IOException {
|
||||
Mockery context = new Mockery();
|
||||
final Writer writer = context.mock(Writer.class);
|
||||
final Header header = context.mock(Header.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Acks
|
||||
oneOf(writer).writeListStart();
|
||||
oneOf(header).getAcks();
|
||||
will(returnValue(Collections.emptySet()));
|
||||
oneOf(writer).writeListEnd();
|
||||
// Subs
|
||||
oneOf(writer).writeListStart();
|
||||
oneOf(header).getSubscriptions();
|
||||
will(returnValue(Collections.emptySet()));
|
||||
oneOf(writer).writeListEnd();
|
||||
// Transports
|
||||
oneOf(header).getTransports();
|
||||
will(returnValue(Collections.emptyMap()));
|
||||
oneOf(writer).writeMap(Collections.emptyMap());
|
||||
// Signature
|
||||
oneOf(header).getSignature();
|
||||
will(returnValue(headerSig));
|
||||
oneOf(writer).writeRaw(headerSig);
|
||||
}});
|
||||
BundleWriter w = new BundleWriterImpl(writer, capacity);
|
||||
|
||||
w.addHeader(header);
|
||||
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBatchBeforeHeaderThrowsException() throws IOException {
|
||||
Mockery context = new Mockery();
|
||||
final Writer writer = context.mock(Writer.class);
|
||||
final Batch batch = context.mock(Batch.class);
|
||||
BundleWriter w = new BundleWriterImpl(writer, capacity);
|
||||
|
||||
try {
|
||||
w.addBatch(batch);
|
||||
assertTrue(false);
|
||||
} catch(IllegalStateException expected) {}
|
||||
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseBeforeHeaderThrowsException() throws IOException {
|
||||
Mockery context = new Mockery();
|
||||
final Writer writer = context.mock(Writer.class);
|
||||
BundleWriter w = new BundleWriterImpl(writer, capacity);
|
||||
|
||||
try {
|
||||
w.close();
|
||||
assertTrue(false);
|
||||
} catch(IllegalStateException expected) {}
|
||||
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseWithoutBatchesDoesNotThrowException()
|
||||
throws IOException {
|
||||
Mockery context = new Mockery();
|
||||
final Writer writer = context.mock(Writer.class);
|
||||
final Header header = context.mock(Header.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Acks
|
||||
oneOf(writer).writeListStart();
|
||||
oneOf(header).getAcks();
|
||||
will(returnValue(acks));
|
||||
oneOf(writer).writeRaw(ack);
|
||||
oneOf(writer).writeListEnd();
|
||||
// Subs
|
||||
oneOf(writer).writeListStart();
|
||||
oneOf(header).getSubscriptions();
|
||||
will(returnValue(subs));
|
||||
oneOf(writer).writeRaw(sub);
|
||||
oneOf(writer).writeListEnd();
|
||||
// Transports
|
||||
oneOf(header).getTransports();
|
||||
will(returnValue(transports));
|
||||
oneOf(writer).writeMap(transports);
|
||||
// Signature
|
||||
oneOf(header).getSignature();
|
||||
will(returnValue(headerSig));
|
||||
oneOf(writer).writeRaw(headerSig);
|
||||
// Close - write an empty list of batches
|
||||
oneOf(writer).writeListStart();
|
||||
oneOf(writer).writeListEnd();
|
||||
oneOf(writer).close();
|
||||
}});
|
||||
BundleWriter w = new BundleWriterImpl(writer, capacity);
|
||||
|
||||
w.addHeader(header);
|
||||
w.close();
|
||||
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddHeaderAndTwoBatches() throws IOException {
|
||||
Mockery context = new Mockery();
|
||||
final Writer writer = context.mock(Writer.class);
|
||||
final Header header = context.mock(Header.class);
|
||||
final Batch batch = context.mock(Batch.class);
|
||||
final Message message = context.mock(Message.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Acks
|
||||
oneOf(writer).writeListStart();
|
||||
oneOf(header).getAcks();
|
||||
will(returnValue(acks));
|
||||
oneOf(writer).writeRaw(ack);
|
||||
oneOf(writer).writeListEnd();
|
||||
// Subs
|
||||
oneOf(writer).writeListStart();
|
||||
oneOf(header).getSubscriptions();
|
||||
will(returnValue(subs));
|
||||
oneOf(writer).writeRaw(sub);
|
||||
oneOf(writer).writeListEnd();
|
||||
// Transports
|
||||
oneOf(header).getTransports();
|
||||
will(returnValue(transports));
|
||||
oneOf(writer).writeMap(transports);
|
||||
// Signature
|
||||
oneOf(header).getSignature();
|
||||
will(returnValue(headerSig));
|
||||
oneOf(writer).writeRaw(headerSig);
|
||||
// First batch
|
||||
oneOf(writer).writeListStart();
|
||||
oneOf(writer).writeListStart();
|
||||
oneOf(batch).getMessages();
|
||||
will(returnValue(Collections.singleton(message)));
|
||||
oneOf(message).getBytes();
|
||||
will(returnValue(messageBody));
|
||||
oneOf(writer).writeRaw(messageBody);
|
||||
oneOf(writer).writeListEnd();
|
||||
oneOf(batch).getSignature();
|
||||
will(returnValue(batchSig));
|
||||
oneOf(writer).writeRaw(batchSig);
|
||||
// Second batch
|
||||
oneOf(writer).writeListStart();
|
||||
oneOf(batch).getMessages();
|
||||
will(returnValue(Collections.singleton(message)));
|
||||
oneOf(message).getBytes();
|
||||
will(returnValue(messageBody));
|
||||
oneOf(writer).writeRaw(messageBody);
|
||||
oneOf(writer).writeListEnd();
|
||||
oneOf(batch).getSignature();
|
||||
will(returnValue(batchSig));
|
||||
oneOf(writer).writeRaw(batchSig);
|
||||
// Close
|
||||
oneOf(writer).writeListEnd();
|
||||
oneOf(writer).close();
|
||||
}});
|
||||
BundleWriter w = new BundleWriterImpl(writer, capacity);
|
||||
|
||||
w.addHeader(header);
|
||||
w.addBatch(batch);
|
||||
w.addBatch(batch);
|
||||
w.close();
|
||||
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
}
|
||||
158
test/net/sf/briar/protocol/SigningStreamTest.java
Normal file
158
test/net/sf/briar/protocol/SigningStreamTest.java
Normal file
@@ -0,0 +1,158 @@
|
||||
package net.sf.briar.protocol;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.security.DigestOutputStream;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.Signature;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class SigningStreamTest extends TestCase {
|
||||
|
||||
private static final String SIGNATURE_ALGO = "SHA256withRSA";
|
||||
private static final String KEY_PAIR_ALGO = "RSA";
|
||||
private static final String DIGEST_ALGO = "SHA-256";
|
||||
|
||||
private final KeyPair keyPair;
|
||||
private final Signature sig;
|
||||
private final MessageDigest dig;
|
||||
private final Random random;
|
||||
|
||||
public SigningStreamTest() throws Exception {
|
||||
super();
|
||||
keyPair = KeyPairGenerator.getInstance(KEY_PAIR_ALGO).generateKeyPair();
|
||||
sig = Signature.getInstance(SIGNATURE_ALGO);
|
||||
dig = MessageDigest.getInstance(DIGEST_ALGO);
|
||||
random = new Random();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutputStreamOutputMatchesInput() throws Exception {
|
||||
byte[] input = new byte[1000];
|
||||
random.nextBytes(input);
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
SigningOutputStream signOut = new SigningOutputStream(out, sig);
|
||||
sig.initSign(keyPair.getPrivate());
|
||||
|
||||
signOut.setSigning(true);
|
||||
signOut.write(input, 0, 500);
|
||||
signOut.setSigning(false);
|
||||
signOut.write(input, 500, 250);
|
||||
signOut.setSigning(true);
|
||||
signOut.write(input, 750, 250);
|
||||
|
||||
byte[] output = out.toByteArray();
|
||||
assertTrue(Arrays.equals(input, output));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInputStreamOutputMatchesInput() throws Exception {
|
||||
byte[] input = new byte[1000];
|
||||
random.nextBytes(input);
|
||||
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(input);
|
||||
SigningDigestingInputStream signIn =
|
||||
new SigningDigestingInputStream(in, sig, dig);
|
||||
sig.initVerify(keyPair.getPublic());
|
||||
|
||||
byte[] output = new byte[1000];
|
||||
signIn.setSigning(true);
|
||||
assertEquals(500, signIn.read(output, 0, 500));
|
||||
signIn.setSigning(false);
|
||||
assertEquals(250, signIn.read(output, 500, 250));
|
||||
signIn.setSigning(true);
|
||||
assertEquals(250, signIn.read(output, 750, 250));
|
||||
|
||||
assertTrue(Arrays.equals(input, output));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVerificationLagsByOneByte() throws Exception {
|
||||
byte[] input = new byte[1000];
|
||||
random.nextBytes(input);
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
SigningOutputStream signOut = new SigningOutputStream(out, sig);
|
||||
sig.initSign(keyPair.getPrivate());
|
||||
|
||||
// Sign bytes 0-499, skip bytes 500-749, sign bytes 750-999
|
||||
signOut.setSigning(true);
|
||||
signOut.write(input, 0, 500);
|
||||
signOut.setSigning(false);
|
||||
signOut.write(input, 500, 250);
|
||||
signOut.setSigning(true);
|
||||
signOut.write(input, 750, 250);
|
||||
|
||||
byte[] signature = sig.sign();
|
||||
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(input);
|
||||
SigningDigestingInputStream signIn =
|
||||
new SigningDigestingInputStream(in, sig, dig);
|
||||
sig.initVerify(keyPair.getPublic());
|
||||
|
||||
byte[] output = new byte[1000];
|
||||
// Consume a lookahead byte
|
||||
assertEquals(1, signIn.read(output, 0, 1));
|
||||
// All the offsets are increased by 1 because of the lookahead byte
|
||||
signIn.setSigning(true);
|
||||
assertEquals(500, signIn.read(output, 1, 500));
|
||||
signIn.setSigning(false);
|
||||
assertEquals(250, signIn.read(output, 501, 250));
|
||||
signIn.setSigning(true);
|
||||
assertEquals(249, signIn.read(output, 751, 249));
|
||||
// Have to reach EOF for the lookahead byte to be processed
|
||||
assertEquals(-1, signIn.read());
|
||||
|
||||
assertTrue(Arrays.equals(input, output));
|
||||
assertTrue(sig.verify(signature));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDigestionLagsByOneByte() throws Exception {
|
||||
byte[] input = new byte[1000];
|
||||
random.nextBytes(input);
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
DigestOutputStream digOut = new DigestOutputStream(out, dig);
|
||||
dig.reset();
|
||||
|
||||
// Digest bytes 0-499, skip bytes 500-749, digest bytes 750-999
|
||||
digOut.on(true);
|
||||
digOut.write(input, 0, 500);
|
||||
digOut.on(false);
|
||||
digOut.write(input, 500, 250);
|
||||
digOut.on(true);
|
||||
digOut.write(input, 750, 250);
|
||||
|
||||
byte[] hash = dig.digest();
|
||||
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(input);
|
||||
SigningDigestingInputStream signIn =
|
||||
new SigningDigestingInputStream(in, sig, dig);
|
||||
dig.reset();
|
||||
|
||||
byte[] output = new byte[1000];
|
||||
// Consume a lookahead byte
|
||||
assertEquals(1, signIn.read(output, 0, 1));
|
||||
// All the offsets are increased by 1 because of the lookahead byte
|
||||
signIn.setDigesting(true);
|
||||
assertEquals(500, signIn.read(output, 1, 500));
|
||||
signIn.setDigesting(false);
|
||||
assertEquals(250, signIn.read(output, 501, 250));
|
||||
signIn.setDigesting(true);
|
||||
assertEquals(249, signIn.read(output, 751, 249));
|
||||
// Have to reach EOF for the lookahead byte to be processed
|
||||
assertEquals(-1, signIn.read());
|
||||
|
||||
assertTrue(Arrays.equals(input, output));
|
||||
assertTrue(Arrays.equals(hash, dig.digest()));
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package net.sf.briar.protocol;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import net.sf.briar.api.serial.Raw;
|
||||
|
||||
class TestRaw implements Raw {
|
||||
|
||||
private final byte[] bytes;
|
||||
|
||||
TestRaw(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(o instanceof Raw) return Arrays.equals(bytes, ((Raw) o).getBytes());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user