Add instrumented tests for RecipientDatabase.

fork-5.53.8
Greyson Parrelli 2021-10-15 10:18:38 -04:00
rodzic 62f9f19540
commit 5711b8a0fa
8 zmienionych plików z 446 dodań i 65 usunięć

Wyświetl plik

@ -162,10 +162,10 @@ android {
buildConfigField "String", "CDSH_PUBLIC_KEY", "\"2fe57da347cd62431528daac5fbb290730fff684afc4cfc2ed90995f58cb3b74\""
buildConfigField "String", "CDSH_CODE_HASH", "\"ec31a51880d19a5e9e0fed404740c1a3ff53a553125564b745acce475f0fded8\""
buildConfigField "String", "CDS_MRENCLAVE", "\"c98e00a4e3ff977a56afefe7362a27e4961e4f19e211febfbb19b897e6b80b15\""
buildConfigField "KbsEnclave", "KBS_ENCLAVE", "new KbsEnclave(\"fe7c1bfae98f9b073d220366ea31163ee82f6d04bead774f71ca8e5c40847bfe\"," +
"\"fe7c1bfae98f9b073d220366ea31163ee82f6d04bead774f71ca8e5c40847bfe\", " +
"\"a3baab19ef6ce6f34ab9ebb25ba722725ae44a8872dc0ff08ad6d83a9489de87\")";
buildConfigField "KbsEnclave[]", "KBS_FALLBACKS", "new KbsEnclave[0]"
buildConfigField "org.thoughtcrime.securesms.KbsEnclave", "KBS_ENCLAVE", "new org.thoughtcrime.securesms.KbsEnclave(\"fe7c1bfae98f9b073d220366ea31163ee82f6d04bead774f71ca8e5c40847bfe\"," +
"\"fe7c1bfae98f9b073d220366ea31163ee82f6d04bead774f71ca8e5c40847bfe\", " +
"\"a3baab19ef6ce6f34ab9ebb25ba722725ae44a8872dc0ff08ad6d83a9489de87\")";
buildConfigField "org.thoughtcrime.securesms.KbsEnclave[]", "KBS_FALLBACKS", "new org.thoughtcrime.securesms.KbsEnclave[0]"
buildConfigField "String", "UNIDENTIFIED_SENDER_TRUST_ROOT", "\"BXu6QIKVz5MA8gstzfOgRQGqyLqOwNKHL6INkv3IHWMF\""
buildConfigField "String", "ZKGROUP_SERVER_PUBLIC_PARAMS", "\"AMhf5ywVwITZMsff/eCyudZx9JDmkkkbV6PInzG4p8x3VqVJSFiMvnvlEKWuRob/1eaIetR31IYeAbm0NdOuHH8Qi+Rexi1wLlpzIo1gstHWBfZzy1+qHRV5A4TqPp15YzBPm0WSggW6PbSn+F4lf57VCnHF7p8SvzAA2ZZJPYJURt8X7bbg+H3i+PEjH9DXItNEqs2sNcug37xZQDLm7X36nOoGPs54XsEGzPdEV+itQNGUFEjY6X9Uv+Acuks7NpyGvCoKxGwgKgE5XyJ+nNKlyHHOLb6N1NuHyBrZrgtY\""
buildConfigField "String[]", "LANGUAGES", "new String[]{\"" + autoResConfig().collect { s -> s.replace('-r', '_') }.join('", "') + '"}'
@ -197,6 +197,11 @@ android {
}
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments clearPackageData: 'true'
}
testOptions {
execution 'ANDROIDX_TEST_ORCHESTRATOR'
}
compileOptions {
@ -342,10 +347,10 @@ android {
buildConfigField "String", "SIGNAL_CONTACT_DISCOVERY_URL", "\"https://api-staging.directory.signal.org\""
buildConfigField "String", "SIGNAL_KEY_BACKUP_URL", "\"https://api-staging.backup.signal.org\""
buildConfigField "String", "CDS_MRENCLAVE", "\"c98e00a4e3ff977a56afefe7362a27e4961e4f19e211febfbb19b897e6b80b15\""
buildConfigField "KbsEnclave", "KBS_ENCLAVE", "new KbsEnclave(\"823a3b2c037ff0cbe305cc48928cfcc97c9ed4a8ca6d49af6f7d6981fb60a4e9\", " +
"\"16b94ac6d2b7f7b9d72928f36d798dbb35ed32e7bb14c42b4301ad0344b46f29\", " +
"\"a3baab19ef6ce6f34ab9ebb25ba722725ae44a8872dc0ff08ad6d83a9489de87\")"
buildConfigField "KbsEnclave[]", "KBS_FALLBACKS", "new KbsEnclave[0]"
buildConfigField "org.thoughtcrime.securesms.KbsEnclave", "KBS_ENCLAVE", "new org.thoughtcrime.securesms.KbsEnclave(\"823a3b2c037ff0cbe305cc48928cfcc97c9ed4a8ca6d49af6f7d6981fb60a4e9\", " +
"\"16b94ac6d2b7f7b9d72928f36d798dbb35ed32e7bb14c42b4301ad0344b46f29\", " +
"\"a3baab19ef6ce6f34ab9ebb25ba722725ae44a8872dc0ff08ad6d83a9489de87\")"
buildConfigField "org.thoughtcrime.securesms.KbsEnclave[]", "KBS_FALLBACKS", "new org.thoughtcrime.securesms.KbsEnclave[0]"
buildConfigField "String", "UNIDENTIFIED_SENDER_TRUST_ROOT", "\"BbqY1DzohE4NUZoVF+L18oUPrK3kILllLEJh2UnPSsEx\""
buildConfigField "String", "ZKGROUP_SERVER_PUBLIC_PARAMS", "\"ABSY21VckQcbSXVNCGRYJcfWHiAMZmpTtTELcDmxgdFbtp/bWsSxZdMKzfCp8rvIs8ocCU3B37fT3r4Mi5qAemeGeR2X+/YmOGR5ofui7tD5mDQfstAI9i+4WpMtIe8KC3wU5w3Inq3uNWVmoGtpKndsNfwJrCg0Hd9zmObhypUnSkfYn2ooMOOnBpfdanRtrvetZUayDMSC5iSRcXKpdlukrpzzsCIvEwjwQlJYVPOQPj4V0F4UXXBdHSLK05uoPBCQG8G9rYIGedYsClJXnbrgGYG3eMTG5hnx4X4ntARB\""
buildConfigField "String", "MOBILE_COIN_ENVIRONMENT", "\"testnet\""
@ -556,6 +561,8 @@ dependencies {
implementation libs.rxjava3.rxandroid
implementation libs.rxjava3.rxkotlin
androidTestUtil 'androidx.test:orchestrator:1.4.0'
}
dependencyVerification {

Wyświetl plik

@ -0,0 +1,366 @@
package org.thoughtcrime.securesms.database
import android.app.Application
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId
import org.whispersystems.libsignal.util.guava.Optional
import java.lang.IllegalArgumentException
import java.util.UUID
@RunWith(AndroidJUnit4::class)
class RecipientDatabaseTest {
private lateinit var recipientDatabase: RecipientDatabase
@Before
fun setup() {
recipientDatabase = DatabaseFactory.getRecipientDatabase(context)
ensureDbEmpty()
}
// ==============================================================
// If both the ACI and E164 map to no one
// ==============================================================
/** If all you have is an ACI, you can just store that, regardless of trust level. */
@Test
fun getAndPossiblyMerge_aciAndE164MapToNoOne_aciOnly_highTrust() {
val recipientId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, null, true)
val recipient = Recipient.resolved(recipientId)
assertEquals(ACI_A, recipient.requireUuid())
assertFalse(recipient.hasE164())
}
/** If all you have is an ACI, you can just store that, regardless of trust level. */
@Test
fun getAndPossiblyMerge_aciAndE164MapToNoOne_aciOnly_lowTrust() {
val recipientId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, null, false)
val recipient = Recipient.resolved(recipientId)
assertEquals(ACI_A, recipient.requireUuid())
assertFalse(recipient.hasE164())
}
/** If all you have is an E164, you can just store that, regardless of trust level. */
@Test
fun getAndPossiblyMerge_aciAndE164MapToNoOne_e164Only_highTrust() {
val recipientId: RecipientId = recipientDatabase.getAndPossiblyMerge(null, E164_A, true)
val recipient = Recipient.resolved(recipientId)
assertEquals(E164_A, recipient.requireE164())
assertFalse(recipient.hasUuid())
}
/** If all you have is an E164, you can just store that, regardless of trust level. */
@Test
fun getAndPossiblyMerge_aciAndE164MapToNoOne_e164Only_lowTrust() {
val recipientId: RecipientId = recipientDatabase.getAndPossiblyMerge(null, E164_A, false)
val recipient = Recipient.resolved(recipientId)
assertEquals(E164_A, recipient.requireE164())
assertFalse(recipient.hasUuid())
}
/** With high trust, you can associate an ACI-e164 pair. */
@Test
fun getAndPossiblyMerge_aciAndE164MapToNoOne_aciAndE164_highTrust() {
val recipientId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, true)
val recipient = Recipient.resolved(recipientId)
assertEquals(ACI_A, recipient.requireUuid())
assertEquals(E164_A, recipient.requireE164())
}
/** With low trust, you cannot associate an ACI-e164 pair, and therefore can only store the ACI. */
@Test
fun getAndPossiblyMerge_aciAndE164MapToNoOne_aciAndE164_lowTrust() {
val recipientId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, false)
val recipient = Recipient.resolved(recipientId)
assertEquals(ACI_A, recipient.requireUuid())
assertFalse(recipient.hasE164())
}
// ==============================================================
// If the ACI maps to an existing user, but the E164 doesn't
// ==============================================================
/** With high trust, you can associate an e164 with an existing ACI. */
@Test
fun getAndPossiblyMerge_aciMapsToExistingUserButE164DoesNot_aciAndE164_highTrust() {
val existingId: RecipientId = recipientDatabase.getOrInsertFromUuid(ACI_A)
val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, true)
assertEquals(existingId, retrievedId)
val retrievedRecipient = Recipient.resolved(retrievedId)
assertEquals(ACI_A, retrievedRecipient.requireUuid())
assertEquals(E164_A, retrievedRecipient.requireE164())
}
/** With low trust, you cannot associate an ACI-e164 pair, and therefore cannot store the e164. */
@Test
fun getAndPossiblyMerge_aciMapsToExistingUserButE164DoesNot_aciAndE164_lowTrust() {
val existingId: RecipientId = recipientDatabase.getOrInsertFromUuid(ACI_A)
val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, false)
assertEquals(existingId, retrievedId)
val retrievedRecipient = Recipient.resolved(retrievedId)
assertEquals(ACI_A, retrievedRecipient.requireUuid())
assertFalse(retrievedRecipient.hasE164())
}
/** Basically the change number case. High trust lets you update the existing user. */
@Test
fun getAndPossiblyMerge_aciMapsToExistingUserButE164DoesNot_aciAndE164_2_highTrust() {
val existingId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, true)
val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_B, true)
assertEquals(existingId, retrievedId)
val retrievedRecipient = Recipient.resolved(retrievedId)
assertEquals(ACI_A, retrievedRecipient.requireUuid())
assertEquals(E164_B, retrievedRecipient.requireE164())
}
/** Low trust means you cant update the underlying data, but you also dont need to create any new rows. */
@Test
fun getAndPossiblyMerge_aciMapsToExistingUserButE164DoesNot_aciAndE164_2_lowTrust() {
val existingId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, true)
val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_B, false)
assertEquals(existingId, retrievedId)
val retrievedRecipient = Recipient.resolved(retrievedId)
assertEquals(ACI_A, retrievedRecipient.requireUuid())
assertEquals(E164_A, retrievedRecipient.requireE164())
}
// ==============================================================
// If the E164 maps to an existing user, but the ACI doesn't
// ==============================================================
/** With high trust, you can associate an e164 with an existing ACI. */
@Test
fun getAndPossiblyMerge_e164MapsToExistingUserButAciDoesNot_aciAndE164_highTrust() {
val existingId: RecipientId = recipientDatabase.getOrInsertFromE164(E164_A)
val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, true)
assertEquals(existingId, retrievedId)
val retrievedRecipient = Recipient.resolved(retrievedId)
assertEquals(ACI_A, retrievedRecipient.requireUuid())
assertEquals(E164_A, retrievedRecipient.requireE164())
}
/** With low trust, you cannot associate an ACI-e164 pair, and therefore need to create a new person with just the ACI. */
@Test
fun getAndPossiblyMerge_e164MapsToExistingUserButAciDoesNot_aciAndE164_lowTrust() {
val existingId: RecipientId = recipientDatabase.getOrInsertFromE164(E164_A)
val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, false)
assertNotEquals(existingId, retrievedId)
val retrievedRecipient = Recipient.resolved(retrievedId)
assertEquals(ACI_A, retrievedRecipient.requireUuid())
assertFalse(retrievedRecipient.hasE164())
val existingRecipient = Recipient.resolved(existingId)
assertEquals(E164_A, existingRecipient.requireE164())
assertFalse(existingRecipient.hasUuid())
}
/** We never change the ACI of an existing row. New ACI = new person, regardless of trust. But high trust lets us take the e164 from the current holder. */
@Test
fun getAndPossiblyMerge_e164MapsToExistingUserButAciDoesNot_aciAndE164_2_highTrust() {
val existingId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, true)
val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_B, E164_A, true)
assertNotEquals(existingId, retrievedId)
val retrievedRecipient = Recipient.resolved(retrievedId)
assertEquals(ACI_B, retrievedRecipient.requireUuid())
assertEquals(E164_A, retrievedRecipient.requireE164())
val existingRecipient = Recipient.resolved(existingId)
assertEquals(ACI_A, existingRecipient.requireUuid())
assertFalse(existingRecipient.hasE164())
}
/** We never change the ACI of an existing row. New ACI = new person, regardless of trust. And low trust means we cant take the e164. */
@Test
fun getAndPossiblyMerge_e164MapsToExistingUserButAciDoesNot_aciAndE164_2_lowTrust() {
val existingId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, true)
val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_B, E164_A, false)
assertNotEquals(existingId, retrievedId)
val retrievedRecipient = Recipient.resolved(retrievedId)
assertEquals(ACI_B, retrievedRecipient.requireUuid())
assertFalse(retrievedRecipient.hasE164())
val existingRecipient = Recipient.resolved(existingId)
assertEquals(ACI_A, existingRecipient.requireUuid())
assertEquals(E164_A, existingRecipient.requireE164())
}
// ==============================================================
// If both the ACI and E164 map to an existing user
// ==============================================================
/** Regardless of trust, if your ACI and e164 match, youre good. */
@Test
fun getAndPossiblyMerge_bothAciAndE164MapToExistingUser_aciAndE164_highTrust() {
val existingId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, true)
val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, true)
assertEquals(existingId, retrievedId)
val retrievedRecipient = Recipient.resolved(retrievedId)
assertEquals(ACI_A, retrievedRecipient.requireUuid())
assertEquals(E164_A, retrievedRecipient.requireE164())
}
/** High trust lets you merge two different users into one. You should prefer the ACI user. Not shown: merging threads, dropping e164 sessions, etc. */
@Test
fun getAndPossiblyMerge_bothAciAndE164MapToExistingUser_aciAndE164_merge_highTrust() {
val existingAciId: RecipientId = recipientDatabase.getOrInsertFromUuid(ACI_A)
val existingE164Id: RecipientId = recipientDatabase.getOrInsertFromE164(E164_A)
val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, true)
assertEquals(existingAciId, retrievedId)
val retrievedRecipient = Recipient.resolved(retrievedId)
assertEquals(ACI_A, retrievedRecipient.requireUuid())
assertEquals(E164_A, retrievedRecipient.requireE164())
val existingE164Recipient = Recipient.resolved(existingE164Id)
assertEquals(retrievedId, existingE164Recipient.id)
}
/** Low trust means you cant merge. If youre retrieving a user from the table with this data, prefer the ACI one. */
@Test
fun getAndPossiblyMerge_bothAciAndE164MapToExistingUser_aciAndE164_lowTrust() {
val existingAciId: RecipientId = recipientDatabase.getOrInsertFromUuid(ACI_A)
val existingE164Id: RecipientId = recipientDatabase.getOrInsertFromE164(E164_A)
val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, false)
assertEquals(existingAciId, retrievedId)
val retrievedRecipient = Recipient.resolved(retrievedId)
assertEquals(ACI_A, retrievedRecipient.requireUuid())
assertFalse(retrievedRecipient.hasE164())
val existingE164Recipient = Recipient.resolved(existingE164Id)
assertEquals(E164_A, existingE164Recipient.requireE164())
assertFalse(existingE164Recipient.hasUuid())
}
/** Another high trust case. No new rules here, just a more complex scenario to show how different rules interact. */
@Test
fun getAndPossiblyMerge_bothAciAndE164MapToExistingUser_aciAndE164_complex_highTrust() {
val existingId1: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_B, true)
val existingId2: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_B, E164_A, true)
val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, true)
assertEquals(existingId1, retrievedId)
val retrievedRecipient = Recipient.resolved(retrievedId)
assertEquals(ACI_A, retrievedRecipient.requireUuid())
assertEquals(E164_A, retrievedRecipient.requireE164())
val existingRecipient2 = Recipient.resolved(existingId2)
assertEquals(ACI_B, existingRecipient2.requireUuid())
assertFalse(existingRecipient2.hasE164())
}
/** Another low trust case. No new rules here, just a more complex scenario to show how different rules interact. */
@Test
fun getAndPossiblyMerge_bothAciAndE164MapToExistingUser_aciAndE164_complex_lowTrust() {
val existingId1: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_B, true)
val existingId2: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_B, E164_A, true)
val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, false)
assertEquals(existingId1, retrievedId)
val retrievedRecipient = Recipient.resolved(retrievedId)
assertEquals(ACI_A, retrievedRecipient.requireUuid())
assertEquals(E164_B, retrievedRecipient.requireE164())
val existingRecipient2 = Recipient.resolved(existingId2)
assertEquals(ACI_B, existingRecipient2.requireUuid())
assertEquals(E164_A, existingRecipient2.requireE164())
}
// ==============================================================
// Misc
// ==============================================================
@Test
fun createByE164SanityCheck() {
// GIVEN one recipient
val recipientId: RecipientId = recipientDatabase.getOrInsertFromE164(E164_A)
// WHEN I retrieve one by E164
val possible: Optional<RecipientId> = recipientDatabase.getByE164(E164_A)
// THEN I get it back, and it has the properties I expect
assertTrue(possible.isPresent)
assertEquals(recipientId, possible.get())
val recipient = Recipient.resolved(recipientId)
assertTrue(recipient.e164.isPresent)
assertEquals(E164_A, recipient.e164.get())
}
@Test
fun createByUuidSanityCheck() {
// GIVEN one recipient
val recipientId: RecipientId = recipientDatabase.getOrInsertFromUuid(ACI_A)
// WHEN I retrieve one by UUID
val possible: Optional<RecipientId> = recipientDatabase.getByUuid(ACI_A)
// THEN I get it back, and it has the properties I expect
assertTrue(possible.isPresent)
assertEquals(recipientId, possible.get())
val recipient = Recipient.resolved(recipientId)
assertTrue(recipient.uuid.isPresent)
assertEquals(ACI_A, recipient.uuid.get())
}
@Test(expected = IllegalArgumentException::class)
fun getAndPossiblyMerge_noArgs_invalid() {
recipientDatabase.getAndPossiblyMerge(null, null, true)
}
private val context: Application
get() = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as Application
private fun ensureDbEmpty() {
DatabaseFactory.getInstance(context).rawDatabase.rawQuery("SELECT COUNT(*) FROM ${RecipientDatabase.TABLE_NAME}", null).use { cursor ->
assertTrue(cursor.moveToFirst())
assertEquals(0, cursor.getLong(0))
}
}
companion object {
val ACI_A = UUID.fromString("3436efbe-5a76-47fa-a98a-7e72c948a82e")
val ACI_B = UUID.fromString("8de7f691-0b60-4a68-9cd9-ed2f8453f9ed")
val E164_A = "+12221234567"
val E164_B = "+13331234567"
}
}

Wyświetl plik

@ -1,6 +1,9 @@
package org.thoughtcrime.securesms.lock;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.thoughtcrime.securesms.util.Hex;
import org.whispersystems.signalservice.api.kbs.HashedPin;
import org.whispersystems.signalservice.api.kbs.KbsData;
@ -12,6 +15,7 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@RunWith(AndroidJUnit4.class)
public final class PinHashing_hashPin_Test {
@Test

Wyświetl plik

@ -38,37 +38,37 @@ class MmsDatabaseTest {
@Test
fun `isGroupQuitMessage when normal message, return false`() {
val id = TestMms.insertMmsMessage(db, type = Types.BASE_SENDING_TYPE or Types.SECURE_MESSAGE_BIT or Types.PUSH_MESSAGE_BIT)
val id = TestMms.insert(db, type = Types.BASE_SENDING_TYPE or Types.SECURE_MESSAGE_BIT or Types.PUSH_MESSAGE_BIT)
assertFalse(mmsDatabase.isGroupQuitMessage(id))
}
@Test
fun `isGroupQuitMessage when legacy quit message, return true`() {
val id = TestMms.insertMmsMessage(db, type = Types.BASE_SENDING_TYPE or Types.SECURE_MESSAGE_BIT or Types.PUSH_MESSAGE_BIT or Types.GROUP_LEAVE_BIT)
val id = TestMms.insert(db, type = Types.BASE_SENDING_TYPE or Types.SECURE_MESSAGE_BIT or Types.PUSH_MESSAGE_BIT or Types.GROUP_LEAVE_BIT)
assertTrue(mmsDatabase.isGroupQuitMessage(id))
}
@Test
fun `isGroupQuitMessage when GV2 leave update, return false`() {
val id = TestMms.insertMmsMessage(db, type = Types.BASE_SENDING_TYPE or Types.SECURE_MESSAGE_BIT or Types.PUSH_MESSAGE_BIT or Types.GROUP_LEAVE_BIT or Types.GROUP_V2_BIT or Types.GROUP_UPDATE_BIT)
val id = TestMms.insert(db, type = Types.BASE_SENDING_TYPE or Types.SECURE_MESSAGE_BIT or Types.PUSH_MESSAGE_BIT or Types.GROUP_LEAVE_BIT or Types.GROUP_V2_BIT or Types.GROUP_UPDATE_BIT)
assertFalse(mmsDatabase.isGroupQuitMessage(id))
}
@Test
fun `getLatestGroupQuitTimestamp when only normal message, return -1`() {
TestMms.insertMmsMessage(db, threadId = 1, sentTimeMillis = 1, type = Types.BASE_SENDING_TYPE or Types.SECURE_MESSAGE_BIT or Types.PUSH_MESSAGE_BIT)
TestMms.insert(db, threadId = 1, sentTimeMillis = 1, type = Types.BASE_SENDING_TYPE or Types.SECURE_MESSAGE_BIT or Types.PUSH_MESSAGE_BIT)
assertEquals(-1, mmsDatabase.getLatestGroupQuitTimestamp(1, 4))
}
@Test
fun `getLatestGroupQuitTimestamp when legacy quit, return message timestamp`() {
TestMms.insertMmsMessage(db, threadId = 1, sentTimeMillis = 2, type = Types.BASE_SENDING_TYPE or Types.SECURE_MESSAGE_BIT or Types.PUSH_MESSAGE_BIT or Types.GROUP_LEAVE_BIT)
TestMms.insert(db, threadId = 1, sentTimeMillis = 2, type = Types.BASE_SENDING_TYPE or Types.SECURE_MESSAGE_BIT or Types.PUSH_MESSAGE_BIT or Types.GROUP_LEAVE_BIT)
assertEquals(2, mmsDatabase.getLatestGroupQuitTimestamp(1, 4))
}
@Test
fun `getLatestGroupQuitTimestamp when GV2 leave update message, return -1`() {
TestMms.insertMmsMessage(db, threadId = 1, sentTimeMillis = 3, type = Types.BASE_SENDING_TYPE or Types.SECURE_MESSAGE_BIT or Types.PUSH_MESSAGE_BIT or Types.GROUP_LEAVE_BIT or Types.GROUP_V2_BIT or Types.GROUP_UPDATE_BIT)
TestMms.insert(db, threadId = 1, sentTimeMillis = 3, type = Types.BASE_SENDING_TYPE or Types.SECURE_MESSAGE_BIT or Types.PUSH_MESSAGE_BIT or Types.GROUP_LEAVE_BIT or Types.GROUP_V2_BIT or Types.GROUP_UPDATE_BIT)
assertEquals(-1, mmsDatabase.getLatestGroupQuitTimestamp(1, 4))
}
}

Wyświetl plik

@ -40,7 +40,7 @@ class MmsSmsDatabaseTest {
@Test
fun `getConversationSnippet when single normal SMS, return SMS message id and transport as false`() {
TestSms.insertSmsMessage(db)
TestSms.insert(db)
mmsSmsDatabase.getConversationSnippetCursor(1).use { cursor ->
cursor.moveToFirst()
assertEquals(1, CursorUtil.requireLong(cursor, MmsSmsColumns.ID))
@ -50,7 +50,7 @@ class MmsSmsDatabaseTest {
@Test
fun `getConversationSnippet when single normal MMS, return MMS message id and transport as true`() {
TestMms.insertMmsMessage(db)
TestMms.insert(db)
mmsSmsDatabase.getConversationSnippetCursor(1).use { cursor ->
cursor.moveToFirst()
assertEquals(1, CursorUtil.requireLong(cursor, MmsSmsColumns.ID))
@ -62,14 +62,14 @@ class MmsSmsDatabaseTest {
fun `getConversationSnippet when single normal MMS then GV2 leave update message, return MMS message id and transport as true both times`() {
val timestamp = System.currentTimeMillis()
TestMms.insertMmsMessage(db, receivedTimestampMillis = timestamp + 2)
TestMms.insert(db, receivedTimestampMillis = timestamp + 2)
mmsSmsDatabase.getConversationSnippetCursor(1).use { cursor ->
cursor.moveToFirst()
assertEquals(1, CursorUtil.requireLong(cursor, MmsSmsColumns.ID))
assertTrue(CursorUtil.requireBoolean(cursor, MmsSmsDatabase.TRANSPORT))
}
TestSms.insertSmsMessage(db, receivedTimestampMillis = timestamp + 3, type = MmsSmsColumns.Types.BASE_SENDING_TYPE or MmsSmsColumns.Types.SECURE_MESSAGE_BIT or MmsSmsColumns.Types.PUSH_MESSAGE_BIT or MmsSmsColumns.Types.GROUP_V2_LEAVE_BITS)
TestSms.insert(db, receivedTimestampMillis = timestamp + 3, type = MmsSmsColumns.Types.BASE_SENDING_TYPE or MmsSmsColumns.Types.SECURE_MESSAGE_BIT or MmsSmsColumns.Types.PUSH_MESSAGE_BIT or MmsSmsColumns.Types.GROUP_V2_LEAVE_BITS)
mmsSmsDatabase.getConversationSnippetCursor(1).use { cursor ->
cursor.moveToFirst()
assertEquals(1, CursorUtil.requireLong(cursor, MmsSmsColumns.ID))

Wyświetl plik

@ -44,7 +44,7 @@ class SmsDatabaseTest {
@Test
fun `getThreadIdForMessage when message present for id, return thread id`() {
TestSms.insertSmsMessage(db)
TestSms.insert(db)
assertThat(smsDatabase.getThreadIdForMessage(1), isEqual(1))
}
@ -55,13 +55,13 @@ class SmsDatabaseTest {
@Test
fun `hasMeaningfulMessage when normal message, return true`() {
TestSms.insertSmsMessage(db)
TestSms.insert(db)
assertTrue(smsDatabase.hasMeaningfulMessage(1))
}
@Test
fun `hasMeaningfulMessage when GV2 create message only, return true`() {
TestSms.insertSmsMessage(db, type = MmsSmsColumns.Types.BASE_INBOX_TYPE or MmsSmsColumns.Types.SECURE_MESSAGE_BIT or MmsSmsColumns.Types.GROUP_V2_BIT or MmsSmsColumns.Types.GROUP_UPDATE_BIT)
TestSms.insert(db, type = MmsSmsColumns.Types.BASE_INBOX_TYPE or MmsSmsColumns.Types.SECURE_MESSAGE_BIT or MmsSmsColumns.Types.GROUP_V2_BIT or MmsSmsColumns.Types.GROUP_UPDATE_BIT)
assertTrue(smsDatabase.hasMeaningfulMessage(1))
}
@ -69,16 +69,16 @@ class SmsDatabaseTest {
fun `hasMeaningfulMessage when empty and then with ignored types, always return false`() {
assertFalse(smsDatabase.hasMeaningfulMessage(1))
TestSms.insertSmsMessage(db, type = SmsDatabase.IGNORABLE_TYPESMASK_WHEN_COUNTING)
TestSms.insert(db, type = SmsDatabase.IGNORABLE_TYPESMASK_WHEN_COUNTING)
assertFalse(smsDatabase.hasMeaningfulMessage(1))
TestSms.insertSmsMessage(db, type = MmsSmsColumns.Types.PROFILE_CHANGE_TYPE)
TestSms.insert(db, type = MmsSmsColumns.Types.PROFILE_CHANGE_TYPE)
assertFalse(smsDatabase.hasMeaningfulMessage(1))
TestSms.insertSmsMessage(db, type = MmsSmsColumns.Types.CHANGE_NUMBER_TYPE)
TestSms.insert(db, type = MmsSmsColumns.Types.CHANGE_NUMBER_TYPE)
assertFalse(smsDatabase.hasMeaningfulMessage(1))
TestSms.insertSmsMessage(db, type = MmsSmsColumns.Types.BASE_INBOX_TYPE or MmsSmsColumns.Types.GROUP_V2_LEAVE_BITS)
TestSms.insert(db, type = MmsSmsColumns.Types.BASE_INBOX_TYPE or MmsSmsColumns.Types.GROUP_V2_LEAVE_BITS)
assertFalse(smsDatabase.hasMeaningfulMessage(1))
}
}

Wyświetl plik

@ -11,7 +11,7 @@ import org.thoughtcrime.securesms.recipients.Recipient
*/
object TestMms {
fun insertMmsMessage(
fun insert(
db: SQLiteDatabase,
recipient: Recipient = Recipient.UNKNOWN,
body: String = "body",
@ -42,7 +42,7 @@ object TestMms {
emptySet()
)
return insertMmsMessage(
return insert(
db = db,
message = message,
body = body,
@ -53,7 +53,7 @@ object TestMms {
)
}
fun insertMmsMessage(
fun insert(
db: SQLiteDatabase,
message: OutgoingMediaMessage,
body: String = message.body,
@ -62,24 +62,25 @@ object TestMms {
threadId: Long = 1,
receivedTimestampMillis: Long = System.currentTimeMillis(),
): Long {
val contentValues = ContentValues()
contentValues.put(MmsDatabase.DATE_SENT, message.sentTimeMillis)
contentValues.put(MmsDatabase.MESSAGE_TYPE, PduHeaders.MESSAGE_TYPE_SEND_REQ)
val contentValues = ContentValues().apply {
put(MmsDatabase.DATE_SENT, message.sentTimeMillis)
put(MmsDatabase.MESSAGE_TYPE, PduHeaders.MESSAGE_TYPE_SEND_REQ)
contentValues.put(MmsDatabase.MESSAGE_BOX, type)
contentValues.put(MmsSmsColumns.THREAD_ID, threadId)
contentValues.put(MmsSmsColumns.READ, if (unread) 0 else 1)
contentValues.put(MmsDatabase.DATE_RECEIVED, receivedTimestampMillis)
contentValues.put(MmsSmsColumns.SUBSCRIPTION_ID, message.subscriptionId)
contentValues.put(MmsSmsColumns.EXPIRES_IN, message.expiresIn)
contentValues.put(MmsDatabase.VIEW_ONCE, message.isViewOnce)
contentValues.put(MmsSmsColumns.RECIPIENT_ID, message.recipient.id.serialize())
contentValues.put(MmsSmsColumns.DELIVERY_RECEIPT_COUNT, 0)
contentValues.put(MmsSmsColumns.RECEIPT_TIMESTAMP, 0)
put(MmsDatabase.MESSAGE_BOX, type)
put(MmsSmsColumns.THREAD_ID, threadId)
put(MmsSmsColumns.READ, if (unread) 0 else 1)
put(MmsDatabase.DATE_RECEIVED, receivedTimestampMillis)
put(MmsSmsColumns.SUBSCRIPTION_ID, message.subscriptionId)
put(MmsSmsColumns.EXPIRES_IN, message.expiresIn)
put(MmsDatabase.VIEW_ONCE, message.isViewOnce)
put(MmsSmsColumns.RECIPIENT_ID, message.recipient.id.serialize())
put(MmsSmsColumns.DELIVERY_RECEIPT_COUNT, 0)
put(MmsSmsColumns.RECEIPT_TIMESTAMP, 0)
contentValues.put(MmsSmsColumns.BODY, body)
contentValues.put(MmsDatabase.PART_COUNT, 0)
contentValues.put(MmsDatabase.MENTIONS_SELF, 0)
put(MmsSmsColumns.BODY, body)
put(MmsDatabase.PART_COUNT, 0)
put(MmsDatabase.MENTIONS_SELF, 0)
}
return db.insert(MmsDatabase.TABLE_NAME, null, contentValues)
}

Wyświetl plik

@ -14,7 +14,7 @@ import android.database.sqlite.SQLiteDatabase as AndroidSQLiteDatabase
*/
object TestSms {
fun insertSmsMessage(
fun insert(
db: AndroidSQLiteDatabase,
sender: RecipientId = RecipientId.from(1),
senderDeviceId: Int = 1,
@ -43,7 +43,7 @@ object TestSms {
serverGuid
)
return insertSmsMessage(
return insert(
db = db,
message = message,
type = type,
@ -52,33 +52,36 @@ object TestSms {
)
}
fun insertSmsMessage(
fun insert(
db: AndroidSQLiteDatabase,
message: IncomingTextMessage,
type: Long = MmsSmsColumns.Types.BASE_INBOX_TYPE,
unread: Boolean = false,
threadId: Long = 1
): Long {
val values = ContentValues()
values.put(MmsSmsColumns.RECIPIENT_ID, message.sender.serialize())
values.put(MmsSmsColumns.ADDRESS_DEVICE_ID, message.senderDeviceId)
values.put(SmsDatabase.DATE_RECEIVED, message.receivedTimestampMillis)
values.put(SmsDatabase.DATE_SENT, message.sentTimestampMillis)
values.put(MmsSmsColumns.DATE_SERVER, message.serverTimestampMillis)
values.put(SmsDatabase.PROTOCOL, message.protocol)
values.put(MmsSmsColumns.READ, if (unread) 0 else 1)
values.put(MmsSmsColumns.SUBSCRIPTION_ID, message.subscriptionId)
values.put(MmsSmsColumns.EXPIRES_IN, message.expiresIn)
values.put(MmsSmsColumns.UNIDENTIFIED, message.isUnidentified)
val values = ContentValues().apply {
put(MmsSmsColumns.RECIPIENT_ID, message.sender.serialize())
put(MmsSmsColumns.ADDRESS_DEVICE_ID, message.senderDeviceId)
put(SmsDatabase.DATE_RECEIVED, message.receivedTimestampMillis)
put(SmsDatabase.DATE_SENT, message.sentTimestampMillis)
put(MmsSmsColumns.DATE_SERVER, message.serverTimestampMillis)
put(SmsDatabase.PROTOCOL, message.protocol)
put(MmsSmsColumns.READ, if (unread) 0 else 1)
put(MmsSmsColumns.SUBSCRIPTION_ID, message.subscriptionId)
put(MmsSmsColumns.EXPIRES_IN, message.expiresIn)
put(MmsSmsColumns.UNIDENTIFIED, message.isUnidentified)
if (!TextUtils.isEmpty(message.pseudoSubject)) values.put(SmsDatabase.SUBJECT, message.pseudoSubject)
if (!TextUtils.isEmpty(message.pseudoSubject)) {
put(SmsDatabase.SUBJECT, message.pseudoSubject)
}
values.put(SmsDatabase.REPLY_PATH_PRESENT, message.isReplyPathPresent)
values.put(SmsDatabase.SERVICE_CENTER, message.serviceCenterAddress)
values.put(MmsSmsColumns.BODY, message.messageBody)
values.put(SmsDatabase.TYPE, type)
values.put(MmsSmsColumns.THREAD_ID, threadId)
values.put(MmsSmsColumns.SERVER_GUID, message.serverGuid)
put(SmsDatabase.REPLY_PATH_PRESENT, message.isReplyPathPresent)
put(SmsDatabase.SERVICE_CENTER, message.serviceCenterAddress)
put(MmsSmsColumns.BODY, message.messageBody)
put(SmsDatabase.TYPE, type)
put(MmsSmsColumns.THREAD_ID, threadId)
put(MmsSmsColumns.SERVER_GUID, message.serverGuid)
}
return db.insert(SmsDatabase.TABLE_NAME, null, values)
}