TI: create account

This commit is contained in:
Benoit Marty 2020-01-06 17:24:01 +01:00
parent fc6d845c0d
commit 6746f68411
6 changed files with 284 additions and 305 deletions

View file

@ -0,0 +1,55 @@
/*
* Copyright 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.account
import im.vector.matrix.android.InstrumentedTest
import im.vector.matrix.android.common.CommonTestHelper
import im.vector.matrix.android.common.SessionTestParams
import im.vector.matrix.android.common.TestConstants
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.runners.MethodSorters
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class AccountCreationTest : InstrumentedTest {
private val commonTestHelper = CommonTestHelper(context())
@Test
fun createAccountTest() {
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
commonTestHelper.signout(session)
session.close()
}
// FIXME This test does not past yet, due to usage of the EventBus.
@Test
fun createAccountAndLoginAgainTest() {
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
// Log again to the same account
val session2 = commonTestHelper.logIntoAccount(session.myUserId, SessionTestParams(withInitialSync = true))
session.close()
session2.close()
}
}

View file

@ -17,85 +17,77 @@
package im.vector.matrix.android.common
// import android.content.Context
// import android.net.Uri
// import androidx.test.InstrumentationRegistry
//
// import org.junit.Assert
//
// import java.util.ArrayList
// import java.util.HashMap
// import java.util.UUID
// import java.util.concurrent.CountDownLatch
// import java.util.concurrent.TimeUnit
//
// import im.vector.matrix.android.api.Matrix
// import im.vector.matrix.android.api.auth.data.Credentials
// import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
// import im.vector.matrix.android.api.session.Session
// import im.vector.matrix.android.internal.auth.registration.AuthParams
// import im.vector.matrix.android.internal.auth.registration.RegistrationFlowResponse
// import im.vector.matrix.android.internal.auth.registration.RegistrationParams
// import io.realm.internal.android.JsonUtils
//
//
// /**
// * This class exposes methods to be used in common cases
// * Registration, login, Sync, Sending messages...
// */
// class CommonTestHelper {
//
// @Throws(InterruptedException::class)
// fun createAccount(userNamePrefix: String, testParams: SessionTestParams): Session {
// return createAccount(userNamePrefix, TestConstants.PASSWORD, testParams)
// }
//
// @Throws(InterruptedException::class)
// fun logIntoAccount(userId: String, testParams: SessionTestParams): Session {
// return logIntoAccount(userId, TestConstants.PASSWORD, testParams)
// }
//
// /**
// * Create a Home server configuration, with Http connection allowed for test
// */
// fun createHomeServerConfig(): HomeServerConnectionConfig {
// return HomeServerConnectionConfig.Builder()
// .withHomeServerUri(Uri.parse(TestConstants.TESTS_HOME_SERVER_URL))
// .build()
// }
//
// /**
// * This methods init the event stream and check for initial sync
// *
// * @param session the session to sync
// * @param withCrypto true if crypto is enabled and should be checked
// */
// @Throws(InterruptedException::class)
// fun syncSession(session: Session, withCrypto: Boolean) {
// val params = HashMap<String, Boolean>()
// val sizeOfLock = if (withCrypto) 2 else 1
// val lock2 = CountDownLatch(sizeOfLock)
// session.getDataHandler().addListener(object : MXEventListener() {
// fun onInitialSyncComplete(toToken: String) {
// params["isInit"] = true
// lock2.countDown()
// }
//
// fun onCryptoSyncComplete() {
// params["onCryptoSyncComplete"] = true
// lock2.countDown()
// }
// })
// session.getDataHandler().getStore().open()
// session.startEventStream(null)
//
// await(lock2)
// Assert.assertTrue(params.containsKey("isInit"))
// if (withCrypto) {
// Assert.assertTrue(params.containsKey("onCryptoSyncComplete"))
import android.content.Context
import android.net.Uri
import im.vector.matrix.android.api.Matrix
import im.vector.matrix.android.api.MatrixConfiguration
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
import im.vector.matrix.android.api.auth.data.LoginFlowResult
import im.vector.matrix.android.api.auth.registration.RegistrationResult
import im.vector.matrix.android.api.session.Session
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import java.util.*
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
/**
* This class exposes methods to be used in common cases
* Registration, login, Sync, Sending messages...
*/
class CommonTestHelper(context: Context) {
val matrix: Matrix
init {
Matrix.initialize(context, MatrixConfiguration("TestFlavor"))
matrix = Matrix.getInstance(context)
}
fun createAccount(userNamePrefix: String, testParams: SessionTestParams): Session {
return createAccount(userNamePrefix, TestConstants.PASSWORD, testParams)
}
fun logIntoAccount(userId: String, testParams: SessionTestParams): Session {
return logIntoAccount(userId, TestConstants.PASSWORD, testParams)
}
/**
* Create a Home server configuration, with Http connection allowed for test
*/
fun createHomeServerConfig(): HomeServerConnectionConfig {
return HomeServerConnectionConfig.Builder()
.withHomeServerUri(Uri.parse(TestConstants.TESTS_HOME_SERVER_URL))
.build()
}
/**
* This methods init the event stream and check for initial sync
*
* @param session the session to sync
*/
fun syncSession(session: Session) {
//val lock = CountDownLatch(1)
// val observer = androidx.lifecycle.Observer<SyncState> { syncState ->
// if (syncState is SyncState.Idle) {
// lock.countDown()
// }
// }
//
// TODO observe?
// while (session.syncState().value !is SyncState.Idle) {
// sleep(100)
// }
session.open()
session.startSync(true)
//await(lock)
//session.syncState().removeObserver(observer)
}
// /**
// * Sends text messages in a room
// *
@ -140,216 +132,153 @@ package im.vector.matrix.android.common
// }
//
//
// // PRIVATE METHODS *****************************************************************************
//
// /**
// * Creates a unique account
// *
// * @param userNamePrefix the user name prefix
// * @param password the password
// * @param testParams test params about the session
// * @return the session associated with the newly created account
// */
// @Throws(InterruptedException::class)
// private fun createAccount(userNamePrefix: String,
// password: String,
// testParams: SessionTestParams): Session {
// val context = InstrumentationRegistry.getContext()
// val session = createAccountAndSync(
// context,
// userNamePrefix + "_" + System.currentTimeMillis() + UUID.randomUUID(),
// password,
// testParams
// )
// Assert.assertNotNull(session)
// return session
// }
//
// /**
// * Logs into an existing account
// *
// * @param userId the userId to log in
// * @param password the password to log in
// * @param testParams test params about the session
// * @return the session associated with the existing account
// */
// @Throws(InterruptedException::class)
// private fun logIntoAccount(userId: String,
// password: String,
// testParams: SessionTestParams): Session {
// val context = InstrumentationRegistry.getContext()
// val session = logAccountAndSync(context, userId, password, testParams)
// Assert.assertNotNull(session)
// return session
// }
//
// /**
// * Create an account and a dedicated session
// *
// * @param context the context
// * @param userName the account username
// * @param password the password
// * @param sessionTestParams parameters for the test
// */
// @Throws(InterruptedException::class)
// private fun createAccountAndSync(context: Context,
// userName: String,
// password: String,
// sessionTestParams: SessionTestParams): Session {
// val hs = createHomeServerConfig()
//
// val loginRestClient = LoginRestClient(hs)
//
// val params = HashMap<String, Any>()
// val registrationParams = RegistrationParams()
//
// var lock = CountDownLatch(1)
//
// // get the registration session id
// loginRestClient.register(registrationParams, object : TestMatrixCallback<Credentials>(lock, false) {
// override fun onFailure(failure: Throwable) {
// // detect if a parameter is expected
// var registrationFlowResponse: RegistrationFlowResponse? = null
//
// // when a response is not completed the server returns an error message
// if (null != failure.mStatus && failure.mStatus === 401) {
// try {
// registrationFlowResponse = JsonUtils.toRegistrationFlowResponse(e.mErrorBodyAsString)
// } catch (castExcept: Exception) {
// }
//
// }
//
// // check if the server response can be casted
// if (null != registrationFlowResponse) {
// params["session"] = registrationFlowResponse!!.session
// }
//
// super.onFailure(failure)
// }
// })
//
// await(lock)
//
// val session = params["session"] as String?
//
// Assert.assertNotNull(session)
//
// registrationParams.username = userName
// registrationParams.password = password
// val authParams = AuthParams(LOGIN_FLOW_TYPE_DUMMY)
// authParams.session = session
//
// registrationParams.auth = authParams
//
// lock = CountDownLatch(1)
// loginRestClient.register(registrationParams, object : TestMatrixCallback<Credentials>(lock) {
// fun onSuccess(credentials: Credentials) {
// params["credentials"] = credentials
// super.onSuccess(credentials)
// }
// })
//
// await(lock)
//
// val credentials = params["credentials"] as Credentials?
//
// Assert.assertNotNull(credentials)
//
// hs.setCredentials(credentials)
//
// val store = MXFileStore(hs, false, context)
//
// val dataHandler = MXDataHandler(store, credentials)
// dataHandler.setLazyLoadingEnabled(sessionTestParams.withLazyLoading)
//
// val Session = Session.Builder(hs, dataHandler, context)
// .withLegacyCryptoStore(sessionTestParams.withLegacyCryptoStore)
// .build()
//
// if (sessionTestParams.withCryptoEnabled) {
// Session.enableCryptoWhenStarting()
// }
// if (sessionTestParams.withInitialSync) {
// syncSession(Session, sessionTestParams.withCryptoEnabled)
// }
// return Session
// }
//
// /**
// * Start an account login
// *
// * @param context the context
// * @param userName the account username
// * @param password the password
// * @param sessionTestParams session test params
// */
// @Throws(InterruptedException::class)
// private fun logAccountAndSync(context: Context,
// userName: String,
// password: String,
// sessionTestParams: SessionTestParams): Session {
// val hs = createHomeServerConfig(null)
// val loginRestClient = LoginRestClient(hs)
// val params = HashMap<String, Any>()
// val lock = CountDownLatch(1)
//
// // get the registration session id
// loginRestClient.loginWithUser(userName, password, object : TestMatrixCallback<Credentials>(lock) {
// fun onSuccess(credentials: Credentials) {
// params["credentials"] = credentials
// super.onSuccess(credentials)
// }
// })
//
// await(lock)
//
// val credentials = params["credentials"] as Credentials?
//
// Assert.assertNotNull(credentials)
//
// hs.setCredentials(credentials)
//
// val store = MXFileStore(hs, false, context)
//
// val mxDataHandler = MXDataHandler(store, credentials)
// mxDataHandler.setLazyLoadingEnabled(sessionTestParams.withLazyLoading)
//
// val Session = Session.Builder(hs, mxDataHandler, context)
// .withLegacyCryptoStore(sessionTestParams.withLegacyCryptoStore)
// .build()
//
// if (sessionTestParams.withCryptoEnabled) {
// Session.enableCryptoWhenStarting()
// }
// if (sessionTestParams.withInitialSync) {
// syncSession(Session, sessionTestParams.withCryptoEnabled)
// }
// return Session
// }
//
// /**
// * Await for a latch and ensure the result is true
// *
// * @param latch
// * @throws InterruptedException
// */
// @Throws(InterruptedException::class)
// fun await(latch: CountDownLatch) {
// Assert.assertTrue(latch.await(TestConstants.timeOutMillis, TimeUnit.MILLISECONDS))
// }
//
// /**
// * Clear all provided sessions
// *
// * @param sessions the sessions to clear
// */
// fun closeAllSessions(sessions: List<Session>) {
// for (session in sessions) {
// session.close()
// }
// }
//
// PRIVATE METHODS *****************************************************************************
/**
* Creates a unique account
*
* @param userNamePrefix the user name prefix
* @param password the password
* @param testParams test params about the session
* @return the session associated with the newly created account
*/
@Throws(InterruptedException::class)
private fun createAccount(userNamePrefix: String,
password: String,
testParams: SessionTestParams): Session {
val session = createAccountAndSync(
userNamePrefix + "_" + System.currentTimeMillis() + UUID.randomUUID(),
password,
testParams
)
assertNotNull(session)
return session
}
/**
* Logs into an existing account
*
* @param userId the userId to log in
* @param password the password to log in
* @param testParams test params about the session
* @return the session associated with the existing account
*/
@Throws(InterruptedException::class)
private fun logIntoAccount(userId: String,
password: String,
testParams: SessionTestParams): Session {
val session = logAccountAndSync(userId, password, testParams)
assertNotNull(session)
return session
}
/**
* Create an account and a dedicated session
*
* @param userName the account username
* @param password the password
* @param sessionTestParams parameters for the test
*/
private fun createAccountAndSync(userName: String,
password: String,
sessionTestParams: SessionTestParams): Session {
val hs = createHomeServerConfig()
var lock = CountDownLatch(1)
matrix.authenticationService.getLoginFlow(hs, object : TestMatrixCallback<LoginFlowResult>(lock) {})
await(lock)
lock = CountDownLatch(1)
matrix.authenticationService.getRegistrationWizard().createAccount(userName, password, null, object : TestMatrixCallback<RegistrationResult>(lock) {
override fun onSuccess(data: RegistrationResult) {
super.onSuccess(data)
}
})
await(lock)
// Preform dummy step
lock = CountDownLatch(1)
var registrationResult: RegistrationResult? = null
matrix.authenticationService.getRegistrationWizard().dummy(object : TestMatrixCallback<RegistrationResult>(lock) {
override fun onSuccess(data: RegistrationResult) {
registrationResult = data
super.onSuccess(data)
}
})
await(lock)
assertTrue(registrationResult is RegistrationResult.Success)
val session = (registrationResult as RegistrationResult.Success).session
if (sessionTestParams.withInitialSync) {
syncSession(session)
}
return session
}
/**
* Start an account login
*
* @param userName the account username
* @param password the password
* @param sessionTestParams session test params
*/
private fun logAccountAndSync(userName: String,
password: String,
sessionTestParams: SessionTestParams): Session {
val hs = createHomeServerConfig()
var lock = CountDownLatch(1)
matrix.authenticationService.getLoginFlow(hs, object : TestMatrixCallback<LoginFlowResult>(lock) {})
await(lock)
lock = CountDownLatch(1)
var session: Session? = null
matrix.authenticationService.getLoginWizard().login(userName, password, "myDevice", object : TestMatrixCallback<Session>(lock) {
override fun onSuccess(data: Session) {
session = data
super.onSuccess(data)
}
})
await(lock)
assertNotNull(session)
if (sessionTestParams.withInitialSync) {
syncSession(session!!)
}
return session!!
}
/**
* Await for a latch and ensure the result is true
*
* @param latch
* @throws InterruptedException
*/
fun await(latch: CountDownLatch) {
assertTrue(latch.await(TestConstants.timeOutMillis, TimeUnit.MILLISECONDS))
}
/**
* Clear all provided sessions
*
* @param sessions the sessions to clear
*/
fun closeAllSessions(sessions: List<Session>) {
for (session in sessions) {
session.close()
}
}
fun signout(session: Session) {
val lock = CountDownLatch(1)
session.signOut(true, object : TestMatrixCallback<Unit>(lock) {})
await(lock)
}
// /**
// * Clone a session.
// * It simulate that the user launches again the application with the same Credentials, contrary to login which will create a new DeviceId
@ -404,4 +333,4 @@ package im.vector.matrix.android.common
//
// return session2
// }
// }
}

View file

@ -15,7 +15,11 @@
*/
package im.vector.matrix.android.common
import okhttp3.*
import okhttp3.Interceptor
import okhttp3.Protocol
import okhttp3.Request
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import javax.net.ssl.HttpsURLConnection
/**
@ -73,7 +77,7 @@ class MockOkHttpInterceptor : Interceptor {
.protocol(Protocol.HTTP_1_1)
.request(originalRequest)
.message("mocked answer")
.body(ResponseBody.create(null, body))
.body(body.toResponseBody(null))
.code(code)
.build()
}

View file

@ -40,8 +40,8 @@ interface SignOutService {
/**
* Sign out, and release the session, clear all the session data, including crypto data
* @param sigOutFromHomeserver true if the sign out request has to be done
* @param signOutFromHomeserver true if the sign out request has to be done
*/
fun signOut(sigOutFromHomeserver: Boolean,
fun signOut(signOutFromHomeserver: Boolean,
callback: MatrixCallback<Unit>): Cancelable
}

View file

@ -108,7 +108,6 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
@MainThread
override fun open() {
assertMainThread()
assert(!isOpen)
isOpen = true
liveEntityObservers.forEach { it.start() }
@ -201,12 +200,4 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
override fun removeListener(listener: Session.Listener) {
sessionListeners.removeListener(listener)
}
// Private methods *****************************************************************************
private fun assertMainThread() {
if (Looper.getMainLooper().thread !== Thread.currentThread()) {
throw IllegalStateException("This method can only be called on the main thread!")
}
}
}

View file

@ -50,10 +50,10 @@ internal class DefaultSignOutService @Inject constructor(private val signOutTask
}
}
override fun signOut(sigOutFromHomeserver: Boolean,
override fun signOut(signOutFromHomeserver: Boolean,
callback: MatrixCallback<Unit>): Cancelable {
return signOutTask
.configureWith(SignOutTask.Params(sigOutFromHomeserver)) {
.configureWith(SignOutTask.Params(signOutFromHomeserver)) {
this.callback = callback
}
.executeBy(taskExecutor)