Tests: fix timeline tests + some small others

This commit is contained in:
ganfra 2021-11-26 18:16:27 +01:00
parent 1d9da6c7d3
commit ccdeeeab4c
6 changed files with 59 additions and 47 deletions

View File

@ -20,6 +20,7 @@ import android.content.Context
import android.net.Uri
import androidx.lifecycle.Observer
import androidx.test.internal.runner.junit4.statement.UiThreadStatement
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
@ -45,6 +46,7 @@ import org.matrix.android.sdk.api.session.room.timeline.Timeline
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
import org.matrix.android.sdk.api.session.sync.SyncState
import timber.log.Timber
import java.util.UUID
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
@ -119,22 +121,21 @@ class CommonTestHelper(context: Context) {
* @param session the session to sync
*/
fun clearCacheAndSync(session: Session, timeout: Long = TestConstants.timeOutMillis) {
val lock = CountDownLatch(1)
coroutineScope.launch {
waitWithLatch(timeout) { latch ->
session.clearCache()
val syncLiveData = session.getSyncStateLive()
val syncObserver = object : Observer<SyncState> {
override fun onChanged(t: SyncState?) {
if (session.hasAlreadySynced()) {
lock.countDown()
Timber.v("Clear cache and synced")
syncLiveData.removeObserver(this)
latch.countDown()
}
}
}
syncLiveData.observeForever(syncObserver)
session.startSync(true)
}
await(lock, timeout)
}
/**
@ -145,9 +146,10 @@ class CommonTestHelper(context: Context) {
* @param nbOfMessages the number of time the message will be sent
*/
fun sendTextMessage(room: Room, message: String, nbOfMessages: Int, timeout: Long = TestConstants.timeOutMillis): List<TimelineEvent> {
val timeline = room.createTimeline(null, TimelineSettings(10))
val sentEvents = ArrayList<TimelineEvent>(nbOfMessages)
waitWithLatch(timeout ) { latch ->
val timeline = room.createTimeline(null, TimelineSettings(10))
timeline.start()
waitWithLatch(timeout + 1_000L * nbOfMessages) { latch ->
val timelineListener = object : Timeline.Listener {
override fun onTimelineFailure(throwable: Throwable) {
}
@ -162,6 +164,7 @@ class CommonTestHelper(context: Context) {
.filter { it.root.getClearType() == EventType.MESSAGE }
.filter { it.root.getClearContent().toModel<MessageContent>()?.body?.startsWith(message) == true }
Timber.v("New synced message size: ${newMessages.size}")
if (newMessages.size == nbOfMessages) {
sentEvents.addAll(newMessages)
// Remove listener now, if not at the next update sendEvents could change
@ -170,13 +173,8 @@ class CommonTestHelper(context: Context) {
}
}
}
timeline.start()
timeline.addListener(timelineListener)
for (i in 0 until nbOfMessages) {
room.sendTextMessage(message + " #" + (i + 1))
// Sleep a bit otherwise database will be flowed and sync won't be live (we might end up with gap then...)
delay(50)
}
sendTextMessagesBatched(room, message, nbOfMessages)
}
timeline.dispose()
// Check that all events has been created
@ -184,6 +182,21 @@ class CommonTestHelper(context: Context) {
return sentEvents
}
/**
* Will send nb of messages provided by count parameter but waits a bit every 10 messages to avoid gap in sync
*/
private fun sendTextMessagesBatched(room: Room, message: String, count: Int) {
(1 until count + 1)
.map { "$message #$it" }
.chunked(10)
.forEach { batchedMessages ->
batchedMessages.forEach { formattedMessage ->
room.sendTextMessage(formattedMessage)
}
Thread.sleep(1_000L)
}
}
// PRIVATE METHODS *****************************************************************************
/**
@ -357,9 +370,9 @@ class CommonTestHelper(context: Context) {
}
}
fun waitWithLatch(timeout: Long? = TestConstants.timeOutMillis, block: suspend (CountDownLatch) -> Unit) {
fun waitWithLatch(timeout: Long? = TestConstants.timeOutMillis, dispatcher: CoroutineDispatcher = Dispatchers.Main, block: suspend (CountDownLatch) -> Unit) {
val latch = CountDownLatch(1)
coroutineScope.launch {
coroutineScope.launch(dispatcher) {
block(latch)
}
await(latch, timeout)

View File

@ -32,6 +32,7 @@ import org.matrix.android.sdk.api.session.securestorage.EncryptedSecretContent
import org.matrix.android.sdk.api.session.securestorage.KeySigner
import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec
import org.matrix.android.sdk.api.session.securestorage.SecretStorageKeyContent
import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageError
import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService
import org.matrix.android.sdk.api.session.securestorage.SsssKeyCreationInfo
import org.matrix.android.sdk.api.util.Optional
@ -90,7 +91,7 @@ class QuadSTests : InstrumentedTest {
testHelper.waitWithLatch { latch ->
quadS.setDefaultKey(TEST_KEY_ID)
val liveDefAccountData =
aliceSession.accountDataService().getLiveUserAccountDataEvent(DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
aliceSession.accountDataService().getLiveUserAccountDataEvent(DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
val accountDefDataObserver = Observer<Optional<UserAccountDataEvent>?> { t ->
if (t?.getOrNull()?.type == DefaultSharedSecretStorageService.DEFAULT_KEY_ID) {
defaultKeyAccountData = t.getOrNull()!!
@ -233,14 +234,18 @@ class QuadSTests : InstrumentedTest {
}
testHelper.runBlockingTest {
aliceSession.sharedSecretStorageService.getSecret("my.secret",
keyId1,
RawBytesKeySpec.fromPassphrase(
"A bad passphrase",
key1Info.content?.passphrase?.salt ?: "",
key1Info.content?.passphrase?.iterations ?: 0,
null)
)
try {
aliceSession.sharedSecretStorageService.getSecret("my.secret",
keyId1,
RawBytesKeySpec.fromPassphrase(
"A bad passphrase",
key1Info.content?.passphrase?.salt ?: "",
key1Info.content?.passphrase?.iterations ?: 0,
null)
)
} catch (throwable: Throwable) {
assert(throwable is SharedSecretStorageError.BadMac)
}
}
// Now try with correct key

View File

@ -84,24 +84,12 @@ class SearchMessagesTest : InstrumentedTest {
val aliceSession = cryptoTestData.firstSession
val aliceRoomId = cryptoTestData.roomId
val roomFromAlicePOV = aliceSession.getRoom(aliceRoomId)!!
val aliceTimeline = roomFromAlicePOV.createTimeline(null, TimelineSettings(10))
aliceTimeline.start()
val lock = CountDownLatch(1)
val eventListener = commonTestHelper.createEventListener(lock) { snapshot ->
snapshot.count { it.root.content.toModel<MessageContent>()?.body?.startsWith(MESSAGE).orFalse() } == 2
}
aliceTimeline.addListener(eventListener)
commonTestHelper.sendTextMessage(
roomFromAlicePOV,
MESSAGE,
2)
commonTestHelper.await(lock)
val data = commonTestHelper.runBlockingTest {
block.invoke(cryptoTestData)
}
@ -114,7 +102,6 @@ class SearchMessagesTest : InstrumentedTest {
}.orFalse()
)
aliceTimeline.removeAllListeners()
cryptoTestData.cleanUp(commonTestHelper)
}
}

View File

@ -59,7 +59,7 @@ class SpaceHierarchyTest : InstrumentedTest {
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
val spaceName = "My Space"
val topic = "A public space for test"
var spaceId: String = ""
var spaceId = ""
commonTestHelper.waitWithLatch {
spaceId = session.spaceService().createSpace(spaceName, topic, null, true)
it.countDown()
@ -67,7 +67,7 @@ class SpaceHierarchyTest : InstrumentedTest {
val syncedSpace = session.spaceService().getSpace(spaceId)
var roomId: String = ""
var roomId = ""
commonTestHelper.waitWithLatch {
roomId = session.createRoom(CreateRoomParams().apply { name = "General" })
it.countDown()
@ -314,6 +314,11 @@ class SpaceHierarchyTest : InstrumentedTest {
session.spaceService().setSpaceParent(spaceBInfo.spaceId, spaceAInfo.spaceId, true, viaServers)
}
val spaceCInfo = createPublicSpace(session, "SpaceC", listOf(
Triple("C1", true /*auto-join*/, true/*canonical*/),
Triple("C2", true, true)
))
commonTestHelper.waitWithLatch { latch ->
val flatAChildren = session.getFlattenRoomSummaryChildrenOfLive(spaceAInfo.spaceId)
@ -329,11 +334,6 @@ class SpaceHierarchyTest : InstrumentedTest {
}
}
val spaceCInfo = createPublicSpace(session, "SpaceC", listOf(
Triple("C1", true /*auto-join*/, true/*canonical*/),
Triple("C2", true, true)
))
// add C as subspace of B
val spaceB = session.spaceService().getSpace(spaceBInfo.spaceId)
spaceB!!.addChildren(spaceCInfo.spaceId, viaServers, null, true)
@ -408,7 +408,7 @@ class SpaceHierarchyTest : InstrumentedTest {
): TestSpaceCreationResult {
var spaceId = ""
var roomIds: List<String> = emptyList()
commonTestHelper.waitWithLatch {
commonTestHelper.waitWithLatch { latch ->
spaceId = session.spaceService().createSpace(spaceName, "My Private Space", null, false)
val syncedSpace = session.spaceService().getSpace(spaceId)
val viaServers = listOf(session.sessionParams.homeServerHost ?: "")
@ -433,6 +433,7 @@ class SpaceHierarchyTest : InstrumentedTest {
session.spaceService().setSpaceParent(roomId, spaceId, canonical, viaServers)
}
}
latch.countDown()
}
return TestSpaceCreationResult(spaceId, roomIds)
}

View File

@ -25,13 +25,18 @@ import javax.inject.Inject
internal class SyncTokenStore @Inject constructor(@SessionDatabase private val monarchy: Monarchy) {
fun getLastToken(): String? {
return Realm.getInstance(monarchy.realmConfiguration).use {
val token = Realm.getInstance(monarchy.realmConfiguration).use {
// Makes sure realm is up-to-date as it's used for querying internally on non looper thread.
it.refresh()
it.where(SyncEntity::class.java).findFirst()?.nextBatch
}
return token
}
fun saveToken(realm: Realm, token: String?) {
val sync = SyncEntity(token)
realm.insertOrUpdate(sync)
if(realm.isInTransaction) {
val sync = SyncEntity(token)
realm.insertOrUpdate(sync)
}
}
}

View File

@ -193,6 +193,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
aggregator: SyncResponsePostTreatmentAggregator): RoomEntity {
Timber.v("Handle join sync for room $roomId")
val ephemeralResult = (roomSync.ephemeral as? LazyRoomSyncEphemeral.Parsed)
?._roomSyncEphemeral
?.events