davidliu
Committed by GitHub

mock e2e tests (#19)

* mock e2e tests

* fix peer connection mock initialization
正在显示 18 个修改的文件 包含 653 行增加163 行删除
... ... @@ -43,7 +43,7 @@ android {
targetCompatibility java_version
}
kotlinOptions {
freeCompilerArgs = ["-Xinline-classes"]
freeCompilerArgs = ["-Xinline-classes", "-Xopt-in=kotlin.RequiresOptIn"]
jvmTarget = java_version
}
}
... ... @@ -117,6 +117,7 @@ dependencies {
testImplementation "org.mockito.kotlin:mockito-kotlin:3.1.0"
testImplementation 'androidx.test:core:1.4.0'
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.3"
kaptTest 'com.google.dagger:dagger-compiler:2.38'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
... ...
... ... @@ -8,27 +8,25 @@ import kotlinx.serialization.json.Json
import javax.inject.Named
@Module
class JsonFormatModule {
companion object {
@Provides
fun protobufJsonFormatParser(): JsonFormat.Parser {
return JsonFormat.parser()
}
object JsonFormatModule {
@Provides
fun protobufJsonFormatParser(): JsonFormat.Parser {
return JsonFormat.parser()
}
@Provides
fun protobufJsonFormatPrinter(): JsonFormat.Printer {
return JsonFormat.printer()
}
@Provides
fun protobufJsonFormatPrinter(): JsonFormat.Printer {
return JsonFormat.printer()
}
@Provides
@Reusable
fun kotlinSerializationJson(): Json =
Json {
ignoreUnknownKeys = true
}
@Provides
@Reusable
fun kotlinSerializationJson(): Json =
Json {
ignoreUnknownKeys = true
}
@Provides
@Named(InjectionNames.SIGNAL_JSON_ENABLED)
fun signalJsonEnabled(): Boolean = false
}
@Provides
@Named(InjectionNames.SIGNAL_JSON_ENABLED)
fun signalJsonEnabled(): Boolean = false
}
\ No newline at end of file
... ...
... ... @@ -13,143 +13,141 @@ import javax.inject.Singleton
@Module
class RTCModule {
companion object {
@Provides
@Singleton
fun audioModule(appContext: Context): AudioDeviceModule {
// Set audio record error callbacks.
val audioRecordErrorCallback = object : JavaAudioDeviceModule.AudioRecordErrorCallback {
override fun onWebRtcAudioRecordInitError(errorMessage: String?) {
LKLog.e { "onWebRtcAudioRecordInitError: $errorMessage" }
}
override fun onWebRtcAudioRecordStartError(
errorCode: JavaAudioDeviceModule.AudioRecordStartErrorCode?,
errorMessage: String?
) {
LKLog.e { "onWebRtcAudioRecordStartError: $errorCode. $errorMessage" }
}
override fun onWebRtcAudioRecordError(errorMessage: String?) {
LKLog.e { "onWebRtcAudioRecordError: $errorMessage" }
}
object RTCModule {
@Provides
@Singleton
fun audioModule(appContext: Context): AudioDeviceModule {
// Set audio record error callbacks.
val audioRecordErrorCallback = object : JavaAudioDeviceModule.AudioRecordErrorCallback {
override fun onWebRtcAudioRecordInitError(errorMessage: String?) {
LKLog.e { "onWebRtcAudioRecordInitError: $errorMessage" }
}
val audioTrackErrorCallback = object : JavaAudioDeviceModule.AudioTrackErrorCallback {
override fun onWebRtcAudioTrackInitError(errorMessage: String?) {
LKLog.e { "onWebRtcAudioTrackInitError: $errorMessage" }
}
override fun onWebRtcAudioTrackStartError(
errorCode: JavaAudioDeviceModule.AudioTrackStartErrorCode?,
errorMessage: String?
) {
LKLog.e { "onWebRtcAudioTrackStartError: $errorCode. $errorMessage" }
}
override fun onWebRtcAudioTrackError(errorMessage: String?) {
LKLog.e { "onWebRtcAudioTrackError: $errorMessage" }
}
override fun onWebRtcAudioRecordStartError(
errorCode: JavaAudioDeviceModule.AudioRecordStartErrorCode?,
errorMessage: String?
) {
LKLog.e { "onWebRtcAudioRecordStartError: $errorCode. $errorMessage" }
}
override fun onWebRtcAudioRecordError(errorMessage: String?) {
LKLog.e { "onWebRtcAudioRecordError: $errorMessage" }
}
val audioRecordStateCallback: JavaAudioDeviceModule.AudioRecordStateCallback = object :
JavaAudioDeviceModule.AudioRecordStateCallback {
override fun onWebRtcAudioRecordStart() {
LKLog.i { "Audio recording starts" }
}
override fun onWebRtcAudioRecordStop() {
LKLog.i { "Audio recording stops" }
}
}
val audioTrackErrorCallback = object : JavaAudioDeviceModule.AudioTrackErrorCallback {
override fun onWebRtcAudioTrackInitError(errorMessage: String?) {
LKLog.e { "onWebRtcAudioTrackInitError: $errorMessage" }
}
// Set audio track state callbacks.
val audioTrackStateCallback: JavaAudioDeviceModule.AudioTrackStateCallback = object :
JavaAudioDeviceModule.AudioTrackStateCallback {
override fun onWebRtcAudioTrackStart() {
LKLog.i { "Audio playout starts" }
}
override fun onWebRtcAudioTrackStartError(
errorCode: JavaAudioDeviceModule.AudioTrackStartErrorCode?,
errorMessage: String?
) {
LKLog.e { "onWebRtcAudioTrackStartError: $errorCode. $errorMessage" }
}
override fun onWebRtcAudioTrackStop() {
LKLog.i { "Audio playout stops" }
}
override fun onWebRtcAudioTrackError(errorMessage: String?) {
LKLog.e { "onWebRtcAudioTrackError: $errorMessage" }
}
return JavaAudioDeviceModule.builder(appContext)
.setUseHardwareAcousticEchoCanceler(true)
.setUseHardwareNoiseSuppressor(true)
.setAudioRecordErrorCallback(audioRecordErrorCallback)
.setAudioTrackErrorCallback(audioTrackErrorCallback)
.setAudioRecordStateCallback(audioRecordStateCallback)
.setAudioTrackStateCallback(audioTrackStateCallback)
.createAudioDeviceModule()
}
val audioRecordStateCallback: JavaAudioDeviceModule.AudioRecordStateCallback = object :
JavaAudioDeviceModule.AudioRecordStateCallback {
override fun onWebRtcAudioRecordStart() {
LKLog.i { "Audio recording starts" }
}
@Provides
@Singleton
fun eglBase(): EglBase {
return EglBase.create()
override fun onWebRtcAudioRecordStop() {
LKLog.i { "Audio recording stops" }
}
}
@Provides
fun eglContext(eglBase: EglBase): EglBase.Context = eglBase.eglBaseContext
@Provides
fun videoEncoderFactory(
@Named(InjectionNames.OPTIONS_VIDEO_HW_ACCEL)
videoHwAccel: Boolean,
eglContext: EglBase.Context
): VideoEncoderFactory {
return if (videoHwAccel) {
SimulcastVideoEncoderFactoryWrapper(
eglContext,
enableIntelVp8Encoder = true,
enableH264HighProfile = false,
)
} else {
SoftwareVideoEncoderFactory()
// Set audio track state callbacks.
val audioTrackStateCallback: JavaAudioDeviceModule.AudioTrackStateCallback = object :
JavaAudioDeviceModule.AudioTrackStateCallback {
override fun onWebRtcAudioTrackStart() {
LKLog.i { "Audio playout starts" }
}
}
@Provides
fun videoDecoderFactory(
@Named(InjectionNames.OPTIONS_VIDEO_HW_ACCEL)
videoHwAccel: Boolean,
eglContext: EglBase.Context,
): VideoDecoderFactory {
return if (videoHwAccel) {
DefaultVideoDecoderFactory(eglContext)
} else {
SoftwareVideoDecoderFactory()
override fun onWebRtcAudioTrackStop() {
LKLog.i { "Audio playout stops" }
}
}
@Provides
@Singleton
fun peerConnectionFactory(
appContext: Context,
audioDeviceModule: AudioDeviceModule,
videoEncoderFactory: VideoEncoderFactory,
videoDecoderFactory: VideoDecoderFactory,
): PeerConnectionFactory {
PeerConnectionFactory.initialize(
PeerConnectionFactory.InitializationOptions
.builder(appContext)
.createInitializationOptions()
)
return JavaAudioDeviceModule.builder(appContext)
.setUseHardwareAcousticEchoCanceler(true)
.setUseHardwareNoiseSuppressor(true)
.setAudioRecordErrorCallback(audioRecordErrorCallback)
.setAudioTrackErrorCallback(audioTrackErrorCallback)
.setAudioRecordStateCallback(audioRecordStateCallback)
.setAudioTrackStateCallback(audioTrackStateCallback)
.createAudioDeviceModule()
}
return PeerConnectionFactory.builder()
.setAudioDeviceModule(audioDeviceModule)
.setVideoEncoderFactory(videoEncoderFactory)
.setVideoDecoderFactory(videoDecoderFactory)
.createPeerConnectionFactory()
@Provides
@Singleton
fun eglBase(): EglBase {
return EglBase.create()
}
@Provides
fun eglContext(eglBase: EglBase): EglBase.Context = eglBase.eglBaseContext
@Provides
fun videoEncoderFactory(
@Named(InjectionNames.OPTIONS_VIDEO_HW_ACCEL)
videoHwAccel: Boolean,
eglContext: EglBase.Context
): VideoEncoderFactory {
return if (videoHwAccel) {
SimulcastVideoEncoderFactoryWrapper(
eglContext,
enableIntelVp8Encoder = true,
enableH264HighProfile = false,
)
} else {
SoftwareVideoEncoderFactory()
}
}
@Provides
@Provides
fun videoDecoderFactory(
@Named(InjectionNames.OPTIONS_VIDEO_HW_ACCEL)
fun videoHwAccel() = true
videoHwAccel: Boolean,
eglContext: EglBase.Context,
): VideoDecoderFactory {
return if (videoHwAccel) {
DefaultVideoDecoderFactory(eglContext)
} else {
SoftwareVideoDecoderFactory()
}
}
@Provides
@Singleton
fun peerConnectionFactory(
appContext: Context,
audioDeviceModule: AudioDeviceModule,
videoEncoderFactory: VideoEncoderFactory,
videoDecoderFactory: VideoDecoderFactory,
): PeerConnectionFactory {
PeerConnectionFactory.initialize(
PeerConnectionFactory.InitializationOptions
.builder(appContext)
.createInitializationOptions()
)
return PeerConnectionFactory.builder()
.setAudioDeviceModule(audioDeviceModule)
.setVideoEncoderFactory(videoEncoderFactory)
.setVideoDecoderFactory(videoDecoderFactory)
.createPeerConnectionFactory()
}
@Provides
@Named(InjectionNames.OPTIONS_VIDEO_HW_ACCEL)
fun videoHwAccel() = true
}
\ No newline at end of file
... ...
... ... @@ -7,17 +7,15 @@ import okhttp3.WebSocket
import javax.inject.Singleton
@Module
class WebModule {
companion object {
@Provides
@Singleton
fun okHttpClient(): OkHttpClient {
return OkHttpClient()
}
object WebModule {
@Provides
@Singleton
fun okHttpClient(): OkHttpClient {
return OkHttpClient()
}
@Provides
fun websocketFactory(okHttpClient: OkHttpClient): WebSocket.Factory {
return okHttpClient
}
@Provides
fun websocketFactory(okHttpClient: OkHttpClient): WebSocket.Factory {
return okHttpClient
}
}
\ No newline at end of file
... ...
package io.livekit.android.mock
import org.webrtc.DataChannel
class MockDataChannel(private val label: String?) : DataChannel(1L) {
var observer: DataChannel.Observer? = null
override fun registerObserver(observer: Observer?) {
this.observer = observer
}
override fun unregisterObserver() {
observer = null
}
override fun label(): String? {
return label
}
override fun id(): Int {
return 0
}
override fun state(): State {
return State.OPEN
}
override fun bufferedAmount(): Long {
return 0
}
override fun send(buffer: Buffer?): Boolean {
return true
}
}
\ No newline at end of file
... ...
package io.livekit.android.room.mock
package io.livekit.android.mock
import android.graphics.SurfaceTexture
import android.view.Surface
... ...
package io.livekit.android.mock
import org.webrtc.*
private class MockNativePeerConnectionFactory : NativePeerConnectionFactory {
override fun createNativePeerConnection(): Long = 0L
}
class MockPeerConnection(
private val observer: PeerConnection.Observer?
) : PeerConnection(MockNativePeerConnectionFactory()) {
var localDesc: SessionDescription? = null
var remoteDesc: SessionDescription? = null
override fun getLocalDescription(): SessionDescription? = localDesc
override fun setLocalDescription(observer: SdpObserver?, sdp: SessionDescription?) {
localDesc = sdp
observer?.onSetSuccess()
}
override fun getRemoteDescription(): SessionDescription? = remoteDesc
override fun setRemoteDescription(observer: SdpObserver?, sdp: SessionDescription?) {
remoteDesc = sdp
observer?.onSetSuccess()
}
override fun getCertificate(): RtcCertificatePem? {
return null
}
override fun createDataChannel(label: String?, init: DataChannel.Init?): DataChannel {
return MockDataChannel(label)
}
override fun createOffer(observer: SdpObserver?, constraints: MediaConstraints?) {
val sdp = SessionDescription(SessionDescription.Type.OFFER, "")
observer?.onCreateSuccess(sdp)
}
override fun createAnswer(observer: SdpObserver?, constraints: MediaConstraints?) {
val sdp = SessionDescription(SessionDescription.Type.ANSWER, "")
observer?.onCreateSuccess(sdp)
}
override fun setAudioPlayout(playout: Boolean) {
}
override fun setAudioRecording(recording: Boolean) {
}
override fun setConfiguration(config: RTCConfiguration?): Boolean {
return true
}
override fun addIceCandidate(candidate: IceCandidate?): Boolean {
return true
}
override fun removeIceCandidates(candidates: Array<out IceCandidate>?): Boolean {
return true
}
override fun addStream(stream: MediaStream?): Boolean {
return super.addStream(stream)
}
override fun removeStream(stream: MediaStream?) {
super.removeStream(stream)
}
override fun createSender(kind: String?, stream_id: String?): RtpSender {
return super.createSender(kind, stream_id)
}
override fun getSenders(): MutableList<RtpSender> {
return super.getSenders()
}
override fun getReceivers(): MutableList<RtpReceiver> {
return super.getReceivers()
}
override fun getTransceivers(): MutableList<RtpTransceiver> {
return super.getTransceivers()
}
override fun addTrack(track: MediaStreamTrack?): RtpSender {
return super.addTrack(track)
}
override fun addTrack(track: MediaStreamTrack?, streamIds: MutableList<String>?): RtpSender {
return super.addTrack(track, streamIds)
}
override fun removeTrack(sender: RtpSender?): Boolean {
return super.removeTrack(sender)
}
override fun addTransceiver(track: MediaStreamTrack?): RtpTransceiver {
return super.addTransceiver(track)
}
override fun addTransceiver(
track: MediaStreamTrack?,
init: RtpTransceiver.RtpTransceiverInit?
): RtpTransceiver {
return super.addTransceiver(track, init)
}
override fun addTransceiver(mediaType: MediaStreamTrack.MediaType?): RtpTransceiver {
return super.addTransceiver(mediaType)
}
override fun addTransceiver(
mediaType: MediaStreamTrack.MediaType?,
init: RtpTransceiver.RtpTransceiverInit?
): RtpTransceiver {
return super.addTransceiver(mediaType, init)
}
override fun getStats(observer: StatsObserver?, track: MediaStreamTrack?): Boolean {
observer?.onComplete(emptyArray())
return true
}
override fun getStats(callback: RTCStatsCollectorCallback?) {
callback?.onStatsDelivered(RTCStatsReport(0, emptyMap()))
}
override fun setBitrate(min: Int?, current: Int?, max: Int?): Boolean {
return true
}
override fun startRtcEventLog(file_descriptor: Int, max_size_bytes: Int): Boolean {
return true
}
override fun stopRtcEventLog() {
}
override fun signalingState(): SignalingState {
return super.signalingState()
}
override fun iceConnectionState(): IceConnectionState {
return super.iceConnectionState()
}
override fun connectionState(): PeerConnectionState {
return super.connectionState()
}
override fun iceGatheringState(): IceGatheringState {
return super.iceGatheringState()
}
override fun close() {
}
override fun dispose() {
}
override fun getNativePeerConnection(): Long = 0L
}
\ No newline at end of file
... ...
package io.livekit.android.mock
import io.livekit.android.room.PeerConnectionTransport
import kotlinx.coroutines.CoroutineDispatcher
import org.webrtc.PeerConnection
import org.webrtc.PeerConnectionFactory
internal class MockPeerConnectionTransportFactory(
private val dispatcher: CoroutineDispatcher,
) : PeerConnectionTransport.Factory {
override fun create(
config: PeerConnection.RTCConfiguration,
pcObserver: PeerConnection.Observer,
listener: PeerConnectionTransport.Listener?
): PeerConnectionTransport {
return PeerConnectionTransport(
config,
pcObserver,
listener,
dispatcher,
PeerConnectionFactory.builder()
.createPeerConnectionFactory()
)
}
}
\ No newline at end of file
... ...
package io.livekit.android.mock
import okhttp3.Request
import okhttp3.WebSocket
import okhttp3.WebSocketListener
import org.mockito.Mockito
class MockWebsocketFactory : WebSocket.Factory {
lateinit var ws: WebSocket
lateinit var request: Request
lateinit var listener: WebSocketListener
override fun newWebSocket(request: Request, listener: WebSocketListener): WebSocket {
this.ws = Mockito.mock(WebSocket::class.java)
this.listener = listener
this.request = request
return ws
}
}
\ No newline at end of file
... ...
package io.livekit.android.mock.dagger
import dagger.Module
import dagger.Provides
import io.livekit.android.dagger.InjectionNames
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineDispatcher
import javax.inject.Named
@Module
object TestCoroutinesModule {
@OptIn(ExperimentalCoroutinesApi::class)
val coroutineDispatcher: CoroutineDispatcher = TestCoroutineDispatcher()
@Provides
@Named(InjectionNames.DISPATCHER_DEFAULT)
fun defaultDispatcher() = coroutineDispatcher
@Provides
@Named(InjectionNames.DISPATCHER_IO)
fun ioDispatcher() = coroutineDispatcher
@Provides
@Named(InjectionNames.DISPATCHER_MAIN)
fun mainDispatcher() = coroutineDispatcher
@Provides
@Named(InjectionNames.DISPATCHER_UNCONFINED)
fun unconfinedDispatcher() = coroutineDispatcher
}
\ No newline at end of file
... ...
package io.livekit.android.mock.dagger
import android.content.Context
import dagger.BindsInstance
import dagger.Component
import io.livekit.android.dagger.JsonFormatModule
import io.livekit.android.dagger.LiveKitComponent
import io.livekit.android.mock.MockWebsocketFactory
import javax.inject.Singleton
@Singleton
@Component(
modules = [
TestCoroutinesModule::class,
TestRTCModule::class,
TestWebModule::class,
JsonFormatModule::class,
]
)
interface TestLiveKitComponent : LiveKitComponent {
fun websocketFactory(): MockWebsocketFactory
@Component.Factory
interface Factory {
fun create(@BindsInstance appContext: Context): TestLiveKitComponent
}
}
\ No newline at end of file
... ...
package io.livekit.android.mock.dagger
import android.content.Context
import dagger.Module
import dagger.Provides
import io.livekit.android.dagger.InjectionNames
import io.livekit.android.mock.MockEglBase
import org.webrtc.*
import javax.inject.Named
import javax.inject.Singleton
@Module
object TestRTCModule {
@Provides
@Singleton
fun eglBase(): EglBase {
return MockEglBase()
}
@Provides
fun eglContext(eglBase: EglBase): EglBase.Context = eglBase.eglBaseContext
@Provides
@Singleton
fun peerConnectionFactory(
appContext: Context
): PeerConnectionFactory {
try {
ContextUtils.initialize(appContext)
NativeLibraryLoaderTestHelper.initialize()
} catch (e: Throwable) {
// do nothing. this is expected.
}
return MockPeerConnectionFactory()
}
@Provides
@Named(InjectionNames.OPTIONS_VIDEO_HW_ACCEL)
fun videoHwAccel() = true
}
\ No newline at end of file
... ...
package io.livekit.android.mock.dagger
import dagger.Module
import dagger.Provides
import io.livekit.android.mock.MockWebsocketFactory
import okhttp3.OkHttpClient
import okhttp3.Response
import okhttp3.WebSocket
import javax.inject.Singleton
@Module
object TestWebModule {
@Provides
@Singleton
fun okHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor {
// Don't make actual network calls
Response.Builder()
.code(200)
.build()
}
.build()
}
@Provides
@Singleton
fun websocketFactory(websocketFactory: MockWebsocketFactory): WebSocket.Factory {
return websocketFactory
}
@Provides
@Singleton
fun mockWebsocketFactory(): MockWebsocketFactory {
return MockWebsocketFactory()
}
}
\ No newline at end of file
... ...
package io.livekit.android.room
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import io.livekit.android.mock.MockWebsocketFactory
import io.livekit.android.mock.dagger.DaggerTestLiveKitComponent
import io.livekit.android.util.toOkioByteString
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Assert
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.junit.MockitoJUnit
import org.robolectric.RobolectricTestRunner
@ExperimentalCoroutinesApi
@RunWith(RobolectricTestRunner::class)
class RoomMockE2ETest {
@get:Rule
var mockitoRule = MockitoJUnit.rule()
lateinit var context: Context
lateinit var room: Room
lateinit var wsFactory: MockWebsocketFactory
@Before
fun setup() {
context = ApplicationProvider.getApplicationContext()
val component = DaggerTestLiveKitComponent
.factory()
.create(context)
room = component.roomFactory()
.create(context)
wsFactory = component.websocketFactory()
}
@Test
fun connectTest() {
val job = TestCoroutineScope().launch {
room.connect(
url = "http://www.example.com",
token = "",
options = null
)
}
wsFactory.listener.onMessage(wsFactory.ws, SignalClientTest.JOIN.toOkioByteString())
runBlockingTest {
job.join()
}
}
@Test
fun roomUpdateTest() {
val handler = CoroutineExceptionHandler { _, exception ->
println("CoroutineExceptionHandler got $exception")
exception.printStackTrace()
}
val job = TestCoroutineScope().launch(handler) {
room.connect(
url = "http://www.example.com",
token = "",
options = null
)
}
wsFactory.listener.onMessage(wsFactory.ws, SignalClientTest.JOIN.toOkioByteString())
runBlockingTest {
job.join()
}
wsFactory.listener.onMessage(wsFactory.ws, SignalClientTest.ROOM_UPDATE.toOkioByteString())
Assert.assertEquals(
SignalClientTest.ROOM_UPDATE.roomUpdate.room.metadata,
room.metadata
)
}
}
\ No newline at end of file
... ...
... ... @@ -2,7 +2,7 @@ package io.livekit.android.room
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import io.livekit.android.room.mock.MockEglBase
import io.livekit.android.mock.MockEglBase
import io.livekit.android.room.participant.LocalParticipant
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch
... ... @@ -18,7 +18,6 @@ import org.mockito.Mockito
import org.mockito.junit.MockitoJUnit
import org.robolectric.RobolectricTestRunner
import org.webrtc.EglBase
import org.webrtc.PeerConnectionFactory
@ExperimentalCoroutinesApi
@RunWith(RobolectricTestRunner::class)
... ...
package io.livekit.android.room
import com.google.protobuf.util.JsonFormat
import io.livekit.android.mock.MockWebsocketFactory
import io.livekit.android.util.toOkioByteString
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async
... ... @@ -29,16 +30,6 @@ class SignalClientTest {
lateinit var coroutineDispatcher: TestCoroutineDispatcher
lateinit var coroutineScope: TestCoroutineScope
class MockWebsocketFactory : WebSocket.Factory {
lateinit var ws: WebSocket
lateinit var request: Request
override fun newWebSocket(request: Request, listener: WebSocketListener): WebSocket {
ws = Mockito.mock(WebSocket::class.java)
this.request = request
return ws
}
}
@Before
fun setup() {
coroutineDispatcher = TestCoroutineDispatcher()
... ... @@ -139,7 +130,7 @@ class SignalClientTest {
companion object {
private const val EXAMPLE_URL = "http://www.example.com"
private val JOIN = with(LivekitRtc.SignalResponse.newBuilder()) {
val JOIN = with(LivekitRtc.SignalResponse.newBuilder()) {
join = with(joinBuilder) {
room = with(roomBuilder) {
name = "roomname"
... ... @@ -150,7 +141,8 @@ class SignalClientTest {
}
build()
}
private val OFFER = with(LivekitRtc.SignalResponse.newBuilder()) {
val OFFER = with(LivekitRtc.SignalResponse.newBuilder()) {
offer = with(offerBuilder) {
sdp = ""
type = "offer"
... ... @@ -158,5 +150,16 @@ class SignalClientTest {
}
build()
}
val ROOM_UPDATE = with(LivekitRtc.SignalResponse.newBuilder()) {
roomUpdate = with(roomUpdateBuilder) {
room = with(roomBuilder) {
metadata = "metadata"
build()
}
build()
}
build()
}
}
}
\ No newline at end of file
... ...
package org.webrtc
import io.livekit.android.mock.MockPeerConnection
class MockPeerConnectionFactory : PeerConnectionFactory(1L) {
override fun createPeerConnectionInternal(
rtcConfig: PeerConnection.RTCConfiguration?,
constraints: MediaConstraints?,
observer: PeerConnection.Observer?,
sslCertificateVerifier: SSLCertificateVerifier?
): PeerConnection {
return MockPeerConnection(observer)
}
}
\ No newline at end of file
... ...
package org.webrtc
object NativeLibraryLoaderTestHelper {
fun initialize() {
NativeLibrary.initialize({ true }, "")
}
}
\ No newline at end of file
... ...