Try to configure okreplay for testing network + start to rework koin modules

This commit is contained in:
ganfra 2018-12-12 21:15:01 +01:00
parent 1d5587c5ba
commit c8c31172b3
16 changed files with 137 additions and 54 deletions

View File

@ -9,6 +9,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.2.1' classpath 'com.android.tools.build:gradle:3.2.1'
classpath "com.airbnb.okreplay:gradle-plugin:1.4.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"


// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong

View File

@ -2,6 +2,7 @@ apply plugin: 'com.android.library'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
apply plugin: 'realm-android' apply plugin: 'realm-android'
apply plugin: 'okreplay'


buildscript { buildscript {


@ -38,6 +39,10 @@ android {
} }
} }


adbOptions {
installOptions "-g"
}

} }


dependencies { dependencies {
@ -94,14 +99,20 @@ dependencies {
// Logging // Logging
implementation 'com.jakewharton.timber:timber:4.7.1' implementation 'com.jakewharton.timber:timber:4.7.1'


debugImplementation 'com.airbnb.okreplay:okreplay:1.4.0'
releaseImplementation 'com.airbnb.okreplay:noop:1.4.0'
androidTestImplementation 'com.airbnb.okreplay:espresso:1.4.0'


testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
testImplementation 'org.robolectric:robolectric:4.0.2' testImplementation 'org.robolectric:robolectric:4.0.2'
testImplementation "org.koin:koin-test:$koin_version"
testImplementation 'org.robolectric:shadows-support-v4:3.0' testImplementation 'org.robolectric:shadows-support-v4:3.0'
testImplementation "io.mockk:mockk:1.8.13.kotlin13" testImplementation "io.mockk:mockk:1.8.13.kotlin13"
testImplementation 'org.amshove.kluent:kluent-android:1.44' testImplementation 'org.amshove.kluent:kluent-android:1.44'


androidTestImplementation "org.koin:koin-test:$koin_version"
androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation "com.android.support.test:rules:1.0.2"
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
androidTestImplementation 'org.amshove.kluent:kluent-android:1.44' androidTestImplementation 'org.amshove.kluent:kluent-android:1.44'



View File

@ -4,7 +4,7 @@ import android.content.Context
import android.support.test.InstrumentationRegistry import android.support.test.InstrumentationRegistry
import java.io.File import java.io.File


abstract class InstrumentedTest { interface InstrumentedTest {
fun context(): Context { fun context(): Context {
return InstrumentationRegistry.getTargetContext() return InstrumentationRegistry.getTargetContext()
} }

View File

@ -0,0 +1,16 @@
package im.vector.matrix.android

import okreplay.OkReplayConfig
import okreplay.PermissionRule
import okreplay.RecorderRule
import org.junit.rules.RuleChain
import org.junit.rules.TestRule

class OkReplayRuleChainNoActivity(
private val configuration: OkReplayConfig) {

fun get(): TestRule {
return RuleChain.outerRule(PermissionRule(configuration))
.around(RecorderRule(configuration))
}
}

View File

@ -0,0 +1,64 @@
package im.vector.matrix.android.auth

import android.support.test.annotation.UiThreadTest
import android.support.test.rule.GrantPermissionRule
import android.support.test.runner.AndroidJUnit4
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.InstrumentedTest
import im.vector.matrix.android.OkReplayRuleChainNoActivity
import im.vector.matrix.android.api.MatrixOptions
import im.vector.matrix.android.api.auth.Authenticator
import im.vector.matrix.android.internal.auth.AuthModule
import im.vector.matrix.android.internal.di.MatrixModule
import im.vector.matrix.android.internal.di.NetworkModule
import okreplay.*
import org.junit.ClassRule
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.koin.standalone.StandAloneContext.loadKoinModules
import org.koin.standalone.inject
import org.koin.test.KoinTest


@RunWith(AndroidJUnit4::class)
internal class AuthenticatorTest : InstrumentedTest, KoinTest {

init {
Monarchy.init(context())
val matrixModule = MatrixModule(MatrixOptions(context())).definition
val networkModule = NetworkModule().definition
val authModule = AuthModule().definition
loadKoinModules(listOf(matrixModule, networkModule, authModule))
}

private val authenticator: Authenticator by inject()
private val okReplayInterceptor: OkReplayInterceptor by inject()

private val okReplayConfig = OkReplayConfig.Builder()
.tapeRoot(AndroidTapeRoot(
context(), javaClass))
.defaultMode(TapeMode.READ_WRITE) // or TapeMode.READ_ONLY
.sslEnabled(true)
.interceptor(okReplayInterceptor)
.build()

@get:Rule
val testRule = OkReplayRuleChainNoActivity(okReplayConfig).get()

@Test
@UiThreadTest
@OkReplay(tape = "auth", mode = TapeMode.READ_WRITE)
fun auth() {

}

companion object {
@ClassRule
@JvmField
val grantExternalStoragePermissionRule: GrantPermissionRule =
GrantPermissionRule.grant(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
}


}

View File

@ -22,7 +22,7 @@ import org.junit.Test
import kotlin.random.Random import kotlin.random.Random




internal class ChunkEntityTest : InstrumentedTest() { internal class ChunkEntityTest : InstrumentedTest {


private lateinit var monarchy: Monarchy private lateinit var monarchy: Monarchy



View File

@ -3,4 +3,5 @@


<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest> </manifest>

View File

@ -23,12 +23,10 @@ class Matrix(matrixOptions: MatrixOptions) : KoinComponent {


init { init {
Monarchy.init(matrixOptions.context) Monarchy.init(matrixOptions.context)

val matrixModule = MatrixModule(matrixOptions).definition
val matrixModule = MatrixModule(matrixOptions) val networkModule = NetworkModule().definition
val networkModule = NetworkModule() val authModule = AuthModule().definition
val authModule = AuthModule()
loadKoinModules(listOf(matrixModule, networkModule, authModule)) loadKoinModules(listOf(matrixModule, networkModule, authModule))

ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver) ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver)


val lastActiveSession = authenticator.getLastActiveSession() val lastActiveSession = authenticator.getLastActiveSession()

View File

@ -4,13 +4,11 @@ import im.vector.matrix.android.api.auth.Authenticator
import im.vector.matrix.android.internal.auth.db.RealmSessionParamsStore import im.vector.matrix.android.internal.auth.db.RealmSessionParamsStore
import im.vector.matrix.android.internal.auth.db.SessionParamsMapper import im.vector.matrix.android.internal.auth.db.SessionParamsMapper
import io.realm.RealmConfiguration import io.realm.RealmConfiguration
import org.koin.dsl.context.ModuleDefinition
import org.koin.dsl.module.Module
import org.koin.dsl.module.module import org.koin.dsl.module.module


class AuthModule : Module { class AuthModule {


override fun invoke(): ModuleDefinition = module { val definition = module {


single { single {
DefaultAuthenticator(get(), get(), get()) as Authenticator DefaultAuthenticator(get(), get(), get()) as Authenticator
@ -22,5 +20,5 @@ class AuthModule : Module {
RealmSessionParamsStore(mapper, realmConfiguration) as SessionParamsStore RealmSessionParamsStore(mapper, realmConfiguration) as SessionParamsStore
} }


}.invoke() }
} }

View File

@ -6,14 +6,12 @@ import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.asCoroutineDispatcher
import org.koin.dsl.context.ModuleDefinition
import org.koin.dsl.module.Module
import org.koin.dsl.module.module import org.koin.dsl.module.module




class MatrixModule(private val options: MatrixOptions) : Module { class MatrixModule(private val options: MatrixOptions) {


override fun invoke(): ModuleDefinition = module { val definition = module {


single { single {
options.context options.context
@ -27,5 +25,5 @@ class MatrixModule(private val options: MatrixOptions) : Module {
BackgroundDetectionObserver() BackgroundDetectionObserver()
} }


}.invoke() }
} }

View File

@ -4,8 +4,7 @@ import im.vector.matrix.android.internal.network.AccessTokenInterceptor
import im.vector.matrix.android.internal.network.NetworkConnectivityChecker import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor import okhttp3.logging.HttpLoggingInterceptor
import org.koin.dsl.context.ModuleDefinition import okreplay.OkReplayInterceptor
import org.koin.dsl.module.Module
import org.koin.dsl.module.module import org.koin.dsl.module.module
import retrofit2.Converter import retrofit2.Converter
import retrofit2.Retrofit import retrofit2.Retrofit
@ -13,9 +12,9 @@ import retrofit2.converter.moshi.MoshiConverterFactory
import timber.log.Timber import timber.log.Timber
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit


class NetworkModule : Module { class NetworkModule {


override fun invoke(): ModuleDefinition = module { val definition = module {


single { single {
AccessTokenInterceptor(get()) AccessTokenInterceptor(get())
@ -28,13 +27,18 @@ class NetworkModule : Module {
interceptor interceptor
} }


single {
OkReplayInterceptor()
}

single { single {
OkHttpClient.Builder() OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS) .connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS)
.addInterceptor(get() as AccessTokenInterceptor) .addInterceptor(get<AccessTokenInterceptor>())
.addInterceptor(get() as HttpLoggingInterceptor) .addInterceptor(get<HttpLoggingInterceptor>())
.addInterceptor(get<OkReplayInterceptor>())
.build() .build()
} }


@ -56,5 +60,5 @@ class NetworkModule : Module {
.addConverterFactory(get()) .addConverterFactory(get())
} }


}.invoke() }
} }

View File

@ -3,6 +3,7 @@ package im.vector.matrix.android.internal.session
import android.arch.lifecycle.LiveData import android.arch.lifecycle.LiveData
import android.os.Looper import android.os.Looper
import android.support.annotation.MainThread import android.support.annotation.MainThread
import im.vector.matrix.android.api.auth.data.SessionParams
import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.group.Group import im.vector.matrix.android.api.session.group.Group
import im.vector.matrix.android.api.session.group.GroupService import im.vector.matrix.android.api.session.group.GroupService
@ -10,7 +11,6 @@ import im.vector.matrix.android.api.session.group.model.GroupSummary
import im.vector.matrix.android.api.session.room.Room import im.vector.matrix.android.api.session.room.Room
import im.vector.matrix.android.api.session.room.RoomService import im.vector.matrix.android.api.session.room.RoomService
import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.android.api.auth.data.SessionParams
import im.vector.matrix.android.internal.database.LiveEntityObserver import im.vector.matrix.android.internal.database.LiveEntityObserver
import im.vector.matrix.android.internal.session.group.GroupModule import im.vector.matrix.android.internal.session.group.GroupModule
import im.vector.matrix.android.internal.session.room.RoomModule import im.vector.matrix.android.internal.session.room.RoomModule
@ -39,13 +39,13 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi


@MainThread @MainThread
override fun open() { override fun open() {
checkIsMainThread() assertMainThread()
assert(!isOpen) assert(!isOpen)
isOpen = true isOpen = true
val sessionModule = SessionModule(sessionParams) val sessionModule = SessionModule(sessionParams).definition
val syncModule = SyncModule() val syncModule = SyncModule().definition
val roomModule = RoomModule() val roomModule = RoomModule().definition
val groupModule = GroupModule() val groupModule = GroupModule().definition
StandAloneContext.loadKoinModules(listOf(sessionModule, syncModule, roomModule, groupModule)) StandAloneContext.loadKoinModules(listOf(sessionModule, syncModule, roomModule, groupModule))
scope = getKoin().getOrCreateScope(SCOPE) scope = getKoin().getOrCreateScope(SCOPE)
liveEntityUpdaters.forEach { it.start() } liveEntityUpdaters.forEach { it.start() }
@ -55,7 +55,7 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi


@MainThread @MainThread
override fun close() { override fun close() {
checkIsMainThread() assertMainThread()
assert(isOpen) assert(isOpen)
syncThread.kill() syncThread.kill()
liveEntityUpdaters.forEach { it.dispose() } liveEntityUpdaters.forEach { it.dispose() }
@ -109,9 +109,9 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi


// Private methods ***************************************************************************** // Private methods *****************************************************************************


private fun checkIsMainThread() { private fun assertMainThread() {
if (Looper.myLooper() != Looper.getMainLooper()) { if (Looper.getMainLooper().thread !== Thread.currentThread()) {
throw IllegalStateException("Should be called on main thread") throw IllegalStateException("This method can only be called on the main thread!")
} }
} }



View File

@ -16,15 +16,13 @@ import im.vector.matrix.android.internal.session.room.members.RoomDisplayNameRes
import im.vector.matrix.android.internal.session.room.members.RoomMemberDisplayNameResolver import im.vector.matrix.android.internal.session.room.members.RoomMemberDisplayNameResolver
import im.vector.matrix.android.internal.util.md5 import im.vector.matrix.android.internal.util.md5
import io.realm.RealmConfiguration import io.realm.RealmConfiguration
import org.koin.dsl.context.ModuleDefinition
import org.koin.dsl.module.Module
import org.koin.dsl.module.module import org.koin.dsl.module.module
import retrofit2.Retrofit import retrofit2.Retrofit
import java.io.File import java.io.File


internal class SessionModule(private val sessionParams: SessionParams) : Module { internal class SessionModule(private val sessionParams: SessionParams) {


override fun invoke(): ModuleDefinition = module(override = true) { val definition = module(override = true) {


scope(DefaultSession.SCOPE) { scope(DefaultSession.SCOPE) {
sessionParams sessionParams
@ -85,7 +83,7 @@ internal class SessionModule(private val sessionParams: SessionParams) : Module
} }




}.invoke() }




} }

View File

@ -1,14 +1,12 @@
package im.vector.matrix.android.internal.session.group package im.vector.matrix.android.internal.session.group


import im.vector.matrix.android.internal.session.DefaultSession import im.vector.matrix.android.internal.session.DefaultSession
import org.koin.dsl.context.ModuleDefinition
import org.koin.dsl.module.Module
import org.koin.dsl.module.module import org.koin.dsl.module.module
import retrofit2.Retrofit import retrofit2.Retrofit


class GroupModule : Module { class GroupModule {


override fun invoke(): ModuleDefinition = module(override = true) { val definition = module(override = true) {


scope(DefaultSession.SCOPE) { scope(DefaultSession.SCOPE) {
val retrofit: Retrofit = get() val retrofit: Retrofit = get()
@ -19,5 +17,5 @@ class GroupModule : Module {
GetGroupDataRequest(get(), get(), get()) GetGroupDataRequest(get(), get(), get())
} }


}.invoke() }
} }

View File

@ -9,16 +9,14 @@ import im.vector.matrix.android.internal.session.room.members.LoadRoomMembersReq
import im.vector.matrix.android.internal.session.room.send.DefaultSendService import im.vector.matrix.android.internal.session.room.send.DefaultSendService
import im.vector.matrix.android.internal.session.room.timeline.* import im.vector.matrix.android.internal.session.room.timeline.*
import im.vector.matrix.android.internal.util.PagingRequestHelper import im.vector.matrix.android.internal.util.PagingRequestHelper
import org.koin.dsl.context.ModuleDefinition
import org.koin.dsl.module.Module
import org.koin.dsl.module.module import org.koin.dsl.module.module
import retrofit2.Retrofit import retrofit2.Retrofit
import java.util.concurrent.Executors import java.util.concurrent.Executors




class RoomModule : Module { class RoomModule {


override fun invoke(): ModuleDefinition = module(override = true) { val definition = module(override = true) {


scope(DefaultSession.SCOPE) { scope(DefaultSession.SCOPE) {
val retrofit: Retrofit = get() val retrofit: Retrofit = get()
@ -56,5 +54,5 @@ class RoomModule : Module {
DefaultSendService(roomId, get(), get()) as SendService DefaultSendService(roomId, get(), get()) as SendService
} }


}.invoke() }
} }

View File

@ -2,15 +2,13 @@ package im.vector.matrix.android.internal.session.sync


import im.vector.matrix.android.internal.session.DefaultSession import im.vector.matrix.android.internal.session.DefaultSession
import im.vector.matrix.android.internal.session.sync.job.SyncThread import im.vector.matrix.android.internal.session.sync.job.SyncThread
import org.koin.dsl.context.ModuleDefinition
import org.koin.dsl.module.Module
import org.koin.dsl.module.module import org.koin.dsl.module.module
import retrofit2.Retrofit import retrofit2.Retrofit




internal class SyncModule : Module { internal class SyncModule {


override fun invoke(): ModuleDefinition = module(override = true) { val definition = module(override = true) {


scope(DefaultSession.SCOPE) { scope(DefaultSession.SCOPE) {
val retrofit: Retrofit = get() val retrofit: Retrofit = get()
@ -49,5 +47,5 @@ internal class SyncModule : Module {
SyncThread(get(), get(), get(), get()) SyncThread(get(), get(), get(), get())
} }


}.invoke() }
} }