Merge branch 'privategroup-testdata' into 'master'

TestDataCreator with support for private groups

See merge request briar/briar!1788
This commit is contained in:
Torsten Grote
2023-04-26 12:38:53 +00:00
4 changed files with 221 additions and 43 deletions

View File

@@ -24,9 +24,10 @@ public class TestDataActivity extends BriarActivity {
@Inject
TestDataCreator testDataCreator;
private TextView contactsTextView, forumsTextView;
private TextView contactsTextView, forumsTextView, privateGroupsTextView;
private SeekBar contactsSeekBar, messagesSeekBar, avatarsSeekBar,
blogPostsSeekBar, forumsSeekBar, forumPostsSeekBar;
blogPostsSeekBar, forumsSeekBar, forumPostsSeekBar,
privateGroupsSeekBar, privateGroupPostsSeekBar;
@Override
public void onCreate(Bundle bundle) {
@@ -46,28 +47,26 @@ public class TestDataActivity extends BriarActivity {
forumsTextView = findViewById(R.id.TextViewForumsSb);
TextView forumPostsTextView =
findViewById(R.id.TextViewForumMessagesSb);
privateGroupsTextView = findViewById(R.id.TextViewPrivateGroupsSb);
TextView privateGroupPostsTextView =
findViewById(R.id.TextViewPrivateGroupMessagesSb);
contactsSeekBar = findViewById(R.id.seekBarContacts);
messagesSeekBar = findViewById(R.id.seekBarMessages);
avatarsSeekBar = findViewById(R.id.seekBarAvatars);
blogPostsSeekBar = findViewById(R.id.seekBarBlogPosts);
forumsSeekBar = findViewById(R.id.seekBarForums);
forumPostsSeekBar = findViewById(R.id.seekBarForumMessages);
privateGroupsSeekBar = findViewById(R.id.seekBarPrivateGroups);
privateGroupPostsSeekBar =
findViewById(R.id.seekBarPrivateGroupMessages);
contactsSeekBar
.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
contactsSeekBar.setOnSeekBarChangeListener(
new AbstractOnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar,
int progress, boolean fromUser) {
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
contactsTextView.setText(String.valueOf(progress + 1));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
messagesSeekBar.setOnSeekBarChangeListener(
@@ -76,35 +75,39 @@ public class TestDataActivity extends BriarActivity {
new OnSeekBarChangeUpdateProgress(avatarsTextView));
blogPostsSeekBar.setOnSeekBarChangeListener(
new OnSeekBarChangeUpdateProgress(blogPostsTextView));
forumsSeekBar
.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
forumsSeekBar.setOnSeekBarChangeListener(
new AbstractOnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar,
int progress, boolean fromUser) {
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
forumsTextView.setText(String.valueOf(progress));
forumPostsSeekBar.setEnabled(progress > 0);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
forumPostsSeekBar.setOnSeekBarChangeListener(
new OnSeekBarChangeUpdateProgress(forumPostsTextView));
findViewById(R.id.buttonZeroValues).setOnClickListener(
v -> {
contactsSeekBar.setProgress(0);
messagesSeekBar.setProgress(0);
avatarsSeekBar.setProgress(0);
blogPostsSeekBar.setProgress(0);
forumsSeekBar.setProgress(0);
forumPostsSeekBar.setProgress(0);
privateGroupsSeekBar.setOnSeekBarChangeListener(
new AbstractOnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
privateGroupsTextView.setText(String.valueOf(progress));
privateGroupPostsSeekBar.setEnabled(progress > 0);
}
});
privateGroupPostsSeekBar.setOnSeekBarChangeListener(
new OnSeekBarChangeUpdateProgress(privateGroupPostsTextView));
findViewById(R.id.buttonZeroValues).setOnClickListener(v -> {
contactsSeekBar.setProgress(0);
messagesSeekBar.setProgress(0);
avatarsSeekBar.setProgress(0);
blogPostsSeekBar.setProgress(0);
forumsSeekBar.setProgress(0);
forumPostsSeekBar.setProgress(0);
privateGroupsSeekBar.setProgress(0);
privateGroupPostsSeekBar.setProgress(0);
});
findViewById(R.id.buttonCreateTestData).setOnClickListener(
v -> createTestData());
@@ -114,7 +117,9 @@ public class TestDataActivity extends BriarActivity {
testDataCreator.createTestData(contactsSeekBar.getProgress() + 1,
messagesSeekBar.getProgress(), avatarsSeekBar.getProgress(),
blogPostsSeekBar.getProgress(), forumsSeekBar.getProgress(),
forumPostsSeekBar.getProgress());
forumPostsSeekBar.getProgress(),
privateGroupsSeekBar.getProgress(),
privateGroupPostsSeekBar.getProgress());
Intent intent = new Intent(this, ENTRY_ACTIVITY);
intent.addFlags(FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
@@ -136,7 +141,7 @@ public class TestDataActivity extends BriarActivity {
}
private static class OnSeekBarChangeUpdateProgress
implements OnSeekBarChangeListener {
extends AbstractOnSeekBarChangeListener {
private final TextView textView;
private OnSeekBarChangeUpdateProgress(TextView textView) {
@@ -148,7 +153,10 @@ public class TestDataActivity extends BriarActivity {
boolean fromUser) {
textView.setText(String.valueOf(progress));
}
}
private abstract static class AbstractOnSeekBarChangeListener
implements OnSeekBarChangeListener {
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@@ -157,5 +165,4 @@ public class TestDataActivity extends BriarActivity {
public void onStopTrackingTouch(SeekBar seekBar) {
}
}
}

View File

@@ -191,6 +191,66 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewForumMessages" />
<TextView
android:id="@+id/textViewPrivateGroups"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/margin_medium"
android:text="Number of private groups"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/seekBarForumMessages" />
<SeekBar
android:id="@+id/seekBarPrivateGroups"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:max="50"
android:paddingTop="5dp"
android:progress="5"
app:layout_constraintEnd_toStartOf="@+id/TextViewPrivateGroupsSb"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewPrivateGroups" />
<TextView
android:id="@+id/TextViewPrivateGroupsSb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="2"
android:text="5"
app:layout_constraintBottom_toBottomOf="@+id/seekBarPrivateGroups"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewPrivateGroups" />
<TextView
android:id="@+id/textViewPrivateGroupMessages"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/margin_medium"
android:text="Number of private group messages"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/seekBarPrivateGroups" />
<SeekBar
android:id="@+id/seekBarPrivateGroupMessages"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:max="50"
android:paddingTop="5dp"
android:progress="20"
app:layout_constraintEnd_toStartOf="@+id/TextViewPrivateGroupMessagesSb"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewPrivateGroupMessages" />
<TextView
android:id="@+id/TextViewPrivateGroupMessagesSb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="2"
android:text="20"
app:layout_constraintBottom_toBottomOf="@+id/seekBarPrivateGroupMessages"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewPrivateGroupMessages" />
<Button
android:id="@+id/buttonZeroValues"
style="@style/BriarButton"
@@ -201,7 +261,7 @@
android:text="Zero values"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/seekBarForumMessages"
app:layout_constraintTop_toBottomOf="@+id/seekBarPrivateGroupMessages"
app:layout_constraintVertical_bias="1.0" />
<Button

View File

@@ -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)

View File

@@ -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<Contact> 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<PrivateGroup> groups =
createPrivateGroups(contacts, numPrivateGroups);
for (PrivateGroup group : groups) {
createRandomPrivateGroupMessages(group, contacts,
numPrivateGroupMessages);
}
}
private List<Contact> createContacts(int numContacts, int avatarPercent)
@@ -464,6 +492,86 @@ public class TestDataCreatorImpl implements TestDataCreator {
}
}
private List<PrivateGroup> createPrivateGroups(List<Contact> contacts,
int numPrivateGroups) throws DbException {
if (!featureFlags.shouldEnablePrivateGroupsInCore()) return emptyList();
List<PrivateGroup> 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<Contact> contacts, int amount) throws DbException {
List<GroupMessage> messages = new ArrayList<>();
PrivateKey creatorPrivateKey =
identityManager.getLocalAuthor().getPrivateKey();
int numMembers = random.nextInt(contacts.size());
if (numMembers == 0) numMembers++;
Map<Contact, MessageId> membersLastMessage = new HashMap<>();
List<Contact> 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;