diff --git a/briar-api/src/main/java/org/briarproject/briar/api/test/TestDataCreator.java b/briar-api/src/main/java/org/briarproject/briar/api/test/TestDataCreator.java index b40fd67d3..01c301f02 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/test/TestDataCreator.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/test/TestDataCreator.java @@ -19,9 +19,12 @@ public interface TestDataCreator { * @param numBlogPosts Number of blog posts to create. * @param numForums Number of forums to create. * @param numForumPosts Number of forum posts to create per forum. + * @param numPrivateGroups Number of private groups to create. + * @param numPrivateGroupMessages Number of messages to create per private group. */ void createTestData(int numContacts, int numPrivateMsgs, int avatarPercent, - int numBlogPosts, int numForums, int numForumPosts); + int numBlogPosts, int numForums, int numForumPosts, + int numPrivateGroups, int numPrivateGroupMessages); @IoExecutor Contact addContact(String name, boolean alias, boolean avatar) diff --git a/briar-core/src/main/java/org/briarproject/briar/test/TestDataCreatorImpl.java b/briar-core/src/main/java/org/briarproject/briar/test/TestDataCreatorImpl.java index 5ff3640d7..e8e2ce342 100644 --- a/briar-core/src/main/java/org/briarproject/briar/test/TestDataCreatorImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/test/TestDataCreatorImpl.java @@ -6,6 +6,7 @@ import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.crypto.CryptoComponent; +import org.briarproject.bramble.api.crypto.PrivateKey; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DbException; @@ -38,6 +39,12 @@ import org.briarproject.briar.api.forum.ForumPost; import org.briarproject.briar.api.messaging.MessagingManager; import org.briarproject.briar.api.messaging.PrivateMessage; import org.briarproject.briar.api.messaging.PrivateMessageFactory; +import org.briarproject.briar.api.privategroup.GroupMessage; +import org.briarproject.briar.api.privategroup.GroupMessageFactory; +import org.briarproject.briar.api.privategroup.PrivateGroup; +import org.briarproject.briar.api.privategroup.PrivateGroupFactory; +import org.briarproject.briar.api.privategroup.PrivateGroupManager; +import org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory; import org.briarproject.briar.api.test.TestAvatarCreator; import org.briarproject.briar.api.test.TestDataCreator; import org.briarproject.nullsafety.NotNullByDefault; @@ -89,6 +96,10 @@ public class TestDataCreatorImpl implements TestDataCreator { private final MessagingManager messagingManager; private final BlogManager blogManager; private final ForumManager forumManager; + private final PrivateGroupManager privateGroupManager; + private final PrivateGroupFactory privateGroupFactory; + private final GroupMessageFactory groupMessageFactory; + private final GroupInvitationFactory groupInvitationFactory; private final TestAvatarCreator testAvatarCreator; private final AvatarMessageEncoder avatarMessageEncoder; @@ -111,6 +122,10 @@ public class TestDataCreatorImpl implements TestDataCreator { TransportPropertyManager transportPropertyManager, MessagingManager messagingManager, BlogManager blogManager, ForumManager forumManager, + PrivateGroupManager privateGroupManager, + PrivateGroupFactory privateGroupFactory, + GroupMessageFactory groupMessageFactory, + GroupInvitationFactory groupInvitationFactory, TestAvatarCreator testAvatarCreator, AvatarMessageEncoder avatarMessageEncoder, FeatureFlags featureFlags, @@ -128,6 +143,10 @@ public class TestDataCreatorImpl implements TestDataCreator { this.messagingManager = messagingManager; this.blogManager = blogManager; this.forumManager = forumManager; + this.privateGroupManager = privateGroupManager; + this.privateGroupFactory = privateGroupFactory; + this.groupMessageFactory = groupMessageFactory; + this.groupInvitationFactory = groupInvitationFactory; this.testAvatarCreator = testAvatarCreator; this.avatarMessageEncoder = avatarMessageEncoder; this.featureFlags = featureFlags; @@ -137,14 +156,16 @@ public class TestDataCreatorImpl implements TestDataCreator { @Override public void createTestData(int numContacts, int numPrivateMsgs, int avatarPercent, int numBlogPosts, int numForums, - int numForumPosts) { + int numForumPosts, int numPrivateGroups, + int numPrivateGroupMessages) { if (numContacts == 0) throw new IllegalArgumentException(); if (avatarPercent < 0 || avatarPercent > 100) throw new IllegalArgumentException(); ioExecutor.execute(() -> { try { createTestDataOnIoExecutor(numContacts, numPrivateMsgs, - avatarPercent, numBlogPosts, numForums, numForumPosts); + avatarPercent, numBlogPosts, numForums, numForumPosts, + numPrivateGroups, numPrivateGroupMessages); } catch (DbException e) { logException(LOG, WARNING, e); } @@ -154,7 +175,8 @@ public class TestDataCreatorImpl implements TestDataCreator { @IoExecutor private void createTestDataOnIoExecutor(int numContacts, int numPrivateMsgs, int avatarPercent, int numBlogPosts, int numForums, - int numForumPosts) throws DbException { + int numForumPosts, int numPrivateGroups, + int numPrivateGroupMessages) throws DbException { List contacts = createContacts(numContacts, avatarPercent); createPrivateMessages(contacts, numPrivateMsgs); createBlogPosts(contacts, numBlogPosts); @@ -162,6 +184,12 @@ public class TestDataCreatorImpl implements TestDataCreator { for (Forum forum : forums) { createRandomForumPosts(forum, contacts, numForumPosts); } + List groups = + createPrivateGroups(contacts, numPrivateGroups); + for (PrivateGroup group : groups) { + createRandomPrivateGroupMessages(group, contacts, + numPrivateGroupMessages); + } } private List createContacts(int numContacts, int avatarPercent) @@ -442,6 +470,10 @@ public class TestDataCreatorImpl implements TestDataCreator { private void createRandomForumPosts(Forum forum, List contacts, int numForumPosts) throws DbException { + if (contacts.isEmpty() && LOG.isLoggable(INFO)) { + LOG.info("No forum posts created due to missing contacts."); + return; + } List posts = new ArrayList<>(); for (int i = 0; i < numForumPosts; i++) { Contact contact = contacts.get(random.nextInt(contacts.size())); @@ -464,6 +496,91 @@ public class TestDataCreatorImpl implements TestDataCreator { } } + private List createPrivateGroups(List contacts, + int numPrivateGroups) throws DbException { + if (!featureFlags.shouldEnablePrivateGroupsInCore()) return emptyList(); + List groups = new ArrayList<>(numPrivateGroups); + for (int i = 0; i < numPrivateGroups; i++) { + // create private group + String name = GROUP_NAMES[random.nextInt(GROUP_NAMES.length)]; + LocalAuthor creator = identityManager.getLocalAuthor(); + PrivateGroup group = + privateGroupFactory.createPrivateGroup(name, creator); + GroupMessage joinMsg = groupMessageFactory.createJoinMessage( + group.getId(), + clock.currentTimeMillis() - (long) (100 - i) * 60 * 1000, + creator + ); + privateGroupManager.addPrivateGroup(group, joinMsg, true); + groups.add(group); + } + if (LOG.isLoggable(INFO)) { + LOG.info("Created " + numPrivateGroups + " private groups."); + } + return groups; + } + + private void createRandomPrivateGroupMessages(PrivateGroup group, + List contacts, int amount) throws DbException { + if (contacts.isEmpty() && LOG.isLoggable(INFO)) { + LOG.info("No private group messages created " + + "due to missing contacts."); + return; + } + List messages = new ArrayList<>(); + PrivateKey creatorPrivateKey = + identityManager.getLocalAuthor().getPrivateKey(); + int numMembers = random.nextInt(contacts.size()); + if (numMembers == 0) numMembers++; + Map membersLastMessage = new HashMap<>(); + List members = new ArrayList<>(numMembers); + for (int i = 0; i < numMembers; i++) { + Contact contact = contacts.get(i); + members.add(contact); + } + for (int i = 0; i < amount; i++) { + Contact contact = members.get(random.nextInt(numMembers)); + LocalAuthor author = localAuthors.get(contact); + long timestamp = + clock.currentTimeMillis() - + (long) (amount - i) * 60 * 1000; + + GroupMessage msg; + if (!membersLastMessage.containsKey(contact)) { + // join message as first message of member + shareGroup(contact.getId(), group.getId()); + long inviteTimestamp = timestamp - 1; + byte[] creatorSignature = + groupInvitationFactory.signInvitation(contact, + group.getId(), inviteTimestamp, + creatorPrivateKey); + msg = groupMessageFactory.createJoinMessage(group.getId(), + timestamp, author, inviteTimestamp, + creatorSignature); + } else { + // random text after first message + String text = getRandomText(); + MessageId parent = null; + if (random.nextBoolean() && messages.size() > 0) { + GroupMessage parentMessage = + messages.get(random.nextInt(messages.size())); + parent = parentMessage.getMessage().getId(); + } + MessageId lastMsg = membersLastMessage.get(contact); + msg = groupMessageFactory.createGroupMessage( + group.getId(), timestamp, parent, author, text, + lastMsg); + messages.add(msg); + } + membersLastMessage.put(contact, msg.getMessage().getId()); + db.transaction(false, txn -> + db.receiveMessage(txn, contact.getId(), msg.getMessage())); + } + if (LOG.isLoggable(INFO)) { + LOG.info("Created " + amount + " private group messages."); + } + } + private String getRandomText() { int minLength = 3 + random.nextInt(500); int maxWordLength = 15;