mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-17 13:19:52 +01:00
More DB support for private messages - needs unit tests.
This commit is contained in:
@@ -92,7 +92,7 @@ interface Database<T> {
|
|||||||
* <p>
|
* <p>
|
||||||
* Locking: messages write.
|
* Locking: messages write.
|
||||||
*/
|
*/
|
||||||
boolean addMessage(T txn, Message m) throws DbException;
|
boolean addGroupMessage(T txn, Message m) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Records a sent batch as needing to be acknowledged.
|
* Records a sent batch as needing to be acknowledged.
|
||||||
@@ -102,6 +102,14 @@ interface Database<T> {
|
|||||||
void addOutstandingBatch(T txn, ContactId c, BatchId b,
|
void addOutstandingBatch(T txn, ContactId c, BatchId b,
|
||||||
Collection<MessageId> sent) throws DbException;
|
Collection<MessageId> sent) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns false if the given message is already in the database. Otherwise
|
||||||
|
* stores the message and returns true.
|
||||||
|
* <p>
|
||||||
|
* Locking: contacts read, messages write.
|
||||||
|
*/
|
||||||
|
boolean addPrivateMessage(T txn, Message m, ContactId c) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscribes to the given group.
|
* Subscribes to the given group.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -360,8 +368,8 @@ interface Database<T> {
|
|||||||
/**
|
/**
|
||||||
* Removes a contact (and all associated state) from the database.
|
* Removes a contact (and all associated state) from the database.
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: contacts write, messageStatuses write, subscriptions write,
|
* Locking: contacts write, messages write, messageStatuses write,
|
||||||
* transports write.
|
* subscriptions write, transports write.
|
||||||
*/
|
*/
|
||||||
void removeContact(T txn, ContactId c) throws DbException;
|
void removeContact(T txn, ContactId c) throws DbException;
|
||||||
|
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ DatabaseCleaner.Callback {
|
|||||||
protected boolean storeGroupMessage(Txn txn, Message m, ContactId sender)
|
protected boolean storeGroupMessage(Txn txn, Message m, ContactId sender)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
if(m.getGroup() == null) throw new IllegalArgumentException();
|
if(m.getGroup() == null) throw new IllegalArgumentException();
|
||||||
boolean stored = db.addMessage(txn, m);
|
boolean stored = db.addGroupMessage(txn, m);
|
||||||
// Mark the message as seen by the sender
|
// Mark the message as seen by the sender
|
||||||
MessageId id = m.getId();
|
MessageId id = m.getId();
|
||||||
if(sender != null) db.setStatus(txn, sender, id, Status.SEEN);
|
if(sender != null) db.setStatus(txn, sender, id, Status.SEEN);
|
||||||
@@ -229,7 +229,7 @@ DatabaseCleaner.Callback {
|
|||||||
protected boolean storePrivateMessage(Txn txn, Message m, ContactId c,
|
protected boolean storePrivateMessage(Txn txn, Message m, ContactId c,
|
||||||
boolean incoming) throws DbException {
|
boolean incoming) throws DbException {
|
||||||
if(m.getGroup() != null) throw new IllegalArgumentException();
|
if(m.getGroup() != null) throw new IllegalArgumentException();
|
||||||
if(!db.addMessage(txn, m)) return false;
|
if(!db.addPrivateMessage(txn, m, c)) return false;
|
||||||
MessageId id = m.getId();
|
MessageId id = m.getId();
|
||||||
if(incoming) db.setStatus(txn, c, id, Status.SEEN);
|
if(incoming) db.setStatus(txn, c, id, Status.SEEN);
|
||||||
else db.setStatus(txn, c, id, Status.NEW);
|
else db.setStatus(txn, c, id, Status.NEW);
|
||||||
|
|||||||
@@ -49,6 +49,12 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " start BIGINT NOT NULL,"
|
+ " start BIGINT NOT NULL,"
|
||||||
+ " PRIMARY KEY (groupId))";
|
+ " PRIMARY KEY (groupId))";
|
||||||
|
|
||||||
|
private static final String CREATE_CONTACTS =
|
||||||
|
"CREATE TABLE contacts"
|
||||||
|
+ " (contactId INT NOT NULL,"
|
||||||
|
+ " secret BINARY NOT NULL,"
|
||||||
|
+ " PRIMARY KEY (contactId))";
|
||||||
|
|
||||||
private static final String CREATE_MESSAGES =
|
private static final String CREATE_MESSAGES =
|
||||||
"CREATE TABLE messages"
|
"CREATE TABLE messages"
|
||||||
+ " (messageId HASH NOT NULL,"
|
+ " (messageId HASH NOT NULL,"
|
||||||
@@ -58,9 +64,12 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " timestamp BIGINT NOT NULL,"
|
+ " timestamp BIGINT NOT NULL,"
|
||||||
+ " size INT NOT NULL,"
|
+ " size INT NOT NULL,"
|
||||||
+ " raw BLOB NOT NULL,"
|
+ " raw BLOB NOT NULL,"
|
||||||
+ " sendability INT NOT NULL,"
|
+ " sendability INT,"
|
||||||
|
+ " contactId INT,"
|
||||||
+ " PRIMARY KEY (messageId),"
|
+ " PRIMARY KEY (messageId),"
|
||||||
+ " FOREIGN KEY (groupId) REFERENCES subscriptions (groupId)"
|
+ " FOREIGN KEY (groupId) REFERENCES subscriptions (groupId)"
|
||||||
|
+ " ON DELETE CASCADE,"
|
||||||
|
+ " FOREIGN KEY (contactId) REFERENCES contacts (contactId)"
|
||||||
+ " ON DELETE CASCADE)";
|
+ " ON DELETE CASCADE)";
|
||||||
|
|
||||||
private static final String INDEX_MESSAGES_BY_PARENT =
|
private static final String INDEX_MESSAGES_BY_PARENT =
|
||||||
@@ -75,12 +84,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
private static final String INDEX_MESSAGES_BY_SENDABILITY =
|
private static final String INDEX_MESSAGES_BY_SENDABILITY =
|
||||||
"CREATE INDEX messagesBySendability ON messages (sendability)";
|
"CREATE INDEX messagesBySendability ON messages (sendability)";
|
||||||
|
|
||||||
private static final String CREATE_CONTACTS =
|
|
||||||
"CREATE TABLE contacts"
|
|
||||||
+ " (contactId INT NOT NULL,"
|
|
||||||
+ " secret BINARY NOT NULL,"
|
|
||||||
+ " PRIMARY KEY (contactId))";
|
|
||||||
|
|
||||||
private static final String CREATE_VISIBILITIES =
|
private static final String CREATE_VISIBILITIES =
|
||||||
"CREATE TABLE visibilities"
|
"CREATE TABLE visibilities"
|
||||||
+ " (groupId HASH NOT NULL,"
|
+ " (groupId HASH NOT NULL,"
|
||||||
@@ -278,12 +281,12 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
try {
|
try {
|
||||||
s = txn.createStatement();
|
s = txn.createStatement();
|
||||||
s.executeUpdate(insertTypeNames(CREATE_SUBSCRIPTIONS));
|
s.executeUpdate(insertTypeNames(CREATE_SUBSCRIPTIONS));
|
||||||
|
s.executeUpdate(insertTypeNames(CREATE_CONTACTS));
|
||||||
s.executeUpdate(insertTypeNames(CREATE_MESSAGES));
|
s.executeUpdate(insertTypeNames(CREATE_MESSAGES));
|
||||||
s.executeUpdate(INDEX_MESSAGES_BY_PARENT);
|
s.executeUpdate(INDEX_MESSAGES_BY_PARENT);
|
||||||
s.executeUpdate(INDEX_MESSAGES_BY_AUTHOR);
|
s.executeUpdate(INDEX_MESSAGES_BY_AUTHOR);
|
||||||
s.executeUpdate(INDEX_MESSAGES_BY_BIGINT);
|
s.executeUpdate(INDEX_MESSAGES_BY_BIGINT);
|
||||||
s.executeUpdate(INDEX_MESSAGES_BY_SENDABILITY);
|
s.executeUpdate(INDEX_MESSAGES_BY_SENDABILITY);
|
||||||
s.executeUpdate(insertTypeNames(CREATE_CONTACTS));
|
|
||||||
s.executeUpdate(insertTypeNames(CREATE_VISIBILITIES));
|
s.executeUpdate(insertTypeNames(CREATE_VISIBILITIES));
|
||||||
s.executeUpdate(INDEX_VISIBILITIES_BY_GROUP);
|
s.executeUpdate(INDEX_VISIBILITIES_BY_GROUP);
|
||||||
s.executeUpdate(insertTypeNames(CREATE_BATCHES_TO_ACK));
|
s.executeUpdate(insertTypeNames(CREATE_BATCHES_TO_ACK));
|
||||||
@@ -527,14 +530,16 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean addMessage(Connection txn, Message m) throws DbException {
|
public boolean addGroupMessage(Connection txn, Message m)
|
||||||
|
throws DbException {
|
||||||
|
assert m.getGroup() != null;
|
||||||
if(containsMessage(txn, m.getId())) return false;
|
if(containsMessage(txn, m.getId())) return false;
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
String sql = "INSERT INTO messages"
|
String sql = "INSERT INTO messages"
|
||||||
+ " (messageId, parentId, groupId, authorId, timestamp, size,"
|
+ " (messageId, parentId, groupId, authorId, timestamp, size,"
|
||||||
+ " raw, sendability)"
|
+ " raw, sendability)"
|
||||||
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ZERO())";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, m.getId().getBytes());
|
ps.setBytes(1, m.getId().getBytes());
|
||||||
if(m.getParent() == null) ps.setNull(2, Types.BINARY);
|
if(m.getParent() == null) ps.setNull(2, Types.BINARY);
|
||||||
@@ -546,7 +551,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.setInt(6, m.getSize());
|
ps.setInt(6, m.getSize());
|
||||||
byte[] raw = m.getBytes();
|
byte[] raw = m.getBytes();
|
||||||
ps.setBinaryStream(7, new ByteArrayInputStream(raw), raw.length);
|
ps.setBinaryStream(7, new ByteArrayInputStream(raw), raw.length);
|
||||||
ps.setInt(8, 0);
|
|
||||||
int affected = ps.executeUpdate();
|
int affected = ps.executeUpdate();
|
||||||
if(affected != 1) throw new DbStateException();
|
if(affected != 1) throw new DbStateException();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -616,6 +620,34 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean addPrivateMessage(Connection txn, Message m, ContactId c)
|
||||||
|
throws DbException {
|
||||||
|
assert m.getGroup() == null;
|
||||||
|
if(containsMessage(txn, m.getId())) return false;
|
||||||
|
PreparedStatement ps = null;
|
||||||
|
try {
|
||||||
|
String sql = "INSERT INTO messages"
|
||||||
|
+ " (messageId, parentId, timestamp, size, raw, contactId)"
|
||||||
|
+ " VALUES (?, ?, ?, ?, ?, ?)";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setBytes(1, m.getId().getBytes());
|
||||||
|
if(m.getParent() == null) ps.setNull(2, Types.BINARY);
|
||||||
|
else ps.setBytes(2, m.getParent().getBytes());
|
||||||
|
ps.setLong(3, m.getTimestamp());
|
||||||
|
ps.setInt(4, m.getSize());
|
||||||
|
byte[] raw = m.getBytes();
|
||||||
|
ps.setBinaryStream(5, new ByteArrayInputStream(raw), raw.length);
|
||||||
|
ps.setInt(6, c.getInt());
|
||||||
|
int affected = ps.executeUpdate();
|
||||||
|
if(affected != 1) throw new DbStateException();
|
||||||
|
ps.close();
|
||||||
|
return true;
|
||||||
|
} catch(SQLException e) {
|
||||||
|
tryToClose(ps);
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void addSubscription(Connection txn, Group g) throws DbException {
|
public void addSubscription(Connection txn, Group g) throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -909,28 +909,33 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Removing contact " + c);
|
if(LOG.isLoggable(Level.FINE)) LOG.fine("Removing contact " + c);
|
||||||
contactLock.writeLock().lock();
|
contactLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
messageStatusLock.writeLock().lock();
|
messageLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
subscriptionLock.writeLock().lock();
|
messageStatusLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
transportLock.writeLock().lock();
|
subscriptionLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
Txn txn = db.startTransaction();
|
transportLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
db.removeContact(txn, c);
|
Txn txn = db.startTransaction();
|
||||||
db.commitTransaction(txn);
|
try {
|
||||||
} catch(DbException e) {
|
db.removeContact(txn, c);
|
||||||
db.abortTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
throw e;
|
} catch(DbException e) {
|
||||||
|
db.abortTransaction(txn);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
transportLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
transportLock.writeLock().unlock();
|
subscriptionLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
subscriptionLock.writeLock().unlock();
|
messageStatusLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
messageStatusLock.writeLock().unlock();
|
messageLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
contactLock.writeLock().unlock();
|
contactLock.writeLock().unlock();
|
||||||
|
|||||||
@@ -689,16 +689,18 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
public void removeContact(ContactId c) throws DbException {
|
public void removeContact(ContactId c) throws DbException {
|
||||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Removing contact " + c);
|
if(LOG.isLoggable(Level.FINE)) LOG.fine("Removing contact " + c);
|
||||||
synchronized(contactLock) {
|
synchronized(contactLock) {
|
||||||
synchronized(messageStatusLock) {
|
synchronized(messageLock) {
|
||||||
synchronized(subscriptionLock) {
|
synchronized(messageStatusLock) {
|
||||||
synchronized(transportLock) {
|
synchronized(subscriptionLock) {
|
||||||
Txn txn = db.startTransaction();
|
synchronized(transportLock) {
|
||||||
try {
|
Txn txn = db.startTransaction();
|
||||||
db.removeContact(txn, c);
|
try {
|
||||||
db.commitTransaction(txn);
|
db.removeContact(txn, c);
|
||||||
} catch(DbException e) {
|
db.commitTransaction(txn);
|
||||||
db.abortTransaction(txn);
|
} catch(DbException e) {
|
||||||
throw e;
|
db.abortTransaction(txn);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -367,7 +367,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
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);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// addLocallyGeneratedMessage(message)
|
// addLocalGroupMessage(message)
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
oneOf(database).containsSubscription(txn, groupId, timestamp);
|
oneOf(database).containsSubscription(txn, groupId, timestamp);
|
||||||
@@ -388,12 +388,12 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
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);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// addLocallyGeneratedMessage(message)
|
// addLocalGroupMessage(message)
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
oneOf(database).containsSubscription(txn, groupId, timestamp);
|
oneOf(database).containsSubscription(txn, groupId, timestamp);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).addMessage(txn, message);
|
oneOf(database).addGroupMessage(txn, message);
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
}});
|
}});
|
||||||
@@ -405,18 +405,18 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddLocallyGeneratedMessage() throws DbException {
|
public void testAddLocalGroupMessage() throws DbException {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
@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);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// addLocallyGeneratedMessage(message)
|
// addLocalGroupMessage(message)
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
oneOf(database).containsSubscription(txn, groupId, timestamp);
|
oneOf(database).containsSubscription(txn, groupId, timestamp);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).addMessage(txn, message);
|
oneOf(database).addGroupMessage(txn, message);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).getContacts(txn);
|
oneOf(database).getContacts(txn);
|
||||||
will(returnValue(Collections.singletonList(contactId)));
|
will(returnValue(Collections.singletonList(contactId)));
|
||||||
@@ -444,12 +444,12 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
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);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// addLocallyGeneratedMessage(message)
|
// addLocalGroupMessage(message)
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
oneOf(database).containsSubscription(txn, groupId, timestamp);
|
oneOf(database).containsSubscription(txn, groupId, timestamp);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).addMessage(txn, message);
|
oneOf(database).addGroupMessage(txn, message);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).getContacts(txn);
|
oneOf(database).getContacts(txn);
|
||||||
will(returnValue(Collections.singletonList(contactId)));
|
will(returnValue(Collections.singletonList(contactId)));
|
||||||
@@ -896,7 +896,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
contactId, timestamp);
|
contactId, timestamp);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
// The message is stored, but it's a duplicate
|
// The message is stored, but it's a duplicate
|
||||||
oneOf(database).addMessage(txn, message);
|
oneOf(database).addGroupMessage(txn, message);
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
oneOf(database).setStatus(txn, contactId, messageId, Status.SEEN);
|
oneOf(database).setStatus(txn, contactId, messageId, Status.SEEN);
|
||||||
// The batch needs to be acknowledged
|
// The batch needs to be acknowledged
|
||||||
@@ -931,7 +931,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
contactId, timestamp);
|
contactId, timestamp);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
// The message is stored, and it's not a duplicate
|
// The message is stored, and it's not a duplicate
|
||||||
oneOf(database).addMessage(txn, message);
|
oneOf(database).addGroupMessage(txn, message);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).setStatus(txn, contactId, messageId, Status.SEEN);
|
oneOf(database).setStatus(txn, contactId, messageId, Status.SEEN);
|
||||||
// Set the status to NEW for all other contacts (there are none)
|
// Set the status to NEW for all other contacts (there are none)
|
||||||
@@ -975,7 +975,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
contactId, timestamp);
|
contactId, timestamp);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
// The message is stored, and it's not a duplicate
|
// The message is stored, and it's not a duplicate
|
||||||
oneOf(database).addMessage(txn, message);
|
oneOf(database).addGroupMessage(txn, message);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).setStatus(txn, contactId, messageId, Status.SEEN);
|
oneOf(database).setStatus(txn, contactId, messageId, Status.SEEN);
|
||||||
// Set the status to NEW for all other contacts (there are none)
|
// Set the status to NEW for all other contacts (there are none)
|
||||||
@@ -1110,12 +1110,12 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||||
final DatabaseListener listener = context.mock(DatabaseListener.class);
|
final DatabaseListener listener = context.mock(DatabaseListener.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// addLocallyGeneratedMessage(message)
|
// addLocalGroupMessage(message)
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
oneOf(database).containsSubscription(txn, groupId, timestamp);
|
oneOf(database).containsSubscription(txn, groupId, timestamp);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).addMessage(txn, message);
|
oneOf(database).addGroupMessage(txn, message);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).getContacts(txn);
|
oneOf(database).getContacts(txn);
|
||||||
will(returnValue(Collections.singletonList(contactId)));
|
will(returnValue(Collections.singletonList(contactId)));
|
||||||
@@ -1145,12 +1145,12 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
||||||
final DatabaseListener listener = context.mock(DatabaseListener.class);
|
final DatabaseListener listener = context.mock(DatabaseListener.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// addLocallyGeneratedMessage(message)
|
// addLocalGroupMessage(message)
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
oneOf(database).containsSubscription(txn, groupId, timestamp);
|
oneOf(database).containsSubscription(txn, groupId, timestamp);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).addMessage(txn, message);
|
oneOf(database).addGroupMessage(txn, message);
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
// The message was not added, so the listener should not be called
|
// The message was not added, so the listener should not be called
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
assertTrue(db.containsSubscription(txn, groupId));
|
assertTrue(db.containsSubscription(txn, groupId));
|
||||||
assertFalse(db.containsMessage(txn, messageId));
|
assertFalse(db.containsMessage(txn, messageId));
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
assertTrue(db.containsMessage(txn, messageId));
|
assertTrue(db.containsMessage(txn, messageId));
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
db.close();
|
db.close();
|
||||||
@@ -195,7 +195,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
|
|
||||||
// Subscribe to a group and store a message
|
// Subscribe to a group and store a message
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
|
|
||||||
// Unsubscribing from the group should delete the message
|
// Unsubscribing from the group should delete the message
|
||||||
assertTrue(db.containsMessage(txn, messageId));
|
assertTrue(db.containsMessage(txn, messageId));
|
||||||
@@ -216,7 +216,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
db.setStatus(txn, contactId, messageId, Status.NEW);
|
db.setStatus(txn, contactId, messageId, Status.NEW);
|
||||||
|
|
||||||
// The message should not be sendable
|
// The message should not be sendable
|
||||||
@@ -254,7 +254,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
db.setSendability(txn, messageId, 1);
|
db.setSendability(txn, messageId, 1);
|
||||||
|
|
||||||
// The message has no status yet, so it should not be sendable
|
// The message has no status yet, so it should not be sendable
|
||||||
@@ -295,7 +295,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
assertEquals(contactId, db.addContact(txn, transports, secret));
|
assertEquals(contactId, db.addContact(txn, transports, secret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
db.setSendability(txn, messageId, 1);
|
db.setSendability(txn, messageId, 1);
|
||||||
db.setStatus(txn, contactId, messageId, Status.NEW);
|
db.setStatus(txn, contactId, messageId, Status.NEW);
|
||||||
|
|
||||||
@@ -334,7 +334,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
assertEquals(contactId, db.addContact(txn, transports, secret));
|
assertEquals(contactId, db.addContact(txn, transports, secret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
db.setSendability(txn, messageId, 1);
|
db.setSendability(txn, messageId, 1);
|
||||||
db.setStatus(txn, contactId, messageId, Status.NEW);
|
db.setStatus(txn, contactId, messageId, Status.NEW);
|
||||||
|
|
||||||
@@ -370,7 +370,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
db.setSendability(txn, messageId, 1);
|
db.setSendability(txn, messageId, 1);
|
||||||
db.setStatus(txn, contactId, messageId, Status.NEW);
|
db.setStatus(txn, contactId, messageId, Status.NEW);
|
||||||
|
|
||||||
@@ -400,7 +400,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
assertEquals(contactId, db.addContact(txn, transports, secret));
|
assertEquals(contactId, db.addContact(txn, transports, secret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
db.setSendability(txn, messageId, 1);
|
db.setSendability(txn, messageId, 1);
|
||||||
db.setStatus(txn, contactId, messageId, Status.NEW);
|
db.setStatus(txn, contactId, messageId, Status.NEW);
|
||||||
|
|
||||||
@@ -485,7 +485,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, transports, secret));
|
assertEquals(contactId, db.addContact(txn, transports, secret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
|
|
||||||
// Add an outstanding batch
|
// Add an outstanding batch
|
||||||
db.addOutstandingBatch(txn, contactId, batchId,
|
db.addOutstandingBatch(txn, contactId, batchId,
|
||||||
@@ -511,7 +511,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
assertEquals(contactId, db.addContact(txn, transports, secret));
|
assertEquals(contactId, db.addContact(txn, transports, secret));
|
||||||
ContactId contactId1 = db.addContact(txn, transports, secret);
|
ContactId contactId1 = db.addContact(txn, transports, secret);
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
|
|
||||||
// Add an outstanding batch for the first contact
|
// Add an outstanding batch for the first contact
|
||||||
db.addOutstandingBatch(txn, contactId, batchId,
|
db.addOutstandingBatch(txn, contactId, batchId,
|
||||||
@@ -535,7 +535,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
db.setSendability(txn, messageId, 1);
|
db.setSendability(txn, messageId, 1);
|
||||||
db.setStatus(txn, contactId, messageId, Status.NEW);
|
db.setStatus(txn, contactId, messageId, Status.NEW);
|
||||||
|
|
||||||
@@ -572,7 +572,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
db.setSendability(txn, messageId, 1);
|
db.setSendability(txn, messageId, 1);
|
||||||
db.setStatus(txn, contactId, messageId, Status.NEW);
|
db.setStatus(txn, contactId, messageId, Status.NEW);
|
||||||
|
|
||||||
@@ -682,8 +682,8 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
|
|
||||||
// Subscribe to a group and store two messages
|
// Subscribe to a group and store two messages
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
db.addMessage(txn, message1);
|
db.addGroupMessage(txn, message1);
|
||||||
|
|
||||||
// Check that each message is retrievable via its author
|
// Check that each message is retrievable via its author
|
||||||
Iterator<MessageId> it =
|
Iterator<MessageId> it =
|
||||||
@@ -721,10 +721,10 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
// Subscribe to the groups and store the messages
|
// Subscribe to the groups and store the messages
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.addSubscription(txn, group1);
|
db.addSubscription(txn, group1);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
db.addMessage(txn, child1);
|
db.addGroupMessage(txn, child1);
|
||||||
db.addMessage(txn, child2);
|
db.addGroupMessage(txn, child2);
|
||||||
db.addMessage(txn, child3);
|
db.addGroupMessage(txn, child3);
|
||||||
// Make all the children sendable
|
// Make all the children sendable
|
||||||
db.setSendability(txn, childId1, 1);
|
db.setSendability(txn, childId1, 1);
|
||||||
db.setSendability(txn, childId2, 5);
|
db.setSendability(txn, childId2, 5);
|
||||||
@@ -751,8 +751,8 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
|
|
||||||
// Subscribe to a group and store two messages
|
// Subscribe to a group and store two messages
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
db.addMessage(txn, message1);
|
db.addGroupMessage(txn, message1);
|
||||||
|
|
||||||
// Allowing enough capacity for one message should return the older one
|
// Allowing enough capacity for one message should return the older one
|
||||||
Iterator<MessageId> it = db.getOldMessages(txn, size).iterator();
|
Iterator<MessageId> it = db.getOldMessages(txn, size).iterator();
|
||||||
@@ -789,7 +789,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
// Storing a message should reduce the free space
|
// Storing a message should reduce the free space
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.addMessage(txn, message1);
|
db.addGroupMessage(txn, message1);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
assertTrue(db.getFreeSpace() < free);
|
assertTrue(db.getFreeSpace() < free);
|
||||||
|
|
||||||
@@ -1036,7 +1036,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
assertEquals(contactId, db.addContact(txn, transports, secret));
|
assertEquals(contactId, db.addContact(txn, transports, secret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
// Set the sendability to > 0
|
// Set the sendability to > 0
|
||||||
db.setSendability(txn, messageId, 1);
|
db.setSendability(txn, messageId, 1);
|
||||||
// Set the status to SEEN
|
// Set the status to SEEN
|
||||||
@@ -1059,7 +1059,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
assertEquals(contactId, db.addContact(txn, transports, secret));
|
assertEquals(contactId, db.addContact(txn, transports, secret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
// Set the sendability to 0
|
// Set the sendability to 0
|
||||||
db.setSendability(txn, messageId, 0);
|
db.setSendability(txn, messageId, 0);
|
||||||
// Set the status to NEW
|
// Set the status to NEW
|
||||||
@@ -1084,7 +1084,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
// The message is older than the contact's subscription
|
// The message is older than the contact's subscription
|
||||||
Map<Group, Long> subs = Collections.singletonMap(group, timestamp + 1);
|
Map<Group, Long> subs = Collections.singletonMap(group, timestamp + 1);
|
||||||
db.setSubscriptions(txn, contactId, subs, 1);
|
db.setSubscriptions(txn, contactId, subs, 1);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
// Set the sendability to > 0
|
// Set the sendability to > 0
|
||||||
db.setSendability(txn, messageId, 1);
|
db.setSendability(txn, messageId, 1);
|
||||||
// Set the status to NEW
|
// Set the status to NEW
|
||||||
@@ -1107,7 +1107,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
// Set the sendability to > 0
|
// Set the sendability to > 0
|
||||||
db.setSendability(txn, messageId, 1);
|
db.setSendability(txn, messageId, 1);
|
||||||
// Set the status to NEW
|
// Set the status to NEW
|
||||||
@@ -1166,7 +1166,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, transports, secret));
|
assertEquals(contactId, db.addContact(txn, transports, secret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
db.setStatus(txn, contactId, messageId, Status.NEW);
|
db.setStatus(txn, contactId, messageId, Status.NEW);
|
||||||
|
|
||||||
// There's no contact subscription for the group
|
// There's no contact subscription for the group
|
||||||
@@ -1185,7 +1185,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
assertEquals(contactId, db.addContact(txn, transports, secret));
|
assertEquals(contactId, db.addContact(txn, transports, secret));
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
db.setStatus(txn, contactId, messageId, Status.NEW);
|
db.setStatus(txn, contactId, messageId, Status.NEW);
|
||||||
|
|
||||||
@@ -1207,7 +1207,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
// The message has already been seen by the contact
|
// The message has already been seen by the contact
|
||||||
db.setStatus(txn, contactId, messageId, Status.SEEN);
|
db.setStatus(txn, contactId, messageId, Status.SEEN);
|
||||||
|
|
||||||
@@ -1228,7 +1228,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
db.setVisibility(txn, groupId, Collections.singleton(contactId));
|
||||||
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
db.setSubscriptions(txn, contactId, subscriptions, 1);
|
||||||
db.addMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
// The message has not been seen by the contact
|
// The message has not been seen by the contact
|
||||||
db.setStatus(txn, contactId, messageId, Status.NEW);
|
db.setStatus(txn, contactId, messageId, Status.NEW);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user