mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 05:39:53 +01:00
DatabaseComponent throws an exception instead of returning silently if a contact is removed during an operation involving that contact. More unit tests.
This commit is contained in:
@@ -21,7 +21,6 @@ public interface DatabaseComponent {
|
|||||||
static final long MAX_BYTES_BETWEEN_SPACE_CHECKS = 5L * MEGABYTES;
|
static final long MAX_BYTES_BETWEEN_SPACE_CHECKS = 5L * MEGABYTES;
|
||||||
static final long MAX_MS_BETWEEN_SPACE_CHECKS = 60L * 1000L; // 1 min
|
static final long MAX_MS_BETWEEN_SPACE_CHECKS = 60L * 1000L; // 1 min
|
||||||
static final long BYTES_PER_SWEEP = 5L * MEGABYTES;
|
static final long BYTES_PER_SWEEP = 5L * MEGABYTES;
|
||||||
static final int RETRANSMIT_THRESHOLD = 3;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the database.
|
* Opens the database.
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ public class DbException extends Exception {
|
|||||||
|
|
||||||
private static final long serialVersionUID = 3706581789209939441L;
|
private static final long serialVersionUID = 3706581789209939441L;
|
||||||
|
|
||||||
|
public DbException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
public DbException(Throwable t) {
|
public DbException(Throwable t) {
|
||||||
super(t);
|
super(t);
|
||||||
}
|
}
|
||||||
|
|||||||
14
api/net/sf/briar/api/db/NoSuchContactException.java
Normal file
14
api/net/sf/briar/api/db/NoSuchContactException.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package net.sf.briar.api.db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when a database operation is attempted for a contact that is not in
|
||||||
|
* the database.
|
||||||
|
*/
|
||||||
|
public class NoSuchContactException extends DbException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -7048538231308207386L;
|
||||||
|
|
||||||
|
public NoSuchContactException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,6 +32,16 @@ import net.sf.briar.api.protocol.MessageId;
|
|||||||
*/
|
*/
|
||||||
interface Database<T> {
|
interface Database<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A batch sent to a contact is considered lost when this many bundles have
|
||||||
|
* been received from the contact since the batch was sent.
|
||||||
|
* <p>
|
||||||
|
* FIXME: Come up with a better retransmission scheme. This scheme doesn't
|
||||||
|
* cope well with transports that have high latency but send bundles
|
||||||
|
* frequently.
|
||||||
|
*/
|
||||||
|
static final int RETRANSMIT_THRESHOLD = 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the database.
|
* Opens the database.
|
||||||
* @param resume True to reopen an existing database, false to create a
|
* @param resume True to reopen an existing database, false to create a
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import net.sf.briar.api.db.ContactId;
|
import net.sf.briar.api.db.ContactId;
|
||||||
import net.sf.briar.api.db.DatabaseComponent;
|
|
||||||
import net.sf.briar.api.db.DbException;
|
import net.sf.briar.api.db.DbException;
|
||||||
import net.sf.briar.api.db.Rating;
|
import net.sf.briar.api.db.Rating;
|
||||||
import net.sf.briar.api.db.Status;
|
import net.sf.briar.api.db.Status;
|
||||||
@@ -527,7 +526,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
Set<BatchId> lost;
|
Set<BatchId> lost;
|
||||||
if(received == DatabaseComponent.RETRANSMIT_THRESHOLD) {
|
if(received == RETRANSMIT_THRESHOLD) {
|
||||||
// Expire batches related to the oldest received bundle
|
// Expire batches related to the oldest received bundle
|
||||||
assert oldestBundle != null;
|
assert oldestBundle != null;
|
||||||
lost = findLostBatches(txn, c, oldestBundle);
|
lost = findLostBatches(txn, c, oldestBundle);
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import net.sf.briar.api.db.DbException;
|
|
||||||
import net.sf.briar.api.db.ContactId;
|
import net.sf.briar.api.db.ContactId;
|
||||||
|
import net.sf.briar.api.db.DbException;
|
||||||
|
import net.sf.briar.api.db.NoSuchContactException;
|
||||||
import net.sf.briar.api.db.Rating;
|
import net.sf.briar.api.db.Rating;
|
||||||
import net.sf.briar.api.protocol.AuthorId;
|
import net.sf.briar.api.protocol.AuthorId;
|
||||||
import net.sf.briar.api.protocol.Batch;
|
import net.sf.briar.api.protocol.Batch;
|
||||||
@@ -120,7 +121,10 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
// unsubscribed from the group
|
// unsubscribed from the group
|
||||||
if(db.containsSubscription(txn, m.getGroup())) {
|
if(db.containsSubscription(txn, m.getGroup())) {
|
||||||
boolean added = storeMessage(txn, m, null);
|
boolean added = storeMessage(txn, m, null);
|
||||||
assert added;
|
if(!added) {
|
||||||
|
if(LOG.isLoggable(Level.FINE))
|
||||||
|
LOG.fine("Duplicate local message");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if(LOG.isLoggable(Level.FINE))
|
if(LOG.isLoggable(Level.FINE))
|
||||||
LOG.fine("Not subscribed");
|
LOG.fine("Not subscribed");
|
||||||
@@ -177,7 +181,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
// Ack all batches received from c
|
// Ack all batches received from c
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
if(!containsContact(c)) return;
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
messageStatusLock.writeLock().lock();
|
messageStatusLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
Txn txn = db.startTransaction();
|
Txn txn = db.startTransaction();
|
||||||
@@ -203,7 +207,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
// Add a list of subscriptions
|
// Add a list of subscriptions
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
if(!containsContact(c)) return;
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
subscriptionLock.readLock().lock();
|
subscriptionLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
Txn txn = db.startTransaction();
|
Txn txn = db.startTransaction();
|
||||||
@@ -246,7 +250,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
private Batch fillBatch(ContactId c, long capacity) throws DbException {
|
private Batch fillBatch(ContactId c, long capacity) throws DbException {
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
if(!containsContact(c)) return null;
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
messageLock.readLock().lock();
|
messageLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
Set<MessageId> sent;
|
Set<MessageId> sent;
|
||||||
@@ -344,7 +348,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
// Mark all messages in acked batches as seen
|
// Mark all messages in acked batches as seen
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
if(!containsContact(c)) return;
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
messageLock.readLock().lock();
|
messageLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
messageStatusLock.writeLock().lock();
|
messageStatusLock.writeLock().lock();
|
||||||
@@ -375,7 +379,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
// Update the contact's subscriptions
|
// Update the contact's subscriptions
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
if(!containsContact(c)) return;
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
messageStatusLock.writeLock().lock();
|
messageStatusLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
Txn txn = db.startTransaction();
|
Txn txn = db.startTransaction();
|
||||||
@@ -406,7 +410,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
waitForPermissionToWrite();
|
waitForPermissionToWrite();
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
if(!containsContact(c)) return;
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
messageLock.writeLock().lock();
|
messageLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
messageStatusLock.writeLock().lock();
|
messageStatusLock.writeLock().lock();
|
||||||
@@ -451,7 +455,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
Set<BatchId> lost;
|
Set<BatchId> lost;
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
if(!containsContact(c)) return;
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
messageLock.readLock().lock();
|
messageLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
messageStatusLock.writeLock().lock();
|
messageStatusLock.writeLock().lock();
|
||||||
@@ -476,7 +480,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
for(BatchId batch : lost) {
|
for(BatchId batch : lost) {
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
if(!containsContact(c)) return;
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
messageLock.readLock().lock();
|
messageLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
messageStatusLock.writeLock().lock();
|
messageStatusLock.writeLock().lock();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import net.sf.briar.api.db.DbException;
|
import net.sf.briar.api.db.DbException;
|
||||||
import net.sf.briar.api.db.ContactId;
|
import net.sf.briar.api.db.ContactId;
|
||||||
|
import net.sf.briar.api.db.NoSuchContactException;
|
||||||
import net.sf.briar.api.db.Rating;
|
import net.sf.briar.api.db.Rating;
|
||||||
import net.sf.briar.api.protocol.AuthorId;
|
import net.sf.briar.api.protocol.AuthorId;
|
||||||
import net.sf.briar.api.protocol.Batch;
|
import net.sf.briar.api.protocol.Batch;
|
||||||
@@ -89,7 +90,10 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
// unsubscribed from the group
|
// unsubscribed from the group
|
||||||
if(db.containsSubscription(txn, m.getGroup())) {
|
if(db.containsSubscription(txn, m.getGroup())) {
|
||||||
boolean added = storeMessage(txn, m, null);
|
boolean added = storeMessage(txn, m, null);
|
||||||
assert added;
|
if(!added) {
|
||||||
|
if(LOG.isLoggable(Level.FINE))
|
||||||
|
LOG.fine("Duplicate local message");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if(LOG.isLoggable(Level.FINE))
|
if(LOG.isLoggable(Level.FINE))
|
||||||
LOG.fine("Not subscribed");
|
LOG.fine("Not subscribed");
|
||||||
@@ -128,7 +132,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Generating bundle for " + c);
|
if(LOG.isLoggable(Level.FINE)) LOG.fine("Generating bundle for " + c);
|
||||||
// Ack all batches received from c
|
// Ack all batches received from c
|
||||||
synchronized(contactLock) {
|
synchronized(contactLock) {
|
||||||
if(!containsContact(c)) return;
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
synchronized(messageStatusLock) {
|
synchronized(messageStatusLock) {
|
||||||
Txn txn = db.startTransaction();
|
Txn txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
@@ -148,7 +152,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
// Add a list of subscriptions
|
// Add a list of subscriptions
|
||||||
synchronized(contactLock) {
|
synchronized(contactLock) {
|
||||||
if(!containsContact(c)) return;
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
synchronized(subscriptionLock) {
|
synchronized(subscriptionLock) {
|
||||||
Txn txn = db.startTransaction();
|
Txn txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
@@ -185,7 +189,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
|
|
||||||
private Batch fillBatch(ContactId c, long capacity) throws DbException {
|
private Batch fillBatch(ContactId c, long capacity) throws DbException {
|
||||||
synchronized(contactLock) {
|
synchronized(contactLock) {
|
||||||
if(!containsContact(c)) return null;
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
synchronized(messageLock) {
|
synchronized(messageLock) {
|
||||||
synchronized(messageStatusLock) {
|
synchronized(messageStatusLock) {
|
||||||
Txn txn = db.startTransaction();
|
Txn txn = db.startTransaction();
|
||||||
@@ -254,7 +258,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
+ b.getSize() + " bytes");
|
+ b.getSize() + " bytes");
|
||||||
// Mark all messages in acked batches as seen
|
// Mark all messages in acked batches as seen
|
||||||
synchronized(contactLock) {
|
synchronized(contactLock) {
|
||||||
if(!containsContact(c)) return;
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
synchronized(messageLock) {
|
synchronized(messageLock) {
|
||||||
synchronized(messageStatusLock) {
|
synchronized(messageStatusLock) {
|
||||||
int acks = 0;
|
int acks = 0;
|
||||||
@@ -276,7 +280,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
// Update the contact's subscriptions
|
// Update the contact's subscriptions
|
||||||
synchronized(contactLock) {
|
synchronized(contactLock) {
|
||||||
if(!containsContact(c)) return;
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
synchronized(messageStatusLock) {
|
synchronized(messageStatusLock) {
|
||||||
Txn txn = db.startTransaction();
|
Txn txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
@@ -301,7 +305,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
batches++;
|
batches++;
|
||||||
waitForPermissionToWrite();
|
waitForPermissionToWrite();
|
||||||
synchronized(contactLock) {
|
synchronized(contactLock) {
|
||||||
if(!containsContact(c)) return;
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
synchronized(messageLock) {
|
synchronized(messageLock) {
|
||||||
synchronized(messageStatusLock) {
|
synchronized(messageStatusLock) {
|
||||||
synchronized(subscriptionLock) {
|
synchronized(subscriptionLock) {
|
||||||
@@ -334,7 +338,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
// Find any lost batches that need to be retransmitted
|
// Find any lost batches that need to be retransmitted
|
||||||
Set<BatchId> lost;
|
Set<BatchId> lost;
|
||||||
synchronized(contactLock) {
|
synchronized(contactLock) {
|
||||||
if(!containsContact(c)) return;
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
synchronized(messageLock) {
|
synchronized(messageLock) {
|
||||||
synchronized(messageStatusLock) {
|
synchronized(messageStatusLock) {
|
||||||
Txn txn = db.startTransaction();
|
Txn txn = db.startTransaction();
|
||||||
@@ -350,7 +354,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
for(BatchId batch : lost) {
|
for(BatchId batch : lost) {
|
||||||
synchronized(contactLock) {
|
synchronized(contactLock) {
|
||||||
if(!containsContact(c)) return;
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
synchronized(messageLock) {
|
synchronized(messageLock) {
|
||||||
synchronized(messageStatusLock) {
|
synchronized(messageStatusLock) {
|
||||||
Txn txn = db.startTransaction();
|
Txn txn = db.startTransaction();
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
</classpath>
|
</classpath>
|
||||||
<test name='net.sf.briar.db.DatabaseCleanerImplTest'/>
|
<test name='net.sf.briar.db.DatabaseCleanerImplTest'/>
|
||||||
<test name='net.sf.briar.db.H2DatabaseTest'/>
|
<test name='net.sf.briar.db.H2DatabaseTest'/>
|
||||||
|
<test name='net.sf.briar.db.ReadWriteLockDatabaseComponentTest'/>
|
||||||
|
<test name='net.sf.briar.db.SynchronizedDatabaseComponentTest'/>
|
||||||
<test name='net.sf.briar.i18n.FontManagerTest'/>
|
<test name='net.sf.briar.i18n.FontManagerTest'/>
|
||||||
<test name='net.sf.briar.i18n.I18nTest'/>
|
<test name='net.sf.briar.i18n.I18nTest'/>
|
||||||
<test name='net.sf.briar.invitation.InvitationWorkerTest'/>
|
<test name='net.sf.briar.invitation.InvitationWorkerTest'/>
|
||||||
|
|||||||
@@ -4,12 +4,16 @@ import java.io.File;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
import java.util.Random;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import net.sf.briar.api.protocol.UniqueId;
|
||||||
|
|
||||||
public class TestUtils {
|
public class TestUtils {
|
||||||
|
|
||||||
private static final AtomicInteger nextTestDir =
|
private static final AtomicInteger nextTestDir =
|
||||||
new AtomicInteger((int) (Math.random() * 1000 * 1000));
|
new AtomicInteger((int) (Math.random() * 1000 * 1000));
|
||||||
|
private static final Random random = new Random();
|
||||||
|
|
||||||
public static void delete(File f) {
|
public static void delete(File f) {
|
||||||
if(f.isDirectory()) for(File child : f.listFiles()) delete(child);
|
if(f.isDirectory()) for(File child : f.listFiles()) delete(child);
|
||||||
@@ -42,4 +46,10 @@ public class TestUtils {
|
|||||||
if(bin.exists() && bin.isDirectory()) return bin;
|
if(bin.exists() && bin.isDirectory()) return bin;
|
||||||
throw new RuntimeException("Could not find build directory");
|
throw new RuntimeException("Could not find build directory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] getRandomId() {
|
||||||
|
byte[] b = new byte[UniqueId.LENGTH];
|
||||||
|
random.nextBytes(b);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
140
test/net/sf/briar/db/DatabaseComponentImplTest.java
Normal file
140
test/net/sf/briar/db/DatabaseComponentImplTest.java
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
package net.sf.briar.db;
|
||||||
|
|
||||||
|
import static net.sf.briar.api.db.DatabaseComponent.BYTES_PER_SWEEP;
|
||||||
|
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.Batch;
|
||||||
|
import net.sf.briar.api.protocol.MessageId;
|
||||||
|
import net.sf.briar.db.DatabaseCleaner.Callback;
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
|
||||||
|
|
||||||
|
protected abstract <T> DatabaseComponentImpl<T> createDatabaseComponentImpl(
|
||||||
|
Database<T> database, DatabaseCleaner cleaner,
|
||||||
|
Provider<Batch> batchProvider);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNotCleanedIfEnoughFreeSpace() throws DbException {
|
||||||
|
Mockery context = new Mockery();
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final Database<Object> database = context.mock(Database.class);
|
||||||
|
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(database).getFreeSpace();
|
||||||
|
will(returnValue(MIN_FREE_SPACE));
|
||||||
|
}});
|
||||||
|
Callback db = createDatabaseComponentImpl(database, cleaner,
|
||||||
|
batchProvider);
|
||||||
|
|
||||||
|
db.checkFreeSpaceAndClean();
|
||||||
|
|
||||||
|
context.assertIsSatisfied();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCleanedIfNotEnoughFreeSpace() throws DbException {
|
||||||
|
Mockery context = new Mockery();
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final Database<Object> database = context.mock(Database.class);
|
||||||
|
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(database).getFreeSpace();
|
||||||
|
will(returnValue(MIN_FREE_SPACE - 1));
|
||||||
|
oneOf(database).startTransaction();
|
||||||
|
will(returnValue(txn));
|
||||||
|
oneOf(database).getOldMessages(txn, BYTES_PER_SWEEP);
|
||||||
|
will(returnValue(Collections.emptySet()));
|
||||||
|
oneOf(database).commitTransaction(txn);
|
||||||
|
// As if by magic, some free space has appeared
|
||||||
|
oneOf(database).getFreeSpace();
|
||||||
|
will(returnValue(MIN_FREE_SPACE));
|
||||||
|
}});
|
||||||
|
Callback db = createDatabaseComponentImpl(database, cleaner,
|
||||||
|
batchProvider);
|
||||||
|
|
||||||
|
db.checkFreeSpaceAndClean();
|
||||||
|
|
||||||
|
context.assertIsSatisfied();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpiringUnsendableMessageDoesNotTriggerBackwardInclusion()
|
||||||
|
throws DbException {
|
||||||
|
Mockery context = new Mockery();
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final Database<Object> database = context.mock(Database.class);
|
||||||
|
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(database).getFreeSpace();
|
||||||
|
will(returnValue(MIN_FREE_SPACE - 1));
|
||||||
|
oneOf(database).startTransaction();
|
||||||
|
will(returnValue(txn));
|
||||||
|
oneOf(database).getOldMessages(txn, BYTES_PER_SWEEP);
|
||||||
|
will(returnValue(Collections.singleton(messageId)));
|
||||||
|
oneOf(database).getSendability(txn, messageId);
|
||||||
|
will(returnValue(0));
|
||||||
|
oneOf(database).removeMessage(txn, messageId);
|
||||||
|
oneOf(database).commitTransaction(txn);
|
||||||
|
oneOf(database).getFreeSpace();
|
||||||
|
will(returnValue(MIN_FREE_SPACE));
|
||||||
|
}});
|
||||||
|
Callback db = createDatabaseComponentImpl(database, cleaner,
|
||||||
|
batchProvider);
|
||||||
|
|
||||||
|
db.checkFreeSpaceAndClean();
|
||||||
|
|
||||||
|
context.assertIsSatisfied();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpiringSendableMessageTriggersBackwardInclusion()
|
||||||
|
throws DbException {
|
||||||
|
Mockery context = new Mockery();
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final Database<Object> database = context.mock(Database.class);
|
||||||
|
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(database).getFreeSpace();
|
||||||
|
will(returnValue(MIN_FREE_SPACE - 1));
|
||||||
|
oneOf(database).startTransaction();
|
||||||
|
will(returnValue(txn));
|
||||||
|
oneOf(database).getOldMessages(txn, BYTES_PER_SWEEP);
|
||||||
|
will(returnValue(Collections.singleton(messageId)));
|
||||||
|
oneOf(database).getSendability(txn, messageId);
|
||||||
|
will(returnValue(1));
|
||||||
|
oneOf(database).getParent(txn, messageId);
|
||||||
|
will(returnValue(MessageId.NONE));
|
||||||
|
oneOf(database).removeMessage(txn, messageId);
|
||||||
|
oneOf(database).commitTransaction(txn);
|
||||||
|
oneOf(database).getFreeSpace();
|
||||||
|
will(returnValue(MIN_FREE_SPACE));
|
||||||
|
}});
|
||||||
|
Callback db = createDatabaseComponentImpl(database, cleaner,
|
||||||
|
batchProvider);
|
||||||
|
|
||||||
|
db.checkFreeSpaceAndClean();
|
||||||
|
|
||||||
|
context.assertIsSatisfied();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
package net.sf.briar.db;
|
package net.sf.briar.db;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Random;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
@@ -10,10 +8,12 @@ import net.sf.briar.TestUtils;
|
|||||||
import net.sf.briar.api.db.ContactId;
|
import net.sf.briar.api.db.ContactId;
|
||||||
import net.sf.briar.api.db.DatabaseComponent;
|
import net.sf.briar.api.db.DatabaseComponent;
|
||||||
import net.sf.briar.api.db.DbException;
|
import net.sf.briar.api.db.DbException;
|
||||||
|
import net.sf.briar.api.db.NoSuchContactException;
|
||||||
import net.sf.briar.api.db.Rating;
|
import net.sf.briar.api.db.Rating;
|
||||||
import net.sf.briar.api.db.Status;
|
import net.sf.briar.api.db.Status;
|
||||||
import net.sf.briar.api.protocol.AuthorId;
|
import net.sf.briar.api.protocol.AuthorId;
|
||||||
import net.sf.briar.api.protocol.Batch;
|
import net.sf.briar.api.protocol.Batch;
|
||||||
|
import net.sf.briar.api.protocol.Bundle;
|
||||||
import net.sf.briar.api.protocol.GroupId;
|
import net.sf.briar.api.protocol.GroupId;
|
||||||
import net.sf.briar.api.protocol.Message;
|
import net.sf.briar.api.protocol.Message;
|
||||||
import net.sf.briar.api.protocol.MessageId;
|
import net.sf.briar.api.protocol.MessageId;
|
||||||
@@ -21,37 +21,32 @@ import net.sf.briar.protocol.MessageImpl;
|
|||||||
|
|
||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
import org.jmock.Mockery;
|
import org.jmock.Mockery;
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
|
||||||
public abstract class DatabaseComponentTest extends TestCase {
|
public abstract class DatabaseComponentTest extends TestCase {
|
||||||
|
|
||||||
private final File testDir = TestUtils.getTestDirectory();
|
protected final Object txn = new Object();
|
||||||
private final Random random = new Random();
|
protected final AuthorId authorId;
|
||||||
private final AuthorId authorId;
|
protected final ContactId contactId;
|
||||||
private final ContactId contactId;
|
protected final GroupId groupId;
|
||||||
private final GroupId groupId;
|
protected final MessageId messageId, parentId;
|
||||||
private final MessageId messageId, parentId;
|
|
||||||
private final long timestamp;
|
private final long timestamp;
|
||||||
private final int size;
|
private final int size;
|
||||||
private final byte[] body;
|
private final byte[] body;
|
||||||
private final Message message;
|
private final Message message;
|
||||||
private final Object txn = new Object();
|
|
||||||
|
|
||||||
public DatabaseComponentTest() {
|
public DatabaseComponentTest() {
|
||||||
super();
|
super();
|
||||||
authorId = new AuthorId(getRandomId());
|
authorId = new AuthorId(TestUtils.getRandomId());
|
||||||
contactId = new ContactId(123);
|
contactId = new ContactId(123);
|
||||||
groupId = new GroupId(getRandomId());
|
groupId = new GroupId(TestUtils.getRandomId());
|
||||||
messageId = new MessageId(getRandomId());
|
messageId = new MessageId(TestUtils.getRandomId());
|
||||||
parentId = new MessageId(getRandomId());
|
parentId = new MessageId(TestUtils.getRandomId());
|
||||||
timestamp = System.currentTimeMillis();
|
timestamp = System.currentTimeMillis();
|
||||||
size = 1234;
|
size = 1234;
|
||||||
body = new byte[size];
|
body = new byte[size];
|
||||||
random.nextBytes(body);
|
|
||||||
message = new MessageImpl(messageId, MessageId.NONE, groupId, authorId,
|
message = new MessageImpl(messageId, MessageId.NONE, groupId, authorId,
|
||||||
timestamp, body);
|
timestamp, body);
|
||||||
}
|
}
|
||||||
@@ -60,11 +55,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
Database<T> database, DatabaseCleaner cleaner,
|
Database<T> database, DatabaseCleaner cleaner,
|
||||||
Provider<Batch> batchProvider);
|
Provider<Batch> batchProvider);
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
testDir.mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSimpleCalls() throws DbException {
|
public void testSimpleCalls() throws DbException {
|
||||||
final Set<GroupId> subs = Collections.singleton(groupId);
|
final Set<GroupId> subs = Collections.singleton(groupId);
|
||||||
@@ -137,8 +127,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).open(false);
|
|
||||||
oneOf(cleaner).startCleaning();
|
|
||||||
// setRating(Rating.GOOD)
|
// setRating(Rating.GOOD)
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -153,15 +141,11 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
oneOf(database).getParent(txn, messageId);
|
oneOf(database).getParent(txn, messageId);
|
||||||
will(returnValue(MessageId.NONE));
|
will(returnValue(MessageId.NONE));
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
oneOf(cleaner).stopCleaning();
|
|
||||||
oneOf(database).close();
|
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||||
batchProvider);
|
batchProvider);
|
||||||
|
|
||||||
db.open(false);
|
|
||||||
db.setRating(authorId, Rating.GOOD);
|
db.setRating(authorId, Rating.GOOD);
|
||||||
db.close();
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
@@ -176,8 +160,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).open(false);
|
|
||||||
oneOf(cleaner).startCleaning();
|
|
||||||
// setRating(Rating.GOOD)
|
// setRating(Rating.GOOD)
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -195,22 +177,18 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
oneOf(database).containsMessage(txn, parentId);
|
oneOf(database).containsMessage(txn, parentId);
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
oneOf(cleaner).stopCleaning();
|
|
||||||
oneOf(database).close();
|
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||||
batchProvider);
|
batchProvider);
|
||||||
|
|
||||||
db.open(false);
|
|
||||||
db.setRating(authorId, Rating.GOOD);
|
db.setRating(authorId, Rating.GOOD);
|
||||||
db.close();
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testChangingGroupsStopsBackwardInclusion() throws DbException {
|
public void testChangingGroupsStopsBackwardInclusion() throws DbException {
|
||||||
final GroupId groupId1 = new GroupId(getRandomId());
|
final GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
||||||
final Set<MessageId> messages = Collections.singleton(messageId);
|
final Set<MessageId> messages = Collections.singleton(messageId);
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -219,8 +197,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).open(false);
|
|
||||||
oneOf(cleaner).startCleaning();
|
|
||||||
// setRating(Rating.GOOD)
|
// setRating(Rating.GOOD)
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -242,15 +218,11 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
oneOf(database).getGroup(txn, parentId);
|
oneOf(database).getGroup(txn, parentId);
|
||||||
will(returnValue(groupId1));
|
will(returnValue(groupId1));
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
oneOf(cleaner).stopCleaning();
|
|
||||||
oneOf(database).close();
|
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||||
batchProvider);
|
batchProvider);
|
||||||
|
|
||||||
db.open(false);
|
|
||||||
db.setRating(authorId, Rating.GOOD);
|
db.setRating(authorId, Rating.GOOD);
|
||||||
db.close();
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
@@ -266,8 +238,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).open(false);
|
|
||||||
oneOf(cleaner).startCleaning();
|
|
||||||
// setRating(Rating.GOOD)
|
// setRating(Rating.GOOD)
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -292,15 +262,11 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
will(returnValue(1));
|
will(returnValue(1));
|
||||||
oneOf(database).setSendability(txn, parentId, 2);
|
oneOf(database).setSendability(txn, parentId, 2);
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
oneOf(cleaner).stopCleaning();
|
|
||||||
oneOf(database).close();
|
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||||
batchProvider);
|
batchProvider);
|
||||||
|
|
||||||
db.open(false);
|
|
||||||
db.setRating(authorId, Rating.GOOD);
|
db.setRating(authorId, Rating.GOOD);
|
||||||
db.close();
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
@@ -316,8 +282,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).open(false);
|
|
||||||
oneOf(cleaner).startCleaning();
|
|
||||||
// setRating(Rating.GOOD)
|
// setRating(Rating.GOOD)
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -344,15 +308,11 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
oneOf(database).getParent(txn, parentId);
|
oneOf(database).getParent(txn, parentId);
|
||||||
will(returnValue(MessageId.NONE));
|
will(returnValue(MessageId.NONE));
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
oneOf(cleaner).stopCleaning();
|
|
||||||
oneOf(database).close();
|
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||||
batchProvider);
|
batchProvider);
|
||||||
|
|
||||||
db.open(false);
|
|
||||||
db.setRating(authorId, Rating.GOOD);
|
db.setRating(authorId, Rating.GOOD);
|
||||||
db.close();
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
@@ -367,23 +327,17 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).open(false);
|
|
||||||
oneOf(cleaner).startCleaning();
|
|
||||||
// addLocallyGeneratedMessage(message)
|
// addLocallyGeneratedMessage(message)
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
oneOf(database).containsSubscription(txn, groupId);
|
oneOf(database).containsSubscription(txn, groupId);
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
oneOf(cleaner).stopCleaning();
|
|
||||||
oneOf(database).close();
|
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||||
batchProvider);
|
batchProvider);
|
||||||
|
|
||||||
db.open(false);
|
|
||||||
db.addLocallyGeneratedMessage(message);
|
db.addLocallyGeneratedMessage(message);
|
||||||
db.close();
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
@@ -397,8 +351,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).open(false);
|
|
||||||
oneOf(cleaner).startCleaning();
|
|
||||||
// addLocallyGeneratedMessage(message)
|
// addLocallyGeneratedMessage(message)
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -407,15 +359,11 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
oneOf(database).addMessage(txn, message);
|
oneOf(database).addMessage(txn, message);
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
oneOf(cleaner).stopCleaning();
|
|
||||||
oneOf(database).close();
|
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||||
batchProvider);
|
batchProvider);
|
||||||
|
|
||||||
db.open(false);
|
|
||||||
db.addLocallyGeneratedMessage(message);
|
db.addLocallyGeneratedMessage(message);
|
||||||
db.close();
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
@@ -429,8 +377,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).open(false);
|
|
||||||
oneOf(cleaner).startCleaning();
|
|
||||||
// addLocallyGeneratedMessage(message)
|
// addLocallyGeneratedMessage(message)
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -448,15 +394,11 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
will(returnValue(0));
|
will(returnValue(0));
|
||||||
oneOf(database).setSendability(txn, messageId, 0);
|
oneOf(database).setSendability(txn, messageId, 0);
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
oneOf(cleaner).stopCleaning();
|
|
||||||
oneOf(database).close();
|
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||||
batchProvider);
|
batchProvider);
|
||||||
|
|
||||||
db.open(false);
|
|
||||||
db.addLocallyGeneratedMessage(message);
|
db.addLocallyGeneratedMessage(message);
|
||||||
db.close();
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
@@ -471,8 +413,6 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).open(false);
|
|
||||||
oneOf(cleaner).startCleaning();
|
|
||||||
// addLocallyGeneratedMessage(message)
|
// addLocallyGeneratedMessage(message)
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -493,27 +433,40 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
oneOf(database).getParent(txn, messageId);
|
oneOf(database).getParent(txn, messageId);
|
||||||
will(returnValue(MessageId.NONE));
|
will(returnValue(MessageId.NONE));
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
oneOf(cleaner).stopCleaning();
|
|
||||||
oneOf(database).close();
|
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||||
batchProvider);
|
batchProvider);
|
||||||
|
|
||||||
db.open(false);
|
|
||||||
db.addLocallyGeneratedMessage(message);
|
db.addLocallyGeneratedMessage(message);
|
||||||
db.close();
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] getRandomId() {
|
@Test
|
||||||
byte[] b = new byte[32];
|
public void testGenerateBundleThrowsExceptionIfContactIsMissing()
|
||||||
random.nextBytes(b);
|
throws DbException {
|
||||||
return b;
|
Mockery context = new Mockery();
|
||||||
}
|
@SuppressWarnings("unchecked")
|
||||||
|
final Database<Object> database = context.mock(Database.class);
|
||||||
|
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final Provider<Batch> batchProvider = context.mock(Provider.class);
|
||||||
|
final Bundle bundle = context.mock(Bundle.class);
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(database).startTransaction();
|
||||||
|
will(returnValue(txn));
|
||||||
|
oneOf(database).containsContact(txn, contactId);
|
||||||
|
will(returnValue(false));
|
||||||
|
oneOf(database).commitTransaction(txn);
|
||||||
|
}});
|
||||||
|
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||||
|
batchProvider);
|
||||||
|
|
||||||
@After
|
try {
|
||||||
public void tearDown() {
|
db.generateBundle(contactId, bundle);
|
||||||
TestUtils.deleteTestDirectory(testDir);
|
assertTrue(false);
|
||||||
|
} catch(NoSuchContactException expected) {}
|
||||||
|
|
||||||
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,11 +53,11 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
|
|
||||||
public H2DatabaseTest() {
|
public H2DatabaseTest() {
|
||||||
super();
|
super();
|
||||||
authorId = new AuthorId(getRandomId());
|
authorId = new AuthorId(TestUtils.getRandomId());
|
||||||
batchId = new BatchId(getRandomId());
|
batchId = new BatchId(TestUtils.getRandomId());
|
||||||
contactId = new ContactId(123);
|
contactId = new ContactId(123);
|
||||||
groupId = new GroupId(getRandomId());
|
groupId = new GroupId(TestUtils.getRandomId());
|
||||||
messageId = new MessageId(getRandomId());
|
messageId = new MessageId(TestUtils.getRandomId());
|
||||||
timestamp = System.currentTimeMillis();
|
timestamp = System.currentTimeMillis();
|
||||||
size = 1234;
|
size = 1234;
|
||||||
body = new byte[size];
|
body = new byte[size];
|
||||||
@@ -338,7 +338,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBatchesToAck() throws DbException {
|
public void testBatchesToAck() throws DbException {
|
||||||
BatchId batchId1 = new BatchId(getRandomId());
|
BatchId batchId1 = new BatchId(TestUtils.getRandomId());
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
||||||
|
|
||||||
@@ -461,13 +461,13 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRetransmission() throws DbException {
|
public void testRetransmission() throws DbException {
|
||||||
BundleId bundleId = new BundleId(getRandomId());
|
BundleId bundleId = new BundleId(TestUtils.getRandomId());
|
||||||
BundleId bundleId1 = new BundleId(getRandomId());
|
BundleId bundleId1 = new BundleId(TestUtils.getRandomId());
|
||||||
BundleId bundleId2 = new BundleId(getRandomId());
|
BundleId bundleId2 = new BundleId(TestUtils.getRandomId());
|
||||||
BundleId bundleId3 = new BundleId(getRandomId());
|
BundleId bundleId3 = new BundleId(TestUtils.getRandomId());
|
||||||
BundleId bundleId4 = new BundleId(getRandomId());
|
BundleId bundleId4 = new BundleId(TestUtils.getRandomId());
|
||||||
BatchId batchId1 = new BatchId(getRandomId());
|
BatchId batchId1 = new BatchId(TestUtils.getRandomId());
|
||||||
BatchId batchId2 = new BatchId(getRandomId());
|
BatchId batchId2 = new BatchId(TestUtils.getRandomId());
|
||||||
Set<MessageId> empty = Collections.emptySet();
|
Set<MessageId> empty = Collections.emptySet();
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
||||||
@@ -508,8 +508,8 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetMessagesByAuthor() throws DbException {
|
public void testGetMessagesByAuthor() throws DbException {
|
||||||
AuthorId authorId1 = new AuthorId(getRandomId());
|
AuthorId authorId1 = new AuthorId(TestUtils.getRandomId());
|
||||||
MessageId messageId1 = new MessageId(getRandomId());
|
MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
||||||
Message message1 = new MessageImpl(messageId1, MessageId.NONE, groupId,
|
Message message1 = new MessageImpl(messageId1, MessageId.NONE, groupId,
|
||||||
authorId1, timestamp, body);
|
authorId1, timestamp, body);
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
@@ -543,10 +543,10 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetNumberOfSendableChildren() throws DbException {
|
public void testGetNumberOfSendableChildren() throws DbException {
|
||||||
MessageId childId1 = new MessageId(getRandomId());
|
MessageId childId1 = new MessageId(TestUtils.getRandomId());
|
||||||
MessageId childId2 = new MessageId(getRandomId());
|
MessageId childId2 = new MessageId(TestUtils.getRandomId());
|
||||||
MessageId childId3 = new MessageId(getRandomId());
|
MessageId childId3 = new MessageId(TestUtils.getRandomId());
|
||||||
GroupId groupId1 = new GroupId(getRandomId());
|
GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
||||||
Message child1 = new MessageImpl(childId1, messageId, groupId,
|
Message child1 = new MessageImpl(childId1, messageId, groupId,
|
||||||
authorId, timestamp, body);
|
authorId, timestamp, body);
|
||||||
Message child2 = new MessageImpl(childId2, messageId, groupId,
|
Message child2 = new MessageImpl(childId2, messageId, groupId,
|
||||||
@@ -588,7 +588,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetOldMessages() throws DbException {
|
public void testGetOldMessages() throws DbException {
|
||||||
MessageId messageId1 = new MessageId(getRandomId());
|
MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
||||||
Message message1 = new MessageImpl(messageId1, MessageId.NONE, groupId,
|
Message message1 = new MessageImpl(messageId1, MessageId.NONE, groupId,
|
||||||
authorId, timestamp + 1000, body);
|
authorId, timestamp + 1000, body);
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
@@ -758,12 +758,6 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
TestUtils.deleteTestDirectory(testDir);
|
TestUtils.deleteTestDirectory(testDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] getRandomId() {
|
|
||||||
byte[] b = new byte[32];
|
|
||||||
random.nextBytes(b);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class TestMessageFactory implements MessageFactory {
|
private static class TestMessageFactory implements MessageFactory {
|
||||||
|
|
||||||
public Message createMessage(MessageId id, MessageId parent,
|
public Message createMessage(MessageId id, MessageId parent,
|
||||||
|
|||||||
@@ -5,12 +5,20 @@ import net.sf.briar.api.protocol.Batch;
|
|||||||
|
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
|
||||||
public class ReadWriteLockDatabaseComponentTest extends DatabaseComponentTest {
|
public class ReadWriteLockDatabaseComponentTest
|
||||||
|
extends DatabaseComponentImplTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected <T> DatabaseComponent createDatabaseComponent(
|
protected <T> DatabaseComponent createDatabaseComponent(
|
||||||
Database<T> database, DatabaseCleaner cleaner,
|
Database<T> database, DatabaseCleaner cleaner,
|
||||||
Provider<Batch> batchProvider) {
|
Provider<Batch> batchProvider) {
|
||||||
|
return createDatabaseComponentImpl(database, cleaner, batchProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected <T> DatabaseComponentImpl<T> createDatabaseComponentImpl(
|
||||||
|
Database<T> database, DatabaseCleaner cleaner,
|
||||||
|
Provider<Batch> batchProvider) {
|
||||||
return new ReadWriteLockDatabaseComponent<T>(database, cleaner,
|
return new ReadWriteLockDatabaseComponent<T>(database, cleaner,
|
||||||
batchProvider);
|
batchProvider);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,21 @@ import net.sf.briar.api.protocol.Batch;
|
|||||||
|
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
|
||||||
public class SynchronizedDatabaseComponentTest extends DatabaseComponentTest {
|
public class SynchronizedDatabaseComponentTest
|
||||||
|
extends DatabaseComponentImplTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected <T> DatabaseComponent createDatabaseComponent(
|
protected <T> DatabaseComponent createDatabaseComponent(
|
||||||
Database<T> database, DatabaseCleaner cleaner,
|
Database<T> database, DatabaseCleaner cleaner,
|
||||||
Provider<Batch> batchProvider) {
|
Provider<Batch> batchProvider) {
|
||||||
|
return createDatabaseComponentImpl(database, cleaner, batchProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected <T> DatabaseComponentImpl<T> createDatabaseComponentImpl(
|
||||||
|
Database<T> database, DatabaseCleaner cleaner,
|
||||||
|
Provider<Batch> batchProvider) {
|
||||||
return new SynchronizedDatabaseComponent<T>(database, cleaner,
|
return new SynchronizedDatabaseComponent<T>(database, cleaner,
|
||||||
batchProvider);
|
batchProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user