mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-15 01:35:07 +08:00
Improve test stability
This commit is contained in:
parent
0675b7c16c
commit
e18402f834
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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.")
|
||||||
|
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user