Improve test stability

This commit is contained in:
Valere 2022-05-13 16:12:06 +02:00
parent 0675b7c16c
commit e18402f834
6 changed files with 67 additions and 57 deletions

View File

@ -50,6 +50,16 @@ import java.util.UUID
import java.util.concurrent.CountDownLatch import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
internal fun withTestHelpers(context: Context, block: (CryptoTestHelper) -> Unit) {
val testHelper = CommonTestHelper(context)
val cryptoTestHelper = CryptoTestHelper(testHelper)
return try {
block(cryptoTestHelper)
} finally {
testHelper.cleanUpOpenedSessions()
}
}
/** /**
* This class exposes methods to be used in common cases * This class exposes methods to be used in common cases
* Registration, login, Sync, Sending messages... * Registration, login, Sync, Sending messages...
@ -60,6 +70,8 @@ class CommonTestHelper(context: Context) {
private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main) private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
private var accountNumber = 0 private var accountNumber = 0
private val trackedSessions = mutableListOf<Session>()
fun getTestInterceptor(session: Session): MockOkHttpInterceptor? = TestModule.interceptorForSession(session.sessionId) as? MockOkHttpInterceptor fun getTestInterceptor(session: Session): MockOkHttpInterceptor? = TestModule.interceptorForSession(session.sessionId) as? MockOkHttpInterceptor
init { init {
@ -84,6 +96,15 @@ class CommonTestHelper(context: Context) {
return logIntoAccount(userId, TestConstants.PASSWORD, testParams) return logIntoAccount(userId, TestConstants.PASSWORD, testParams)
} }
fun cleanUpOpenedSessions() {
trackedSessions.forEach {
runBlockingTest {
it.signOutService().signOut(true)
}
}
trackedSessions.clear()
}
/** /**
* Create a homeserver configuration, with Http connection allowed for test * Create a homeserver configuration, with Http connection allowed for test
*/ */
@ -245,7 +266,9 @@ class CommonTestHelper(context: Context) {
testParams testParams
) )
assertNotNull(session) assertNotNull(session)
return session return session.also {
trackedSessions.add(session)
}
} }
/** /**
@ -261,7 +284,9 @@ class CommonTestHelper(context: Context) {
testParams: SessionTestParams): Session { testParams: SessionTestParams): Session {
val session = logAccountAndSync(userId, password, testParams) val session = logAccountAndSync(userId, password, testParams)
assertNotNull(session) assertNotNull(session)
return session return session.also {
trackedSessions.add(session)
}
} }
/** /**
@ -436,6 +461,7 @@ class CommonTestHelper(context: Context) {
fun Iterable<Session>.signOutAndClose() = forEach { signOutAndClose(it) } fun Iterable<Session>.signOutAndClose() = forEach { signOutAndClose(it) }
fun signOutAndClose(session: Session) { fun signOutAndClose(session: Session) {
trackedSessions.remove(session)
runBlockingTest(timeout = 60_000) { runBlockingTest(timeout = 60_000) {
session.signOutService().signOut(true) session.signOutService().signOut(true)
} }

View File

@ -66,7 +66,7 @@ import java.util.UUID
import kotlin.coroutines.Continuation import kotlin.coroutines.Continuation
import kotlin.coroutines.resume import kotlin.coroutines.resume
class CryptoTestHelper(private val testHelper: CommonTestHelper) { class CryptoTestHelper(val testHelper: CommonTestHelper) {
private val messagesFromAlice: List<String> = listOf("0 - Hello I'm Alice!", "4 - Go!") private val messagesFromAlice: List<String> = listOf("0 - Hello I'm Alice!", "4 - Go!")
private val messagesFromBob: List<String> = listOf("1 - Hello I'm Bob!", "2 - Isn't life grand?", "3 - Let's go to the opera.") private val messagesFromBob: List<String> = listOf("1 - Hello I'm Bob!", "2 - Isn't life grand?", "3 - Let's go to the opera.")

View File

@ -30,18 +30,15 @@ import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventCon
import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.getTimelineEvent import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.withTestHelpers
import org.matrix.android.sdk.common.CryptoTestHelper
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM) @FixMethodOrder(MethodSorters.JVM)
class PreShareKeysTest : InstrumentedTest { class PreShareKeysTest : InstrumentedTest {
private val testHelper = CommonTestHelper(context())
private val cryptoTestHelper = CryptoTestHelper(testHelper)
@Test @Test
fun ensure_outbound_session_happy_path() { fun ensure_outbound_session_happy_path() = withTestHelpers(context()) { cryptoTestHelper ->
val testHelper = cryptoTestHelper.testHelper
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true) val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
val e2eRoomID = testData.roomId val e2eRoomID = testData.roomId
val aliceSession = testData.firstSession val aliceSession = testData.firstSession
@ -94,7 +91,5 @@ class PreShareKeysTest : InstrumentedTest {
bobSession.getRoom(e2eRoomID)?.getTimelineEvent(sentEvent.eventId)?.root?.getClearType() == EventType.MESSAGE bobSession.getRoom(e2eRoomID)?.getTimelineEvent(sentEvent.eventId)?.root?.getClearType() == EventType.MESSAGE
} }
} }
testData.cleanUp(testHelper)
} }
} }

View File

@ -38,9 +38,8 @@ import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.timeline.Timeline 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.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.CryptoTestHelper
import org.matrix.android.sdk.common.TestConstants import org.matrix.android.sdk.common.TestConstants
import org.matrix.android.sdk.common.withTestHelpers
import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper
import org.matrix.android.sdk.internal.crypto.store.db.deserializeFromRealm import org.matrix.android.sdk.internal.crypto.store.db.deserializeFromRealm
import org.matrix.android.sdk.internal.crypto.store.db.serializeForRealm import org.matrix.android.sdk.internal.crypto.store.db.serializeForRealm
@ -63,8 +62,6 @@ import kotlin.coroutines.resume
class UnwedgingTest : InstrumentedTest { class UnwedgingTest : InstrumentedTest {
private lateinit var messagesReceivedByBob: List<TimelineEvent> private lateinit var messagesReceivedByBob: List<TimelineEvent>
private val testHelper = CommonTestHelper(context())
private val cryptoTestHelper = CryptoTestHelper(testHelper)
@Before @Before
fun init() { fun init() {
@ -85,7 +82,8 @@ class UnwedgingTest : InstrumentedTest {
* -> This is automatically fixed after SDKs restarted the olm session * -> This is automatically fixed after SDKs restarted the olm session
*/ */
@Test @Test
fun testUnwedging() { fun testUnwedging() = withTestHelpers(context()) { cryptoTestHelper ->
val testHelper = cryptoTestHelper.testHelper
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession val aliceSession = cryptoTestData.firstSession
@ -240,8 +238,6 @@ class UnwedgingTest : InstrumentedTest {
} }
bobTimeline.dispose() bobTimeline.dispose()
cryptoTestData.cleanUp(testHelper)
} }
private fun createEventListener(latch: CountDownLatch, expectedNumberOfMessages: Int): Timeline.Listener { private fun createEventListener(latch: CountDownLatch, expectedNumberOfMessages: Int): Timeline.Listener {

View File

@ -37,10 +37,9 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.isCrossSignedVerif
import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.CryptoTestHelper
import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.SessionTestParams
import org.matrix.android.sdk.common.TestConstants import org.matrix.android.sdk.common.TestConstants
import org.matrix.android.sdk.common.withTestHelpers
import kotlin.coroutines.Continuation import kotlin.coroutines.Continuation
import kotlin.coroutines.resume import kotlin.coroutines.resume
@ -49,11 +48,9 @@ import kotlin.coroutines.resume
@LargeTest @LargeTest
class XSigningTest : InstrumentedTest { class XSigningTest : InstrumentedTest {
private val testHelper = CommonTestHelper(context())
private val cryptoTestHelper = CryptoTestHelper(testHelper)
@Test @Test
fun test_InitializeAndStoreKeys() { fun test_InitializeAndStoreKeys() = withTestHelpers(context()) { cryptoTestHelper ->
val testHelper = cryptoTestHelper.testHelper
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true)) val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
testHelper.doSync<Unit> { testHelper.doSync<Unit> {
@ -87,7 +84,8 @@ class XSigningTest : InstrumentedTest {
} }
@Test @Test
fun test_CrossSigningCheckBobSeesTheKeys() { fun test_CrossSigningCheckBobSeesTheKeys() = withTestHelpers(context()) { cryptoTestHelper ->
val testHelper = cryptoTestHelper.testHelper
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession val aliceSession = cryptoTestData.firstSession
@ -137,12 +135,11 @@ class XSigningTest : InstrumentedTest {
) )
assertFalse("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV.isTrusted()) assertFalse("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV.isTrusted())
cryptoTestData.cleanUp(testHelper)
} }
@Test @Test
fun test_CrossSigningTestAliceTrustBobNewDevice() { fun test_CrossSigningTestAliceTrustBobNewDevice() = withTestHelpers(context()) { cryptoTestHelper ->
val testHelper = cryptoTestHelper.testHelper
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession val aliceSession = cryptoTestData.firstSession
@ -216,9 +213,5 @@ class XSigningTest : InstrumentedTest {
val result = aliceSession.cryptoService().crossSigningService().checkDeviceTrust(bobUserId, bobSecondDeviceId, null) val result = aliceSession.cryptoService().crossSigningService().checkDeviceTrust(bobUserId, bobSecondDeviceId, null)
assertTrue("Bob second device should be trusted from alice POV", result.isCrossSignedVerified()) assertTrue("Bob second device should be trusted from alice POV", result.isCrossSignedVerified())
testHelper.signOutAndClose(aliceSession)
testHelper.signOutAndClose(bobSession)
testHelper.signOutAndClose(bobSession2)
} }
} }

View File

@ -34,43 +34,44 @@ import org.matrix.android.sdk.api.session.room.send.SendState
import org.matrix.android.sdk.api.session.room.timeline.Timeline 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.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.CryptoTestHelper
import org.matrix.android.sdk.common.withTestHelpers
import java.util.concurrent.CountDownLatch import java.util.concurrent.CountDownLatch
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING) @FixMethodOrder(MethodSorters.NAME_ASCENDING)
class EncryptionTest : InstrumentedTest { class EncryptionTest : InstrumentedTest {
private val testHelper = CommonTestHelper(context())
private val cryptoTestHelper = CryptoTestHelper(testHelper)
@Test @Test
fun test_EncryptionEvent() { fun test_EncryptionEvent() {
performTest(roomShouldBeEncrypted = false) { room -> withTestHelpers(context()) { cryptoTestHelper ->
// Send an encryption Event as an Event (and not as a state event) performTest(cryptoTestHelper, roomShouldBeEncrypted = false) { room ->
room.sendService().sendEvent( // Send an encryption Event as an Event (and not as a state event)
eventType = EventType.STATE_ROOM_ENCRYPTION, room.sendService().sendEvent(
content = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent()
)
}
}
@Test
fun test_EncryptionStateEvent() {
performTest(roomShouldBeEncrypted = true) { room ->
runBlocking {
// Send an encryption Event as a State Event
room.stateService().sendStateEvent(
eventType = EventType.STATE_ROOM_ENCRYPTION, eventType = EventType.STATE_ROOM_ENCRYPTION,
stateKey = "", content = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent()
body = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent()
) )
} }
} }
} }
private fun performTest(roomShouldBeEncrypted: Boolean, action: (Room) -> Unit) { @Test
fun test_EncryptionStateEvent() {
withTestHelpers(context()) { cryptoTestHelper ->
performTest(cryptoTestHelper, roomShouldBeEncrypted = true) { room ->
runBlocking {
// Send an encryption Event as a State Event
room.stateService().sendStateEvent(
eventType = EventType.STATE_ROOM_ENCRYPTION,
stateKey = "",
body = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent()
)
}
}
}
}
private fun performTest(cryptoTestHelper: CryptoTestHelper, roomShouldBeEncrypted: Boolean, action: (Room) -> Unit) {
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(encryptedRoom = false) val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(encryptedRoom = false)
val aliceSession = cryptoTestData.firstSession val aliceSession = cryptoTestData.firstSession
@ -103,12 +104,11 @@ class EncryptionTest : InstrumentedTest {
timeline.addListener(timelineListener) timeline.addListener(timelineListener)
action.invoke(room) action.invoke(room)
testHelper.await(latch) cryptoTestHelper.testHelper.await(latch)
timeline.dispose() timeline.dispose()
testHelper.waitWithLatch { cryptoTestHelper.testHelper.waitWithLatch {
room.roomCryptoService().isEncrypted() shouldBe roomShouldBeEncrypted room.roomCryptoService().isEncrypted() shouldBe roomShouldBeEncrypted
it.countDown() it.countDown()
} }
cryptoTestData.cleanUp(testHelper)
} }
} }