proton-mail-android/app/src/androidTest/java/ch/protonmail/android/api/models/room/contacts/ContactDaoTest.kt

509 lines
17 KiB
Kotlin

/*
* Copyright (c) 2022 Proton AG
*
* This file is part of Proton Mail.
*
* Proton Mail is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Proton Mail 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Proton Mail. If not, see https://www.gnu.org/licenses/.
*/
package ch.protonmail.android.api.models.room.contacts
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.test.InstrumentationRegistry
import ch.protonmail.android.api.models.ContactEncryptedData
import ch.protonmail.android.api.models.MessageRecipient
import ch.protonmail.android.api.models.room.testValue
import ch.protonmail.android.core.Constants
import ch.protonmail.android.data.local.ContactDao
import ch.protonmail.android.data.local.ContactDatabase
import ch.protonmail.android.data.local.model.ContactData
import ch.protonmail.android.data.local.model.ContactEmail
import ch.protonmail.android.data.local.model.FullContactDetails
import kotlinx.coroutines.runBlocking
import org.hamcrest.Matchers.`is`
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
import kotlin.test.BeforeTest
internal class ContactDaoTest {
private val context = InstrumentationRegistry.getTargetContext()
private var databaseFactory = ContactDatabase.buildInMemoryDatabase(context)
private var database = databaseFactory.getDao()
private val initiallyEmptyDatabase = databaseFactory.getDao()
@get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()
private val contactData = listOf(
ContactData(contactId = "aa", name = "aaa").apply { dbId = 2 },
ContactData(contactId = "bb", name = "bbb").apply { dbId = 4 },
ContactData(contactId = "cc", name = "ccc").apply { dbId = 3 },
ContactData(contactId = "dd", name = "ddd").apply { dbId = 1 },
ContactData(contactId = "ee", name = "eee").apply { dbId = 7 }
)
private val contactEmails = listOf(
ContactEmail(
contactEmailId = "a",
email = "a@a.com",
contactId = "aa",
labelIds = listOf("aaa", "aaaa", "aaaaa"),
name = "ce1",
lastUsedTime = 111
),
ContactEmail(
contactEmailId = "b",
email = "b@b.com",
contactId = "bb",
labelIds = listOf("bbb", "bbbb", "bbbbb"),
name = "ce2",
lastUsedTime = 113
),
ContactEmail(
contactEmailId = "c",
email = "c@c.com",
contactId = "bb",
labelIds = listOf("ccc", "cccc", "ccccc"),
name = "ce3",
lastUsedTime = 115
),
ContactEmail(
contactEmailId = "d",
email = "b@b.com",
contactId = "dd",
labelIds = listOf("ddd", "dddd", "ddddd"),
name = "ce4",
lastUsedTime = 114
),
ContactEmail(
contactEmailId = "e",
email = "e@e.com",
contactId = "ee",
labelIds = listOf("eee", "eeee", "eeeee"),
name = "ce5",
lastUsedTime = 112
)
)
private val fullContactDetails = listOf(
FullContactDetails(
contactId = "a",
name = "aa",
uid = "aaa",
createTime = 1,
modifyTime = 1,
size = 5,
defaults = 3,
encryptedData = mutableListOf(
ContactEncryptedData("aaaa", "aaaaa", Constants.VCardType.SIGNED),
ContactEncryptedData("aaaaaa", "aaaaaaa", Constants.VCardType.SIGNED_ENCRYPTED)
)
),
FullContactDetails(
contactId = "b",
name = "bb",
uid = "bbb",
createTime = 5,
modifyTime = 7,
size = 12,
defaults = 2,
encryptedData = mutableListOf(
ContactEncryptedData("bbbb", "bbbbb", Constants.VCardType.SIGNED),
ContactEncryptedData("bbbbbb", "bbbbbbb", Constants.VCardType.SIGNED_ENCRYPTED)
)
),
FullContactDetails(
contactId = "c",
name = "cc",
uid = "ccc",
createTime = 12,
modifyTime = 1100,
size = 2,
defaults = 123,
encryptedData = mutableListOf(
ContactEncryptedData("cccc", "ccccc", Constants.VCardType.SIGNED),
ContactEncryptedData("cccccc", "ccccccc", Constants.VCardType.SIGNED_ENCRYPTED)
)
),
FullContactDetails(
contactId = "d",
name = "dd",
uid = "ddd",
createTime = 3,
modifyTime = 12,
size = 112,
defaults = 31,
encryptedData = mutableListOf(
ContactEncryptedData("dddd", "ddddd", Constants.VCardType.SIGNED),
ContactEncryptedData("dddddd", "ddddddd", Constants.VCardType.SIGNED_ENCRYPTED)
)
),
FullContactDetails(
contactId = "e",
name = "ee",
uid = "eee",
createTime = 1,
modifyTime = 131,
size = 12,
defaults = 321,
encryptedData = mutableListOf(
ContactEncryptedData("eeee", "eeeee", Constants.VCardType.SIGNED),
ContactEncryptedData("eeeeee", "eeeeeee", Constants.VCardType.SIGNED_ENCRYPTED)
)
),
FullContactDetails("f")
)
private fun ContactDao.populate() {
runBlocking {
saveAllContactsData(contactData)
saveAllContactsEmails(contactEmails)
}
fullContactDetails.forEach(this::insertFullContactDetailsBlocking)
}
private fun assertDatabaseState(
expectedContactData: Iterable<ContactData> = contactData,
expectedContactEmails: Iterable<ContactEmail> = contactEmails,
expectedFullContactDetails: Iterable<FullContactDetails> = fullContactDetails
) {
val expectedContactDataSet = expectedContactData.toSet()
val expectedContactEmailsSet = expectedContactEmails.toSet()
//hack as encrypted data has equals not defined
val expectedFullContactDetailsSet = expectedFullContactDetails
.map { it.apply { encryptedData = mutableListOf() } }.toSet()
val actualContactDataSet = database.findAllContactDataAsync().testValue!!.toSet()
val actualContactEmailsSet = database.findAllContactsEmailsAsync().testValue!!.toSet()
//hack as encrypted data has equals not defined
val actualFullContactDetailsSet = expectedFullContactDetails
.map(FullContactDetails::contactId)
.map(database::findFullContactDetailsByIdBlocking)
.map { it?.apply { encryptedData = mutableListOf() } }
.toSet()
Assert.assertEquals(expectedContactDataSet, actualContactDataSet)
Assert.assertEquals(expectedContactEmailsSet, actualContactEmailsSet)
Assert.assertEquals(expectedFullContactDetailsSet, actualFullContactDetailsSet)
}
@BeforeTest
fun setUp() {
database.populate()
}
@Test
fun findContactDataById() {
val expected = contactData[3]
val actual = database.findContactDataByIdBlocking(expected.contactId!!)
Assert.assertEquals(expected, actual)
assertDatabaseState()
}
@Test
fun findContactDataByDbId() {
val expected = contactData[3]
val actual = database.findContactDataByDbId(expected.dbId!!)
Assert.assertEquals(expected, actual)
assertDatabaseState()
}
@Test
fun findAllContactDataAsync() {
val expected = contactData
val actual = database.findAllContactDataAsync().testValue
Assert.assertEquals(expected, actual)
assertDatabaseState()
}
@Test
fun clearContactDataCache() {
database.clearContactDataCache()
assertDatabaseState(expectedContactData = emptyList())
}
@Test
fun saveContactData() {
val inserted = ContactData("z", "zz")
val expected = contactData + inserted
database.saveContactDataBlocking(inserted)
assertDatabaseState(expectedContactData = expected)
}
@Test
fun saveAllContactsData() {
runBlocking {
val inserted = listOf(
ContactData("y", "yy"), ContactData("z", "zz")
)
val expected = contactData + inserted
database.saveAllContactsData(inserted)
assertDatabaseState(expectedContactData = expected)
}
}
@Test
fun saveAllContactsData1() {
val inserted = listOf(
ContactData("y", "yy"), ContactData("z", "zz")
)
val expected = contactData + inserted
database.saveAllContactsData(*inserted.toTypedArray())
assertDatabaseState(expectedContactData = expected)
}
@Test
fun deleteContactData() {
val deleted = contactData[3]
val expected = contactData - deleted
database.deleteContactData(deleted)
assertDatabaseState(expectedContactData = expected)
}
@Test
fun deleteContactsData() {
val deleted = listOf(contactData[3], contactData[1])
val expected = contactData - deleted
database.deleteContactsData(deleted)
assertDatabaseState(expectedContactData = expected)
}
@Test
fun findContactEmailById() = runBlocking{
val expected = contactEmails[2]
val actual = database.findContactEmailById(expected.contactEmailId!!)
Assert.assertEquals(expected, actual)
assertDatabaseState()
}
@Test
fun findContactEmailByEmail() {
val expected = contactEmails[2]
val actual = database.findContactEmailByEmailBlocking(expected.email)
Assert.assertEquals(expected, actual)
assertDatabaseState()
}
@Test
fun findContactEmailsByContactId() {
val contactId = contactEmails[2].contactId!!
val expected = contactEmails.filter { it.contactId == contactId }
val actual = database.findContactEmailsByContactIdBlocking(contactId)
Assert.assertEquals(expected, actual)
assertDatabaseState()
}
@Test
fun findAllContactsEmailsAsync() {
val expected = contactEmails.toSet()
val actual = database.findAllContactsEmailsAsync().testValue?.toSet()
Assert.assertEquals(expected, actual)
assertDatabaseState()
}
@Test
fun findAllMessageRecipients() {
// given
val expected = contactEmails
.sortedByDescending { it.lastUsedTime }
.map { contactEmail ->
MessageRecipient(contactData.find { it.contactId == contactEmail.contactId }?.name, contactEmail.email)
}.toSet()
// when
val actual = database.findAllMessageRecipients().blockingFirst().toSet()
// then
Assert.assertEquals(expected, actual)
assertDatabaseState()
}
@Test
fun clearByEmail() {
val deletedEmail = contactEmails[1].email
val expected = contactEmails.filterNot { it.email == deletedEmail }
database.clearByEmailBlocking(deletedEmail)
assertDatabaseState(expectedContactEmails = expected)
}
@Test
fun clearContactEmailsCache() {
val expected = emptyList<ContactEmail>()
database.clearContactEmailsCache()
assertDatabaseState(expectedContactEmails = expected)
}
@Test
fun deleteContactEmail() {
val deleted = listOf(contactEmails[3], contactEmails[1])
val expected = contactEmails - deleted
database.deleteContactEmail(*deleted.toTypedArray())
assertDatabaseState(expectedContactEmails = expected)
}
@Test
fun deleteAllContactsEmails() {
val deleted = listOf(contactEmails[3], contactEmails[1])
val expected = contactEmails - deleted
database.deleteAllContactsEmailsBlocking(deleted)
assertDatabaseState(expectedContactEmails = expected)
}
@Test
fun saveContactEmail() = runBlocking {
val inserted = ContactEmail(
"z",
"z@z.com",
contactId = "zzz",
labelIds = listOf("zzzz", "zzzzz", "zzzzzz"),
name = "ce1",
lastUsedTime = 116
)
val expected = contactEmails + inserted
database.saveContactEmail(inserted)
assertDatabaseState(expectedContactEmails = expected)
}
@Test
fun saveAllContactsEmails() {
val inserted = listOf(
ContactEmail(
"y",
"y@y.com",
contactId = "yyy",
labelIds = listOf("yyyy", "yyyyy", "yyyyyy"),
name = "ce1",
lastUsedTime = 118
),
ContactEmail(
"z",
"z@z.com",
contactId = "zzz",
labelIds = listOf("zzzz", "zzzzz", "zzzzzz"),
name = "ce2",
lastUsedTime = 116
)
)
val expected = contactEmails + inserted
database.saveAllContactsEmailsBlocking(inserted)
assertDatabaseState(expectedContactEmails = expected)
}
@Test
fun saveAllContactsEmails1() = runBlocking{
val inserted = listOf(
ContactEmail(
"y",
"y@y.com",
contactId = "yyy",
labelIds = listOf("yyyy", "yyyyy", "yyyyyy"),
name = "ce1",
lastUsedTime = 118
),
ContactEmail(
"z",
"z@z.com",
contactId = "zzz",
labelIds = listOf("zzzz", "zzzzz", "zzzzzz"),
name = "ce2",
lastUsedTime = 116
)
)
val expected = contactEmails + inserted
database.saveAllContactsEmails(inserted)
assertDatabaseState(expectedContactEmails = expected)
}
@Test
fun insertFullContactDetails() {
val inserted = FullContactDetails(
contactId = "z",
name = "zz",
uid = "zzz",
createTime = 1,
modifyTime = 131,
size = 12,
defaults = 321,
encryptedData = mutableListOf(
ContactEncryptedData("zzzz", "zzzzz", Constants.VCardType.SIGNED),
ContactEncryptedData("zzzzzz", "zzzzzzz", Constants.VCardType.SIGNED_ENCRYPTED)
)
)
val expected = fullContactDetails + inserted
database.insertFullContactDetailsBlocking(inserted)
assertDatabaseState(expectedFullContactDetails = expected)
}
@Test
fun findFullContactDetailsById() {
val expected = fullContactDetails[1]
val actual = database.findFullContactDetailsByIdBlocking(expected.contactId)
Assert.assertThat(
actual, `is`(FullContactsDetailsMatcher(expected))
)
assertDatabaseState()
}
@Test
fun clearFullContactDetailsCache() {
val expected = emptyList<FullContactDetails>()
database.clearFullContactDetailsCache()
assertDatabaseState(expectedFullContactDetails = expected)
}
@Test
fun deleteFullContactsDetails() {
val deleted = fullContactDetails[1]
val expected = fullContactDetails - deleted
database.deleteFullContactsDetails(deleted)
val found = database.findFullContactDetailsByIdBlocking(deleted.contactId)
Assert.assertNull(found)
assertDatabaseState(expectedFullContactDetails = expected)
}
@Test
fun testContactEmailsConverter() = runBlocking {
val email1 = ContactEmail(
"e1",
"1@1.1",
"a",
labelIds = listOf("la", "lc"),
lastUsedTime = 121
)
val email2 = ContactEmail(
"e2",
"2@2.2",
"b",
labelIds = listOf("la", "lc"),
lastUsedTime = 123
)
val email3 = ContactEmail(
"e3",
"3@3.3",
"c",
labelIds = listOf("la", "lc"),
lastUsedTime = 122
)
initiallyEmptyDatabase.saveAllContactsEmails(listOf(email1, email2, email3))
val emailFromDb = initiallyEmptyDatabase.findContactEmailById("e1")
Assert.assertNotNull(emailFromDb)
val listOfGroups = emailFromDb?.labelIds
Assert.assertNotNull(listOfGroups)
val expectedGroupId = "la"
Assert.assertEquals(expectedGroupId, listOfGroups?.get(0))
}
}