Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • briar/briar
  • goapunk/briar
  • johndoe4221/briar
  • thomas/briar
4 results
Show changes
Commits on Source (1)
Showing
with 420 additions and 578 deletions
......@@ -18,11 +18,10 @@ public interface ContactGroupFactory {
* Creates a group for the given client to share with the given contact.
*/
Group createContactGroup(ClientId clientId, int majorVersion,
Contact contact);
Contact contact, AuthorId local);
/**
* Creates a group for the given client to share between the given authors
* identified by their AuthorIds.
* Creates a group for the given client to share between the given authors.
*/
Group createContactGroup(ClientId clientId, int majorVersion,
AuthorId authorId1, AuthorId authorId2);
......
package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
......@@ -17,16 +16,14 @@ public class Contact {
private final ContactId id;
private final Author author;
private final AuthorId localAuthorId;
@Nullable
private final String alias;
@Nullable
private final byte[] handshakePublicKey;
private final boolean verified;
public Contact(ContactId id, Author author, AuthorId localAuthorId,
@Nullable String alias, @Nullable byte[] handshakePublicKey,
boolean verified) {
public Contact(ContactId id, Author author, @Nullable String alias,
@Nullable byte[] handshakePublicKey, boolean verified) {
if (alias != null) {
int aliasLength = toUtf8(alias).length;
if (aliasLength == 0 || aliasLength > MAX_AUTHOR_NAME_LENGTH)
......@@ -38,7 +35,6 @@ public class Contact {
}
this.id = id;
this.author = author;
this.localAuthorId = localAuthorId;
this.alias = alias;
this.handshakePublicKey = handshakePublicKey;
this.verified = verified;
......@@ -52,10 +48,6 @@ public class Contact {
return author;
}
public AuthorId getLocalAuthorId() {
return localAuthorId;
}
@Nullable
public String getAlias() {
return alias;
......
......@@ -24,33 +24,30 @@ public interface ContactManager {
void registerContactHook(ContactHook hook);
/**
* Stores a contact associated with the given local and remote pseudonyms,
* derives and stores transport keys for each transport, and returns an ID
* for the contact.
* Stores a contact with the given pseudonym, derives and stores transport
* keys for each transport, and returns an ID for the contact.
*
* @param alice true if the local party is Alice
*/
ContactId addContact(Transaction txn, Author remote, AuthorId local,
SecretKey rootKey, long timestamp, boolean alice, boolean verified,
boolean active) throws DbException;
ContactId addContact(Transaction txn, Author a, SecretKey rootKey,
long timestamp, boolean alice, boolean verified, boolean active)
throws DbException;
/**
* Stores a contact associated with the given local and remote pseudonyms
* and returns an ID for the contact.
* Stores a contact with the given pseudonym and returns an ID for the
* contact.
*/
ContactId addContact(Transaction txn, Author remote, AuthorId local,
boolean verified) throws DbException;
ContactId addContact(Transaction txn, Author a, boolean verified)
throws DbException;
/**
* Stores a contact associated with the given local and remote pseudonyms,
* derives and stores transport keys for each transport, and returns an ID
* for the contact.
* Stores a contact with the given pseudonym, derives and stores transport
* keys for each transport, and returns an ID for the contact.
*
* @param alice true if the local party is Alice
*/
ContactId addContact(Author remote, AuthorId local, SecretKey rootKey,
long timestamp, boolean alice, boolean verified, boolean active)
throws DbException;
ContactId addContact(Author a, SecretKey rootKey, long timestamp,
boolean alice, boolean verified, boolean active) throws DbException;
/**
* Returns the static link that needs to be sent to the contact to be added.
......@@ -88,22 +85,14 @@ public interface ContactManager {
Contact getContact(ContactId c) throws DbException;
/**
* Returns the contact with the given remoteAuthorId
* that was added by the LocalAuthor with the given localAuthorId
*
* @throws org.briarproject.bramble.api.db.NoSuchContactException
* Returns the contact with the given ID.
*/
Contact getContact(AuthorId remoteAuthorId, AuthorId localAuthorId)
throws DbException;
Contact getContact(AuthorId a) throws DbException;
/**
* Returns the contact with the given remoteAuthorId
* that was added by the LocalAuthor with the given localAuthorId
*
* @throws org.briarproject.bramble.api.db.NoSuchContactException
* Returns the contact with the given ID.
*/
Contact getContact(Transaction txn, AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException;
Contact getContact(Transaction txn, AuthorId a) throws DbException;
/**
* Returns all active contacts.
......@@ -133,16 +122,14 @@ public interface ContactManager {
throws DbException;
/**
* Return true if a contact with this name and public key already exists
* Returns true if a contact with this pseudonym already exists.
*/
boolean contactExists(Transaction txn, AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException;
boolean contactExists(Transaction txn, AuthorId a) throws DbException;
/**
* Return true if a contact with this name and public key already exists
* Returns true if a contact with this pseudonym already exists.
*/
boolean contactExists(AuthorId remoteAuthorId, AuthorId localAuthorId)
throws DbException;
boolean contactExists(AuthorId a) throws DbException;
/**
* Returns the {@link AuthorInfo} for the given author.
......
......@@ -102,11 +102,11 @@ public interface DatabaseComponent {
NullableDbCallable<R, E> task) throws DbException, E;
/**
* Stores a contact associated with the given local and remote pseudonyms,
* and returns an ID for the contact.
* Stores a contact with the given pseudonym and returns an ID for the
* contact.
*/
ContactId addContact(Transaction txn, Author remote, AuthorId local,
boolean verified) throws DbException;
ContactId addContact(Transaction txn, Author a, boolean verified)
throws DbException;
/**
* Stores a group.
......@@ -158,13 +158,11 @@ public interface DatabaseComponent {
TransportKeys k) throws DbException;
/**
* Returns true if the database contains the given contact for the given
* local pseudonym.
* Returns true if the database contains the given contact.
* <p/>
* Read-only.
*/
boolean containsContact(Transaction txn, AuthorId remote, AuthorId local)
throws DbException;
boolean containsContact(Transaction txn, AuthorId a) throws DbException;
/**
* Returns true if the database contains the given group.
......@@ -255,27 +253,18 @@ public interface DatabaseComponent {
Contact getContact(Transaction txn, ContactId c) throws DbException;
/**
* Returns all contacts.
* Returns the contact with the given author ID.
* <p/>
* Read-only.
*/
Collection<Contact> getContacts(Transaction txn) throws DbException;
Contact getContact(Transaction txn, AuthorId a) throws DbException;
/**
* Returns a possibly empty collection of contacts with the given author ID.
* <p/>
* Read-only.
*/
Collection<Contact> getContactsByAuthorId(Transaction txn, AuthorId remote)
throws DbException;
/**
* Returns all contacts associated with the given local pseudonym.
* Returns all contacts.
* <p/>
* Read-only.
*/
Collection<ContactId> getContacts(Transaction txn, AuthorId a)
throws DbException;
Collection<Contact> getContacts(Transaction txn) throws DbException;
/**
* Returns the group with the given ID.
......
......@@ -163,19 +163,15 @@ public class TestUtils {
}
public static Contact getContact() {
return getContact(getAuthor(), new AuthorId(getRandomId()),
random.nextBoolean());
return getContact(getAuthor(), random.nextBoolean());
}
public static Contact getContact(Author remote, AuthorId local,
boolean verified) {
return getContact(getContactId(), remote, local, verified);
public static Contact getContact(Author a, boolean verified) {
return getContact(getContactId(), a, verified);
}
public static Contact getContact(ContactId c, Author remote, AuthorId local,
boolean verified) {
return new Contact(c, remote, local,
getRandomString(MAX_AUTHOR_NAME_LENGTH),
public static Contact getContact(ContactId c, Author a, boolean verified) {
return new Contact(c, a, getRandomString(MAX_AUTHOR_NAME_LENGTH),
getRandomBytes(MAX_PUBLIC_KEY_LENGTH), verified);
}
......
......@@ -39,8 +39,7 @@ class ContactGroupFactoryImpl implements ContactGroupFactory {
@Override
public Group createContactGroup(ClientId clientId, int majorVersion,
Contact contact) {
AuthorId local = contact.getLocalAuthorId();
Contact contact, AuthorId local) {
AuthorId remote = contact.getAuthor().getId();
byte[] descriptor = createGroupDescriptor(local, remote);
return groupFactory.createGroup(clientId, majorVersion, descriptor);
......
......@@ -293,8 +293,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
throws DbException {
return db.transactionWithResult(false, txn -> {
ContactId contactId = contactManager.addContact(txn, remoteAuthor,
localAuthor.getId(), masterKey, timestamp, alice,
true, true);
masterKey, timestamp, alice, true, true);
transportPropertyManager.addRemoteProperties(txn, contactId,
remoteProperties);
return contactId;
......
......@@ -8,7 +8,6 @@ import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.NoSuchContactException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
......@@ -68,10 +67,10 @@ class ContactManagerImpl implements ContactManager {
}
@Override
public ContactId addContact(Transaction txn, Author remote, AuthorId local,
SecretKey rootKey, long timestamp, boolean alice, boolean verified,
boolean active) throws DbException {
ContactId c = db.addContact(txn, remote, local, verified);
public ContactId addContact(Transaction txn, Author a, SecretKey rootKey,
long timestamp, boolean alice, boolean verified, boolean active)
throws DbException {
ContactId c = db.addContact(txn, a, verified);
keyManager.addContact(txn, c, rootKey, timestamp, alice, active);
Contact contact = db.getContact(txn, c);
for (ContactHook hook : hooks) hook.addingContact(txn, contact);
......@@ -79,20 +78,20 @@ class ContactManagerImpl implements ContactManager {
}
@Override
public ContactId addContact(Transaction txn, Author remote, AuthorId local,
boolean verified) throws DbException {
ContactId c = db.addContact(txn, remote, local, verified);
public ContactId addContact(Transaction txn, Author a, boolean verified)
throws DbException {
ContactId c = db.addContact(txn, a, verified);
Contact contact = db.getContact(txn, c);
for (ContactHook hook : hooks) hook.addingContact(txn, contact);
return c;
}
@Override
public ContactId addContact(Author remote, AuthorId local,
SecretKey rootKey, long timestamp, boolean alice, boolean verified,
boolean active) throws DbException {
public ContactId addContact(Author a, SecretKey rootKey, long timestamp,
boolean alice, boolean verified, boolean active)
throws DbException {
return db.transactionWithResult(false, txn ->
addContact(txn, remote, local, rootKey, timestamp, alice,
addContact(txn, a, rootKey, timestamp, alice,
verified, active));
}
......@@ -144,23 +143,13 @@ class ContactManagerImpl implements ContactManager {
}
@Override
public Contact getContact(AuthorId remoteAuthorId, AuthorId localAuthorId)
throws DbException {
return db.transactionWithResult(true, txn ->
getContact(txn, remoteAuthorId, localAuthorId));
public Contact getContact(AuthorId a) throws DbException {
return db.transactionWithResult(true, txn -> getContact(txn, a));
}
@Override
public Contact getContact(Transaction txn, AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException {
Collection<Contact> contacts =
db.getContactsByAuthorId(txn, remoteAuthorId);
for (Contact c : contacts) {
if (c.getLocalAuthorId().equals(localAuthorId)) {
return c;
}
}
throw new NoSuchContactException();
public Contact getContact(Transaction txn, AuthorId a) throws DbException {
return db.getContact(txn, a);
}
@Override
......@@ -191,16 +180,14 @@ class ContactManagerImpl implements ContactManager {
}
@Override
public boolean contactExists(Transaction txn, AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException {
return db.containsContact(txn, remoteAuthorId, localAuthorId);
public boolean contactExists(Transaction txn, AuthorId a)
throws DbException {
return db.containsContact(txn, a);
}
@Override
public boolean contactExists(AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException {
return db.transactionWithResult(true, txn ->
contactExists(txn, remoteAuthorId, localAuthorId));
public boolean contactExists(AuthorId a) throws DbException {
return db.transactionWithResult(true, txn -> contactExists(txn, a));
}
@Override
......@@ -222,12 +209,12 @@ class ContactManagerImpl implements ContactManager {
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
if (localAuthor.getId().equals(authorId))
return new AuthorInfo(OURSELVES);
Collection<Contact> contacts = db.getContactsByAuthorId(txn, authorId);
if (contacts.isEmpty()) return new AuthorInfo(UNKNOWN);
if (contacts.size() > 1) throw new AssertionError();
Contact c = contacts.iterator().next();
if (c.isVerified()) return new AuthorInfo(VERIFIED, c.getAlias());
else return new AuthorInfo(UNVERIFIED, c.getAlias());
if (db.containsContact(txn, authorId)) {
Contact c = db.getContact(txn, authorId);
if (c.isVerified()) return new AuthorInfo(VERIFIED, c.getAlias());
else return new AuthorInfo(UNVERIFIED, c.getAlias());
}
return new AuthorInfo(UNKNOWN);
}
}
......@@ -87,11 +87,10 @@ interface Database<T> {
void commitTransaction(T txn) throws DbException;
/**
* Stores a contact associated with the given local and remote pseudonyms,
* and returns an ID for the contact.
* Stores a contact with the given pseudonym and returns an ID for the
* contact.
*/
ContactId addContact(T txn, Author remote, AuthorId local, boolean verified)
throws DbException;
ContactId addContact(T txn, Author a, boolean verified) throws DbException;
/**
* Stores a group.
......@@ -164,13 +163,11 @@ interface Database<T> {
throws DbException;
/**
* Returns true if the database contains the given contact for the given
* local pseudonym.
* Returns true if the database contains the given contact.
* <p/>
* Read-only.
*/
boolean containsContact(T txn, AuthorId remote, AuthorId local)
throws DbException;
boolean containsContact(T txn, AuthorId a) throws DbException;
/**
* Returns true if the database contains the given contact.
......@@ -253,26 +250,18 @@ interface Database<T> {
Contact getContact(T txn, ContactId c) throws DbException;
/**
* Returns all contacts.
* <p/>
* Read-only.
*/
Collection<Contact> getContacts(T txn) throws DbException;
/**
* Returns a possibly empty collection of contacts with the given author ID.
* Returns the contact with the given author ID.
* <p/>
* Read-only.
*/
Collection<Contact> getContactsByAuthorId(T txn, AuthorId remote)
throws DbException;
Contact getContact(T txn, AuthorId a) throws DbException;
/**
* Returns all contacts associated with the given local pseudonym.
* Returns all contacts.
* <p/>
* Read-only.
*/
Collection<ContactId> getContacts(T txn, AuthorId a) throws DbException;
Collection<Contact> getContacts(T txn) throws DbException;
/**
* Returns the group with the given ID.
......
......@@ -232,18 +232,15 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
}
@Override
public ContactId addContact(Transaction transaction, Author remote,
AuthorId local, boolean verified)
throws DbException {
public ContactId addContact(Transaction transaction, Author a,
boolean verified) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsLocalAuthor(txn, local))
throw new NoSuchLocalAuthorException();
if (db.containsLocalAuthor(txn, remote.getId()))
if (db.containsLocalAuthor(txn, a.getId()))
throw new ContactExistsException();
if (db.containsContact(txn, remote.getId(), local))
if (db.containsContact(txn, a.getId()))
throw new ContactExistsException();
ContactId c = db.addContact(txn, remote, local, verified);
ContactId c = db.addContact(txn, a, verified);
transaction.attach(new ContactAddedEvent(c));
return c;
}
......@@ -342,12 +339,10 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
}
@Override
public boolean containsContact(Transaction transaction, AuthorId remote,
AuthorId local) throws DbException {
public boolean containsContact(Transaction transaction, AuthorId a)
throws DbException {
T txn = unbox(transaction);
if (!db.containsLocalAuthor(txn, local))
throw new NoSuchLocalAuthorException();
return db.containsContact(txn, remote, local);
return db.containsContact(txn, a);
}
@Override
......@@ -488,26 +483,19 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
}
@Override
public Collection<Contact> getContacts(Transaction transaction)
public Contact getContact(Transaction transaction, AuthorId a)
throws DbException {
T txn = unbox(transaction);
return db.getContacts(txn);
}
@Override
public Collection<Contact> getContactsByAuthorId(Transaction transaction,
AuthorId remote) throws DbException {
T txn = unbox(transaction);
return db.getContactsByAuthorId(txn, remote);
if (!db.containsContact(txn, a))
throw new NoSuchContactException();
return db.getContact(txn, a);
}
@Override
public Collection<ContactId> getContacts(Transaction transaction,
AuthorId a) throws DbException {
public Collection<Contact> getContacts(Transaction transaction)
throws DbException {
T txn = unbox(transaction);
if (!db.containsLocalAuthor(txn, a))
throw new NoSuchLocalAuthorException();
return db.getContacts(txn, a);
return db.getContacts(txn);
}
@Override
......
......@@ -92,7 +92,7 @@ import static org.briarproject.bramble.util.LogUtils.now;
abstract class JdbcDatabase implements Database<Connection> {
// Package access for testing
static final int CODE_SCHEMA_VERSION = 43;
static final int CODE_SCHEMA_VERSION = 44;
// Time period offsets for incoming transport keys
private static final int OFFSET_PREV = -1;
......@@ -127,12 +127,8 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " alias _STRING," // Null if no alias has been set
+ " publicKey _BINARY NOT NULL,"
+ " handshakePublicKey _BINARY," // Null if key is unknown
+ " localAuthorId _HASH NOT NULL,"
+ " verified BOOLEAN NOT NULL,"
+ " PRIMARY KEY (contactId),"
+ " FOREIGN KEY (localAuthorId)"
+ " REFERENCES localAuthors (authorId)"
+ " ON DELETE CASCADE)";
+ " PRIMARY KEY (contactId))";
private static final String CREATE_GROUPS =
"CREATE TABLE groups"
......@@ -486,7 +482,8 @@ abstract class JdbcDatabase implements Database<Connection> {
new Migration39_40(),
new Migration40_41(dbTypes),
new Migration41_42(dbTypes),
new Migration42_43(dbTypes)
new Migration42_43(dbTypes),
new Migration43_44()
);
}
......@@ -662,23 +659,21 @@ abstract class JdbcDatabase implements Database<Connection> {
}
@Override
public ContactId addContact(Connection txn, Author remote, AuthorId local,
boolean verified) throws DbException {
public ContactId addContact(Connection txn, Author a, boolean verified)
throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
// Create a contact row
String sql = "INSERT INTO contacts"
+ " (authorId, formatVersion, name, publicKey,"
+ " localAuthorId, verified)"
+ " VALUES (?, ?, ?, ?, ?, ?)";
ps = txn.prepareStatement(sql);
ps.setBytes(1, remote.getId().getBytes());
ps.setInt(2, remote.getFormatVersion());
ps.setString(3, remote.getName());
ps.setBytes(4, remote.getPublicKey());
ps.setBytes(5, local.getBytes());
ps.setBoolean(6, verified);
+ " (authorId, formatVersion, name, publicKey, verified)"
+ " VALUES (?, ?, ?, ?, ?)";
ps = txn.prepareStatement(sql);
ps.setBytes(1, a.getId().getBytes());
ps.setInt(2, a.getFormatVersion());
ps.setString(3, a.getName());
ps.setBytes(4, a.getPublicKey());
ps.setBoolean(5, verified);
int affected = ps.executeUpdate();
if (affected != 1) throw new DbStateException();
ps.close();
......@@ -1180,16 +1175,14 @@ abstract class JdbcDatabase implements Database<Connection> {
}
@Override
public boolean containsContact(Connection txn, AuthorId remote,
AuthorId local) throws DbException {
public boolean containsContact(Connection txn, AuthorId a)
throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT NULL FROM contacts"
+ " WHERE authorId = ? AND localAuthorId = ?";
String sql = "SELECT NULL FROM contacts WHERE authorId = ?";
ps = txn.prepareStatement(sql);
ps.setBytes(1, remote.getBytes());
ps.setBytes(2, local.getBytes());
ps.setBytes(1, a.getBytes());
rs = ps.executeQuery();
boolean found = rs.next();
if (rs.next()) throw new DbStateException();
......@@ -1432,7 +1425,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ResultSet rs = null;
try {
String sql = "SELECT authorId, formatVersion, name, alias,"
+ " publicKey, handshakePublicKey, localAuthorId, verified"
+ " publicKey, handshakePublicKey, verified"
+ " FROM contacts"
+ " WHERE contactId = ?";
ps = txn.prepareStatement(sql);
......@@ -1445,14 +1438,12 @@ abstract class JdbcDatabase implements Database<Connection> {
String alias = rs.getString(4);
byte[] publicKey = rs.getBytes(5);
byte[] handshakePublicKey = rs.getBytes(6);
AuthorId localAuthorId = new AuthorId(rs.getBytes(7));
boolean verified = rs.getBoolean(8);
boolean verified = rs.getBoolean(7);
rs.close();
ps.close();
Author author =
new Author(authorId, formatVersion, name, publicKey);
return new Contact(c, author, localAuthorId, alias,
handshakePublicKey, verified);
return new Contact(c, author, alias, handshakePublicKey, verified);
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
......@@ -1461,58 +1452,30 @@ abstract class JdbcDatabase implements Database<Connection> {
}
@Override
public Collection<Contact> getContacts(Connection txn) throws DbException {
Statement s = null;
ResultSet rs = null;
try {
String sql = "SELECT contactId, authorId, formatVersion, name,"
+ " alias, publicKey, handshakePublicKey, localAuthorId,"
+ " verified"
+ " FROM contacts";
s = txn.createStatement();
rs = s.executeQuery(sql);
List<Contact> contacts = new ArrayList<>();
while (rs.next()) {
ContactId contactId = new ContactId(rs.getInt(1));
AuthorId authorId = new AuthorId(rs.getBytes(2));
int formatVersion = rs.getInt(3);
String name = rs.getString(4);
String alias = rs.getString(5);
byte[] publicKey = rs.getBytes(6);
byte[] handshakePublicKey = rs.getBytes(7);
AuthorId localAuthorId = new AuthorId(rs.getBytes(8));
boolean verified = rs.getBoolean(9);
Author author =
new Author(authorId, formatVersion, name, publicKey);
contacts.add(new Contact(contactId, author, localAuthorId,
alias, handshakePublicKey, verified));
}
rs.close();
s.close();
return contacts;
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(s, LOG, WARNING);
throw new DbException(e);
}
}
@Override
public Collection<ContactId> getContacts(Connection txn, AuthorId local)
throws DbException {
public Contact getContact(Connection txn, AuthorId a) throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT contactId FROM contacts"
+ " WHERE localAuthorId = ?";
String sql = "SELECT contactId, formatVersion, name, alias,"
+ " publicKey, handshakePublicKey, verified"
+ " FROM contacts"
+ " WHERE authorId = ?";
ps = txn.prepareStatement(sql);
ps.setBytes(1, local.getBytes());
ps.setBytes(1, a.getBytes());
rs = ps.executeQuery();
List<ContactId> ids = new ArrayList<>();
while (rs.next()) ids.add(new ContactId(rs.getInt(1)));
if (!rs.next()) throw new DbStateException();
ContactId contactId = new ContactId(rs.getInt(1));
int formatVersion = rs.getInt(2);
String name = rs.getString(3);
String alias = rs.getString(4);
byte[] publicKey = rs.getBytes(5);
byte[] handshakePublicKey = rs.getBytes(6);
boolean verified = rs.getBoolean(7);
rs.close();
ps.close();
return ids;
Author author = new Author(a, formatVersion, name, publicKey);
return new Contact(contactId, author, alias, handshakePublicKey,
verified);
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
......@@ -1521,39 +1484,36 @@ abstract class JdbcDatabase implements Database<Connection> {
}
@Override
public Collection<Contact> getContactsByAuthorId(Connection txn,
AuthorId remote) throws DbException {
PreparedStatement ps = null;
public Collection<Contact> getContacts(Connection txn) throws DbException {
Statement s = null;
ResultSet rs = null;
try {
String sql = "SELECT contactId, formatVersion, name, alias,"
+ " publicKey, handshakePublicKey, localAuthorId, verified"
+ " FROM contacts"
+ " WHERE authorId = ?";
ps = txn.prepareStatement(sql);
ps.setBytes(1, remote.getBytes());
rs = ps.executeQuery();
String sql = "SELECT contactId, authorId, formatVersion, name,"
+ " alias, publicKey, handshakePublicKey, verified"
+ " FROM contacts";
s = txn.createStatement();
rs = s.executeQuery(sql);
List<Contact> contacts = new ArrayList<>();
while (rs.next()) {
ContactId contactId = new ContactId(rs.getInt(1));
int formatVersion = rs.getInt(2);
String name = rs.getString(3);
String alias = rs.getString(4);
byte[] publicKey = rs.getBytes(5);
byte[] handshakePublicKey = rs.getBytes(6);
AuthorId localAuthorId = new AuthorId(rs.getBytes(7));
AuthorId authorId = new AuthorId(rs.getBytes(2));
int formatVersion = rs.getInt(3);
String name = rs.getString(4);
String alias = rs.getString(5);
byte[] publicKey = rs.getBytes(6);
byte[] handshakePublicKey = rs.getBytes(7);
boolean verified = rs.getBoolean(8);
Author author =
new Author(remote, formatVersion, name, publicKey);
contacts.add(new Contact(contactId, author, localAuthorId,
alias, handshakePublicKey, verified));
new Author(authorId, formatVersion, name, publicKey);
contacts.add(new Contact(contactId, author, alias,
handshakePublicKey, verified));
}
rs.close();
ps.close();
s.close();
return contacts;
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
tryToClose(s, LOG, WARNING);
throw new DbException(e);
}
}
......
package org.briarproject.bramble.db;
import org.briarproject.bramble.api.db.DbException;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Logger;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
class Migration43_44 implements Migration<Connection> {
private static final Logger LOG = getLogger(Migration43_44.class.getName());
@Override
public int getStartVersion() {
return 43;
}
@Override
public int getEndVersion() {
return 44;
}
@Override
public void migrate(Connection txn) throws DbException {
Statement s = null;
try {
s = txn.createStatement();
s.execute("ALTER TABLE contacts"
+ " DROP COLUMN localAuthorId");
} catch (SQLException e) {
tryToClose(s, LOG, WARNING);
throw new DbException(e);
}
}
}
......@@ -13,6 +13,8 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties;
......@@ -44,6 +46,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
private final DatabaseComponent db;
private final ClientHelper clientHelper;
private final IdentityManager identityManager;
private final ClientVersioningManager clientVersioningManager;
private final MetadataParser metadataParser;
private final ContactGroupFactory contactGroupFactory;
......@@ -53,11 +56,13 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
@Inject
TransportPropertyManagerImpl(DatabaseComponent db,
ClientHelper clientHelper,
IdentityManager identityManager,
ClientVersioningManager clientVersioningManager,
MetadataParser metadataParser,
ContactGroupFactory contactGroupFactory, Clock clock) {
this.db = db;
this.clientHelper = clientHelper;
this.identityManager = identityManager;
this.clientVersioningManager = clientVersioningManager;
this.metadataParser = metadataParser;
this.contactGroupFactory = contactGroupFactory;
......@@ -77,7 +82,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
@Override
public void addingContact(Transaction txn, Contact c) throws DbException {
// Create a group to share with the contact
Group g = getContactGroup(c);
Group g = getContactGroup(c, getLocalAuthorId(txn));
db.addGroup(txn, g);
// Apply the client's visibility to the contact group
Visibility client = clientVersioningManager.getClientVisibility(txn,
......@@ -93,14 +98,14 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
@Override
public void removingContact(Transaction txn, Contact c) throws DbException {
db.removeGroup(txn, getContactGroup(c));
db.removeGroup(txn, getContactGroup(c, getLocalAuthorId(txn)));
}
@Override
public void onClientVisibilityChanging(Transaction txn, Contact c,
Visibility v) throws DbException {
// Apply the client's visibility to the contact group
Group g = getContactGroup(c);
Group g = getContactGroup(c, getLocalAuthorId(txn));
db.setGroupVisibility(txn, c.getId(), g.getId(), v);
}
......@@ -132,7 +137,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
@Override
public void addRemoteProperties(Transaction txn, ContactId c,
Map<TransportId, TransportProperties> props) throws DbException {
Group g = getContactGroup(db.getContact(txn, c));
Group g = getContactGroup(db.getContact(txn, c), getLocalAuthorId(txn));
for (Entry<TransportId, TransportProperties> e : props.entrySet()) {
storeMessage(txn, g.getId(), e.getKey(), e.getValue(), 0,
false, false);
......@@ -191,15 +196,16 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
TransportId t) throws DbException {
return db.transactionWithResult(true, txn -> {
Map<ContactId, TransportProperties> remote = new HashMap<>();
AuthorId local = getLocalAuthorId(txn);
for (Contact c : db.getContacts(txn))
remote.put(c.getId(), getRemoteProperties(txn, c, t));
remote.put(c.getId(), getRemoteProperties(txn, c, local, t));
return remote;
});
}
private TransportProperties getRemoteProperties(Transaction txn, Contact c,
TransportId t) throws DbException {
Group g = getContactGroup(c);
AuthorId local, TransportId t) throws DbException {
Group g = getContactGroup(c, local);
try {
// Find the latest remote update
LatestUpdate latest = findLatest(txn, g.getId(), t, false);
......@@ -216,8 +222,11 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
@Override
public TransportProperties getRemoteProperties(ContactId c, TransportId t)
throws DbException {
return db.transactionWithResult(true, txn ->
getRemoteProperties(txn, db.getContact(txn, c), t));
return db.transactionWithResult(true, txn -> {
Contact contact = db.getContact(txn ,c);
AuthorId local = getLocalAuthorId(txn);
return getRemoteProperties(txn, contact, local, t);
});
}
@Override
......@@ -250,8 +259,9 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
if (latest != null)
db.removeMessage(txn, latest.messageId);
// Store the merged properties in each contact's group
AuthorId localAuthorId = getLocalAuthorId(txn);
for (Contact c : db.getContacts(txn)) {
Group g = getContactGroup(c);
Group g = getContactGroup(c, localAuthorId);
latest = findLatest(txn, g.getId(), t, true);
version = latest == null ? 1 : latest.version + 1;
storeMessage(txn, g.getId(), t, merged, version,
......@@ -267,9 +277,13 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
}
}
private Group getContactGroup(Contact c) {
private AuthorId getLocalAuthorId(Transaction txn) throws DbException {
return identityManager.getLocalAuthor(txn).getId();
}
private Group getContactGroup(Contact c, AuthorId local) {
return contactGroupFactory.createContactGroup(CLIENT_ID,
MAJOR_VERSION, c);
MAJOR_VERSION, c, local);
}
private void storeMessage(Transaction txn, GroupId g, TransportId t,
......
......@@ -12,6 +12,8 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.lifecycle.ServiceException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
......@@ -58,6 +60,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
private final DatabaseComponent db;
private final ClientHelper clientHelper;
private final IdentityManager identityManager;
private final ContactGroupFactory contactGroupFactory;
private final Clock clock;
private final Group localGroup;
......@@ -68,9 +71,11 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
@Inject
ClientVersioningManagerImpl(DatabaseComponent db, ClientHelper clientHelper,
IdentityManager identityManager,
ContactGroupFactory contactGroupFactory, Clock clock) {
this.db = db;
this.clientHelper = clientHelper;
this.identityManager = identityManager;
this.contactGroupFactory = contactGroupFactory;
this.clock = clock;
localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID,
......@@ -154,7 +159,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
@Override
public void addingContact(Transaction txn, Contact c) throws DbException {
// Create a group and share it with the contact
Group g = getContactGroup(c);
Group g = getContactGroup(c, getLocalAuthorId(txn));
db.addGroup(txn, g);
db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED);
// Attach the contact ID to the group
......@@ -173,7 +178,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
@Override
public void removingContact(Transaction txn, Contact c) throws DbException {
db.removeGroup(txn, getContactGroup(c));
db.removeGroup(txn, getContactGroup(c, getLocalAuthorId(txn)));
}
@Override
......@@ -308,7 +313,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
List<ClientVersion> versions) throws DbException {
try {
// Find the latest local and remote updates
Group g = getContactGroup(c);
Group g = getContactGroup(c, getLocalAuthorId(txn));
LatestUpdates latest = findLatestUpdates(txn, g.getId());
// Load and parse the latest local update
if (latest.local == null) throw new DbException();
......@@ -344,16 +349,20 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
}
}
private Group getContactGroup(Contact c) {
private AuthorId getLocalAuthorId(Transaction txn) throws DbException {
return identityManager.getLocalAuthor(txn).getId();
}
private Group getContactGroup(Contact c, AuthorId local) {
return contactGroupFactory.createContactGroup(CLIENT_ID,
MAJOR_VERSION, c);
MAJOR_VERSION, c, local);
}
@Nullable
private LatestUpdates findLatestUpdates(Transaction txn, ContactId c)
throws DbException, FormatException {
Contact contact = db.getContact(txn, c);
Group g = getContactGroup(contact);
Group g = getContactGroup(contact, getLocalAuthorId(txn));
// Contact may be in the process of being added or removed, so
// contact group may not exist
if (!db.containsGroup(txn, g.getId())) return null;
......
......@@ -5,25 +5,20 @@ import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.NoSuchContactException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.AuthorInfo;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.transport.KeyManager;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.DbExpectations;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;
import java.util.Collection;
import java.util.Random;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
......@@ -33,7 +28,6 @@ import static org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED;
import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getContact;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertEquals;
......@@ -48,11 +42,10 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
private final IdentityManager identityManager =
context.mock(IdentityManager.class);
private final ContactManager contactManager;
private final Author remote = getAuthor();
private final Author author = getAuthor();
private final LocalAuthor localAuthor = getLocalAuthor();
private final AuthorId local = localAuthor.getId();
private final boolean verified = false, active = true;
private final Contact contact = getContact(remote, local, verified);
private final Contact contact = getContact(author, verified);
private final ContactId contactId = contact.getId();
public ContactManagerImplTest() {
......@@ -69,7 +62,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(false), withDbCallable(txn));
oneOf(db).addContact(txn, remote, local, verified);
oneOf(db).addContact(txn, author, verified);
will(returnValue(contactId));
oneOf(keyManager).addContact(txn, contactId, rootKey, timestamp,
alice, active);
......@@ -77,12 +70,12 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
will(returnValue(contact));
}});
assertEquals(contactId, contactManager.addContact(remote, local,
rootKey, timestamp, alice, verified, active));
assertEquals(contactId, contactManager.addContact(author, rootKey,
timestamp, alice, verified, active));
}
@Test
public void testGetContact() throws Exception {
public void testGetContactByContactId() throws Exception {
Transaction txn = new Transaction(null, true);
context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
......@@ -94,41 +87,15 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
}
@Test
public void testGetContactByAuthor() throws Exception {
public void testGetContactByAuthorId() throws Exception {
Transaction txn = new Transaction(null, true);
Collection<Contact> contacts = singletonList(contact);
context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(db).getContactsByAuthorId(txn, remote.getId());
will(returnValue(contacts));
}});
assertEquals(contact, contactManager.getContact(remote.getId(), local));
}
@Test(expected = NoSuchContactException.class)
public void testGetContactByUnknownAuthor() throws Exception {
Transaction txn = new Transaction(null, true);
context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(db).getContactsByAuthorId(txn, remote.getId());
will(returnValue(emptyList()));
}});
contactManager.getContact(remote.getId(), local);
}
@Test(expected = NoSuchContactException.class)
public void testGetContactByUnknownLocalAuthor() throws Exception {
Transaction txn = new Transaction(null, true);
Collection<Contact> contacts = singletonList(contact);
context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(db).getContactsByAuthorId(txn, remote.getId());
will(returnValue(contacts));
oneOf(db).getContact(txn, author.getId());
will(returnValue(contact));
}});
contactManager.getContact(remote.getId(), new AuthorId(getRandomId()));
assertEquals(contact, contactManager.getContact(author.getId()));
}
@Test
......@@ -182,78 +149,82 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
Transaction txn = new Transaction(null, true);
context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(db).containsContact(txn, remote.getId(), local);
oneOf(db).containsContact(txn, author.getId());
will(returnValue(true));
}});
assertTrue(contactManager.contactExists(remote.getId(), local));
assertTrue(contactManager.contactExists(author.getId()));
}
@Test
public void testGetAuthorInfo() throws Exception {
public void testGetAuthorInfoOurselves() throws Exception {
Transaction txn = new Transaction(null, true);
context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
oneOf(db).getContactsByAuthorId(txn, remote.getId());
will(returnValue(singletonList(contact)));
}});
AuthorInfo authorInfo =
contactManager.getAuthorInfo(txn, remote.getId());
assertEquals(UNVERIFIED, authorInfo.getStatus());
assertEquals(contact.getAlias(), authorInfo.getAlias());
contactManager.getAuthorInfo(txn, localAuthor.getId());
assertEquals(OURSELVES, authorInfo.getStatus());
assertNull(authorInfo.getAlias());
}
@Test
public void testGetAuthorInfoTransaction() throws DbException {
public void testGetAuthorInfoVerified() throws Exception {
Transaction txn = new Transaction(null, true);
Contact verified = getContact(author, true);
// check unknown author
context.checking(new Expectations() {{
context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
oneOf(db).getContactsByAuthorId(txn, remote.getId());
will(returnValue(emptyList()));
oneOf(db).containsContact(txn, author.getId());
will(returnValue(true));
oneOf(db).getContact(txn, author.getId());
will(returnValue(verified));
}});
AuthorInfo authorInfo =
contactManager.getAuthorInfo(txn, remote.getId());
assertEquals(UNKNOWN, authorInfo.getStatus());
assertNull(authorInfo.getAlias());
// check unverified contact
checkAuthorInfoContext(txn, remote.getId(), singletonList(contact));
authorInfo = contactManager.getAuthorInfo(txn, remote.getId());
assertEquals(UNVERIFIED, authorInfo.getStatus());
assertEquals(contact.getAlias(), authorInfo.getAlias());
// check verified contact
Contact verified = getContact(remote, local, true);
checkAuthorInfoContext(txn, remote.getId(), singletonList(verified));
authorInfo = contactManager.getAuthorInfo(txn, remote.getId());
contactManager.getAuthorInfo(txn, author.getId());
assertEquals(VERIFIED, authorInfo.getStatus());
assertEquals(verified.getAlias(), authorInfo.getAlias());
}
// check ourselves
context.checking(new Expectations() {{
@Test
public void testGetAuthorInfoUnverified() throws Exception {
Transaction txn = new Transaction(null, true);
Contact unverified = getContact(author, false);
context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
never(db).getContactsByAuthorId(txn, remote.getId());
oneOf(db).containsContact(txn, author.getId());
will(returnValue(true));
oneOf(db).getContact(txn, author.getId());
will(returnValue(unverified));
}});
authorInfo = contactManager.getAuthorInfo(txn, localAuthor.getId());
assertEquals(OURSELVES, authorInfo.getStatus());
assertNull(authorInfo.getAlias());
AuthorInfo authorInfo =
contactManager.getAuthorInfo(txn, author.getId());
assertEquals(UNVERIFIED, authorInfo.getStatus());
assertEquals(unverified.getAlias(), authorInfo.getAlias());
}
private void checkAuthorInfoContext(Transaction txn, AuthorId authorId,
Collection<Contact> contacts) throws DbException {
context.checking(new Expectations() {{
@Test
public void testGetAuthorInfoUnknown() throws Exception {
Transaction txn = new Transaction(null, true);
context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
oneOf(db).getContactsByAuthorId(txn, authorId);
will(returnValue(contacts));
oneOf(db).containsContact(txn, author.getId());
will(returnValue(false));
}});
AuthorInfo authorInfo =
contactManager.getAuthorInfo(txn, author.getId());
assertEquals(UNKNOWN, authorInfo.getStatus());
assertNull(authorInfo.getAlias());
}
}
......@@ -131,7 +131,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
metadata.put("foo", new byte[] {'b', 'a', 'r'});
transportId = getTransportId();
maxLatency = Integer.MAX_VALUE;
contact = getContact(author, localAuthor.getId(), true);
contact = getContact(author, true);
contactId = contact.getId();
alias = contact.getAlias();
keySetId = new TransportKeySetId(345);
......@@ -163,14 +163,11 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
oneOf(database).addLocalAuthor(txn, localAuthor);
oneOf(eventBus).broadcast(with(any(LocalAuthorAddedEvent.class)));
// addContact()
oneOf(database).containsLocalAuthor(txn, localAuthor.getId());
will(returnValue(true));
oneOf(database).containsLocalAuthor(txn, author.getId());
will(returnValue(false));
oneOf(database).containsContact(txn, author.getId(),
localAuthor.getId());
oneOf(database).containsContact(txn, author.getId());
will(returnValue(false));
oneOf(database).addContact(txn, author, localAuthor.getId(), true);
oneOf(database).addContact(txn, author, true);
will(returnValue(contactId));
oneOf(eventBus).broadcast(with(any(ContactAddedEvent.class)));
// getContacts()
......@@ -217,8 +214,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
assertFalse(db.open(key, null));
db.transaction(false, transaction -> {
db.addLocalAuthor(transaction, localAuthor);
assertEquals(contactId, db.addContact(transaction, author,
localAuthor.getId(), true));
assertEquals(contactId, db.addContact(transaction, author, true));
assertEquals(singletonList(contact),
db.getContacts(transaction));
db.addGroup(transaction, group); // First time - listeners called
......@@ -279,11 +275,13 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
throws Exception {
context.checking(new Expectations() {{
// Check whether the contact is in the DB (which it's not)
exactly(17).of(database).startTransaction();
exactly(18).of(database).startTransaction();
will(returnValue(txn));
exactly(17).of(database).containsContact(txn, contactId);
will(returnValue(false));
exactly(17).of(database).abortTransaction(txn);
oneOf(database).containsContact(txn, author.getId());
will(returnValue(false));
exactly(18).of(database).abortTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, eventBus,
eventExecutor, shutdownManager);
......@@ -346,6 +344,14 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
// Expected
}
try {
db.transaction(false, transaction ->
db.getContact(transaction, author.getId()));
fail();
} catch (NoSuchContactException expected) {
// Expected
}
try {
db.transaction(false, transaction ->
db.getMessageStatus(transaction, contactId, groupId));
......@@ -436,25 +442,16 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
throws Exception {
context.checking(new Expectations() {{
// Check whether the pseudonym is in the DB (which it's not)
exactly(3).of(database).startTransaction();
exactly(2).of(database).startTransaction();
will(returnValue(txn));
exactly(3).of(database).containsLocalAuthor(txn,
exactly(2).of(database).containsLocalAuthor(txn,
localAuthor.getId());
will(returnValue(false));
exactly(3).of(database).abortTransaction(txn);
exactly(2).of(database).abortTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, eventBus,
eventExecutor, shutdownManager);
try {
db.transaction(false, transaction ->
db.addContact(transaction, author, localAuthor.getId(),
true));
fail();
} catch (NoSuchLocalAuthorException expected) {
// Expected
}
try {
db.transaction(false, transaction ->
db.getLocalAuthor(transaction, localAuthor.getId()));
......@@ -1403,8 +1400,6 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
context.checking(new Expectations() {{
oneOf(database).startTransaction();
will(returnValue(txn));
oneOf(database).containsLocalAuthor(txn, localAuthor.getId());
will(returnValue(true));
// Contact is a local identity
oneOf(database).containsLocalAuthor(txn, author.getId());
will(returnValue(true));
......@@ -1416,8 +1411,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
try {
db.transaction(false, transaction ->
db.addContact(transaction, author, localAuthor.getId(),
true));
db.addContact(transaction, author, true));
fail();
} catch (ContactExistsException expected) {
// Expected
......@@ -1429,13 +1423,10 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
context.checking(new Expectations() {{
oneOf(database).startTransaction();
will(returnValue(txn));
oneOf(database).containsLocalAuthor(txn, localAuthor.getId());
will(returnValue(true));
oneOf(database).containsLocalAuthor(txn, author.getId());
will(returnValue(false));
// Contact already exists for this local identity
oneOf(database).containsContact(txn, author.getId(),
localAuthor.getId());
// Contact already exists
oneOf(database).containsContact(txn, author.getId());
will(returnValue(true));
oneOf(database).abortTransaction(txn);
}});
......@@ -1445,8 +1436,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
try {
db.transaction(false, transaction ->
db.addContact(transaction, author, localAuthor.getId(),
true));
db.addContact(transaction, author, true));
fail();
} catch (ContactExistsException expected) {
// Expected
......
......@@ -4,7 +4,6 @@ import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group;
......@@ -131,11 +130,10 @@ public abstract class DatabasePerformanceTest extends BrambleTestCase {
@Test
public void testContainsContactByAuthorId() throws Exception {
String name = "containsContact(T, AuthorId, AuthorId)";
String name = "containsContact(T, AuthorId)";
benchmark(name, db -> {
Connection txn = db.startTransaction();
AuthorId remote = pickRandom(contacts).getAuthor().getId();
db.containsContact(txn, remote, localAuthor.getId());
db.containsContact(txn, pickRandom(contacts).getAuthor().getId());
db.commitTransaction(txn);
});
}
......@@ -202,7 +200,7 @@ public abstract class DatabasePerformanceTest extends BrambleTestCase {
}
@Test
public void testGetContact() throws Exception {
public void testGetContactByContactId() throws Exception {
String name = "getContact(T, ContactId)";
benchmark(name, db -> {
Connection txn = db.startTransaction();
......@@ -212,32 +210,21 @@ public abstract class DatabasePerformanceTest extends BrambleTestCase {
}
@Test
public void testGetContacts() throws Exception {
String name = "getContacts(T)";
public void testGetContactByAuthorId() throws Exception {
String name = "getContact(T, AuthorId)";
benchmark(name, db -> {
Connection txn = db.startTransaction();
db.getContacts(txn);
db.getContact(txn, pickRandom(contacts).getAuthor().getId());
db.commitTransaction(txn);
});
}
@Test
public void testGetContactsByRemoteAuthorId() throws Exception {
String name = "getContactsByAuthorId(T, AuthorId)";
benchmark(name, db -> {
Connection txn = db.startTransaction();
AuthorId remote = pickRandom(contacts).getAuthor().getId();
db.getContactsByAuthorId(txn, remote);
db.commitTransaction(txn);
});
}
@Test
public void testGetContactsByLocalAuthorId() throws Exception {
String name = "getContacts(T, AuthorId)";
public void testGetContacts() throws Exception {
String name = "getContacts(T)";
benchmark(name, db -> {
Connection txn = db.startTransaction();
db.getContacts(txn, localAuthor.getId());
db.getContacts(txn);
db.commitTransaction(txn);
});
}
......@@ -545,8 +532,7 @@ public abstract class DatabasePerformanceTest extends BrambleTestCase {
Connection txn = db.startTransaction();
db.addLocalAuthor(txn, localAuthor);
for (int i = 0; i < CONTACTS; i++) {
ContactId c = db.addContact(txn, getAuthor(), localAuthor.getId(),
random.nextBoolean());
ContactId c = db.addContact(txn, getAuthor(), random.nextBoolean());
contacts.add(db.getContact(txn, c));
contactGroups.put(c, new ArrayList<>());
for (int j = 0; j < GROUPS_PER_CONTACT; j++) {
......
......@@ -84,7 +84,6 @@ import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
......@@ -146,8 +145,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
assertFalse(db.containsContact(txn, contactId));
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
assertTrue(db.containsContact(txn, contactId));
assertFalse(db.containsGroup(txn, groupId));
db.addGroup(txn, group);
......@@ -208,9 +206,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true);
db.addMessage(txn, message, DELIVERED, true, null);
......@@ -239,9 +235,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared but unvalidated message
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true);
db.addMessage(txn, message, UNKNOWN, true, null);
......@@ -284,9 +278,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, an invisible group and a shared message
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addGroup(txn, group);
db.addMessage(txn, message, DELIVERED, true, null);
......@@ -335,9 +327,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a shared group and an unshared message
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true);
db.addMessage(txn, message, DELIVERED, false, null);
......@@ -366,17 +356,14 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true);
db.addMessage(txn, message, DELIVERED, true, null);
// The message is sendable, but too large to send
Collection<MessageId> ids =
db.getMessagesToSend(txn, contactId, message.getRawLength() - 1,
MAX_LATENCY);
Collection<MessageId> ids = db.getMessagesToSend(txn, contactId,
message.getRawLength() - 1, MAX_LATENCY);
assertTrue(ids.isEmpty());
// The message is just the right size to send
ids = db.getMessagesToSend(txn, contactId, message.getRawLength(),
......@@ -393,9 +380,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact and a visible group
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, false);
......@@ -434,9 +419,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true);
db.addMessage(txn, message, DELIVERED, true, null);
......@@ -566,9 +549,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact and a shared group
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true);
......@@ -586,9 +567,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
// The group is not in the database
assertFalse(db.containsVisibleMessage(txn, contactId, messageId));
......@@ -604,9 +583,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, an invisible group and a message
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addGroup(txn, group);
db.addMessage(txn, message, DELIVERED, true, null);
......@@ -623,9 +600,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact and a group
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addGroup(txn, group);
// The group should not be visible to the contact
......@@ -675,9 +650,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertEquals(emptyList(), db.getTransportKeys(txn, transportId));
// Add the contact, the transport and the transport keys
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addTransport(txn, transportId, 123);
assertEquals(keySetId, db.addTransportKeys(txn, contactId, keys));
assertEquals(keySetId1, db.addTransportKeys(txn, contactId, keys1));
......@@ -776,9 +749,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertEquals(emptyList(), db.getHandshakeKeys(txn, transportId));
// Add the contact, the transport and the handshake keys
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addTransport(txn, transportId, 123);
assertEquals(handshakeKeySetId,
db.addHandshakeKeys(txn, contactId, keys));
......@@ -929,9 +900,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add the contact, transport and transport keys
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addTransport(txn, transportId, 123);
assertEquals(keySetId, db.addTransportKeys(txn, contactId, keys));
......@@ -973,9 +942,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add the contact, transport and handshake keys
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addTransport(txn, transportId, 123);
assertEquals(handshakeKeySetId,
db.addHandshakeKeys(txn, contactId, keys));
......@@ -1020,9 +987,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add the contact, transport and transport keys
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addTransport(txn, transportId, 123);
assertEquals(keySetId, db.addTransportKeys(txn, contactId, keys));
......@@ -1067,9 +1032,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add the contact, transport and handshake keys
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author,true));
db.addTransport(txn, transportId, 123);
assertEquals(handshakeKeySetId,
db.addHandshakeKeys(txn, contactId, keys));
......@@ -1105,54 +1068,42 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
}
@Test
public void testGetContactsByAuthorId() throws Exception {
public void testGetContactByContactId() throws Exception {
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
// Add a local author - no contacts should be associated
db.addLocalAuthor(txn, localAuthor);
// Add a contact associated with the local author
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
// Ensure contact is returned from database by Author ID
Collection<Contact> contacts =
db.getContactsByAuthorId(txn, author.getId());
assertEquals(1, contacts.size());
assertEquals(contactId, contacts.iterator().next().getId());
// Add a contact
assertEquals(contactId, db.addContact(txn, author, true));
// Ensure no contacts are returned after contact was deleted
db.removeContact(txn, contactId);
contacts = db.getContactsByAuthorId(txn, author.getId());
assertEquals(0, contacts.size());
// Check the contact is returned
Contact c = db.getContact(txn, contactId);
assertEquals(contactId, c.getId());
assertEquals(author.getId(), c.getAuthor().getId());
assertEquals(author.getFormatVersion(),
c.getAuthor().getFormatVersion());
assertEquals(author.getName(), c.getAuthor().getName());
assertArrayEquals(author.getPublicKey(), c.getAuthor().getPublicKey());
db.commitTransaction(txn);
db.close();
}
@Test
public void testGetContactsByLocalAuthorId() throws Exception {
public void testGetContactByAuthorId() throws Exception {
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
// Add a local author - no contacts should be associated
db.addLocalAuthor(txn, localAuthor);
Collection<ContactId> contacts =
db.getContacts(txn, localAuthor.getId());
assertEquals(emptyList(), contacts);
// Add a contact associated with the local author
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
contacts = db.getContacts(txn, localAuthor.getId());
assertEquals(singletonList(contactId), contacts);
// Remove the local author - the contact should be removed
db.removeLocalAuthor(txn, localAuthor.getId());
contacts = db.getContacts(txn, localAuthor.getId());
assertEquals(emptyList(), contacts);
assertFalse(db.containsContact(txn, contactId));
// Add a contact
assertEquals(contactId, db.addContact(txn, author, true));
// Check the contact is returned
Contact c = db.getContact(txn, author.getId());
assertEquals(contactId, c.getId());
assertEquals(author.getId(), c.getAuthor().getId());
assertEquals(author.getFormatVersion(),
c.getAuthor().getFormatVersion());
assertEquals(author.getName(), c.getAuthor().getName());
assertArrayEquals(author.getPublicKey(), c.getAuthor().getPublicKey());
db.commitTransaction(txn);
db.close();
......@@ -1164,9 +1115,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact - initially there should be no offered messages
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
assertEquals(0, db.countOfferedMessages(txn, contactId));
// Add some offered messages and count them
......@@ -1748,9 +1697,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true);
db.addMessage(txn, message, DELIVERED, true, null);
......@@ -1847,43 +1794,13 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
db.close();
}
@Test
public void testDifferentLocalAuthorsCanHaveTheSameContact()
throws Exception {
LocalAuthor localAuthor1 = getLocalAuthor();
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
// Add two local authors
db.addLocalAuthor(txn, localAuthor);
db.addLocalAuthor(txn, localAuthor1);
// Add the same contact for each local author
ContactId contactId =
db.addContact(txn, author, localAuthor.getId(), true);
ContactId contactId1 =
db.addContact(txn, author, localAuthor1.getId(), true);
// The contacts should be distinct
assertNotEquals(contactId, contactId1);
assertEquals(2, db.getContacts(txn).size());
assertEquals(1, db.getContacts(txn, localAuthor.getId()).size());
assertEquals(1, db.getContacts(txn, localAuthor1.getId()).size());
db.commitTransaction(txn);
db.close();
}
@Test
public void testDeleteMessage() throws Exception {
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true);
db.addMessage(txn, message, DELIVERED, true, null);
......@@ -1935,9 +1852,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
// The contact should have no alias
Contact contact = db.getContact(txn, contactId);
......@@ -1992,9 +1907,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a group and a message
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addGroup(txn, group);
db.addMessage(txn, message, UNKNOWN, false, null);
......@@ -2076,9 +1989,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true);
db.addMessage(txn, message, DELIVERED, true, null);
......@@ -2121,9 +2032,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(contactId, db.addContact(txn, author, true));
db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true);
db.addMessage(txn, message, DELIVERED, true, null);
......
......@@ -11,6 +11,8 @@ import org.briarproject.bramble.api.data.MetadataParser;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.sync.Group;
......@@ -37,6 +39,7 @@ import static org.briarproject.bramble.api.properties.TransportPropertyManager.M
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.test.TestUtils.getContact;
import static org.briarproject.bramble.test.TestUtils.getGroup;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static org.briarproject.bramble.test.TestUtils.getMessage;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.junit.Assert.assertEquals;
......@@ -46,6 +49,8 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
private final ClientHelper clientHelper = context.mock(ClientHelper.class);
private final IdentityManager identityManager =
context.mock(IdentityManager.class);
private final ClientVersioningManager clientVersioningManager =
context.mock(ClientVersioningManager.class);
private final MetadataParser metadataParser =
......@@ -55,6 +60,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
private final Clock clock = context.mock(Clock.class);
private final Group localGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
private final LocalAuthor localAuthor = getLocalAuthor();
private final BdfDictionary fooPropertiesDict = BdfDictionary.of(
new BdfEntry("fooKey1", "fooValue1"),
new BdfEntry("fooKey2", "fooValue2")
......@@ -81,8 +87,8 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
will(returnValue(localGroup));
}});
return new TransportPropertyManagerImpl(db, clientHelper,
clientVersioningManager, metadataParser, contactGroupFactory,
clock);
identityManager, clientVersioningManager, metadataParser,
contactGroupFactory, clock);
}
@Test
......@@ -95,10 +101,12 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
oneOf(db).containsGroup(txn, localGroup.getId());
will(returnValue(false));
oneOf(db).addGroup(txn, localGroup);
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
oneOf(db).getContacts(txn);
will(returnValue(singletonList(contact)));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
MAJOR_VERSION, contact, localAuthor.getId());
will(returnValue(contactGroup));
oneOf(db).addGroup(txn, contactGroup);
oneOf(clientVersioningManager).getClientVisibility(txn,
......@@ -140,8 +148,10 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
context.checking(new Expectations() {{
// Create the group and share it with the contact
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
MAJOR_VERSION, contact, localAuthor.getId());
will(returnValue(contactGroup));
oneOf(db).addGroup(txn, contactGroup);
oneOf(clientVersioningManager).getClientVisibility(txn,
......@@ -168,8 +178,10 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
context.checking(new Expectations() {{
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
MAJOR_VERSION, contact, localAuthor.getId());
will(returnValue(contactGroup));
oneOf(db).removeGroup(txn, contactGroup);
}});
......@@ -307,8 +319,10 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
context.checking(new Expectations() {{
oneOf(db).getContact(txn, contact.getId());
will(returnValue(contact));
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
MAJOR_VERSION, contact, localAuthor.getId());
will(returnValue(contactGroup));
}});
expectStoreMessage(txn, contactGroup.getId(), "foo", fooPropertiesDict,
......@@ -432,18 +446,20 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
oneOf(db).getContacts(txn);
will(returnValue(contacts));
// First contact: no updates
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact1);
MAJOR_VERSION, contact1, localAuthor.getId());
will(returnValue(contactGroup1));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup1.getId());
will(returnValue(Collections.emptyMap()));
// Second contact: returns an update
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact2);
MAJOR_VERSION, contact2, localAuthor.getId());
will(returnValue(contactGroup2));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup2.getId());
......@@ -510,10 +526,12 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
expectStoreMessage(txn, localGroup.getId(), "foo",
fooPropertiesDict, 1, true, false);
// Store the new properties in each contact's group, version 1
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
oneOf(db).getContacts(txn);
will(returnValue(singletonList(contact)));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
MAJOR_VERSION, contact, localAuthor.getId());
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId());
......@@ -566,10 +584,12 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
// Delete the previous update
oneOf(db).removeMessage(txn, localGroupUpdateId);
// Store the merged properties in each contact's group, version 2
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
oneOf(db).getContacts(txn);
will(returnValue(singletonList(contact)));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
MAJOR_VERSION, contact, localAuthor.getId());
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId());
......
......@@ -10,6 +10,8 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility;
......@@ -36,6 +38,7 @@ import static org.briarproject.bramble.api.versioning.ClientVersioningManager.MA
import static org.briarproject.bramble.test.TestUtils.getClientId;
import static org.briarproject.bramble.test.TestUtils.getContact;
import static org.briarproject.bramble.test.TestUtils.getGroup;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static org.briarproject.bramble.test.TestUtils.getMessage;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.versioning.ClientVersioningConstants.GROUP_KEY_CONTACT_ID;
......@@ -48,12 +51,15 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
private final ClientHelper clientHelper = context.mock(ClientHelper.class);
private final IdentityManager identityManager =
context.mock(IdentityManager.class);
private final ContactGroupFactory contactGroupFactory =
context.mock(ContactGroupFactory.class);
private final Clock clock = context.mock(Clock.class);
private final ClientVersioningHook hook =
context.mock(ClientVersioningHook.class);
private final LocalAuthor localAuthor = getLocalAuthor();
private final Group localGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
private final Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
private final Contact contact = getContact();
......@@ -68,7 +74,7 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
will(returnValue(localGroup));
}});
return new ClientVersioningManagerImpl(db, clientHelper,
contactGroupFactory, clock);
identityManager, contactGroupFactory, clock);
}
@Test
......@@ -117,8 +123,10 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
new BdfEntry(MSG_KEY_LOCAL, true));
context.checking(new Expectations() {{
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
MAJOR_VERSION, contact, localAuthor.getId());
will(returnValue(contactGroup));
oneOf(db).addGroup(txn, contactGroup);
oneOf(db).setGroupVisibility(txn, contact.getId(),
......@@ -138,8 +146,10 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
@Test
public void testRemovesGroupWhenRemovingContact() throws Exception {
context.checking(new Expectations() {{
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
MAJOR_VERSION, contact, localAuthor.getId());
will(returnValue(contactGroup));
oneOf(db).removeGroup(txn, contactGroup);
}});
......@@ -174,10 +184,12 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
oneOf(db).addLocalMessage(txn, localVersions, new Metadata(),
false);
// Inform contacts that client versions have changed
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
oneOf(db).getContacts(txn);
will(returnValue(singletonList(contact)));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
MAJOR_VERSION, contact, localAuthor.getId());
will(returnValue(contactGroup));
// Find the latest local and remote updates (no remote update)
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
......@@ -261,10 +273,12 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
oneOf(db).addLocalMessage(txn, newLocalVersions, new Metadata(),
false);
// Inform contacts that client versions have changed
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
oneOf(db).getContacts(txn);
will(returnValue(singletonList(contact)));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
MAJOR_VERSION, contact, localAuthor.getId());
will(returnValue(contactGroup));
// Find the latest local and remote updates (no remote update)
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
......@@ -357,10 +371,12 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
oneOf(db).addLocalMessage(txn, newLocalVersions, new Metadata(),
false);
// Inform contacts that client versions have changed
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
oneOf(db).getContacts(txn);
will(returnValue(singletonList(contact)));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
MAJOR_VERSION, contact, localAuthor.getId());
will(returnValue(contactGroup));
// Find the latest local and remote updates
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
......@@ -970,8 +986,10 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
context.checking(new Expectations() {{
oneOf(db).getContact(txn, contact.getId());
will(returnValue(contact));
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
MAJOR_VERSION, contact, localAuthor.getId());
will(returnValue(contactGroup));
oneOf(db).containsGroup(txn, contactGroup.getId());
will(returnValue(exists));
......