mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-27 13:13:43 +00:00
Migrate SMS messages into the MMS table.
This commit is contained in:
@@ -21,16 +21,16 @@ import org.thoughtcrime.securesms.testing.TestDatabaseUtil
|
||||
@Config(manifest = Config.NONE, application = Application::class)
|
||||
class MmsDatabaseTest {
|
||||
private lateinit var db: SQLiteDatabase
|
||||
private lateinit var mmsTable: MmsTable
|
||||
private lateinit var messageTable: MessageTable
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
val sqlCipher = TestDatabaseUtil.inMemoryDatabase {
|
||||
execSQL(MmsTable.CREATE_TABLE)
|
||||
execSQL(MessageTable.CREATE_TABLE)
|
||||
}
|
||||
|
||||
db = sqlCipher.writableDatabase
|
||||
mmsTable = MmsTable(ApplicationProvider.getApplicationContext(), sqlCipher)
|
||||
messageTable = MessageTable(ApplicationProvider.getApplicationContext(), sqlCipher)
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -41,75 +41,75 @@ class MmsDatabaseTest {
|
||||
@Test
|
||||
fun `isGroupQuitMessage when normal message, return false`() {
|
||||
val id = TestMms.insert(db, type = Types.BASE_SENDING_TYPE or Types.SECURE_MESSAGE_BIT or Types.PUSH_MESSAGE_BIT)
|
||||
assertFalse(mmsTable.isGroupQuitMessage(id))
|
||||
assertFalse(messageTable.isGroupQuitMessage(id))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isGroupQuitMessage when legacy quit message, return true`() {
|
||||
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(mmsTable.isGroupQuitMessage(id))
|
||||
assertTrue(messageTable.isGroupQuitMessage(id))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isGroupQuitMessage when GV2 leave update, return false`() {
|
||||
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(mmsTable.isGroupQuitMessage(id))
|
||||
assertFalse(messageTable.isGroupQuitMessage(id))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getLatestGroupQuitTimestamp when only normal message, return -1`() {
|
||||
TestMms.insert(db, threadId = 1, sentTimeMillis = 1, type = Types.BASE_SENDING_TYPE or Types.SECURE_MESSAGE_BIT or Types.PUSH_MESSAGE_BIT)
|
||||
assertEquals(-1, mmsTable.getLatestGroupQuitTimestamp(1, 4))
|
||||
assertEquals(-1, messageTable.getLatestGroupQuitTimestamp(1, 4))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getLatestGroupQuitTimestamp when legacy quit, return message timestamp`() {
|
||||
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, mmsTable.getLatestGroupQuitTimestamp(1, 4))
|
||||
assertEquals(2, messageTable.getLatestGroupQuitTimestamp(1, 4))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getLatestGroupQuitTimestamp when GV2 leave update message, return -1`() {
|
||||
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, mmsTable.getLatestGroupQuitTimestamp(1, 4))
|
||||
assertEquals(-1, messageTable.getLatestGroupQuitTimestamp(1, 4))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Given no stories in database, when I getStoryViewState, then I expect NONE`() {
|
||||
assertEquals(StoryViewState.NONE, mmsTable.getStoryViewState(1))
|
||||
assertEquals(StoryViewState.NONE, messageTable.getStoryViewState(1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Given stories in database not in thread 1, when I getStoryViewState for thread 1, then I expect NONE`() {
|
||||
TestMms.insert(db, threadId = 2, storyType = StoryType.STORY_WITH_REPLIES)
|
||||
TestMms.insert(db, threadId = 2, storyType = StoryType.STORY_WITH_REPLIES)
|
||||
assertEquals(StoryViewState.NONE, mmsTable.getStoryViewState(1))
|
||||
assertEquals(StoryViewState.NONE, messageTable.getStoryViewState(1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Given viewed incoming stories in database, when I getStoryViewState, then I expect VIEWED`() {
|
||||
TestMms.insert(db, threadId = 1, storyType = StoryType.STORY_WITH_REPLIES, viewed = true)
|
||||
TestMms.insert(db, threadId = 1, storyType = StoryType.STORY_WITH_REPLIES, viewed = true)
|
||||
assertEquals(StoryViewState.VIEWED, mmsTable.getStoryViewState(1))
|
||||
assertEquals(StoryViewState.VIEWED, messageTable.getStoryViewState(1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Given unviewed incoming stories in database, when I getStoryViewState, then I expect UNVIEWED`() {
|
||||
TestMms.insert(db, threadId = 1, storyType = StoryType.STORY_WITH_REPLIES, viewed = false)
|
||||
TestMms.insert(db, threadId = 1, storyType = StoryType.STORY_WITH_REPLIES, viewed = false)
|
||||
assertEquals(StoryViewState.UNVIEWED, mmsTable.getStoryViewState(1))
|
||||
assertEquals(StoryViewState.UNVIEWED, messageTable.getStoryViewState(1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Given mix of viewed and unviewed incoming stories in database, when I getStoryViewState, then I expect UNVIEWED`() {
|
||||
TestMms.insert(db, threadId = 1, storyType = StoryType.STORY_WITH_REPLIES, viewed = true)
|
||||
TestMms.insert(db, threadId = 1, storyType = StoryType.STORY_WITH_REPLIES, viewed = false)
|
||||
assertEquals(StoryViewState.UNVIEWED, mmsTable.getStoryViewState(1))
|
||||
assertEquals(StoryViewState.UNVIEWED, messageTable.getStoryViewState(1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Given only outgoing story in database, when I getStoryViewState, then I expect VIEWED`() {
|
||||
TestMms.insert(db, threadId = 1, storyType = StoryType.STORY_WITH_REPLIES, type = Types.BASE_OUTBOX_TYPE)
|
||||
assertEquals(StoryViewState.VIEWED, mmsTable.getStoryViewState(1))
|
||||
assertEquals(StoryViewState.VIEWED, messageTable.getStoryViewState(1))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import android.database.sqlite.SQLiteDatabase
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -25,8 +23,7 @@ class MmsSmsDatabaseTest {
|
||||
@Before
|
||||
fun setup() {
|
||||
val sqlCipher = TestDatabaseUtil.inMemoryDatabase {
|
||||
execSQL(MmsTable.CREATE_TABLE)
|
||||
execSQL(SmsTable.CREATE_TABLE)
|
||||
execSQL(MessageTable.CREATE_TABLE)
|
||||
}
|
||||
|
||||
db = sqlCipher.writableDatabase
|
||||
@@ -44,7 +41,6 @@ class MmsSmsDatabaseTest {
|
||||
mmsSmsTable.getConversationSnippetCursor(1).use { cursor ->
|
||||
cursor.moveToFirst()
|
||||
assertEquals(1, CursorUtil.requireLong(cursor, MmsSmsColumns.ID))
|
||||
assertFalse(CursorUtil.requireBoolean(cursor, MmsSmsTable.TRANSPORT))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +50,6 @@ class MmsSmsDatabaseTest {
|
||||
mmsSmsTable.getConversationSnippetCursor(1).use { cursor ->
|
||||
cursor.moveToFirst()
|
||||
assertEquals(1, CursorUtil.requireLong(cursor, MmsSmsColumns.ID))
|
||||
assertTrue(CursorUtil.requireBoolean(cursor, MmsSmsTable.TRANSPORT))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,14 +61,12 @@ class MmsSmsDatabaseTest {
|
||||
mmsSmsTable.getConversationSnippetCursor(1).use { cursor ->
|
||||
cursor.moveToFirst()
|
||||
assertEquals(1, CursorUtil.requireLong(cursor, MmsSmsColumns.ID))
|
||||
assertTrue(CursorUtil.requireBoolean(cursor, MmsSmsTable.TRANSPORT))
|
||||
}
|
||||
|
||||
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)
|
||||
mmsSmsTable.getConversationSnippetCursor(1).use { cursor ->
|
||||
cursor.moveToFirst()
|
||||
assertEquals(1, CursorUtil.requireLong(cursor, MmsSmsColumns.ID))
|
||||
assertTrue(CursorUtil.requireBoolean(cursor, MmsSmsTable.TRANSPORT))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,16 +20,16 @@ import org.hamcrest.CoreMatchers.`is` as isEqual
|
||||
class SmsDatabaseTest {
|
||||
|
||||
private lateinit var db: AndroidSQLiteDatabase
|
||||
private lateinit var smsTable: SmsTable
|
||||
private lateinit var messageTable: MessageTable
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
val sqlCipher = TestDatabaseUtil.inMemoryDatabase {
|
||||
execSQL(SmsTable.CREATE_TABLE)
|
||||
execSQL(MessageTable.CREATE_TABLE)
|
||||
}
|
||||
|
||||
db = sqlCipher.writableDatabase
|
||||
smsTable = SmsTable(ApplicationProvider.getApplicationContext(), sqlCipher)
|
||||
messageTable = MessageTable(ApplicationProvider.getApplicationContext(), sqlCipher)
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -39,52 +39,52 @@ class SmsDatabaseTest {
|
||||
|
||||
@Test
|
||||
fun `getThreadIdForMessage when no message absent for id, return -1`() {
|
||||
assertThat(smsTable.getThreadIdForMessage(1), isEqual(-1))
|
||||
assertThat(messageTable.getThreadIdForMessage(1), isEqual(-1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getThreadIdForMessage when message present for id, return thread id`() {
|
||||
TestSms.insert(db)
|
||||
assertThat(smsTable.getThreadIdForMessage(1), isEqual(1))
|
||||
assertThat(messageTable.getThreadIdForMessage(1), isEqual(1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hasMeaningfulMessage when no messages, return false`() {
|
||||
assertFalse(smsTable.hasMeaningfulMessage(1))
|
||||
assertFalse(messageTable.hasMeaningfulMessage(1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hasMeaningfulMessage when normal message, return true`() {
|
||||
TestSms.insert(db)
|
||||
assertTrue(smsTable.hasMeaningfulMessage(1))
|
||||
assertTrue(messageTable.hasMeaningfulMessage(1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hasMeaningfulMessage when GV2 create message only, return true`() {
|
||||
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(smsTable.hasMeaningfulMessage(1))
|
||||
assertTrue(messageTable.hasMeaningfulMessage(1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hasMeaningfulMessage when empty and then with ignored types, always return false`() {
|
||||
assertFalse(smsTable.hasMeaningfulMessage(1))
|
||||
assertFalse(messageTable.hasMeaningfulMessage(1))
|
||||
|
||||
TestSms.insert(db, type = SmsTable.IGNORABLE_TYPESMASK_WHEN_COUNTING)
|
||||
assertFalse(smsTable.hasMeaningfulMessage(1))
|
||||
TestSms.insert(db, type = MmsSmsColumns.Types.IGNORABLE_TYPESMASK_WHEN_COUNTING)
|
||||
assertFalse(messageTable.hasMeaningfulMessage(1))
|
||||
|
||||
TestSms.insert(db, type = MmsSmsColumns.Types.PROFILE_CHANGE_TYPE)
|
||||
assertFalse(smsTable.hasMeaningfulMessage(1))
|
||||
assertFalse(messageTable.hasMeaningfulMessage(1))
|
||||
|
||||
TestSms.insert(db, type = MmsSmsColumns.Types.CHANGE_NUMBER_TYPE)
|
||||
assertFalse(smsTable.hasMeaningfulMessage(1))
|
||||
assertFalse(messageTable.hasMeaningfulMessage(1))
|
||||
|
||||
TestSms.insert(db, type = MmsSmsColumns.Types.BOOST_REQUEST_TYPE)
|
||||
assertFalse(smsTable.hasMeaningfulMessage(1))
|
||||
assertFalse(messageTable.hasMeaningfulMessage(1))
|
||||
|
||||
TestSms.insert(db, type = MmsSmsColumns.Types.SMS_EXPORT_TYPE)
|
||||
assertFalse(smsTable.hasMeaningfulMessage(1))
|
||||
assertFalse(messageTable.hasMeaningfulMessage(1))
|
||||
|
||||
TestSms.insert(db, type = MmsSmsColumns.Types.BASE_INBOX_TYPE or MmsSmsColumns.Types.GROUP_V2_LEAVE_BITS)
|
||||
assertFalse(smsTable.hasMeaningfulMessage(1))
|
||||
assertFalse(messageTable.hasMeaningfulMessage(1))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,39 +76,39 @@ object TestMms {
|
||||
receivedTimestampMillis: Long = System.currentTimeMillis(),
|
||||
): Long {
|
||||
val contentValues = ContentValues().apply {
|
||||
put(MmsTable.DATE_SENT, message.sentTimeMillis)
|
||||
put(MmsTable.MMS_MESSAGE_TYPE, PduHeaders.MESSAGE_TYPE_SEND_REQ)
|
||||
put(MessageTable.DATE_SENT, message.sentTimeMillis)
|
||||
put(MessageTable.MMS_MESSAGE_TYPE, PduHeaders.MESSAGE_TYPE_SEND_REQ)
|
||||
|
||||
put(MmsTable.TYPE, type)
|
||||
put(MessageTable.TYPE, type)
|
||||
put(MmsSmsColumns.THREAD_ID, threadId)
|
||||
put(MmsSmsColumns.READ, if (unread) 0 else 1)
|
||||
put(MmsTable.DATE_RECEIVED, receivedTimestampMillis)
|
||||
put(MessageTable.DATE_RECEIVED, receivedTimestampMillis)
|
||||
put(MmsSmsColumns.SMS_SUBSCRIPTION_ID, message.subscriptionId)
|
||||
put(MmsSmsColumns.EXPIRES_IN, message.expiresIn)
|
||||
put(MmsTable.VIEW_ONCE, message.isViewOnce)
|
||||
put(MessageTable.VIEW_ONCE, message.isViewOnce)
|
||||
put(MmsSmsColumns.RECIPIENT_ID, recipientId.serialize())
|
||||
put(MmsSmsColumns.DELIVERY_RECEIPT_COUNT, 0)
|
||||
put(MmsSmsColumns.RECEIPT_TIMESTAMP, 0)
|
||||
put(MmsSmsColumns.VIEWED_RECEIPT_COUNT, if (viewed) 1 else 0)
|
||||
put(MmsTable.STORY_TYPE, message.storyType.code)
|
||||
put(MessageTable.STORY_TYPE, message.storyType.code)
|
||||
|
||||
put(MmsSmsColumns.BODY, body)
|
||||
put(MmsTable.MENTIONS_SELF, 0)
|
||||
put(MessageTable.MENTIONS_SELF, 0)
|
||||
}
|
||||
|
||||
return db.insert(MmsTable.TABLE_NAME, null, contentValues)
|
||||
return db.insert(MessageTable.TABLE_NAME, null, contentValues)
|
||||
}
|
||||
|
||||
fun markAsRemoteDelete(db: SQLiteDatabase, messageId: Long) {
|
||||
val values = ContentValues()
|
||||
values.put(MmsSmsColumns.REMOTE_DELETED, 1)
|
||||
values.putNull(MmsSmsColumns.BODY)
|
||||
values.putNull(MmsTable.QUOTE_BODY)
|
||||
values.putNull(MmsTable.QUOTE_AUTHOR)
|
||||
values.put(MmsTable.QUOTE_TYPE, -1)
|
||||
values.putNull(MmsTable.QUOTE_ID)
|
||||
values.putNull(MmsTable.LINK_PREVIEWS)
|
||||
values.putNull(MmsTable.SHARED_CONTACTS)
|
||||
db.update(MmsTable.TABLE_NAME, values, DatabaseTable.ID_WHERE, arrayOf(messageId.toString()))
|
||||
values.putNull(MessageTable.QUOTE_BODY)
|
||||
values.putNull(MessageTable.QUOTE_AUTHOR)
|
||||
values.put(MessageTable.QUOTE_TYPE, -1)
|
||||
values.putNull(MessageTable.QUOTE_ID)
|
||||
values.putNull(MessageTable.LINK_PREVIEWS)
|
||||
values.putNull(MessageTable.SHARED_CONTACTS)
|
||||
db.update(MessageTable.TABLE_NAME, values, DatabaseTable.ID_WHERE, arrayOf(messageId.toString()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,19 +61,19 @@ object TestSms {
|
||||
val values = ContentValues().apply {
|
||||
put(MmsSmsColumns.RECIPIENT_ID, message.sender.serialize())
|
||||
put(MmsSmsColumns.RECIPIENT_DEVICE_ID, message.senderDeviceId)
|
||||
put(SmsTable.DATE_RECEIVED, message.receivedTimestampMillis)
|
||||
put(SmsTable.DATE_SENT, message.sentTimestampMillis)
|
||||
put(MmsSmsColumns.DATE_RECEIVED, message.receivedTimestampMillis)
|
||||
put(MmsSmsColumns.DATE_SENT, message.sentTimestampMillis)
|
||||
put(MmsSmsColumns.DATE_SERVER, message.serverTimestampMillis)
|
||||
put(MmsSmsColumns.READ, if (unread) 0 else 1)
|
||||
put(MmsSmsColumns.SMS_SUBSCRIPTION_ID, message.subscriptionId)
|
||||
put(MmsSmsColumns.EXPIRES_IN, message.expiresIn)
|
||||
put(MmsSmsColumns.UNIDENTIFIED, message.isUnidentified)
|
||||
put(MmsSmsColumns.BODY, message.messageBody)
|
||||
put(SmsTable.TYPE, type)
|
||||
put(MmsSmsColumns.TYPE, type)
|
||||
put(MmsSmsColumns.THREAD_ID, threadId)
|
||||
put(MmsSmsColumns.SERVER_GUID, message.serverGuid)
|
||||
}
|
||||
|
||||
return db.insert(SmsTable.TABLE_NAME, null, values)
|
||||
return db.insert(MessageTable.TABLE_NAME, null, values)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user