Skip to content

Commit e60d053

Browse files
authored
Merge pull request #4568 from vector-im/feature/fga/fix_sdk_integration_tests
Feature/fga/fix sdk integration tests
2 parents 9f4f15a + 667bf1a commit e60d053

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+905
-933
lines changed

changelog.d/4546.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix lots of integration tests by introducing TestMatrix class and MatrixWorkerFactory.

matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt

+93-68
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,17 @@ import android.content.Context
2020
import android.net.Uri
2121
import androidx.lifecycle.Observer
2222
import androidx.test.internal.runner.junit4.statement.UiThreadStatement
23-
import androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread
23+
import kotlinx.coroutines.CoroutineDispatcher
24+
import kotlinx.coroutines.CoroutineScope
2425
import kotlinx.coroutines.Dispatchers
25-
import kotlinx.coroutines.GlobalScope
26+
import kotlinx.coroutines.SupervisorJob
2627
import kotlinx.coroutines.delay
2728
import kotlinx.coroutines.launch
2829
import kotlinx.coroutines.runBlocking
2930
import kotlinx.coroutines.withTimeout
3031
import org.junit.Assert.assertEquals
3132
import org.junit.Assert.assertNotNull
3233
import org.junit.Assert.assertTrue
33-
import org.matrix.android.sdk.api.Matrix
3434
import org.matrix.android.sdk.api.MatrixCallback
3535
import org.matrix.android.sdk.api.MatrixConfiguration
3636
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
@@ -45,7 +45,7 @@ import org.matrix.android.sdk.api.session.room.timeline.Timeline
4545
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
4646
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
4747
import org.matrix.android.sdk.api.session.sync.SyncState
48-
import java.util.ArrayList
48+
import timber.log.Timber
4949
import java.util.UUID
5050
import java.util.concurrent.CountDownLatch
5151
import java.util.concurrent.TimeUnit
@@ -56,21 +56,22 @@ import java.util.concurrent.TimeUnit
5656
*/
5757
class CommonTestHelper(context: Context) {
5858

59-
val matrix: Matrix
59+
internal val matrix: TestMatrix
60+
val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
6061

61-
fun getTestInterceptor(session: Session): MockOkHttpInterceptor? = TestNetworkModule.interceptorForSession(session.sessionId) as? MockOkHttpInterceptor
62+
fun getTestInterceptor(session: Session): MockOkHttpInterceptor? = TestModule.interceptorForSession(session.sessionId) as? MockOkHttpInterceptor
6263

6364
init {
6465
UiThreadStatement.runOnUiThread {
65-
Matrix.initialize(
66+
TestMatrix.initialize(
6667
context,
6768
MatrixConfiguration(
6869
applicationFlavor = "TestFlavor",
6970
roomDisplayNameFallbackProvider = TestRoomDisplayNameFallbackProvider()
7071
)
7172
)
7273
}
73-
matrix = Matrix.getInstance(context)
74+
matrix = TestMatrix.getInstance(context)
7475
}
7576

7677
fun createAccount(userNamePrefix: String, testParams: SessionTestParams): Session {
@@ -95,31 +96,45 @@ class CommonTestHelper(context: Context) {
9596
*
9697
* @param session the session to sync
9798
*/
98-
@Suppress("EXPERIMENTAL_API_USAGE")
99-
fun syncSession(session: Session, timeout: Long = TestConstants.timeOutMillis) {
99+
fun syncSession(session: Session, timeout: Long = TestConstants.timeOutMillis * 10) {
100100
val lock = CountDownLatch(1)
101-
102-
val job = GlobalScope.launch(Dispatchers.Main) {
103-
session.open()
101+
coroutineScope.launch {
102+
session.startSync(true)
103+
val syncLiveData = session.getSyncStateLive()
104+
val syncObserver = object : Observer<SyncState> {
105+
override fun onChanged(t: SyncState?) {
106+
if (session.hasAlreadySynced()) {
107+
lock.countDown()
108+
syncLiveData.removeObserver(this)
109+
}
110+
}
111+
}
112+
syncLiveData.observeForever(syncObserver)
104113
}
105-
runBlocking { job.join() }
106-
107-
session.startSync(true)
114+
await(lock, timeout)
115+
}
108116

109-
val syncLiveData = runBlocking(Dispatchers.Main) {
110-
session.getSyncStateLive()
111-
}
112-
val syncObserver = object : Observer<SyncState> {
113-
override fun onChanged(t: SyncState?) {
114-
if (session.hasAlreadySynced()) {
115-
lock.countDown()
116-
syncLiveData.removeObserver(this)
117+
/**
118+
* This methods clear the cache and waits for initialSync
119+
*
120+
* @param session the session to sync
121+
*/
122+
fun clearCacheAndSync(session: Session, timeout: Long = TestConstants.timeOutMillis) {
123+
waitWithLatch(timeout) { latch ->
124+
session.clearCache()
125+
val syncLiveData = session.getSyncStateLive()
126+
val syncObserver = object : Observer<SyncState> {
127+
override fun onChanged(t: SyncState?) {
128+
if (session.hasAlreadySynced()) {
129+
Timber.v("Clear cache and synced")
130+
syncLiveData.removeObserver(this)
131+
latch.countDown()
132+
}
117133
}
118134
}
135+
syncLiveData.observeForever(syncObserver)
136+
session.startSync(true)
119137
}
120-
GlobalScope.launch(Dispatchers.Main) { syncLiveData.observeForever(syncObserver) }
121-
122-
await(lock, timeout)
123138
}
124139

125140
/**
@@ -130,46 +145,57 @@ class CommonTestHelper(context: Context) {
130145
* @param nbOfMessages the number of time the message will be sent
131146
*/
132147
fun sendTextMessage(room: Room, message: String, nbOfMessages: Int, timeout: Long = TestConstants.timeOutMillis): List<TimelineEvent> {
133-
val timeline = room.createTimeline(null, TimelineSettings(10))
134148
val sentEvents = ArrayList<TimelineEvent>(nbOfMessages)
135-
val latch = CountDownLatch(1)
136-
val timelineListener = object : Timeline.Listener {
137-
override fun onTimelineFailure(throwable: Throwable) {
138-
}
149+
val timeline = room.createTimeline(null, TimelineSettings(10))
150+
timeline.start()
151+
waitWithLatch(timeout + 1_000L * nbOfMessages) { latch ->
152+
val timelineListener = object : Timeline.Listener {
153+
override fun onTimelineFailure(throwable: Throwable) {
154+
}
139155

140-
override fun onNewTimelineEvents(eventIds: List<String>) {
141-
// noop
142-
}
156+
override fun onNewTimelineEvents(eventIds: List<String>) {
157+
// noop
158+
}
143159

144-
override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
145-
val newMessages = snapshot
146-
.filter { it.root.sendState == SendState.SYNCED }
147-
.filter { it.root.getClearType() == EventType.MESSAGE }
148-
.filter { it.root.getClearContent().toModel<MessageContent>()?.body?.startsWith(message) == true }
149-
150-
if (newMessages.size == nbOfMessages) {
151-
sentEvents.addAll(newMessages)
152-
// Remove listener now, if not at the next update sendEvents could change
153-
timeline.removeListener(this)
154-
latch.countDown()
160+
override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
161+
val newMessages = snapshot
162+
.filter { it.root.sendState == SendState.SYNCED }
163+
.filter { it.root.getClearType() == EventType.MESSAGE }
164+
.filter { it.root.getClearContent().toModel<MessageContent>()?.body?.startsWith(message) == true }
165+
166+
Timber.v("New synced message size: ${newMessages.size}")
167+
if (newMessages.size == nbOfMessages) {
168+
sentEvents.addAll(newMessages)
169+
// Remove listener now, if not at the next update sendEvents could change
170+
timeline.removeListener(this)
171+
latch.countDown()
172+
}
155173
}
156174
}
175+
timeline.addListener(timelineListener)
176+
sendTextMessagesBatched(room, message, nbOfMessages)
157177
}
158-
timeline.start()
159-
timeline.addListener(timelineListener)
160-
for (i in 0 until nbOfMessages) {
161-
room.sendTextMessage(message + " #" + (i + 1))
162-
}
163-
// Wait 3 second more per message
164-
await(latch, timeout = timeout + 3_000L * nbOfMessages)
165178
timeline.dispose()
166-
167179
// Check that all events has been created
168180
assertEquals("Message number do not match $sentEvents", nbOfMessages.toLong(), sentEvents.size.toLong())
169-
170181
return sentEvents
171182
}
172183

184+
/**
185+
* Will send nb of messages provided by count parameter but waits a bit every 10 messages to avoid gap in sync
186+
*/
187+
private fun sendTextMessagesBatched(room: Room, message: String, count: Int) {
188+
(1 until count + 1)
189+
.map { "$message #$it" }
190+
.chunked(10)
191+
.forEach { batchedMessages ->
192+
batchedMessages.forEach { formattedMessage ->
193+
room.sendTextMessage(formattedMessage)
194+
}
195+
Thread.sleep(1_000L)
196+
}
197+
}
198+
173199
// PRIVATE METHODS *****************************************************************************
174200

175201
/**
@@ -239,10 +265,10 @@ class CommonTestHelper(context: Context) {
239265

240266
assertTrue(registrationResult is RegistrationResult.Success)
241267
val session = (registrationResult as RegistrationResult.Success).session
268+
session.open()
242269
if (sessionTestParams.withInitialSync) {
243270
syncSession(session, 60_000)
244271
}
245-
246272
return session
247273
}
248274

@@ -267,7 +293,7 @@ class CommonTestHelper(context: Context) {
267293
.getLoginWizard()
268294
.login(userName, password, "myDevice")
269295
}
270-
296+
session.open()
271297
if (sessionTestParams.withInitialSync) {
272298
syncSession(session)
273299
}
@@ -332,22 +358,21 @@ class CommonTestHelper(context: Context) {
332358
assertTrue(latch.await(timeout ?: TestConstants.timeOutMillis, TimeUnit.MILLISECONDS))
333359
}
334360

335-
@Suppress("EXPERIMENTAL_API_USAGE")
336-
fun retryPeriodicallyWithLatch(latch: CountDownLatch, condition: (() -> Boolean)) {
337-
GlobalScope.launch {
338-
while (true) {
339-
delay(1000)
340-
if (condition()) {
341-
latch.countDown()
342-
return@launch
343-
}
361+
suspend fun retryPeriodicallyWithLatch(latch: CountDownLatch, condition: (() -> Boolean)) {
362+
while (true) {
363+
delay(1000)
364+
if (condition()) {
365+
latch.countDown()
366+
return
344367
}
345368
}
346369
}
347370

348-
fun waitWithLatch(timeout: Long? = TestConstants.timeOutMillis, block: (CountDownLatch) -> Unit) {
371+
fun waitWithLatch(timeout: Long? = TestConstants.timeOutMillis, dispatcher: CoroutineDispatcher = Dispatchers.Main, block: suspend (CountDownLatch) -> Unit) {
349372
val latch = CountDownLatch(1)
350-
block(latch)
373+
coroutineScope.launch(dispatcher) {
374+
block(latch)
375+
}
351376
await(latch, timeout)
352377
}
353378

0 commit comments

Comments
 (0)