Unshared messages.

This commit is contained in:
akwizgran
2016-01-29 13:22:56 +00:00
parent 062b987585
commit e76aef3dc8
13 changed files with 271 additions and 126 deletions

View File

@@ -56,7 +56,7 @@ public interface DatabaseComponent {
void addLocalAuthor(LocalAuthor a) throws DbException; void addLocalAuthor(LocalAuthor a) throws DbException;
/** Stores a local message. */ /** Stores a local message. */
void addLocalMessage(Message m, ClientId c, Metadata meta) void addLocalMessage(Message m, ClientId c, Metadata meta, boolean shared)
throws DbException; throws DbException;
/** /**
@@ -277,8 +277,11 @@ public interface DatabaseComponent {
void setLocalAuthorStatus(AuthorId a, StorageStatus s) void setLocalAuthorStatus(AuthorId a, StorageStatus s)
throws DbException; throws DbException;
/** Marks the given message as shared or unshared. */
void setMessageShared(Message m, boolean shared) throws DbException;
/** Marks the given message as valid or invalid. */ /** Marks the given message as valid or invalid. */
void setMessageValidity(Message m, ClientId c, boolean valid) void setMessageValid(Message m, ClientId c, boolean valid)
throws DbException; throws DbException;
/** /**

View File

@@ -0,0 +1,17 @@
package org.briarproject.api.event;
import org.briarproject.api.sync.Message;
/** An event that is broadcast when a message is shared. */
public class MessageSharedEvent extends Event {
private final Message message;
public MessageSharedEvent(Message message) {
this.message = message;
}
public Message getMessage() {
return message;
}
}

View File

@@ -6,13 +6,13 @@ package org.briarproject.api.sync;
*/ */
public interface ValidationManager { public interface ValidationManager {
enum Status { enum Validity {
UNKNOWN(0), INVALID(1), VALID(2); UNKNOWN(0), INVALID(1), VALID(2);
private final int value; private final int value;
Status(int value) { Validity(int value) {
this.value = value; this.value = value;
} }
@@ -20,8 +20,8 @@ public interface ValidationManager {
return value; return value;
} }
public static Status fromValue(int value) { public static Validity fromValue(int value) {
for (Status s : values()) if (s.value == value) return s; for (Validity s : values()) if (s.value == value) return s;
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
} }

View File

@@ -19,6 +19,7 @@ import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.MessageStatus; import org.briarproject.api.sync.MessageStatus;
import org.briarproject.api.sync.SubscriptionAck; import org.briarproject.api.sync.SubscriptionAck;
import org.briarproject.api.sync.SubscriptionUpdate; import org.briarproject.api.sync.SubscriptionUpdate;
import org.briarproject.api.sync.ValidationManager.Validity;
import org.briarproject.api.transport.TransportKeys; import org.briarproject.api.transport.TransportKeys;
import java.io.IOException; import java.io.IOException;
@@ -111,7 +112,8 @@ interface Database<T> {
* <p> * <p>
* Locking: write. * Locking: write.
*/ */
void addMessage(T txn, Message m, boolean local) throws DbException; void addMessage(T txn, Message m, Validity validity, boolean shared)
throws DbException;
/** /**
* Records that a message has been offered by the given contact. * Records that a message has been offered by the given contact.
@@ -617,13 +619,20 @@ interface Database<T> {
void setLocalAuthorStatus(T txn, AuthorId a, StorageStatus s) void setLocalAuthorStatus(T txn, AuthorId a, StorageStatus s)
throws DbException; throws DbException;
/**
* Marks the given message as shared or unshared.
* <p>
* Locking: write.
*/
void setMessageShared(T txn, MessageId m, boolean shared)
throws DbException;
/** /**
* Marks the given message as valid or invalid. * Marks the given message as valid or invalid.
* <p> * <p>
* Locking: write. * Locking: write.
*/ */
void setMessageValidity(T txn, MessageId m, boolean valid) void setMessageValid(T txn, MessageId m, boolean valid) throws DbException;
throws DbException;
/** /**
* Sets the reordering window for the given contact and transport in the * Sets the reordering window for the given contact and transport in the

View File

@@ -20,6 +20,7 @@ import org.briarproject.api.event.EventBus;
import org.briarproject.api.event.LocalSubscriptionsUpdatedEvent; import org.briarproject.api.event.LocalSubscriptionsUpdatedEvent;
import org.briarproject.api.event.MessageAddedEvent; import org.briarproject.api.event.MessageAddedEvent;
import org.briarproject.api.event.MessageRequestedEvent; import org.briarproject.api.event.MessageRequestedEvent;
import org.briarproject.api.event.MessageSharedEvent;
import org.briarproject.api.event.MessageToAckEvent; import org.briarproject.api.event.MessageToAckEvent;
import org.briarproject.api.event.MessageToRequestEvent; import org.briarproject.api.event.MessageToRequestEvent;
import org.briarproject.api.event.MessageValidatedEvent; import org.briarproject.api.event.MessageValidatedEvent;
@@ -47,6 +48,7 @@ import org.briarproject.api.sync.Offer;
import org.briarproject.api.sync.Request; import org.briarproject.api.sync.Request;
import org.briarproject.api.sync.SubscriptionAck; import org.briarproject.api.sync.SubscriptionAck;
import org.briarproject.api.sync.SubscriptionUpdate; import org.briarproject.api.sync.SubscriptionUpdate;
import org.briarproject.api.sync.ValidationManager.Validity;
import org.briarproject.api.transport.TransportKeys; import org.briarproject.api.transport.TransportKeys;
import java.io.IOException; import java.io.IOException;
@@ -64,6 +66,8 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.api.sync.ValidationManager.Validity.UNKNOWN;
import static org.briarproject.api.sync.ValidationManager.Validity.VALID;
import static org.briarproject.db.DatabaseConstants.MAX_OFFERED_MESSAGES; import static org.briarproject.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
/** /**
@@ -214,8 +218,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
} }
} }
public void addLocalMessage(Message m, ClientId c, Metadata meta) public void addLocalMessage(Message m, ClientId c, Metadata meta,
throws DbException { boolean shared) throws DbException {
lock.writeLock().lock(); lock.writeLock().lock();
try { try {
T txn = db.startTransaction(); T txn = db.startTransaction();
@@ -224,7 +228,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
throw new MessageExistsException(); throw new MessageExistsException();
if (!db.containsGroup(txn, m.getGroupId())) if (!db.containsGroup(txn, m.getGroupId()))
throw new NoSuchSubscriptionException(); throw new NoSuchSubscriptionException();
addMessage(txn, m, null); addMessage(txn, m, VALID, shared, null);
db.mergeMessageMetadata(txn, m.getId(), meta); db.mergeMessageMetadata(txn, m.getId(), meta);
db.commitTransaction(txn); db.commitTransaction(txn);
} catch (DbException e) { } catch (DbException e) {
@@ -244,9 +248,9 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
* Locking: write. * Locking: write.
* @param sender null for a locally generated message. * @param sender null for a locally generated message.
*/ */
private void addMessage(T txn, Message m, ContactId sender) private void addMessage(T txn, Message m, Validity validity, boolean shared,
throws DbException { ContactId sender) throws DbException {
db.addMessage(txn, m, sender == null); db.addMessage(txn, m, validity, shared);
GroupId g = m.getGroupId(); GroupId g = m.getGroupId();
Collection<ContactId> visibility = db.getVisibility(txn, g); Collection<ContactId> visibility = db.getVisibility(txn, g);
visibility = new HashSet<ContactId>(visibility); visibility = new HashSet<ContactId>(visibility);
@@ -982,7 +986,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
duplicate = db.containsMessage(txn, m.getId()); duplicate = db.containsMessage(txn, m.getId());
visible = db.containsVisibleGroup(txn, c, m.getGroupId()); visible = db.containsVisibleGroup(txn, c, m.getGroupId());
if (visible) { if (visible) {
if (!duplicate) addMessage(txn, m, c); if (!duplicate) addMessage(txn, m, UNKNOWN, true, c);
db.raiseAckFlag(txn, c, m.getId()); db.raiseAckFlag(txn, c, m.getId());
} }
db.commitTransaction(txn); db.commitTransaction(txn);
@@ -1214,7 +1218,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
} }
} }
public void setMessageValidity(Message m, ClientId c, boolean valid) public void setMessageShared(Message m, boolean shared)
throws DbException { throws DbException {
lock.writeLock().lock(); lock.writeLock().lock();
try { try {
@@ -1222,7 +1226,27 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
try { try {
if (!db.containsMessage(txn, m.getId())) if (!db.containsMessage(txn, m.getId()))
throw new NoSuchMessageException(); throw new NoSuchMessageException();
db.setMessageValidity(txn, m.getId(), valid); db.setMessageShared(txn, m.getId(), shared);
db.commitTransaction(txn);
} catch (DbException e) {
db.abortTransaction(txn);
throw e;
}
} finally {
lock.writeLock().unlock();
}
if (shared) eventBus.broadcast(new MessageSharedEvent(m));
}
public void setMessageValid(Message m, ClientId c, boolean valid)
throws DbException {
lock.writeLock().lock();
try {
T txn = db.startTransaction();
try {
if (!db.containsMessage(txn, m.getId()))
throw new NoSuchMessageException();
db.setMessageValid(txn, m.getId(), valid);
db.commitTransaction(txn); db.commitTransaction(txn);
} catch (DbException e) { } catch (DbException e) {
db.abortTransaction(txn); db.abortTransaction(txn);

View File

@@ -22,6 +22,7 @@ import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.MessageStatus; import org.briarproject.api.sync.MessageStatus;
import org.briarproject.api.sync.SubscriptionAck; import org.briarproject.api.sync.SubscriptionAck;
import org.briarproject.api.sync.SubscriptionUpdate; import org.briarproject.api.sync.SubscriptionUpdate;
import org.briarproject.api.sync.ValidationManager.Validity;
import org.briarproject.api.system.Clock; import org.briarproject.api.system.Clock;
import org.briarproject.api.transport.IncomingKeys; import org.briarproject.api.transport.IncomingKeys;
import org.briarproject.api.transport.OutgoingKeys; import org.briarproject.api.transport.OutgoingKeys;
@@ -54,9 +55,9 @@ import static java.util.logging.Level.WARNING;
import static org.briarproject.api.db.Metadata.REMOVE; import static org.briarproject.api.db.Metadata.REMOVE;
import static org.briarproject.api.db.StorageStatus.ADDING; import static org.briarproject.api.db.StorageStatus.ADDING;
import static org.briarproject.api.sync.SyncConstants.MAX_SUBSCRIPTIONS; import static org.briarproject.api.sync.SyncConstants.MAX_SUBSCRIPTIONS;
import static org.briarproject.api.sync.ValidationManager.Status.INVALID; import static org.briarproject.api.sync.ValidationManager.Validity.INVALID;
import static org.briarproject.api.sync.ValidationManager.Status.UNKNOWN; import static org.briarproject.api.sync.ValidationManager.Validity.UNKNOWN;
import static org.briarproject.api.sync.ValidationManager.Status.VALID; import static org.briarproject.api.sync.ValidationManager.Validity.VALID;
import static org.briarproject.db.DatabaseConstants.DB_SETTINGS_NAMESPACE; import static org.briarproject.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
import static org.briarproject.db.DatabaseConstants.DEVICE_ID_KEY; import static org.briarproject.db.DatabaseConstants.DEVICE_ID_KEY;
import static org.briarproject.db.DatabaseConstants.DEVICE_SETTINGS_NAMESPACE; import static org.briarproject.db.DatabaseConstants.DEVICE_SETTINGS_NAMESPACE;
@@ -70,8 +71,8 @@ import static org.briarproject.db.ExponentialBackoff.calculateExpiry;
*/ */
abstract class JdbcDatabase implements Database<Connection> { abstract class JdbcDatabase implements Database<Connection> {
private static final int SCHEMA_VERSION = 18; private static final int SCHEMA_VERSION = 19;
private static final int MIN_SCHEMA_VERSION = 18; private static final int MIN_SCHEMA_VERSION = 19;
private static final String CREATE_SETTINGS = private static final String CREATE_SETTINGS =
"CREATE TABLE settings" "CREATE TABLE settings"
@@ -164,8 +165,8 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " (messageId HASH NOT NULL," + " (messageId HASH NOT NULL,"
+ " groupId HASH NOT NULL," + " groupId HASH NOT NULL,"
+ " timestamp BIGINT NOT NULL," + " timestamp BIGINT NOT NULL,"
+ " local BOOLEAN NOT NULL,"
+ " valid INT NOT NULL," + " valid INT NOT NULL,"
+ " shared BOOLEAN NOT NULL,"
+ " length INT NOT NULL," + " length INT NOT NULL,"
+ " raw BLOB NOT NULL," + " raw BLOB NOT NULL,"
+ " PRIMARY KEY (messageId)," + " PRIMARY KEY (messageId),"
@@ -674,19 +675,19 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
public void addMessage(Connection txn, Message m, boolean local) public void addMessage(Connection txn, Message m, Validity validity,
throws DbException { boolean shared) throws DbException {
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {
String sql = "INSERT INTO messages (messageId, groupId, timestamp," String sql = "INSERT INTO messages (messageId, groupId, timestamp,"
+ " local, valid, length, raw)" + " valid, shared, length, raw)"
+ " VALUES (?, ?, ?, ?, ?, ?, ?)"; + " VALUES (?, ?, ?, ?, ?, ?, ?)";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, m.getId().getBytes()); ps.setBytes(1, m.getId().getBytes());
ps.setBytes(2, m.getGroupId().getBytes()); ps.setBytes(2, m.getGroupId().getBytes());
ps.setLong(3, m.getTimestamp()); ps.setLong(3, m.getTimestamp());
ps.setBoolean(4, local); ps.setInt(4, validity.getValue());
ps.setInt(5, local ? VALID.getValue() : UNKNOWN.getValue()); ps.setBoolean(5, shared);
byte[] raw = m.getRaw(); byte[] raw = m.getRaw();
ps.setInt(6, raw.length); ps.setInt(6, raw.length);
ps.setBytes(7, raw); ps.setBytes(7, raw);
@@ -1031,7 +1032,8 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " JOIN groupVisibilities AS gv" + " JOIN groupVisibilities AS gv"
+ " ON m.groupId = gv.groupId" + " ON m.groupId = gv.groupId"
+ " WHERE messageId = ?" + " WHERE messageId = ?"
+ " AND contactId = ?"; + " AND contactId = ?"
+ " AND shared = TRUE";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, m.getBytes()); ps.setBytes(1, m.getBytes());
ps.setInt(2, c.getInt()); ps.setInt(2, c.getInt());
@@ -1482,7 +1484,7 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " ON m.messageId = s.messageId" + " ON m.messageId = s.messageId"
+ " AND cg.contactId = s.contactId" + " AND cg.contactId = s.contactId"
+ " WHERE cg.contactId = ?" + " WHERE cg.contactId = ?"
+ " AND valid = ?" + " AND valid = ? AND shared = TRUE"
+ " AND seen = FALSE AND requested = FALSE" + " AND seen = FALSE AND requested = FALSE"
+ " AND s.expiry < ?" + " AND s.expiry < ?"
+ " ORDER BY timestamp DESC LIMIT ?"; + " ORDER BY timestamp DESC LIMIT ?";
@@ -1544,7 +1546,7 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " ON m.messageId = s.messageId" + " ON m.messageId = s.messageId"
+ " AND cg.contactId = s.contactId" + " AND cg.contactId = s.contactId"
+ " WHERE cg.contactId = ?" + " WHERE cg.contactId = ?"
+ " AND valid = ?" + " AND valid = ? AND shared = TRUE"
+ " AND seen = FALSE" + " AND seen = FALSE"
+ " AND s.expiry < ?" + " AND s.expiry < ?"
+ " ORDER BY timestamp DESC"; + " ORDER BY timestamp DESC";
@@ -1633,7 +1635,7 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " ON m.messageId = s.messageId" + " ON m.messageId = s.messageId"
+ " AND cg.contactId = s.contactId" + " AND cg.contactId = s.contactId"
+ " WHERE cg.contactId = ?" + " WHERE cg.contactId = ?"
+ " AND valid = ?" + " AND valid = ? AND shared = TRUE"
+ " AND seen = FALSE AND requested = TRUE" + " AND seen = FALSE AND requested = TRUE"
+ " AND s.expiry < ?" + " AND s.expiry < ?"
+ " ORDER BY timestamp DESC"; + " ORDER BY timestamp DESC";
@@ -1660,7 +1662,8 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
public Settings getSettings(Connection txn, String namespace) throws DbException { public Settings getSettings(Connection txn, String namespace)
throws DbException {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
@@ -2397,7 +2400,24 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
public void setMessageValidity(Connection txn, MessageId m, boolean valid) public void setMessageShared(Connection txn, MessageId m, boolean shared)
throws DbException {
PreparedStatement ps = null;
try {
String sql = "UPDATE messages SET shared = ? WHERE messageId = ?";
ps = txn.prepareStatement(sql);
ps.setBoolean(1, shared);
ps.setBytes(2, m.getBytes());
int affected = ps.executeUpdate();
if (affected < 0) throw new DbStateException();
ps.close();
} catch (SQLException e) {
tryToClose(ps);
throw new DbException(e);
}
}
public void setMessageValid(Connection txn, MessageId m, boolean valid)
throws DbException { throws DbException {
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {

View File

@@ -135,7 +135,7 @@ class ForumManagerImpl implements ForumManager {
d.put("read", true); d.put("read", true);
try { try {
Metadata meta = metadataEncoder.encode(d); Metadata meta = metadataEncoder.encode(d);
db.addLocalMessage(p.getMessage(), CLIENT_ID, meta); db.addLocalMessage(p.getMessage(), CLIENT_ID, meta, true);
} catch (FormatException e) { } catch (FormatException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} }

View File

@@ -116,7 +116,7 @@ class MessagingManagerImpl implements MessagingManager, AddContactHook,
d.put("read", true); d.put("read", true);
try { try {
Metadata meta = metadataEncoder.encode(d); Metadata meta = metadataEncoder.encode(d);
db.addLocalMessage(m.getMessage(), CLIENT_ID, meta); db.addLocalMessage(m.getMessage(), CLIENT_ID, meta, true);
} catch (FormatException e) { } catch (FormatException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

View File

@@ -130,7 +130,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
d.put("transportId", t.getString()); d.put("transportId", t.getString());
d.put("version", version); d.put("version", version);
d.put("local", true); d.put("local", true);
db.addLocalMessage(m, CLIENT_ID, metadataEncoder.encode(d)); db.addLocalMessage(m, CLIENT_ID, metadataEncoder.encode(d), true);
} }
private byte[] encodeProperties(DeviceId dev, TransportId t, private byte[] encodeProperties(DeviceId dev, TransportId t,

View File

@@ -10,6 +10,7 @@ import org.briarproject.api.event.EventBus;
import org.briarproject.api.event.EventListener; import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.LocalSubscriptionsUpdatedEvent; import org.briarproject.api.event.LocalSubscriptionsUpdatedEvent;
import org.briarproject.api.event.MessageRequestedEvent; import org.briarproject.api.event.MessageRequestedEvent;
import org.briarproject.api.event.MessageSharedEvent;
import org.briarproject.api.event.MessageToAckEvent; import org.briarproject.api.event.MessageToAckEvent;
import org.briarproject.api.event.MessageToRequestEvent; import org.briarproject.api.event.MessageToRequestEvent;
import org.briarproject.api.event.MessageValidatedEvent; import org.briarproject.api.event.MessageValidatedEvent;
@@ -154,6 +155,8 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
if (e instanceof ContactRemovedEvent) { if (e instanceof ContactRemovedEvent) {
ContactRemovedEvent c = (ContactRemovedEvent) e; ContactRemovedEvent c = (ContactRemovedEvent) e;
if (c.getContactId().equals(contactId)) interrupt(); if (c.getContactId().equals(contactId)) interrupt();
} else if (e instanceof MessageSharedEvent) {
dbExecutor.execute(new GenerateOffer());
} else if (e instanceof MessageValidatedEvent) { } else if (e instanceof MessageValidatedEvent) {
if (((MessageValidatedEvent) e).isValid()) if (((MessageValidatedEvent) e).isValid())
dbExecutor.execute(new GenerateOffer()); dbExecutor.execute(new GenerateOffer());

View File

@@ -117,10 +117,10 @@ class ValidationManagerImpl implements ValidationManager, Service,
public void run() { public void run() {
try { try {
if (meta == null) { if (meta == null) {
db.setMessageValidity(m, c, false); db.setMessageValid(m, c, false);
} else { } else {
db.mergeMessageMetadata(m.getId(), meta); db.mergeMessageMetadata(m.getId(), meta);
db.setMessageValidity(m, c, true); db.setMessageValid(m, c, true);
} }
} catch (NoSuchMessageException e) { } catch (NoSuchMessageException e) {
LOG.info("Message removed during validation"); LOG.info("Message removed during validation");

View File

@@ -53,6 +53,8 @@ import java.util.Collections;
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH; import static org.briarproject.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
import static org.briarproject.api.sync.ValidationManager.Validity.UNKNOWN;
import static org.briarproject.api.sync.ValidationManager.Validity.VALID;
import static org.briarproject.db.DatabaseConstants.MAX_OFFERED_MESSAGES; import static org.briarproject.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
@@ -211,7 +213,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
shutdown); shutdown);
try { try {
db.addLocalMessage(message, clientId, metadata); db.addLocalMessage(message, clientId, metadata, true);
fail(); fail();
} catch (MessageExistsException expected) { } catch (MessageExistsException expected) {
// Expected // Expected
@@ -241,7 +243,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
shutdown); shutdown);
try { try {
db.addLocalMessage(message, clientId, metadata); db.addLocalMessage(message, clientId, metadata, true);
fail(); fail();
} catch (NoSuchSubscriptionException expected) { } catch (NoSuchSubscriptionException expected) {
// Expected // Expected
@@ -264,7 +266,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
will(returnValue(false)); will(returnValue(false));
oneOf(database).containsGroup(txn, groupId); oneOf(database).containsGroup(txn, groupId);
will(returnValue(true)); will(returnValue(true));
oneOf(database).addMessage(txn, message, true); oneOf(database).addMessage(txn, message, VALID, true);
oneOf(database).mergeMessageMetadata(txn, messageId, metadata); oneOf(database).mergeMessageMetadata(txn, messageId, metadata);
oneOf(database).getVisibility(txn, groupId); oneOf(database).getVisibility(txn, groupId);
will(returnValue(Collections.singletonList(contactId))); will(returnValue(Collections.singletonList(contactId)));
@@ -281,7 +283,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
DatabaseComponent db = createDatabaseComponent(database, eventBus, DatabaseComponent db = createDatabaseComponent(database, eventBus,
shutdown); shutdown);
db.addLocalMessage(message, clientId, metadata); db.addLocalMessage(message, clientId, metadata, true);
context.assertIsSatisfied(); context.assertIsSatisfied();
} }
@@ -559,11 +561,11 @@ public class DatabaseComponentImplTest extends BriarTestCase {
final EventBus eventBus = context.mock(EventBus.class); final EventBus eventBus = context.mock(EventBus.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Check whether the message is in the DB (which it's not) // Check whether the message is in the DB (which it's not)
exactly(4).of(database).startTransaction(); exactly(6).of(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
exactly(4).of(database).containsMessage(txn, messageId); exactly(6).of(database).containsMessage(txn, messageId);
will(returnValue(false)); will(returnValue(false));
exactly(4).of(database).abortTransaction(txn); exactly(6).of(database).abortTransaction(txn);
// This is needed for getMessageStatus() to proceed // This is needed for getMessageStatus() to proceed
exactly(1).of(database).containsContact(txn, contactId); exactly(1).of(database).containsContact(txn, contactId);
will(returnValue(true)); will(returnValue(true));
@@ -599,6 +601,20 @@ public class DatabaseComponentImplTest extends BriarTestCase {
// Expected // Expected
} }
try {
db.setMessageShared(message, true);
fail();
} catch (NoSuchMessageException expected) {
// Expected
}
try {
db.setMessageValid(message, clientId, true);
fail();
} catch (NoSuchMessageException expected) {
// Expected
}
context.assertIsSatisfied(); context.assertIsSatisfied();
} }
@@ -932,7 +948,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
will(returnValue(false)); will(returnValue(false));
oneOf(database).containsVisibleGroup(txn, contactId, groupId); oneOf(database).containsVisibleGroup(txn, contactId, groupId);
will(returnValue(true)); will(returnValue(true));
oneOf(database).addMessage(txn, message, false); oneOf(database).addMessage(txn, message, UNKNOWN, true);
oneOf(database).getVisibility(txn, groupId); oneOf(database).getVisibility(txn, groupId);
will(returnValue(Collections.singletonList(contactId))); will(returnValue(Collections.singletonList(contactId)));
oneOf(database).getContactIds(txn); oneOf(database).getContactIds(txn);

View File

@@ -34,7 +34,6 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
@@ -47,6 +46,8 @@ import static org.briarproject.api.db.Metadata.REMOVE;
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH; import static org.briarproject.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_LENGTH; import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_LENGTH;
import static org.briarproject.api.sync.ValidationManager.Validity.UNKNOWN;
import static org.briarproject.api.sync.ValidationManager.Validity.VALID;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
@@ -113,7 +114,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.addGroup(txn, group); db.addGroup(txn, group);
assertTrue(db.containsGroup(txn, groupId)); assertTrue(db.containsGroup(txn, groupId));
assertFalse(db.containsMessage(txn, messageId)); assertFalse(db.containsMessage(txn, messageId));
db.addMessage(txn, message, true); db.addMessage(txn, message, VALID, true);
assertTrue(db.containsMessage(txn, messageId)); assertTrue(db.containsMessage(txn, messageId));
db.commitTransaction(txn); db.commitTransaction(txn);
db.close(); db.close();
@@ -126,6 +127,7 @@ public class H2DatabaseTest extends BriarTestCase {
assertTrue(db.containsMessage(txn, messageId)); assertTrue(db.containsMessage(txn, messageId));
byte[] raw1 = db.getRawMessage(txn, messageId); byte[] raw1 = db.getRawMessage(txn, messageId);
assertArrayEquals(raw, raw1); assertArrayEquals(raw, raw1);
// Delete the records // Delete the records
db.removeMessage(txn, messageId); db.removeMessage(txn, messageId);
db.removeContact(txn, contactId); db.removeContact(txn, contactId);
@@ -150,7 +152,7 @@ public class H2DatabaseTest extends BriarTestCase {
// Subscribe to a group and store a message // Subscribe to a group and store a message
db.addGroup(txn, group); db.addGroup(txn, group);
db.addMessage(txn, message, true); db.addMessage(txn, message, VALID, true);
// Unsubscribing from the group should remove the message // Unsubscribing from the group should remove the message
assertTrue(db.containsMessage(txn, messageId)); assertTrue(db.containsMessage(txn, messageId));
@@ -172,26 +174,106 @@ public class H2DatabaseTest extends BriarTestCase {
db.addGroup(txn, group); db.addGroup(txn, group);
db.addVisibility(txn, contactId, groupId); db.addVisibility(txn, contactId, groupId);
db.setGroups(txn, contactId, Collections.singletonList(group), 1); db.setGroups(txn, contactId, Collections.singletonList(group), 1);
db.addMessage(txn, message, true); db.addMessage(txn, message, VALID, true);
// The message has no status yet, so it should not be sendable // The message has no status yet, so it should not be sendable
Collection<MessageId> ids = db.getMessagesToSend(txn, contactId, Collection<MessageId> ids = db.getMessagesToSend(txn, contactId,
ONE_MEGABYTE); ONE_MEGABYTE);
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100);
assertTrue(ids.isEmpty());
// Adding a status with seen = false should make the message sendable // Adding a status with seen = false should make the message sendable
db.addStatus(txn, contactId, messageId, false, false); db.addStatus(txn, contactId, messageId, false, false);
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE); ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
assertFalse(ids.isEmpty()); assertEquals(Collections.singletonList(messageId), ids);
Iterator<MessageId> it = ids.iterator(); ids = db.getMessagesToOffer(txn, contactId, 100);
assertTrue(it.hasNext()); assertEquals(Collections.singletonList(messageId), ids);
assertEquals(messageId, it.next());
assertFalse(it.hasNext());
// Changing the status to seen = true should make the message unsendable // Changing the status to seen = true should make the message unsendable
db.raiseSeenFlag(txn, contactId, messageId); db.raiseSeenFlag(txn, contactId, messageId);
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE); ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100);
assertTrue(ids.isEmpty());
db.commitTransaction(txn);
db.close();
}
@Test
public void testSendableMessagesMustBeValid() throws Exception {
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
// Add a contact, subscribe to a group and store an unvalidated message
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group);
db.addVisibility(txn, contactId, groupId);
db.setGroups(txn, contactId, Collections.singletonList(group), 1);
db.addMessage(txn, message, UNKNOWN, true);
db.addStatus(txn, contactId, messageId, false, false);
// The message has not been validated, so it should not be sendable
Collection<MessageId> ids = db.getMessagesToSend(txn, contactId,
ONE_MEGABYTE);
assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100);
assertTrue(ids.isEmpty());
// Marking the message valid should make it sendable
db.setMessageValid(txn, messageId, true);
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
assertEquals(Collections.singletonList(messageId), ids);
ids = db.getMessagesToOffer(txn, contactId, 100);
assertEquals(Collections.singletonList(messageId), ids);
// Marking the message invalid should make it unsendable
db.setMessageValid(txn, messageId, false);
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100);
assertTrue(ids.isEmpty());
db.commitTransaction(txn);
db.close();
}
@Test
public void testSendableMessagesMustBeShared() throws Exception {
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
// Add a contact, subscribe to a group and store an unshared message
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group);
db.addVisibility(txn, contactId, groupId);
db.setGroups(txn, contactId, Collections.singletonList(group), 1);
db.addMessage(txn, message, VALID, false);
db.addStatus(txn, contactId, messageId, false, false);
// The message is not shared, so it should not be sendable
Collection<MessageId> ids = db.getMessagesToSend(txn, contactId,
ONE_MEGABYTE);
assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100);
assertTrue(ids.isEmpty());
// Sharing the message should make it sendable
db.setMessageShared(txn, messageId, true);
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
assertEquals(Collections.singletonList(messageId), ids);
ids = db.getMessagesToOffer(txn, contactId, 100);
assertEquals(Collections.singletonList(messageId), ids);
// Unsharing the message should make it unsendable
db.setMessageShared(txn, messageId, false);
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100);
assertTrue(ids.isEmpty());
db.commitTransaction(txn); db.commitTransaction(txn);
db.close(); db.close();
@@ -207,27 +289,29 @@ public class H2DatabaseTest extends BriarTestCase {
assertEquals(contactId, db.addContact(txn, author, localAuthorId)); assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addVisibility(txn, contactId, groupId); db.addVisibility(txn, contactId, groupId);
db.addMessage(txn, message, true); db.addMessage(txn, message, VALID, true);
db.addStatus(txn, contactId, messageId, false, false); db.addStatus(txn, contactId, messageId, false, false);
// The contact is not subscribed, so the message should not be sendable // The contact is not subscribed, so the message should not be sendable
Collection<MessageId> ids = db.getMessagesToSend(txn, contactId, Collection<MessageId> ids = db.getMessagesToSend(txn, contactId,
ONE_MEGABYTE); ONE_MEGABYTE);
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100);
assertTrue(ids.isEmpty());
// The contact subscribing should make the message sendable // The contact subscribing should make the message sendable
db.setGroups(txn, contactId, Collections.singletonList(group), 1); db.setGroups(txn, contactId, Collections.singletonList(group), 1);
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE); ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
assertFalse(ids.isEmpty()); assertEquals(Collections.singletonList(messageId), ids);
Iterator<MessageId> it = ids.iterator(); ids = db.getMessagesToOffer(txn, contactId, 100);
assertTrue(it.hasNext()); assertEquals(Collections.singletonList(messageId), ids);
assertEquals(messageId, it.next());
assertFalse(it.hasNext());
// The contact unsubscribing should make the message unsendable // The contact unsubscribing should make the message unsendable
db.setGroups(txn, contactId, Collections.<Group>emptyList(), 2); db.setGroups(txn, contactId, Collections.<Group>emptyList(), 2);
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE); ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100);
assertTrue(ids.isEmpty());
db.commitTransaction(txn); db.commitTransaction(txn);
db.close(); db.close();
@@ -244,7 +328,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.addGroup(txn, group); db.addGroup(txn, group);
db.addVisibility(txn, contactId, groupId); db.addVisibility(txn, contactId, groupId);
db.setGroups(txn, contactId, Collections.singletonList(group), 1); db.setGroups(txn, contactId, Collections.singletonList(group), 1);
db.addMessage(txn, message, true); db.addMessage(txn, message, VALID, true);
db.addStatus(txn, contactId, messageId, false, false); db.addStatus(txn, contactId, messageId, false, false);
// The message is sendable, but too large to send // The message is sendable, but too large to send
@@ -254,11 +338,7 @@ public class H2DatabaseTest extends BriarTestCase {
// The message is just the right size to send // The message is just the right size to send
ids = db.getMessagesToSend(txn, contactId, size); ids = db.getMessagesToSend(txn, contactId, size);
assertFalse(ids.isEmpty()); assertEquals(Collections.singletonList(messageId), ids);
Iterator<MessageId> it = ids.iterator();
assertTrue(it.hasNext());
assertEquals(messageId, it.next());
assertFalse(it.hasNext());
db.commitTransaction(txn); db.commitTransaction(txn);
db.close(); db.close();
@@ -274,7 +354,7 @@ public class H2DatabaseTest extends BriarTestCase {
assertEquals(contactId, db.addContact(txn, author, localAuthorId)); assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group); db.addGroup(txn, group);
db.setGroups(txn, contactId, Collections.singletonList(group), 1); db.setGroups(txn, contactId, Collections.singletonList(group), 1);
db.addMessage(txn, message, true); db.addMessage(txn, message, VALID, true);
db.addStatus(txn, contactId, messageId, false, false); db.addStatus(txn, contactId, messageId, false, false);
// The subscription is not visible to the contact, so the message // The subscription is not visible to the contact, so the message
@@ -282,15 +362,22 @@ public class H2DatabaseTest extends BriarTestCase {
Collection<MessageId> ids = db.getMessagesToSend(txn, contactId, Collection<MessageId> ids = db.getMessagesToSend(txn, contactId,
ONE_MEGABYTE); ONE_MEGABYTE);
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100);
assertTrue(ids.isEmpty());
// Making the subscription visible should make the message sendable // Making the subscription visible should make the message sendable
db.addVisibility(txn, contactId, groupId); db.addVisibility(txn, contactId, groupId);
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE); ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
assertFalse(ids.isEmpty()); assertEquals(Collections.singletonList(messageId), ids);
Iterator<MessageId> it = ids.iterator(); ids = db.getMessagesToOffer(txn, contactId, 100);
assertTrue(it.hasNext()); assertEquals(Collections.singletonList(messageId), ids);
assertEquals(messageId, it.next());
assertFalse(it.hasNext()); // Making the subscription invisible should make the message unsendable
db.removeVisibility(txn, contactId, groupId);
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100);
assertTrue(ids.isEmpty());
db.commitTransaction(txn); db.commitTransaction(txn);
db.close(); db.close();
@@ -310,16 +397,16 @@ public class H2DatabaseTest extends BriarTestCase {
// Add some messages to ack // Add some messages to ack
MessageId messageId1 = new MessageId(TestUtils.getRandomId()); MessageId messageId1 = new MessageId(TestUtils.getRandomId());
Message message1 = new Message(messageId1, groupId, timestamp, raw); Message message1 = new Message(messageId1, groupId, timestamp, raw);
db.addMessage(txn, message, true); db.addMessage(txn, message, VALID, true);
db.addStatus(txn, contactId, messageId, false, true); db.addStatus(txn, contactId, messageId, false, true);
db.raiseAckFlag(txn, contactId, messageId); db.raiseAckFlag(txn, contactId, messageId);
db.addMessage(txn, message1, true); db.addMessage(txn, message1, VALID, true);
db.addStatus(txn, contactId, messageId1, false, true); db.addStatus(txn, contactId, messageId1, false, true);
db.raiseAckFlag(txn, contactId, messageId1); db.raiseAckFlag(txn, contactId, messageId1);
// Both message IDs should be returned // Both message IDs should be returned
Collection<MessageId> ids = Arrays.asList(messageId, messageId1); Collection<MessageId> ids = db.getMessagesToAck(txn, contactId, 1234);
assertEquals(ids, db.getMessagesToAck(txn, contactId, 1234)); assertEquals(Arrays.asList(messageId, messageId1), ids);
// Remove both message IDs // Remove both message IDs
db.lowerAckFlag(txn, contactId, Arrays.asList(messageId, messageId1)); db.lowerAckFlag(txn, contactId, Arrays.asList(messageId, messageId1));
@@ -332,38 +419,6 @@ public class H2DatabaseTest extends BriarTestCase {
db.close(); db.close();
} }
@Test
public void testDuplicateMessageReceived() throws Exception {
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
// Add a contact and subscribe to a group
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group);
db.setGroups(txn, contactId, Collections.singletonList(group), 1);
// Receive the same message twice
db.addMessage(txn, message, true);
db.addStatus(txn, contactId, messageId, false, true);
db.raiseAckFlag(txn, contactId, messageId);
db.raiseAckFlag(txn, contactId, messageId);
// The message ID should only be returned once
Collection<MessageId> ids = db.getMessagesToAck(txn, contactId, 1234);
assertEquals(Collections.singletonList(messageId), ids);
// Remove the message ID
db.lowerAckFlag(txn, contactId, Collections.singletonList(messageId));
// The message ID should have been removed
assertEquals(Collections.emptyList(), db.getMessagesToAck(txn,
contactId, 1234));
db.commitTransaction(txn);
db.close();
}
@Test @Test
public void testOutstandingMessageAcked() throws Exception { public void testOutstandingMessageAcked() throws Exception {
Database<Connection> db = open(false); Database<Connection> db = open(false);
@@ -375,27 +430,25 @@ public class H2DatabaseTest extends BriarTestCase {
db.addGroup(txn, group); db.addGroup(txn, group);
db.addVisibility(txn, contactId, groupId); db.addVisibility(txn, contactId, groupId);
db.setGroups(txn, contactId, Collections.singletonList(group), 1); db.setGroups(txn, contactId, Collections.singletonList(group), 1);
db.addMessage(txn, message, true); db.addMessage(txn, message, VALID, true);
db.addStatus(txn, contactId, messageId, false, false); db.addStatus(txn, contactId, messageId, false, false);
// Retrieve the message from the database and mark it as sent // Retrieve the message from the database and mark it as sent
Iterator<MessageId> it = Collection<MessageId> ids = db.getMessagesToSend(txn, contactId,
db.getMessagesToSend(txn, contactId, ONE_MEGABYTE).iterator(); ONE_MEGABYTE);
assertTrue(it.hasNext()); assertEquals(Collections.singletonList(messageId), ids);
assertEquals(messageId, it.next());
assertFalse(it.hasNext());
db.updateExpiryTime(txn, contactId, messageId, Integer.MAX_VALUE); db.updateExpiryTime(txn, contactId, messageId, Integer.MAX_VALUE);
// The message should no longer be sendable // The message should no longer be sendable
it = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE).iterator(); ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
assertFalse(it.hasNext()); assertTrue(ids.isEmpty());
// Pretend that the message was acked // Pretend that the message was acked
db.raiseSeenFlag(txn, contactId, messageId); db.raiseSeenFlag(txn, contactId, messageId);
// The message still should not be sendable // The message still should not be sendable
it = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE).iterator(); ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
assertFalse(it.hasNext()); assertTrue(ids.isEmpty());
db.commitTransaction(txn); db.commitTransaction(txn);
db.close(); db.close();
@@ -419,7 +472,7 @@ public class H2DatabaseTest extends BriarTestCase {
// 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.addGroup(txn, group); db.addGroup(txn, group);
db.addMessage(txn, message, true); db.addMessage(txn, message, VALID, true);
db.commitTransaction(txn); db.commitTransaction(txn);
assertTrue(db.getFreeSpace() < free); assertTrue(db.getFreeSpace() < free);
@@ -579,7 +632,7 @@ public class H2DatabaseTest extends BriarTestCase {
assertEquals(contactId, db.addContact(txn, author, localAuthorId)); assertEquals(contactId, db.addContact(txn, author, localAuthorId));
db.addGroup(txn, group); db.addGroup(txn, group);
db.setGroups(txn, contactId, Collections.singletonList(group), 1); db.setGroups(txn, contactId, Collections.singletonList(group), 1);
db.addMessage(txn, message, true); db.addMessage(txn, message, VALID, true);
db.addStatus(txn, contactId, messageId, false, false); db.addStatus(txn, contactId, messageId, false, false);
// The subscription is not visible // The subscription is not visible
@@ -904,7 +957,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.addVisibility(txn, contactId, groupId); db.addVisibility(txn, contactId, groupId);
// Add a message - it should be sendable to the contact // Add a message - it should be sendable to the contact
db.addMessage(txn, message, true); db.addMessage(txn, message, VALID, true);
db.addStatus(txn, contactId, messageId, false, false); db.addStatus(txn, contactId, messageId, false, false);
Collection<MessageId> sendable = db.getMessagesToSend(txn, contactId, Collection<MessageId> sendable = db.getMessagesToSend(txn, contactId,
ONE_MEGABYTE); ONE_MEGABYTE);
@@ -974,7 +1027,7 @@ public class H2DatabaseTest extends BriarTestCase {
// Add a group and a message // Add a group and a message
db.addGroup(txn, group); db.addGroup(txn, group);
db.addMessage(txn, message, true); db.addMessage(txn, message, VALID, true);
// Attach some metadata to the message // Attach some metadata to the message
Metadata metadata = new Metadata(); Metadata metadata = new Metadata();
@@ -1042,7 +1095,7 @@ public class H2DatabaseTest extends BriarTestCase {
db.addVisibility(txn, contactId, groupId); db.addVisibility(txn, contactId, groupId);
// Add a message to the group // Add a message to the group
db.addMessage(txn, message, true); db.addMessage(txn, message, VALID, true);
db.addStatus(txn, contactId, messageId, false, false); db.addStatus(txn, contactId, messageId, false, false);
// The message should not be sent or seen // The message should not be sent or seen