mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-20 22:59:54 +01:00
Added a lock for the connectionWindows table and exposed
getConnectionWindow() and setConnectionWindow() through the DatabaseComponent interface.
This commit is contained in:
@@ -22,6 +22,7 @@ import net.sf.briar.api.protocol.writers.OfferWriter;
|
|||||||
import net.sf.briar.api.protocol.writers.RequestWriter;
|
import net.sf.briar.api.protocol.writers.RequestWriter;
|
||||||
import net.sf.briar.api.protocol.writers.SubscriptionWriter;
|
import net.sf.briar.api.protocol.writers.SubscriptionWriter;
|
||||||
import net.sf.briar.api.protocol.writers.TransportWriter;
|
import net.sf.briar.api.protocol.writers.TransportWriter;
|
||||||
|
import net.sf.briar.api.transport.ConnectionWindow;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulates the database implementation and exposes high-level operations
|
* Encapsulates the database implementation and exposes high-level operations
|
||||||
@@ -103,6 +104,13 @@ public interface DatabaseComponent {
|
|||||||
void generateTransportUpdate(ContactId c, TransportWriter t) throws
|
void generateTransportUpdate(ContactId c, TransportWriter t) throws
|
||||||
DbException, IOException;
|
DbException, IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the connection reordering window for the given contact and
|
||||||
|
* transport.
|
||||||
|
*/
|
||||||
|
ConnectionWindow getConnectionWindow(ContactId c, int transportId)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/** Returns the IDs of all contacts. */
|
/** Returns the IDs of all contacts. */
|
||||||
Collection<ContactId> getContacts() throws DbException;
|
Collection<ContactId> getContacts() throws DbException;
|
||||||
|
|
||||||
@@ -156,6 +164,13 @@ public interface DatabaseComponent {
|
|||||||
/** Removes a contact (and all associated state) from the database. */
|
/** Removes a contact (and all associated state) from the database. */
|
||||||
void removeContact(ContactId c) throws DbException;
|
void removeContact(ContactId c) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the connection reordering window for the given contact and
|
||||||
|
* transport.
|
||||||
|
*/
|
||||||
|
void setConnectionWindow(ContactId c, int transportId, ConnectionWindow w)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/** Records the user's rating for the given author. */
|
/** Records the user's rating for the given author. */
|
||||||
void setRating(AuthorId a, Rating r) throws DbException;
|
void setRating(AuthorId a, Rating r) throws DbException;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package net.sf.briar.api.transport;
|
package net.sf.briar.api.transport;
|
||||||
|
|
||||||
import net.sf.briar.api.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
|
import net.sf.briar.api.db.DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maintains a transport plugin's connection reordering window and decides
|
* Maintains a transport plugin's connection reordering window and decides
|
||||||
@@ -12,5 +13,5 @@ public interface ConnectionRecogniser {
|
|||||||
* Returns the ID of the contact who created the tag if the connection
|
* Returns the ID of the contact who created the tag if the connection
|
||||||
* should be accepted, or null if the connection should be rejected.
|
* should be accepted, or null if the connection should be rejected.
|
||||||
*/
|
*/
|
||||||
ContactId acceptConnection(byte[] tag);
|
ContactId acceptConnection(byte[] tag) throws DbException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import net.sf.briar.api.transport.ConnectionWindow;
|
|||||||
* <li> ratings
|
* <li> ratings
|
||||||
* <li> subscriptions
|
* <li> subscriptions
|
||||||
* <li> transports
|
* <li> transports
|
||||||
|
* <li> windows
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
interface Database<T> {
|
interface Database<T> {
|
||||||
@@ -159,8 +160,10 @@ interface Database<T> {
|
|||||||
/**
|
/**
|
||||||
* Returns the connection reordering window for the given contact and
|
* Returns the connection reordering window for the given contact and
|
||||||
* transport.
|
* transport.
|
||||||
|
* <p>
|
||||||
|
* Locking: contacts read, windows read.
|
||||||
*/
|
*/
|
||||||
ConnectionWindow getConnectionWindow(T txn, ContactId c, int transport)
|
ConnectionWindow getConnectionWindow(T txn, ContactId c, int transportId)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -382,8 +385,10 @@ interface Database<T> {
|
|||||||
/**
|
/**
|
||||||
* Sets the connection reordering window for the given contact and
|
* Sets the connection reordering window for the given contact and
|
||||||
* transport.
|
* transport.
|
||||||
|
* <p>
|
||||||
|
* Locking: contacts read, windows write.
|
||||||
*/
|
*/
|
||||||
void setConnectionWindow(T txn, ContactId c, int transport,
|
void setConnectionWindow(T txn, ContactId c, int transportId,
|
||||||
ConnectionWindow w) throws DbException;
|
ConnectionWindow w) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -734,7 +734,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ConnectionWindow getConnectionWindow(Connection txn, ContactId c,
|
public ConnectionWindow getConnectionWindow(Connection txn, ContactId c,
|
||||||
int transport) throws DbException {
|
int transportId) throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
@@ -742,7 +742,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " WHERE contactId = ? AND transportId = ?";
|
+ " WHERE contactId = ? AND transportId = ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setInt(1, c.getInt());
|
ps.setInt(1, c.getInt());
|
||||||
ps.setInt(2, transport);
|
ps.setInt(2, transportId);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
long centre = 0L;
|
long centre = 0L;
|
||||||
int bitmap = 0;
|
int bitmap = 0;
|
||||||
@@ -1528,8 +1528,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConnectionWindow(Connection txn, ContactId c, int transport,
|
public void setConnectionWindow(Connection txn, ContactId c,
|
||||||
ConnectionWindow w) throws DbException {
|
int transportId, ConnectionWindow w) throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
@@ -1537,7 +1537,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " WHERE contactId = ? AND transportId = ?";
|
+ " WHERE contactId = ? AND transportId = ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setInt(1, c.getInt());
|
ps.setInt(1, c.getInt());
|
||||||
ps.setInt(2, transport);
|
ps.setInt(2, transportId);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
if(rs.next()) {
|
if(rs.next()) {
|
||||||
if(rs.next()) throw new DbStateException();
|
if(rs.next()) throw new DbStateException();
|
||||||
@@ -1556,7 +1556,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " VALUES(?, ?, ?, ?)";
|
+ " VALUES(?, ?, ?, ?)";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setInt(1, c.getInt());
|
ps.setInt(1, c.getInt());
|
||||||
ps.setInt(2, transport);
|
ps.setInt(2, transportId);
|
||||||
ps.setLong(3, w.getCentre());
|
ps.setLong(3, w.getCentre());
|
||||||
ps.setInt(4, w.getBitmap());
|
ps.setInt(4, w.getBitmap());
|
||||||
int affected = ps.executeUpdate();
|
int affected = ps.executeUpdate();
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import net.sf.briar.api.protocol.writers.OfferWriter;
|
|||||||
import net.sf.briar.api.protocol.writers.RequestWriter;
|
import net.sf.briar.api.protocol.writers.RequestWriter;
|
||||||
import net.sf.briar.api.protocol.writers.SubscriptionWriter;
|
import net.sf.briar.api.protocol.writers.SubscriptionWriter;
|
||||||
import net.sf.briar.api.protocol.writers.TransportWriter;
|
import net.sf.briar.api.protocol.writers.TransportWriter;
|
||||||
|
import net.sf.briar.api.transport.ConnectionWindow;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
@@ -61,6 +62,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
new ReentrantReadWriteLock(true);
|
new ReentrantReadWriteLock(true);
|
||||||
private final ReentrantReadWriteLock transportLock =
|
private final ReentrantReadWriteLock transportLock =
|
||||||
new ReentrantReadWriteLock(true);
|
new ReentrantReadWriteLock(true);
|
||||||
|
private final ReentrantReadWriteLock windowLock =
|
||||||
|
new ReentrantReadWriteLock(true);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ReadWriteLockDatabaseComponent(Database<Txn> db, DatabaseCleaner cleaner) {
|
ReadWriteLockDatabaseComponent(Database<Txn> db, DatabaseCleaner cleaner) {
|
||||||
@@ -488,6 +491,31 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ConnectionWindow getConnectionWindow(ContactId c, int transportId)
|
||||||
|
throws DbException {
|
||||||
|
contactLock.readLock().lock();
|
||||||
|
try {
|
||||||
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
|
windowLock.readLock().lock();
|
||||||
|
try {
|
||||||
|
Txn txn = db.startTransaction();
|
||||||
|
try {
|
||||||
|
ConnectionWindow w =
|
||||||
|
db.getConnectionWindow(txn, c, transportId);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
return w;
|
||||||
|
} catch(DbException e) {
|
||||||
|
db.abortTransaction(txn);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
windowLock.readLock().unlock();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
contactLock.readLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Collection<ContactId> getContacts() throws DbException {
|
public Collection<ContactId> getContacts() throws DbException {
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
@@ -869,6 +897,28 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setConnectionWindow(ContactId c, int transportId,
|
||||||
|
ConnectionWindow w) throws DbException {
|
||||||
|
contactLock.readLock().lock();
|
||||||
|
try {
|
||||||
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
|
windowLock.writeLock().lock();
|
||||||
|
try {
|
||||||
|
Txn txn = db.startTransaction();
|
||||||
|
try {
|
||||||
|
db.setConnectionWindow(txn, c, transportId, w);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} catch(DbException e) {
|
||||||
|
db.abortTransaction(txn);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
windowLock.writeLock().unlock();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
contactLock.readLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setRating(AuthorId a, Rating r) throws DbException {
|
public void setRating(AuthorId a, Rating r) throws DbException {
|
||||||
messageLock.writeLock().lock();
|
messageLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import net.sf.briar.api.protocol.writers.OfferWriter;
|
|||||||
import net.sf.briar.api.protocol.writers.RequestWriter;
|
import net.sf.briar.api.protocol.writers.RequestWriter;
|
||||||
import net.sf.briar.api.protocol.writers.SubscriptionWriter;
|
import net.sf.briar.api.protocol.writers.SubscriptionWriter;
|
||||||
import net.sf.briar.api.protocol.writers.TransportWriter;
|
import net.sf.briar.api.protocol.writers.TransportWriter;
|
||||||
|
import net.sf.briar.api.transport.ConnectionWindow;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
@@ -54,6 +55,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
private final Object ratingLock = new Object();
|
private final Object ratingLock = new Object();
|
||||||
private final Object subscriptionLock = new Object();
|
private final Object subscriptionLock = new Object();
|
||||||
private final Object transportLock = new Object();
|
private final Object transportLock = new Object();
|
||||||
|
private final Object windowLock = new Object();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
SynchronizedDatabaseComponent(Database<Txn> db, DatabaseCleaner cleaner) {
|
SynchronizedDatabaseComponent(Database<Txn> db, DatabaseCleaner cleaner) {
|
||||||
@@ -373,6 +375,25 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ConnectionWindow getConnectionWindow(ContactId c, int transportId)
|
||||||
|
throws DbException {
|
||||||
|
synchronized(contactLock) {
|
||||||
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
|
synchronized(windowLock) {
|
||||||
|
Txn txn = db.startTransaction();
|
||||||
|
try {
|
||||||
|
ConnectionWindow w =
|
||||||
|
db.getConnectionWindow(txn, c, transportId);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
return w;
|
||||||
|
} catch(DbException e) {
|
||||||
|
db.abortTransaction(txn);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Collection<ContactId> getContacts() throws DbException {
|
public Collection<ContactId> getContacts() throws DbException {
|
||||||
synchronized(contactLock) {
|
synchronized(contactLock) {
|
||||||
Txn txn = db.startTransaction();
|
Txn txn = db.startTransaction();
|
||||||
@@ -659,6 +680,22 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setConnectionWindow(ContactId c, int transportId,
|
||||||
|
ConnectionWindow w) throws DbException {
|
||||||
|
synchronized(contactLock) {
|
||||||
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
|
synchronized(windowLock) {
|
||||||
|
Txn txn = db.startTransaction();
|
||||||
|
try {
|
||||||
|
db.setConnectionWindow(txn, c, transportId, w);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} catch(DbException e) {
|
||||||
|
db.abortTransaction(txn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setRating(AuthorId a, Rating r) throws DbException {
|
public void setRating(AuthorId a, Rating r) throws DbException {
|
||||||
synchronized(messageLock) {
|
synchronized(messageLock) {
|
||||||
synchronized(ratingLock) {
|
synchronized(ratingLock) {
|
||||||
|
|||||||
@@ -20,16 +20,15 @@ class InvitationWorker implements Runnable {
|
|||||||
|
|
||||||
private final InvitationCallback callback;
|
private final InvitationCallback callback;
|
||||||
private final InvitationParameters parameters;
|
private final InvitationParameters parameters;
|
||||||
private final DatabaseComponent databaseComponent;
|
private final DatabaseComponent db;
|
||||||
private final WriterFactory writerFactory;
|
private final WriterFactory writerFactory;
|
||||||
|
|
||||||
InvitationWorker(final InvitationCallback callback,
|
InvitationWorker(final InvitationCallback callback,
|
||||||
InvitationParameters parameters,
|
InvitationParameters parameters, DatabaseComponent db,
|
||||||
DatabaseComponent databaseComponent,
|
|
||||||
WriterFactory writerFactory) {
|
WriterFactory writerFactory) {
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.parameters = parameters;
|
this.parameters = parameters;
|
||||||
this.databaseComponent = databaseComponent;
|
this.db = db;
|
||||||
this.writerFactory = writerFactory;
|
this.writerFactory = writerFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +72,7 @@ class InvitationWorker implements Runnable {
|
|||||||
// FIXME: Create a real invitation
|
// FIXME: Create a real invitation
|
||||||
Map<String, Map<String, String>> transports;
|
Map<String, Map<String, String>> transports;
|
||||||
try {
|
try {
|
||||||
transports = databaseComponent.getTransports();
|
transports = db.getTransports();
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
throw new IOException(e.getMessage());
|
throw new IOException(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import net.sf.briar.TestUtils;
|
|||||||
import net.sf.briar.api.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
import net.sf.briar.api.Rating;
|
import net.sf.briar.api.Rating;
|
||||||
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.DatabaseListener;
|
import net.sf.briar.api.db.DatabaseListener;
|
||||||
|
import net.sf.briar.api.db.DbException;
|
||||||
import net.sf.briar.api.db.NoSuchContactException;
|
import net.sf.briar.api.db.NoSuchContactException;
|
||||||
import net.sf.briar.api.db.Status;
|
import net.sf.briar.api.db.Status;
|
||||||
import net.sf.briar.api.protocol.Ack;
|
import net.sf.briar.api.protocol.Ack;
|
||||||
@@ -32,6 +32,7 @@ import net.sf.briar.api.protocol.writers.OfferWriter;
|
|||||||
import net.sf.briar.api.protocol.writers.RequestWriter;
|
import net.sf.briar.api.protocol.writers.RequestWriter;
|
||||||
import net.sf.briar.api.protocol.writers.SubscriptionWriter;
|
import net.sf.briar.api.protocol.writers.SubscriptionWriter;
|
||||||
import net.sf.briar.api.protocol.writers.TransportWriter;
|
import net.sf.briar.api.protocol.writers.TransportWriter;
|
||||||
|
import net.sf.briar.api.transport.ConnectionWindow;
|
||||||
|
|
||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
import org.jmock.Mockery;
|
import org.jmock.Mockery;
|
||||||
@@ -81,6 +82,8 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Database<Object> database = context.mock(Database.class);
|
final Database<Object> database = context.mock(Database.class);
|
||||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||||
|
final ConnectionWindow connectionWindow =
|
||||||
|
context.mock(ConnectionWindow.class);
|
||||||
final Group group = context.mock(Group.class);
|
final Group group = context.mock(Group.class);
|
||||||
final DatabaseListener listener = context.mock(DatabaseListener.class);
|
final DatabaseListener listener = context.mock(DatabaseListener.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
@@ -99,6 +102,11 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
// getContacts()
|
// getContacts()
|
||||||
oneOf(database).getContacts(txn);
|
oneOf(database).getContacts(txn);
|
||||||
will(returnValue(Collections.singletonList(contactId)));
|
will(returnValue(Collections.singletonList(contactId)));
|
||||||
|
// getConnectionWindow(contactId, 123)
|
||||||
|
oneOf(database).containsContact(txn, contactId);
|
||||||
|
will(returnValue(true));
|
||||||
|
oneOf(database).getConnectionWindow(txn, contactId, 123);
|
||||||
|
will(returnValue(connectionWindow));
|
||||||
// getTransports(contactId)
|
// getTransports(contactId)
|
||||||
oneOf(database).containsContact(txn, contactId);
|
oneOf(database).containsContact(txn, contactId);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
@@ -129,6 +137,11 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
// unsubscribe(groupId) again
|
// unsubscribe(groupId) again
|
||||||
oneOf(database).containsSubscription(txn, groupId);
|
oneOf(database).containsSubscription(txn, groupId);
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
|
// setConnectionWindow(contactId, 123, connectionWindow)
|
||||||
|
oneOf(database).containsContact(txn, contactId);
|
||||||
|
will(returnValue(true));
|
||||||
|
oneOf(database).setConnectionWindow(txn, contactId, 123,
|
||||||
|
connectionWindow);
|
||||||
// removeContact(contactId)
|
// removeContact(contactId)
|
||||||
oneOf(database).removeContact(txn, contactId);
|
oneOf(database).removeContact(txn, contactId);
|
||||||
// close()
|
// close()
|
||||||
@@ -142,12 +155,14 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
assertEquals(Rating.UNRATED, db.getRating(authorId));
|
assertEquals(Rating.UNRATED, db.getRating(authorId));
|
||||||
assertEquals(contactId, db.addContact(transports));
|
assertEquals(contactId, db.addContact(transports));
|
||||||
assertEquals(Collections.singletonList(contactId), db.getContacts());
|
assertEquals(Collections.singletonList(contactId), db.getContacts());
|
||||||
|
assertEquals(connectionWindow, db.getConnectionWindow(contactId, 123));
|
||||||
assertEquals(transports, db.getTransports(contactId));
|
assertEquals(transports, db.getTransports(contactId));
|
||||||
db.subscribe(group);
|
db.subscribe(group);
|
||||||
db.subscribe(group); // Again - check listeners aren't called
|
db.subscribe(group); // Again - check listeners aren't called
|
||||||
assertEquals(Collections.singletonList(groupId), db.getSubscriptions());
|
assertEquals(Collections.singletonList(groupId), db.getSubscriptions());
|
||||||
db.unsubscribe(groupId);
|
db.unsubscribe(groupId);
|
||||||
db.unsubscribe(groupId); // Again - check listeners aren't called
|
db.unsubscribe(groupId); // Again - check listeners aren't called
|
||||||
|
db.setConnectionWindow(contactId, 123, connectionWindow);
|
||||||
db.removeContact(contactId);
|
db.removeContact(contactId);
|
||||||
db.removeListener(listener);
|
db.removeListener(listener);
|
||||||
db.close();
|
db.close();
|
||||||
@@ -472,11 +487,11 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Check whether the contact is still in the DB (which it's not)
|
// Check whether the contact is still in the DB (which it's not)
|
||||||
// once for each method
|
// once for each method
|
||||||
exactly(14).of(database).startTransaction();
|
exactly(16).of(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
exactly(14).of(database).containsContact(txn, contactId);
|
exactly(16).of(database).containsContact(txn, contactId);
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
exactly(14).of(database).commitTransaction(txn);
|
exactly(16).of(database).commitTransaction(txn);
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner);
|
DatabaseComponent db = createDatabaseComponent(database, cleaner);
|
||||||
|
|
||||||
@@ -516,6 +531,11 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
fail();
|
fail();
|
||||||
} catch(NoSuchContactException expected) {}
|
} catch(NoSuchContactException expected) {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
db.getConnectionWindow(contactId, 123);
|
||||||
|
fail();
|
||||||
|
} catch(NoSuchContactException expected) {}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
db.getTransports(contactId);
|
db.getTransports(contactId);
|
||||||
fail();
|
fail();
|
||||||
@@ -551,6 +571,11 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
fail();
|
fail();
|
||||||
} catch(NoSuchContactException expected) {}
|
} catch(NoSuchContactException expected) {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
db.setConnectionWindow(contactId, 123, null);
|
||||||
|
fail();
|
||||||
|
} catch(NoSuchContactException expected) {}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import org.junit.Test;
|
|||||||
|
|
||||||
public class ConnectionWindowImplTest extends TestCase {
|
public class ConnectionWindowImplTest extends TestCase {
|
||||||
|
|
||||||
|
private static final long MAX_32_BIT_UNSIGNED = 4294967295L; // 2^32 - 1
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWindowSliding() {
|
public void testWindowSliding() {
|
||||||
ConnectionWindowImpl w = new ConnectionWindowImpl(0L, 0);
|
ConnectionWindowImpl w = new ConnectionWindowImpl(0L, 0);
|
||||||
@@ -40,6 +42,13 @@ public class ConnectionWindowImplTest extends TestCase {
|
|||||||
w.setSeen(48);
|
w.setSeen(48);
|
||||||
fail();
|
fail();
|
||||||
} catch(IllegalArgumentException expected) {}
|
} catch(IllegalArgumentException expected) {}
|
||||||
|
w = new ConnectionWindowImpl(MAX_32_BIT_UNSIGNED - 1, 0);
|
||||||
|
// Values greater than 2^31 - 1 should never be allowed
|
||||||
|
w.setSeen(MAX_32_BIT_UNSIGNED);
|
||||||
|
try {
|
||||||
|
w.setSeen(MAX_32_BIT_UNSIGNED + 1);
|
||||||
|
fail();
|
||||||
|
} catch(IllegalArgumentException expected) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user