diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestDeterministicConversations.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestDeterministicConversations.kt index 90736bbe4396f900e8e2b264b8c7fb046868f705..553588c8adfc195053090bd3ddc66a97d4d38364 100644 --- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestDeterministicConversations.kt +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestDeterministicConversations.kt @@ -19,6 +19,6 @@ package org.briarproject.briar.desktop fun main() = RunWithTemporaryAccount { - getDeterministicTestDataCreator().createTestData(5, 20, 50, 10, 20) + getDeterministicTestDataCreator().createTestData() getContactManager().addPendingContact("briar://aatkjq4seoualafpwh4cfckdzr4vpr4slk3bbvpxklf7y7lv4ajw6", "Faythe") }.run() diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestMixedConversations.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestMixedConversations.kt index 41647e12e712bd562a201f7d497ad1db8236106a..5b3d1b20ab79c94eb3230bdc14cad7d105dd71ea 100644 --- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestMixedConversations.kt +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestMixedConversations.kt @@ -19,6 +19,6 @@ package org.briarproject.briar.desktop fun main() = RunWithTemporaryAccount { - getDeterministicTestDataCreator().createTestData(5, 20, 50, 10, 20) + getDeterministicTestDataCreator().createTestData() getTestDataCreator().createTestData(5, 20, 50, 4, 10, 10) }.run() diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestScreenshot.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestScreenshot.kt index c9a31cdf70342ed2096f2098ab043230aef8fff0..fdea3c367f3c80d2e444ab3c55f75dd2e0e884f9 100644 --- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestScreenshot.kt +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestScreenshot.kt @@ -27,7 +27,7 @@ import org.briarproject.bramble.api.plugin.LanTcpConstants * This includes faking connections to two contacts to make them appear as online. */ fun main() = RunWithTemporaryAccount { - getDeterministicTestDataCreator().createTestData(5, 20, 50, 10, 20) + getDeterministicTestDataCreator().createTestData() getContactManager().addPendingContact("briar://aatkjq4seoualafpwh4cfckdzr4vpr4slk3bbvpxklf7y7lv4ajw6", "Faythe") getEventBus().addListener { e -> diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithInvitationAndThreeConnectedTemporaryAccounts.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithInvitationAndThreeConnectedTemporaryAccounts.kt index 31a490e405e3eb8b662e6f8c9051605c9a101dd5..acdd7cd66a6c4fd6019b60e7a0b0f1896424849d 100644 --- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithInvitationAndThreeConnectedTemporaryAccounts.kt +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithInvitationAndThreeConnectedTemporaryAccounts.kt @@ -28,7 +28,7 @@ fun main() = RunWithMultipleTemporaryAccounts(listOf("alice", "bob", "eve")) { / val eve = this[2] listOf(bob, eve).forEach { - it.getDeterministicTestDataCreator().createTestData(1, 2, 0, 0, 0) + it.getDeterministicTestDataCreator().createTestData() connectAppsInstantly(alice, it) } diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithThreeConnectedTemporaryAccounts.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithThreeConnectedTemporaryAccounts.kt index db1857b22e2236f4c6914c97a4165f978187d82d..eb25db4e5e5f4de0a99843304d25ac552bb6e3bb 100644 --- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithThreeConnectedTemporaryAccounts.kt +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithThreeConnectedTemporaryAccounts.kt @@ -23,7 +23,7 @@ import org.briarproject.briar.desktop.TestUtils.createForumForAll fun main() = RunWithMultipleTemporaryAccounts(listOf("alice", "bob", "eve")) { // NON-NLS forEach { - it.getDeterministicTestDataCreator().createTestData(5, 20, 50, 10, 20) + it.getDeterministicTestDataCreator().createTestData() } connectAllInstantly() createForumForAll() diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithTwoConnectedAsPendingTemporaryAccounts.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithTwoConnectedAsPendingTemporaryAccounts.kt index 3c6f9c5cd1e34e086c568b1357be75609507b6b2..1a36d2193ba53645e4a9c5593c5f4770269f28b8 100644 --- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithTwoConnectedAsPendingTemporaryAccounts.kt +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithTwoConnectedAsPendingTemporaryAccounts.kt @@ -22,7 +22,7 @@ import org.briarproject.briar.desktop.TestUtils.connectAllPending fun main() = RunWithMultipleTemporaryAccounts(listOf("alice", "bob")) { // NON-NLS forEach { - it.getDeterministicTestDataCreator().createTestData(5, 20, 50, 10, 20) + it.getDeterministicTestDataCreator().createTestData() } connectAllPending() }.run() diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithTwoConnectedTemporaryAccounts.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithTwoConnectedTemporaryAccounts.kt index c13c5e994369c29f0007acff8d7747bb60c7a31c..9f3e91df15526f4f39b94a2a1e05ef18027f3531 100644 --- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithTwoConnectedTemporaryAccounts.kt +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithTwoConnectedTemporaryAccounts.kt @@ -23,7 +23,7 @@ import org.briarproject.briar.desktop.TestUtils.createForumForAll fun main() = RunWithMultipleTemporaryAccounts(listOf("alice", "bob")) { // NON-NLS forEach { - it.getDeterministicTestDataCreator().createTestData(5, 20, 50, 10, 20) + it.getDeterministicTestDataCreator().createTestData() } connectAllInstantly() createForumForAll() diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithTwoTemporaryAccounts.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithTwoTemporaryAccounts.kt index aff1eef29b713b62c0bbf4782fa3ecba5ae731d2..be9a409a6a7f840be5a3a3b8bb1a5138a25cfa7c 100644 --- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithTwoTemporaryAccounts.kt +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/TestWithTwoTemporaryAccounts.kt @@ -20,6 +20,6 @@ package org.briarproject.briar.desktop fun main() = RunWithMultipleTemporaryAccounts(listOf("alice", "bob")) { // NON-NLS forEach { - it.getDeterministicTestDataCreator().createTestData(5, 20, 50, 10, 20) + it.getDeterministicTestDataCreator().createTestData() } }.run() diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/DeterministicTestDataCreator.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/DeterministicTestDataCreator.kt index 89f8fab55b22d11e77422836833d848ac961497b..a0067b688d67968c1a152a8a04b18ebb97a02e5b 100644 --- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/DeterministicTestDataCreator.kt +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/DeterministicTestDataCreator.kt @@ -18,22 +18,20 @@ package org.briarproject.briar.desktop.testdata +import org.briarproject.briar.desktop.testdata.conversation.Conversations +import org.briarproject.briar.desktop.testdata.conversation.defaultConversations +import org.briarproject.briar.desktop.testdata.forum.Forums +import org.briarproject.briar.desktop.testdata.forum.defaultForums + interface DeterministicTestDataCreator { /** - * Create fake test data on the IoExecutor + * Create deterministic test data on the IoExecutor * - * @param numContacts Number of contacts to create. Must be >= 1 - * @param numPrivateMsgs Number of private messages to create for each contact. - * @param avatarPercent Percentage of contacts that will use a random profile image. - * Between 0 and 100. - * @param numPrivateGroups Number of private groups to create. Must be >= 1 - * @param numPrivateGroupPosts Number of private group messages to create in each group + * @param conversations map of contacts and private messages + * @param forums list of forums */ fun createTestData( - numContacts: Int, - numPrivateMsgs: Int, - avatarPercent: Int, - numPrivateGroups: Int, - numPrivateGroupPosts: Int, + conversations: Conversations = TestData.defaultConversations, + forums: Forums = TestData.defaultForums, ) } diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/DeterministicTestDataCreatorImpl.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/DeterministicTestDataCreatorImpl.kt index 4c3ab340fe68d608959058af0dd8589462b31dd8..40ce4f54b7c73f7f2364a9fcea59cea3d68fa51b 100644 --- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/DeterministicTestDataCreatorImpl.kt +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/DeterministicTestDataCreatorImpl.kt @@ -51,6 +51,8 @@ import org.briarproject.briar.api.avatar.AvatarMessageEncoder import org.briarproject.briar.api.conversation.ConversationManager import org.briarproject.briar.api.forum.ForumFactory import org.briarproject.briar.api.forum.ForumManager +import org.briarproject.briar.api.forum.ForumPostFactory +import org.briarproject.briar.api.identity.AuthorManager import org.briarproject.briar.api.messaging.MessagingManager import org.briarproject.briar.api.messaging.PrivateMessageFactory import org.briarproject.briar.api.privategroup.GroupMessageFactory @@ -60,12 +62,13 @@ import org.briarproject.briar.api.privategroup.PrivateGroupManager import org.briarproject.briar.api.test.TestAvatarCreator import org.briarproject.briar.desktop.GroupCountHelper import org.briarproject.briar.desktop.attachment.media.ImageCompressor +import org.briarproject.briar.desktop.testdata.contact.Contact +import org.briarproject.briar.desktop.testdata.conversation.Conversations import org.briarproject.briar.desktop.testdata.conversation.Direction import org.briarproject.briar.desktop.testdata.conversation.Message -import org.briarproject.briar.desktop.testdata.conversation.conversations +import org.briarproject.briar.desktop.testdata.forum.Forums import org.briarproject.briar.desktop.testdata.forum.Post import org.briarproject.briar.desktop.testdata.forum.PostAuthor -import org.briarproject.briar.desktop.testdata.forum.forums import org.briarproject.briar.desktop.utils.KLoggerUtils.i import org.briarproject.briar.desktop.utils.KLoggerUtils.w import java.io.IOException @@ -80,6 +83,7 @@ import javax.inject.Inject import kotlin.math.min class DeterministicTestDataCreatorImpl @Inject internal constructor( + private val authorManager: AuthorManager, private val authorFactory: AuthorFactory, private val clock: Clock, private val groupFactory: GroupFactory, @@ -92,6 +96,7 @@ class DeterministicTestDataCreatorImpl @Inject internal constructor( private val privateGroupFactory: PrivateGroupFactory, private val forumManager: ForumManager, private val forumFactory: ForumFactory, + private val forumPostFactory: ForumPostFactory, private val transportPropertyManager: TransportPropertyManager, private val conversationManager: ConversationManager, private val messagingManager: MessagingManager, @@ -112,23 +117,12 @@ class DeterministicTestDataCreatorImpl @Inject internal constructor( private val localAuthors: MutableMap<ContactId, LocalAuthor> = HashMap() override fun createTestData( - numContacts: Int, - numPrivateMsgs: Int, - avatarPercent: Int, - numPrivateGroups: Int, - numPrivateGroupPosts: Int, + conversations: Conversations, + forums: Forums, ) { - require(numContacts != 0 || numPrivateGroups != 0) - require(!(avatarPercent < 0 || avatarPercent > 100)) ioExecutor.execute { try { - createTestDataOnIoExecutor( - numContacts, - numPrivateMsgs, - avatarPercent, - numPrivateGroups, - numPrivateGroupPosts - ) + createTestDataOnIoExecutor(conversations, forums) } catch (e: DbException) { LOG.w(e) { } } @@ -138,35 +132,31 @@ class DeterministicTestDataCreatorImpl @Inject internal constructor( @IoExecutor @Throws(DbException::class) private fun createTestDataOnIoExecutor( - numContacts: Int, - numPrivateMsgs: Int, - avatarPercent: Int, - numPrivateGroups: Int, - numPrivateGroupPosts: Int + conversations: Conversations, + forums: Forums, ) { - val contacts = createContacts(numContacts, avatarPercent) - createPrivateMessages(contacts, numPrivateMsgs) + val contacts = createContacts(conversations) + createPrivateMessages(contacts, conversations) - val privateGroups = createPrivateGroups(contacts, numPrivateGroups) + /*val privateGroups = createPrivateGroups(contacts, numPrivateGroups) for (privateGroup in privateGroups) { createRandomPrivateGroupMessages(privateGroup, contacts, numPrivateGroupPosts) - } + }*/ - createForums() + createForums(contacts, forums) } @Throws(DbException::class) - private fun createContacts(numContacts: Int, avatarPercent: Int): List<ContactId> { - val contacts: MutableList<ContactId> = ArrayList(numContacts) + private fun createContacts(conversations: Conversations): Map<Contact, ContactId> { + val contacts = mutableMapOf<Contact, ContactId>() val localAuthor = identityManager.localAuthor - for (i in 0 until min(numContacts, conversations.persons.size)) { - val person = conversations.persons[i] + for ((person, conversation) in conversations) { val remote = authorFactory.createLocalAuthor(person.name) - val date = person.messages.map { it.date }.sorted().last() - val contact = addContact(localAuthor.id, remote, null, avatarPercent, date) - contacts.add(contact) + val date = conversation.messages.map { it.date }.maxOf { it } + val contact = addContact(localAuthor.id, remote, person.alias, 100, date) + contacts[person] = contact } return contacts } @@ -331,29 +321,24 @@ class DeterministicTestDataCreatorImpl @Inject internal constructor( @Throws(DbException::class) private fun createPrivateMessages( - contacts: List<ContactId>, - numPrivateMsgs: Int + contacts: Map<Contact, ContactId>, + conversations: Conversations, ) { - for (i in contacts.indices) { - val contactId = contacts[i] - // this cannot cause an IndexOutOfBoundsException here with conversation.persons - // because we already made sure to only create as many contacts as we have - // conversation templates available. - val person = conversations.persons[i] + for ((person, conversation) in conversations) { + val contactId = contacts[person] ?: error("contact for ${person.name} not created") val groupId = messagingManager.getConversationId(contactId) shareGroup(contactId, groupId) - for (k in 0 until min(numPrivateMsgs, person.messages.size)) { - createPrivateMessage(contactId, groupId, person.messages[k]) + for (message in conversation.messages) { + createPrivateMessage(contactId, groupId, message) } } - LOG.i { "Created $numPrivateMsgs private messages per contact." } } @Throws(DbException::class) private fun createPrivateMessage( contactId: ContactId, groupId: GroupId, - message: Message + message: Message, ) { val timestamp = message.date.toEpochSecond(ZoneOffset.UTC) * 1000 val text = message.text @@ -371,7 +356,7 @@ class DeterministicTestDataCreatorImpl @Inject internal constructor( images: List<String>, timestamp: Long, local: Boolean, - autoDelete: Boolean + autoDelete: Boolean, ) { val timer = if (autoDelete) AutoDeleteConstants.MIN_AUTO_DELETE_TIMER_MS else AutoDeleteConstants.NO_AUTO_DELETE_TIMER @@ -431,41 +416,62 @@ class DeterministicTestDataCreatorImpl @Inject internal constructor( return privateGroups } - @Throws(DbException::class) - private fun createRandomPrivateGroupMessages( - privateGroup: PrivateGroup, - contacts: List<ContactId>, - numPrivateGroupMessages: Int + private fun createForums( + contacts: Map<Contact, ContactId>, + forums: Forums, ) { - // TODO - } - - private fun createForums() { - for (f in forums.forums) { + for (f in forums) { // create forum val forum = forumManager.addForum(f.name) - val members = f.members.associateWith { - if (it is PostAuthor.RemoteAuthor) authorFactory.createLocalAuthor(it.name) - else identityManager.localAuthor + // handle members + var receiveMessagesVia: ContactId? = null + val membersStrangers = mutableMapOf<PostAuthor.StrangerAuthor, LocalAuthor>() + f.members.forEach { member -> + when (member) { + is PostAuthor.ContactAuthor -> { + val contactId = contacts[member.contact] ?: error("Contact not found.") + if (member.sharedWith) { + shareGroup(contactId, forum.id) + if (receiveMessagesVia == null) receiveMessagesVia = contactId + } + } + + is PostAuthor.StrangerAuthor -> + membersStrangers[member] = authorFactory.createLocalAuthor(member.name) + + else -> {} + } } - // todo: create real contact to also share forum! // add posts fun addPost(post: Post, parentId: MessageId?) { + val author = when (post.author) { + is PostAuthor.Me -> identityManager.localAuthor + is PostAuthor.StrangerAuthor -> membersStrangers[post.author] + is PostAuthor.ContactAuthor -> localAuthors[contacts[post.author.contact]] + } ?: error("LocalAuthor not found.") val m = forumManager.createLocalPost( forum.id, post.text, post.date.toEpochSecond(ZoneOffset.UTC) * 1000, parentId, - members[post.author]!! + author ) - // todo: add non-local posts using incoming message via some contact this forum is shared with - forumManager.addLocalPost(m) + if (post.author == PostAuthor.Me) + forumManager.addLocalPost(m) + else { + val receiveVia = + (if (post.author is PostAuthor.ContactAuthor) contacts[post.author.contact] else receiveMessagesVia) + ?: error("Contact to receive via not found.") + db.transaction<RuntimeException>(false) { txn -> + db.receiveMessage(txn, receiveVia, m.message) + } + } post.replies.forEach { addPost(it, m.message.id) } } f.posts.forEach { addPost(it, null) } } - LOG.i { "Created ${forums.forums.size} forums." } + LOG.i { "Created ${forums.size} forums." } } } diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/TestData.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/TestData.kt new file mode 100644 index 0000000000000000000000000000000000000000..8c1fec307b61268f9b1d65bef27e9ed98b66eedd --- /dev/null +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/TestData.kt @@ -0,0 +1,23 @@ +/* + * Briar Desktop + * Copyright (C) 2021-2022 The Briar Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package org.briarproject.briar.desktop.testdata + +object TestData { + object Contacts +} diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/TestDeterministicData.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/TestDeterministicData.kt index 8249d89353513576ba9fa8abf2b97090e275d419..a46349ef25b10c26ea5564ba05d9561e56f6b956 100644 --- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/TestDeterministicData.kt +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/TestDeterministicData.kt @@ -18,24 +18,22 @@ package org.briarproject.briar.desktop.testdata -import org.briarproject.briar.desktop.testdata.conversation.conversations +import org.briarproject.briar.desktop.testdata.conversation.defaultConversations import org.briarproject.briar.desktop.testdata.forum.Post -import org.briarproject.briar.desktop.testdata.forum.PostAuthor -import org.briarproject.briar.desktop.testdata.forum.forums +import org.briarproject.briar.desktop.testdata.forum.defaultForums fun main() { - for (conversation in conversations.persons) { - println("conversation with: ${conversation.name}") // NON-NLS + for ((contact, conversation) in TestData.defaultConversations) { + println("conversation with: ${contact.name}") // NON-NLS for (message in conversation.messages) { println(" ${message.direction} ${message.text} ${message.read} ${message.date}") } } - for (forum in forums.forums) { + for (forum in TestData.defaultForums) { println("Forum: ${forum.name}") // NON-NLS fun printPost(post: Post, level: Int) { - val name = if (post.author is PostAuthor.RemoteAuthor) post.author.name else "me" - println("|".repeat(level) + "+ ${post.date} - $name: ${post.text}") + println("|".repeat(level) + "+ ${post.date} - ${post.author.name}: ${post.text}") post.replies.forEach { printPost(it, level + 1) } } forum.posts.forEach { printPost(it, 0) } diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/contact/Contact.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/contact/Contact.kt new file mode 100644 index 0000000000000000000000000000000000000000..4a77b865d1563c341a4a6cb09e09f5dc47c48f47 --- /dev/null +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/contact/Contact.kt @@ -0,0 +1,21 @@ +/* + * Briar Desktop + * Copyright (C) 2021-2022 The Briar Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package org.briarproject.briar.desktop.testdata.contact + +data class Contact(val name: String, val alias: String?) diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/contact/ContactData.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/contact/ContactData.kt new file mode 100644 index 0000000000000000000000000000000000000000..04811ea94c2d72368a14f601b7f91e7a679c66cd --- /dev/null +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/contact/ContactData.kt @@ -0,0 +1,34 @@ +/* + * Briar Desktop + * Copyright (C) 2021-2022 The Briar Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package org.briarproject.briar.desktop.testdata.contact + +import org.briarproject.briar.desktop.testdata.TestData + +val TestData.Contacts.anna: Contact + get() = contact { name = "Anna" } +val TestData.Contacts.bob: Contact + get() = contact { name = "Bob" } +val TestData.Contacts.chuck: Contact + get() = contact { name = "Chuck" } +val TestData.Contacts.polonius: Contact + get() = contact { name = "Polonius" } +val TestData.Contacts.dan: Contact + get() = contact { name = "Dan" } +val TestData.Contacts.george: Contact + get() = contact { name = "Georgy Voronoy" } diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/contact/ContactDsl.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/contact/ContactDsl.kt new file mode 100644 index 0000000000000000000000000000000000000000..08cd683aa4c3c3aa9854f816b54d171086320115 --- /dev/null +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/contact/ContactDsl.kt @@ -0,0 +1,33 @@ +/* + * Briar Desktop + * Copyright (C) 2021-2022 The Briar Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package org.briarproject.briar.desktop.testdata.contact + +fun contact(block: ContactBuilder.() -> Unit): Contact = ContactBuilder().apply(block).build() + +class ContactBuilder { + lateinit var name: String + var alias: String? = null + // todo: support avatar + + // todo: contacts are only really created if conversation is called with this contact -> change + fun build(): Contact { + check(this::name.isInitialized) { "A contact needs a name to be valid." } // NON-NLS + return Contact(name, alias) + } +} diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/conversation/Conversations.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/conversation/Conversations.kt index 2734f8b52b207d6014b1ea46166e0db332978668..b93a83dbce77328914b320126fd1d48912884303 100644 --- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/conversation/Conversations.kt +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/conversation/Conversations.kt @@ -18,15 +18,13 @@ package org.briarproject.briar.desktop.testdata.conversation +import org.briarproject.briar.desktop.testdata.contact.Contact import java.time.LocalDateTime -data class Conversations( - val persons: List<Conversation> -) +typealias Conversations = Map<Contact, Conversation> data class Conversation( - val name: String, - var messages: List<Message> + val messages: List<Message>, ) data class Message( @@ -34,7 +32,7 @@ data class Message( val images: List<String>, val direction: Direction, val date: LocalDateTime, - val read: Boolean + val read: Boolean, ) enum class Direction { diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/conversation/ConversationsData.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/conversation/ConversationsData.kt index b3d4da40ee14a77e5963eb23aa5f7462c85a1a90..d6be5f644b13b2aeec0179f7c2ac17d2f739f12b 100644 --- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/conversation/ConversationsData.kt +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/conversation/ConversationsData.kt @@ -19,149 +19,158 @@ package org.briarproject.briar.desktop.testdata.conversation +import org.briarproject.briar.desktop.testdata.TestData +import org.briarproject.briar.desktop.testdata.contact.anna +import org.briarproject.briar.desktop.testdata.contact.bob +import org.briarproject.briar.desktop.testdata.contact.chuck +import org.briarproject.briar.desktop.testdata.contact.dan +import org.briarproject.briar.desktop.testdata.contact.george +import org.briarproject.briar.desktop.testdata.contact.polonius import java.time.LocalDateTime.of as dt -val conversations = conversations { - conversation { - contactName = "Bob" - outgoing { - text = "Hi, Bob" - read = true - date = "2022-01-21 10:10:15" - } - incoming { - text = "What's up?" - read = true - date = "2022-01-21 10:11:05" - } - outgoing { - text = "Nothing much, lately. Have you seen the new Briar Desktop release?" - read = true - date = "2022-01-21 10:12:34" - } - incoming { - text = "Oh, wow. I have to check it out! \uD83E\uDD2F" - read = true - date = "2022-01-21 10:13:05" - } - outgoing { - images = listOf("images/do-it-now.png") - read = true - date = "2022-01-21 10:13:15" - } - } - conversation { - contactName = "Chuck" - val start = dt(2020, 1, 12, 19, 43, 17) - outgoing { - text = "Hey Chuck!" - read = true - date = start - } - incoming { - text = "Good evening, Alice" - read = true - date = start.plusSeconds(100) - } - } - conversation { - contactName = "Polonius" - val start = dt(2019, 2, 24, 22, 22) - incoming { - text = "My lord, the queen would speak with you, and presently." - read = true - date = start - } - outgoing { - text = "Do you see yonder cloud that's almost in shape of a camel?" - read = true - date = start.plusSeconds(100) - } - incoming { - text = "By the mass, and 'tis like a camel, indeed." - read = true - date = start.plusSeconds(300) - } - outgoing { - text = "Methinks it is like a weasel." - read = true - date = start.plusSeconds(400) - } - incoming { - text = "It is backed like a weasel." - read = true - date = start.plusSeconds(500) - } - outgoing { - text = "Or like a whale?" - read = true - date = start.plusSeconds(550) - } - incoming { - text = "Very like a whale." - read = true - date = start.plusSeconds(600) - } - outgoing { - text = "Then I will come to my mother by and by. They fool me to the top of my bent. I will come by and by." - read = true - date = start.plusSeconds(620) - } - incoming { - text = "I will say so." - read = true - date = start.plusSeconds(680) - } - outgoing { - text = "By and by is easily said." - read = true - date = start.plusSeconds(777) - } - } - conversation { - contactName = "Dan" - outgoing { - text = "Welcome to Briar!" - read = true - date = "2019-02-13 13:15:00" - } - } - conversation { - contactName = "Georgy Voronoy" - val start = dt(2021, 3, 13, 10, 3, 1) - outgoing { - text = "Hey Georgy!" - read = true - date = start - } - incoming { - text = "Good morning, Alice" - read = true - date = start.plusSeconds(100) - } - incoming { - text = "Check out my latest diagrams" - images = listOf("images/voronoi1.png") - read = true - date = start.plusSeconds(120) - } - outgoing { - text = "Awesome, thanks!" - read = true - date = start.plusSeconds(240) - } - outgoing { - text = "I've also made some" - images = listOf( - "images/voronoi2.png", - "images/voronoi3.png", - "images/voronoi4.png", - "images/voronoi2.png", - "images/voronoi3.png", - "images/voronoi4.png", - ) - read = true - date = start.plusSeconds(250) +val TestData.defaultConversations: Conversations + get() = conversations { + conversation(TestData.Contacts.anna) { + incoming { + text = "Hi!" + } + } // todo: instead create all contacts / allow contacts without messages + conversation(TestData.Contacts.bob) { + outgoing { + text = "Hi, Bob" + read = true + date = "2022-01-21 10:10:15" + } + incoming { + text = "What's up?" + read = true + date = "2022-01-21 10:11:05" + } + outgoing { + text = "Nothing much, lately. Have you seen the new Briar Desktop release?" + read = true + date = "2022-01-21 10:12:34" + } + incoming { + text = "Oh, wow. I have to check it out! \uD83E\uDD2F" + read = true + date = "2022-01-21 10:13:05" + } + outgoing { + images = listOf("images/do-it-now.png") + read = true + date = "2022-01-21 10:13:15" + } + } + conversation(TestData.Contacts.chuck) { + val start = dt(2020, 1, 12, 19, 43, 17) + outgoing { + text = "Hey Chuck!" + read = true + date = start + } + incoming { + text = "Good evening, Alice" + read = true + date = start.plusSeconds(100) + } + } + conversation(TestData.Contacts.polonius) { + val start = dt(2019, 2, 24, 22, 22) + incoming { + text = "My lord, the queen would speak with you, and presently." + read = true + date = start + } + outgoing { + text = "Do you see yonder cloud that's almost in shape of a camel?" + read = true + date = start.plusSeconds(100) + } + incoming { + text = "By the mass, and 'tis like a camel, indeed." + read = true + date = start.plusSeconds(300) + } + outgoing { + text = "Methinks it is like a weasel." + read = true + date = start.plusSeconds(400) + } + incoming { + text = "It is backed like a weasel." + read = true + date = start.plusSeconds(500) + } + outgoing { + text = "Or like a whale?" + read = true + date = start.plusSeconds(550) + } + incoming { + text = "Very like a whale." + read = true + date = start.plusSeconds(600) + } + outgoing { + text = + "Then I will come to my mother by and by. They fool me to the top of my bent. I will come by and by." + read = true + date = start.plusSeconds(620) + } + incoming { + text = "I will say so." + read = true + date = start.plusSeconds(680) + } + outgoing { + text = "By and by is easily said." + read = true + date = start.plusSeconds(777) + } + } + conversation(TestData.Contacts.dan) { + outgoing { + text = "Welcome to Briar!" + read = true + date = "2019-02-13 13:15:00" + } + } + conversation(TestData.Contacts.george) { + val start = dt(2021, 3, 13, 10, 3, 1) + outgoing { + text = "Hey Georgy!" + read = true + date = start + } + incoming { + text = "Good morning, Alice" + read = true + date = start.plusSeconds(100) + } + incoming { + text = "Check out my latest diagrams" + images = listOf("images/voronoi1.png") + read = true + date = start.plusSeconds(120) + } + outgoing { + text = "Awesome, thanks!" + read = true + date = start.plusSeconds(240) + } + outgoing { + text = "I've also made some" + images = listOf( + "images/voronoi2.png", + "images/voronoi3.png", + "images/voronoi4.png", + "images/voronoi2.png", + "images/voronoi3.png", + "images/voronoi4.png", + ) + read = true + date = start.plusSeconds(250) + } } } -} diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/conversation/ConversationsDsl.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/conversation/ConversationsDsl.kt index e27bb923cfc21eca18e1252aacd1832b4eeb3d19..58bd3575fee24262bb4d7a98f57042ca6e588a4e 100644 --- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/conversation/ConversationsDsl.kt +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/conversation/ConversationsDsl.kt @@ -18,6 +18,7 @@ package org.briarproject.briar.desktop.testdata.conversation +import org.briarproject.briar.desktop.testdata.contact.Contact import org.briarproject.briar.desktop.testdata.conversation.Direction.INCOMING import org.briarproject.briar.desktop.testdata.conversation.Direction.OUTGOING import java.time.LocalDateTime @@ -31,20 +32,19 @@ fun conversations(block: ConversationsBuilder.() -> Unit): Conversations = Conve @ConversationsDsl class ConversationsBuilder { - private val conversations = mutableListOf<Conversation>() + private val conversations = mutableMapOf<Contact, Conversation>() - fun conversation(block: ConversationBuilder.() -> Unit) { - conversations.add(ConversationBuilder().apply(block).build()) + fun conversation(contact: Contact, block: ConversationBuilder.() -> Unit) { + check(!conversations.contains(contact)) { "A contact cannot be linked to two conversations." } // NON-NLS + conversations[contact] = ConversationBuilder().apply(block).build() } - fun build(): Conversations = Conversations(conversations) + fun build(): Conversations = conversations } @ConversationsDsl class ConversationBuilder { - var contactName: String = "" - private val messages = mutableListOf<Message>() fun incoming(block: MessageBuilder.() -> Unit) { @@ -55,7 +55,9 @@ class ConversationBuilder { messages.add(MessageBuilder(OUTGOING).apply(block).build()) } - fun build(): Conversation = Conversation(contactName, messages) + fun build(): Conversation { + return Conversation(messages) + } } var formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/forum/Forums.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/forum/Forums.kt index 05909ed261086eef2d026f78eb6018e4dbe8e892..f3a73a67e601892374b10a5bfe7157fc07ea24dc 100644 --- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/forum/Forums.kt +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/forum/Forums.kt @@ -18,16 +18,15 @@ package org.briarproject.briar.desktop.testdata.forum +import org.briarproject.briar.desktop.testdata.contact.Contact import java.time.LocalDateTime -data class Forums( - val forums: List<Forum> -) +typealias Forums = List<Forum> data class Forum( val name: String, - var members: List<PostAuthor>, - var posts: List<Post>, + val members: List<PostAuthor>, + val posts: List<Post>, ) data class Post( @@ -38,10 +37,21 @@ data class Post( ) sealed interface PostAuthor { - object Me : PostAuthor - data class RemoteAuthor( - val name: String, - val sharedWith: Boolean, // todo: not supported yet + val name: String + + object Me : PostAuthor { + override val name: String = "" // todo: real name + } + + data class ContactAuthor( + val contact: Contact, + val sharedWith: Boolean, + ) : PostAuthor { + override val name: String = contact.name + } + + data class StrangerAuthor( + override val name: String, ) : PostAuthor } diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/forum/ForumsData.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/forum/ForumsData.kt index 8db914762cfe76d1d976c050a1dcd29313f10166..b26c88b4a4c32900a0b135f8f446c941f8fee4a7 100644 --- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/forum/ForumsData.kt +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/forum/ForumsData.kt @@ -19,108 +19,113 @@ package org.briarproject.briar.desktop.testdata.forum +import org.briarproject.briar.desktop.testdata.TestData +import org.briarproject.briar.desktop.testdata.contact.anna +import org.briarproject.briar.desktop.testdata.contact.chuck import java.time.LocalDateTime -val forums = forums { - forum { - name = "Briar Friends" +val TestData.defaultForums: Forums + get() = forums { + forum { + name = "Briar Friends" - val me = myself() - val anna = member("Anna", sharedForum = true) - val paul = member("Paul") - val claudia = member("Claudia", sharedForum = true) - - post { - author = anna - text = "Hi everybody!" + val me = myself() + val anna = memberContact(TestData.Contacts.anna) + val paul = memberStranger("Paul") // todo: change one more to contacts, but not shared from start + val claudia = memberStranger("Claudia") post { - author = paul - text = "Hey Anna! It's me, Paul \uD83D\uDC4Bï¸" - - post { - author = anna - text = "Hi Paul! Nice to have you around!" - } + author = anna + text = "Hi everybody!" post { author = paul - text = "Yes indeed. Thanks for sharing the forum with me! \uD83D\uDC99\uD83E\uDD17ï¸ï¸" - } - } - - post { - author = me - text = "Hi Anna! Where can I see who else is in here?" + text = "Hey ${anna.name}! It's me, ${paul.name} \uD83D\uDC4Bï¸" - post { - author = anna - text = "Right now it's only Paul, you and me. " + - "But it's actually not possible to have a list of all members of a forum, " + - "since every person in the forum could share it with any of their contacts." + post { + author = anna + text = "Hi ${paul.name}! Nice to have you around!" + } post { - author = me - text = "Oh, that's a bit unexpected!ï¸ï¸" + author = paul + text = "Yes indeed. Thanks for sharing the forum with me! \uD83D\uDC99\uD83E\uDD17ï¸ï¸" } + } + + post { + author = me + text = "Hi ${anna.name}! Where can I see who else is in here?" post { - author = claudia - text = "That's actually how Paul slipped me in here. Hello everyone!ï¸ï¸" + author = anna + text = "Right now it's only ${paul.name}, you and me. " + + "But it's actually not possible to have a list of all members of a forum, " + + "since every person in the forum could share it with any of their contacts." + + post { + author = me + text = "Oh, that's a bit unexpected!ï¸ï¸" + } post { - author = paul - text = "ï¸ï¸\uD83D\uDE08ï¸" + author = claudia + text = "That's actually how ${paul.name} slipped me in here. Hello everyone!ï¸ï¸" + + post { + author = paul + text = "ï¸ï¸\uD83D\uDE08ï¸" + } } } } } - } - post { - author = anna - text = "What do you think about Briar?" + post { + author = anna + text = "What do you think about Briar?" + } } - } - forum { - name = "Let's try forums" + forum { + name = "Let's try forums" - val me = myself() - val brian = member("Brian", sharedForum = true) - val claudia = member("Claudia", sharedForum = true) - val claudia2 = member("Claudia") - - post { - author = brian - text = "I've just started and shared this forum using Briar Desktop, " + - "did everything work as expected?" - date = LocalDateTime.of(2022, 11, 28, 16, 12, 38) + val me = myself() + val chuck = memberContact(TestData.Contacts.chuck) + val claudia = memberStranger("Claudia") + val claudia2 = memberStranger("Claudia") post { - author = me - text = "Wow nice, yes, everything seems to work!" + author = chuck + text = "I've just started and shared this forum using Briar Desktop, " + + "did everything work as expected?" + date = LocalDateTime.of(2022, 11, 28, 16, 12, 38) post { - author = brian - text = "Perfect, that's amazing!" - } - } + author = me + text = "Wow nice, yes, everything seems to work!" - post { - author = claudia - text = "Hey people! That's so exciting that forums work on Briar Desktop now, too!" + post { + author = chuck + text = "Perfect, that's amazing!" + } + } post { - author = claudia2 - text = "And it is fully compatible with Briar Android as well! I'm writing this on my phone just now." + author = claudia + text = "Hey people! That's so exciting that forums work on Briar Desktop now, too!" post { - author = me - text = "Oh hi, can you introduce me to your Briar account on the phone, please?" + author = claudia2 + text = + "And it is fully compatible with Briar Android as well! I'm writing this on my phone just now." + + post { + author = me + text = "Oh hi, can you introduce me to your Briar account on the phone, please?" + } } } } } } -} diff --git a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/forum/ForumsDsl.kt b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/forum/ForumsDsl.kt index 44d9a52a7bfaaf519ec9313d95eb6e868d19c867..5a9552bd23a4a529c6638b58cb3a2bc289db293b 100644 --- a/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/forum/ForumsDsl.kt +++ b/briar-desktop/src/test/kotlin/org/briarproject/briar/desktop/testdata/forum/ForumsDsl.kt @@ -18,6 +18,7 @@ package org.briarproject.briar.desktop.testdata.forum +import org.briarproject.briar.desktop.testdata.contact.Contact import java.time.LocalDateTime import java.time.format.DateTimeFormatter import kotlin.random.Random @@ -42,7 +43,7 @@ class ForumsBuilder { forums.add(ForumBuilder().apply(block).build()) } - fun build() = Forums(forums) + fun build() = forums } @PostsDsl @@ -54,15 +55,24 @@ class ForumBuilder : PostHierarchyBuilder() { */ lateinit var name: String - private var members = mutableListOf<PostAuthor>(PostAuthor.Me) + private var memberList = mutableListOf<PostAuthor>(PostAuthor.Me) override var lastReplySent: LocalDateTime = LocalDateTime.now() + override val members: Set<PostAuthor> + get() = memberList.toSet() /** * Create and return a new member for this forum. * You can use the return value as the `author` of a [post]. */ - fun member(name: String, sharedForum: Boolean = false) = - PostAuthor.RemoteAuthor(name, sharedForum).also { members.add(it) } + fun memberContact(contact: Contact, sharedForum: Boolean = true) = + PostAuthor.ContactAuthor(contact, sharedForum).also { memberList.add(it) } + + /** + * Create and return a new member for this forum. + * You can use the return value as the `author` of a [post]. + */ + fun memberStranger(name: String) = + PostAuthor.StrangerAuthor(name).also { memberList.add(it) } /** * Reference to the local author. @@ -72,19 +82,26 @@ class ForumBuilder : PostHierarchyBuilder() { fun build(): Forum { check(this::name.isInitialized) { "A forum needs a name to be valid." } // NON-NLS - return Forum(name, members, posts) + check(memberList.isEmpty() || memberList.find { it is PostAuthor.ContactAuthor && it.sharedWith } != null) { + "A forum needs to have no other members or at least one member who is a contact and with whom the forum is shared." // NON-NLS + } + return Forum(name, memberList, posts) } } @PostsDsl -class PostBuilder(parentPostSent: LocalDateTime) : PostHierarchyBuilder() { +class PostBuilder(override val members: Set<PostAuthor>, parentPostSent: LocalDateTime) : PostHierarchyBuilder() { /** * The author of the post. - * You have to create authors using `member` in a forum. + * You have to create authors using `memberContact` or `memberStranger` in a forum. * If not set, defaults to the local author. */ var author: PostAuthor = PostAuthor.Me + set(value) { + check(value is PostAuthor.Me || value in members) { "$value is not member of this forum." } // NON-NLS + field = value + } /** * The text of the post. @@ -126,12 +143,13 @@ class PostBuilder(parentPostSent: LocalDateTime) : PostHierarchyBuilder() { abstract class PostHierarchyBuilder { protected val posts = mutableListOf<Post>() protected abstract var lastReplySent: LocalDateTime + protected abstract val members: Set<PostAuthor> /** * Add a new post to the forum or a new reply to the enclosing post. */ fun post(block: PostBuilder.() -> Unit) { - val post = PostBuilder(lastReplySent).apply(block).build() + val post = PostBuilder(members, lastReplySent).apply(block).build() posts.add(post) lastReplySent = post.date }