Add unit testing to story download enqueuer.
This commit is contained in:
parent
d2f639c57f
commit
13eb89746b
3 changed files with 300 additions and 0 deletions
|
@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.database
|
|||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import net.zetetic.database.sqlcipher.SQLiteOpenHelper
|
||||
import org.signal.core.util.SqlUtil
|
||||
import org.signal.core.util.logging.Log
|
||||
|
@ -221,6 +222,12 @@ open class SignalDatabase(private val context: Application, databaseSecret: Data
|
|||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@VisibleForTesting
|
||||
fun setSignalDatabaseInstanceForTesting(signalDatabase: SignalDatabase) {
|
||||
this.instance = signalDatabase
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val rawDatabase: net.zetetic.database.sqlcipher.SQLiteDatabase
|
||||
get() = instance!!.rawWritableDatabase
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
package org.thoughtcrime.securesms.database
|
||||
|
||||
import org.thoughtcrime.securesms.attachments.AttachmentId
|
||||
import org.thoughtcrime.securesms.attachments.DatabaseAttachment
|
||||
import org.thoughtcrime.securesms.audio.AudioHash
|
||||
import org.thoughtcrime.securesms.blurhash.BlurHash
|
||||
import org.thoughtcrime.securesms.contactshare.Contact
|
||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch
|
||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure
|
||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.ParentStoryId
|
||||
import org.thoughtcrime.securesms.database.model.Quote
|
||||
import org.thoughtcrime.securesms.database.model.ReactionRecord
|
||||
import org.thoughtcrime.securesms.database.model.StoryType
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.stickers.StickerLocator
|
||||
import org.thoughtcrime.securesms.util.MediaUtil
|
||||
|
||||
/**
|
||||
* Builds MessageRecords and related components for direct usage in unit testing. Does not modify the database.
|
||||
*/
|
||||
object FakeMessageRecords {
|
||||
|
||||
fun buildDatabaseAttachment(
|
||||
attachmentId: AttachmentId = AttachmentId(1, 1),
|
||||
mmsId: Long = 1,
|
||||
hasData: Boolean = true,
|
||||
hasThumbnail: Boolean = true,
|
||||
contentType: String = MediaUtil.IMAGE_JPEG,
|
||||
transferProgress: Int = AttachmentDatabase.TRANSFER_PROGRESS_DONE,
|
||||
size: Long = 0L,
|
||||
fileName: String = "",
|
||||
cdnNumber: Int = 1,
|
||||
location: String = "",
|
||||
key: String = "",
|
||||
relay: String = "",
|
||||
digest: ByteArray = byteArrayOf(),
|
||||
fastPreflightId: String = "",
|
||||
voiceNote: Boolean = false,
|
||||
borderless: Boolean = false,
|
||||
videoGif: Boolean = false,
|
||||
width: Int = 0,
|
||||
height: Int = 0,
|
||||
quote: Boolean = false,
|
||||
caption: String? = null,
|
||||
stickerLocator: StickerLocator? = null,
|
||||
blurHash: BlurHash? = null,
|
||||
audioHash: AudioHash? = null,
|
||||
transformProperties: AttachmentDatabase.TransformProperties? = null,
|
||||
displayOrder: Int = 0,
|
||||
uploadTimestamp: Long = 200
|
||||
): DatabaseAttachment {
|
||||
return DatabaseAttachment(
|
||||
attachmentId,
|
||||
mmsId,
|
||||
hasData,
|
||||
hasThumbnail,
|
||||
contentType,
|
||||
transferProgress,
|
||||
size,
|
||||
fileName,
|
||||
cdnNumber,
|
||||
location,
|
||||
key,
|
||||
relay,
|
||||
digest,
|
||||
fastPreflightId,
|
||||
voiceNote,
|
||||
borderless,
|
||||
videoGif,
|
||||
width,
|
||||
height,
|
||||
quote,
|
||||
caption,
|
||||
stickerLocator,
|
||||
blurHash,
|
||||
audioHash,
|
||||
transformProperties,
|
||||
displayOrder,
|
||||
uploadTimestamp
|
||||
)
|
||||
}
|
||||
|
||||
fun buildLinkPreview(
|
||||
url: String = "",
|
||||
title: String = "",
|
||||
description: String = "",
|
||||
date: Long = 200,
|
||||
attachmentId: AttachmentId? = null
|
||||
): LinkPreview {
|
||||
return LinkPreview(
|
||||
url,
|
||||
title,
|
||||
description,
|
||||
date,
|
||||
attachmentId
|
||||
)
|
||||
}
|
||||
|
||||
fun buildMediaMmsMessageRecord(
|
||||
id: Long = 1,
|
||||
conversationRecipient: Recipient = Recipient.UNKNOWN,
|
||||
individualRecipient: Recipient = conversationRecipient,
|
||||
recipientDeviceId: Int = 1,
|
||||
dateSent: Long = 200,
|
||||
dateReceived: Long = 400,
|
||||
dateServer: Long = 300,
|
||||
deliveryReceiptCount: Int = 0,
|
||||
threadId: Long = 1,
|
||||
body: String = "body",
|
||||
slideDeck: SlideDeck = SlideDeck(),
|
||||
partCount: Int = slideDeck.slides.count(),
|
||||
mailbox: Long = MmsSmsColumns.Types.BASE_INBOX_TYPE,
|
||||
mismatches: Set<IdentityKeyMismatch> = emptySet(),
|
||||
failures: Set<NetworkFailure> = emptySet(),
|
||||
subscriptionId: Int = -1,
|
||||
expiresIn: Long = -1,
|
||||
expireStarted: Long = -1,
|
||||
viewOnce: Boolean = false,
|
||||
readReceiptCount: Int = 0,
|
||||
quote: Quote? = null,
|
||||
contacts: List<Contact> = emptyList(),
|
||||
linkPreviews: List<LinkPreview> = emptyList(),
|
||||
unidentified: Boolean = false,
|
||||
reactions: List<ReactionRecord> = emptyList(),
|
||||
remoteDelete: Boolean = false,
|
||||
mentionsSelf: Boolean = false,
|
||||
notifiedTimestamp: Long = 350,
|
||||
viewedReceiptCount: Int = 0,
|
||||
receiptTimestamp: Long = 0,
|
||||
messageRanges: BodyRangeList? = null,
|
||||
storyType: StoryType = StoryType.NONE,
|
||||
parentStoryId: ParentStoryId? = null,
|
||||
giftBadge: GiftBadge? = null
|
||||
): MediaMmsMessageRecord {
|
||||
return MediaMmsMessageRecord(
|
||||
id,
|
||||
conversationRecipient,
|
||||
individualRecipient,
|
||||
recipientDeviceId,
|
||||
dateSent,
|
||||
dateReceived,
|
||||
dateServer,
|
||||
deliveryReceiptCount,
|
||||
threadId,
|
||||
body,
|
||||
slideDeck,
|
||||
partCount,
|
||||
mailbox,
|
||||
mismatches,
|
||||
failures,
|
||||
subscriptionId,
|
||||
expiresIn,
|
||||
expireStarted,
|
||||
viewOnce,
|
||||
readReceiptCount,
|
||||
quote,
|
||||
contacts,
|
||||
linkPreviews,
|
||||
unidentified,
|
||||
reactions,
|
||||
remoteDelete,
|
||||
mentionsSelf,
|
||||
notifiedTimestamp,
|
||||
viewedReceiptCount,
|
||||
receiptTimestamp,
|
||||
messageRanges,
|
||||
storyType,
|
||||
parentStoryId,
|
||||
giftBadge
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
package org.thoughtcrime.securesms.stories
|
||||
|
||||
import io.reactivex.rxjava3.plugins.RxJavaPlugins
|
||||
import io.reactivex.rxjava3.schedulers.TestScheduler
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mockito.Mock
|
||||
import org.mockito.MockedStatic
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
import org.mockito.junit.MockitoRule
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.isA
|
||||
import org.mockito.kotlin.never
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.whenever
|
||||
import org.thoughtcrime.securesms.attachments.AttachmentId
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase
|
||||
import org.thoughtcrime.securesms.database.FakeMessageRecords
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager
|
||||
import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob
|
||||
|
||||
class StoriesTest {
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
val mockitoRule: MockitoRule = MockitoJUnit.rule()
|
||||
|
||||
@Mock
|
||||
private lateinit var mockAttachmentDatabase: AttachmentDatabase
|
||||
|
||||
@Mock
|
||||
private lateinit var mockJobManager: JobManager
|
||||
|
||||
@Mock
|
||||
private lateinit var mockApplicationDependenciesStatic: MockedStatic<ApplicationDependencies>
|
||||
|
||||
@Mock
|
||||
private lateinit var mockSignalDatabaseStatic: MockedStatic<SignalDatabase>
|
||||
|
||||
@Mock
|
||||
private lateinit var mockSignalDatabase: SignalDatabase
|
||||
|
||||
private val testScheduler = TestScheduler()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
RxJavaPlugins.setInitIoSchedulerHandler { testScheduler }
|
||||
RxJavaPlugins.setIoSchedulerHandler { testScheduler }
|
||||
|
||||
SignalDatabase.setSignalDatabaseInstanceForTesting(mockSignalDatabase)
|
||||
whenever(SignalDatabase.attachments).thenReturn(mockAttachmentDatabase)
|
||||
whenever(ApplicationDependencies.getJobManager()).thenReturn(mockJobManager)
|
||||
whenever(mockAttachmentDatabase.getAttachmentsForMessage(any())).thenReturn(emptyList())
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
RxJavaPlugins.reset()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Given a MessageRecord with no attachments and a LinkPreview without a thumbnail, when I enqueueAttachmentsFromStoryForDownload, then I enqueue nothing`() {
|
||||
// GIVEN
|
||||
val messageRecord = FakeMessageRecords.buildMediaMmsMessageRecord(
|
||||
linkPreviews = listOf(FakeMessageRecords.buildLinkPreview())
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val testObserver = Stories.enqueueAttachmentsFromStoryForDownload(messageRecord, true).test()
|
||||
testScheduler.triggerActions()
|
||||
|
||||
// THEN
|
||||
testObserver.assertComplete()
|
||||
verify(mockJobManager, never()).add(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Given a MessageRecord with no attachments and a LinkPreview with a thumbnail, when I enqueueAttachmentsFromStoryForDownload, then I enqueue once`() {
|
||||
// GIVEN
|
||||
val messageRecord = FakeMessageRecords.buildMediaMmsMessageRecord(
|
||||
linkPreviews = listOf(
|
||||
FakeMessageRecords.buildLinkPreview(
|
||||
attachmentId = AttachmentId(1, 2)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val testObserver = Stories.enqueueAttachmentsFromStoryForDownload(messageRecord, true).test()
|
||||
testScheduler.triggerActions()
|
||||
|
||||
// THEN
|
||||
testObserver.assertComplete()
|
||||
verify(mockJobManager).add(isA<AttachmentDownloadJob>())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Given a MessageRecord with an attachment, when I enqueueAttachmentsFromStoryForDownload, then I enqueue once`() {
|
||||
// GIVEN
|
||||
val attachment = FakeMessageRecords.buildDatabaseAttachment()
|
||||
val messageRecord = FakeMessageRecords.buildMediaMmsMessageRecord()
|
||||
whenever(mockAttachmentDatabase.getAttachmentsForMessage(any())).thenReturn(listOf(attachment))
|
||||
|
||||
// WHEN
|
||||
val testObserver = Stories.enqueueAttachmentsFromStoryForDownload(messageRecord, true).test()
|
||||
testScheduler.triggerActions()
|
||||
|
||||
// THEN
|
||||
testObserver.assertComplete()
|
||||
verify(mockJobManager).add(isA<AttachmentDownloadJob>())
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue