Committed by
GitHub
Separate mocks & tests into a separate publishable package (#395)
* Separate mocks and tests into separate package * publishing for testing package * Make NetworkCallbackManager injectable * various fixes and upgrades to test package * fix tests
正在显示
88 个修改的文件
包含
908 行增加
和
528 行删除
| @@ -55,7 +55,7 @@ jobs: | @@ -55,7 +55,7 @@ jobs: | ||
| 55 | ./gradlew spotlessCheck | 55 | ./gradlew spotlessCheck |
| 56 | 56 | ||
| 57 | - name: Build with Gradle | 57 | - name: Build with Gradle |
| 58 | - run: ./gradlew assembleRelease livekit-android-sdk:testRelease | 58 | + run: ./gradlew assembleRelease livekit-android-test:testRelease |
| 59 | 59 | ||
| 60 | # TODO: Figure out appropriate place to run this. Takes ~3 mins, so pretty slow. | 60 | # TODO: Figure out appropriate place to run this. Takes ~3 mins, so pretty slow. |
| 61 | # # generates coverage-report.md and publishes as checkrun | 61 | # # generates coverage-report.md and publishes as checkrun |
| @@ -40,7 +40,7 @@ jobs: | @@ -40,7 +40,7 @@ jobs: | ||
| 40 | AWS_DEFAULT_REGION: "us-east-1" | 40 | AWS_DEFAULT_REGION: "us-east-1" |
| 41 | 41 | ||
| 42 | - name: Build with Gradle | 42 | - name: Build with Gradle |
| 43 | - run: ./gradlew livekit-android-sdk:assembleRelease livekit-android-sdk:testRelease | 43 | + run: ./gradlew livekit-android-sdk:assembleRelease livekit-android-test:testRelease |
| 44 | 44 | ||
| 45 | - name: Create gpg key and import into gradle properties | 45 | - name: Create gpg key and import into gradle properties |
| 46 | run: | | 46 | run: | |
| @@ -17,6 +17,9 @@ okhttp = "4.12.0" | @@ -17,6 +17,9 @@ okhttp = "4.12.0" | ||
| 17 | protobuf = "3.22.0" | 17 | protobuf = "3.22.0" |
| 18 | protobufJavalite = "3.22.0" | 18 | protobufJavalite = "3.22.0" |
| 19 | semver4j = "3.1.0" | 19 | semver4j = "3.1.0" |
| 20 | +core-ktx = "1.12.0" | ||
| 21 | +appcompat = "1.6.1" | ||
| 22 | +material = "1.11.0" | ||
| 20 | 23 | ||
| 21 | [libraries] | 24 | [libraries] |
| 22 | android-jain-sip-ri = { module = "javax.sip:android-jain-sip-ri", version.ref = "androidJainSipRi" } | 25 | android-jain-sip-ri = { module = "javax.sip:android-jain-sip-ri", version.ref = "androidJainSipRi" } |
| @@ -58,10 +61,20 @@ espresso = { module = "androidx.test.espresso:espresso-core", version = "3.5.1" | @@ -58,10 +61,20 @@ espresso = { module = "androidx.test.espresso:espresso-core", version = "3.5.1" | ||
| 58 | junit = { module = "junit:junit", version.ref = "junit-lib" } | 61 | junit = { module = "junit:junit", version.ref = "junit-lib" } |
| 59 | junitJupiterApi = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit-jupiter" } | 62 | junitJupiterApi = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit-jupiter" } |
| 60 | junitJupiterEngine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit-jupiter" } | 63 | junitJupiterEngine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit-jupiter" } |
| 61 | -mockito-core = { module = "org.mockito:mockito-core", version = "4.0.0" } | ||
| 62 | -mockito-kotlin = { module = "org.mockito.kotlin:mockito-kotlin", version = "4.0.0" } | ||
| 63 | -robolectric = { module = "org.robolectric:robolectric", version = "4.10.2" } | 64 | + |
| 65 | +# Mockito 5 requires JVM 11. | ||
| 66 | +#noinspection GradleDependency | ||
| 67 | +mockito-core = { module = "org.mockito:mockito-core", version = "4.11.0" } | ||
| 68 | +#noinspection GradleDependency | ||
| 69 | +mockito-kotlin = { module = "org.mockito.kotlin:mockito-kotlin", version = "4.1.0" } | ||
| 70 | +#noinspection GradleDependency | ||
| 71 | +mockito-inline = { module = "org.mockito:mockito-inline", version = "4.11.0" } | ||
| 72 | + | ||
| 73 | +robolectric = { module = "org.robolectric:robolectric", version = "4.11.1" } | ||
| 64 | turbine = { module = "app.cash.turbine:turbine", version = "1.0.0" } | 74 | turbine = { module = "app.cash.turbine:turbine", version = "1.0.0" } |
| 75 | +core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" } | ||
| 76 | +appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } | ||
| 77 | +material = { group = "com.google.android.material", name = "material", version.ref = "material" } | ||
| 65 | 78 | ||
| 66 | [plugins] | 79 | [plugins] |
| 67 | 80 |
| @@ -16,44 +16,47 @@ | @@ -16,44 +16,47 @@ | ||
| 16 | 16 | ||
| 17 | package io.livekit.android.dagger | 17 | package io.livekit.android.dagger |
| 18 | 18 | ||
| 19 | -internal object InjectionNames { | 19 | +/** |
| 20 | + * @suppress | ||
| 21 | + */ | ||
| 22 | +object InjectionNames { | ||
| 20 | 23 | ||
| 21 | /** | 24 | /** |
| 22 | * @see [kotlinx.coroutines.Dispatchers.Default] | 25 | * @see [kotlinx.coroutines.Dispatchers.Default] |
| 23 | */ | 26 | */ |
| 24 | - internal const val DISPATCHER_DEFAULT = "dispatcher_default" | 27 | + const val DISPATCHER_DEFAULT = "dispatcher_default" |
| 25 | 28 | ||
| 26 | /** | 29 | /** |
| 27 | * @see [kotlinx.coroutines.Dispatchers.IO] | 30 | * @see [kotlinx.coroutines.Dispatchers.IO] |
| 28 | */ | 31 | */ |
| 29 | - internal const val DISPATCHER_IO = "dispatcher_io" | 32 | + const val DISPATCHER_IO = "dispatcher_io" |
| 30 | 33 | ||
| 31 | /** | 34 | /** |
| 32 | * @see [kotlinx.coroutines.Dispatchers.Main] | 35 | * @see [kotlinx.coroutines.Dispatchers.Main] |
| 33 | */ | 36 | */ |
| 34 | - internal const val DISPATCHER_MAIN = "dispatcher_main" | 37 | + const val DISPATCHER_MAIN = "dispatcher_main" |
| 35 | 38 | ||
| 36 | /** | 39 | /** |
| 37 | * @see [kotlinx.coroutines.Dispatchers.Unconfined] | 40 | * @see [kotlinx.coroutines.Dispatchers.Unconfined] |
| 38 | */ | 41 | */ |
| 39 | - internal const val DISPATCHER_UNCONFINED = "dispatcher_unconfined" | 42 | + const val DISPATCHER_UNCONFINED = "dispatcher_unconfined" |
| 40 | 43 | ||
| 41 | - internal const val SENDER = "sender" | 44 | + const val SENDER = "sender" |
| 42 | 45 | ||
| 43 | - internal const val OPTIONS_VIDEO_HW_ACCEL = "options_video_hw_accel" | 46 | + const val OPTIONS_VIDEO_HW_ACCEL = "options_video_hw_accel" |
| 44 | 47 | ||
| 45 | - internal const val LIB_WEBRTC_INITIALIZATION = "lib_webrtc_initialization" | 48 | + const val LIB_WEBRTC_INITIALIZATION = "lib_webrtc_initialization" |
| 46 | 49 | ||
| 47 | // Overrides | 50 | // Overrides |
| 48 | - internal const val OVERRIDE_OKHTTP = "override_okhttp" | ||
| 49 | - internal const val OVERRIDE_AUDIO_DEVICE_MODULE = "override_audio_device_module" | ||
| 50 | - internal const val OVERRIDE_AUDIO_PROCESSOR_OPTIONS = "override_audio_processor_options" | ||
| 51 | - internal const val OVERRIDE_JAVA_AUDIO_DEVICE_MODULE_CUSTOMIZER = "override_java_audio_device_module_customizer" | ||
| 52 | - internal const val OVERRIDE_VIDEO_ENCODER_FACTORY = "override_video_encoder_factory" | ||
| 53 | - internal const val OVERRIDE_VIDEO_DECODER_FACTORY = "override_video_decoder_factory" | ||
| 54 | - internal const val OVERRIDE_AUDIO_HANDLER = "override_audio_handler" | ||
| 55 | - internal const val OVERRIDE_AUDIO_OUTPUT_TYPE = "override_audio_output_type" | ||
| 56 | - internal const val OVERRIDE_DISABLE_COMMUNICATION_WORKAROUND = "override_disable_communication_workaround" | ||
| 57 | - internal const val OVERRIDE_EGL_BASE = "override_egl_base" | ||
| 58 | - internal const val OVERRIDE_PEER_CONNECTION_FACTORY_OPTIONS = "override_peer_connection_factory_options" | 51 | + const val OVERRIDE_OKHTTP = "override_okhttp" |
| 52 | + const val OVERRIDE_AUDIO_DEVICE_MODULE = "override_audio_device_module" | ||
| 53 | + const val OVERRIDE_AUDIO_PROCESSOR_OPTIONS = "override_audio_processor_options" | ||
| 54 | + const val OVERRIDE_JAVA_AUDIO_DEVICE_MODULE_CUSTOMIZER = "override_java_audio_device_module_customizer" | ||
| 55 | + const val OVERRIDE_VIDEO_ENCODER_FACTORY = "override_video_encoder_factory" | ||
| 56 | + const val OVERRIDE_VIDEO_DECODER_FACTORY = "override_video_decoder_factory" | ||
| 57 | + const val OVERRIDE_AUDIO_HANDLER = "override_audio_handler" | ||
| 58 | + const val OVERRIDE_AUDIO_OUTPUT_TYPE = "override_audio_output_type" | ||
| 59 | + const val OVERRIDE_DISABLE_COMMUNICATION_WORKAROUND = "override_disable_communication_workaround" | ||
| 60 | + const val OVERRIDE_EGL_BASE = "override_egl_base" | ||
| 61 | + const val OVERRIDE_PEER_CONNECTION_FACTORY_OPTIONS = "override_peer_connection_factory_options" | ||
| 59 | } | 62 | } |
| @@ -21,8 +21,11 @@ import dagger.Provides | @@ -21,8 +21,11 @@ import dagger.Provides | ||
| 21 | import dagger.Reusable | 21 | import dagger.Reusable |
| 22 | import kotlinx.serialization.json.Json | 22 | import kotlinx.serialization.json.Json |
| 23 | 23 | ||
| 24 | +/** | ||
| 25 | + * @suppress | ||
| 26 | + */ | ||
| 24 | @Module | 27 | @Module |
| 25 | -internal object JsonFormatModule { | 28 | +object JsonFormatModule { |
| 26 | @Provides | 29 | @Provides |
| 27 | @Reusable | 30 | @Reusable |
| 28 | fun kotlinSerializationJson(): Json = | 31 | fun kotlinSerializationJson(): Json = |
| @@ -25,6 +25,9 @@ import livekit.org.webrtc.EglBase | @@ -25,6 +25,9 @@ import livekit.org.webrtc.EglBase | ||
| 25 | import livekit.org.webrtc.PeerConnectionFactory | 25 | import livekit.org.webrtc.PeerConnectionFactory |
| 26 | import javax.inject.Singleton | 26 | import javax.inject.Singleton |
| 27 | 27 | ||
| 28 | +/** | ||
| 29 | + * @suppress | ||
| 30 | + */ | ||
| 28 | @Singleton | 31 | @Singleton |
| 29 | @Component( | 32 | @Component( |
| 30 | modules = [ | 33 | modules = [ |
| @@ -37,7 +40,7 @@ import javax.inject.Singleton | @@ -37,7 +40,7 @@ import javax.inject.Singleton | ||
| 37 | MemoryModule::class, | 40 | MemoryModule::class, |
| 38 | ], | 41 | ], |
| 39 | ) | 42 | ) |
| 40 | -internal interface LiveKitComponent { | 43 | +interface LiveKitComponent { |
| 41 | 44 | ||
| 42 | fun roomFactory(): Room.Factory | 45 | fun roomFactory(): Room.Factory |
| 43 | 46 |
| @@ -21,8 +21,11 @@ import dagger.Provides | @@ -21,8 +21,11 @@ import dagger.Provides | ||
| 21 | import io.livekit.android.memory.CloseableManager | 21 | import io.livekit.android.memory.CloseableManager |
| 22 | import javax.inject.Singleton | 22 | import javax.inject.Singleton |
| 23 | 23 | ||
| 24 | +/** | ||
| 25 | + * @suppress | ||
| 26 | + */ | ||
| 24 | @Module | 27 | @Module |
| 25 | -internal object MemoryModule { | 28 | +object MemoryModule { |
| 26 | 29 | ||
| 27 | @Singleton | 30 | @Singleton |
| 28 | @Provides | 31 | @Provides |
| @@ -23,9 +23,12 @@ import dagger.Provides | @@ -23,9 +23,12 @@ import dagger.Provides | ||
| 23 | import io.livekit.android.LiveKitOverrides | 23 | import io.livekit.android.LiveKitOverrides |
| 24 | import javax.inject.Named | 24 | import javax.inject.Named |
| 25 | 25 | ||
| 26 | +/** | ||
| 27 | + * @suppress | ||
| 28 | + */ | ||
| 26 | @SuppressLint("KotlinNullnessAnnotation") | 29 | @SuppressLint("KotlinNullnessAnnotation") |
| 27 | @Module | 30 | @Module |
| 28 | -internal class OverridesModule(private val overrides: LiveKitOverrides) { | 31 | +class OverridesModule(private val overrides: LiveKitOverrides) { |
| 29 | 32 | ||
| 30 | @Provides | 33 | @Provides |
| 31 | @Named(InjectionNames.OVERRIDE_OKHTTP) | 34 | @Named(InjectionNames.OVERRIDE_OKHTTP) |
| @@ -41,8 +41,14 @@ import timber.log.Timber | @@ -41,8 +41,14 @@ import timber.log.Timber | ||
| 41 | import javax.inject.Named | 41 | import javax.inject.Named |
| 42 | import javax.inject.Singleton | 42 | import javax.inject.Singleton |
| 43 | 43 | ||
| 44 | -internal typealias CapabilitiesGetter = @JvmSuppressWildcards (MediaStreamTrack.MediaType) -> RtpCapabilities | 44 | +/** |
| 45 | + * @suppress | ||
| 46 | + */ | ||
| 47 | +typealias CapabilitiesGetter = @JvmSuppressWildcards (MediaStreamTrack.MediaType) -> RtpCapabilities | ||
| 45 | 48 | ||
| 49 | +/** | ||
| 50 | + * @suppress | ||
| 51 | + */ | ||
| 46 | @Module | 52 | @Module |
| 47 | internal object RTCModule { | 53 | internal object RTCModule { |
| 48 | 54 |
| @@ -17,10 +17,16 @@ | @@ -17,10 +17,16 @@ | ||
| 17 | package io.livekit.android.dagger | 17 | package io.livekit.android.dagger |
| 18 | 18 | ||
| 19 | import android.content.Context | 19 | import android.content.Context |
| 20 | +import android.net.ConnectivityManager | ||
| 20 | import androidx.annotation.Nullable | 21 | import androidx.annotation.Nullable |
| 21 | import dagger.Module | 22 | import dagger.Module |
| 22 | import dagger.Provides | 23 | import dagger.Provides |
| 23 | import dagger.Reusable | 24 | import dagger.Reusable |
| 25 | +import io.livekit.android.memory.CloseableManager | ||
| 26 | +import io.livekit.android.room.network.NetworkCallbackManagerFactory | ||
| 27 | +import io.livekit.android.room.network.NetworkCallbackManagerImpl | ||
| 28 | +import io.livekit.android.room.network.NetworkCallbackRegistry | ||
| 29 | +import io.livekit.android.room.network.NetworkCallbackRegistryImpl | ||
| 24 | import io.livekit.android.stats.AndroidNetworkInfo | 30 | import io.livekit.android.stats.AndroidNetworkInfo |
| 25 | import io.livekit.android.stats.NetworkInfo | 31 | import io.livekit.android.stats.NetworkInfo |
| 26 | import okhttp3.OkHttpClient | 32 | import okhttp3.OkHttpClient |
| @@ -50,4 +56,23 @@ internal object WebModule { | @@ -50,4 +56,23 @@ internal object WebModule { | ||
| 50 | fun networkInfo(context: Context): NetworkInfo { | 56 | fun networkInfo(context: Context): NetworkInfo { |
| 51 | return AndroidNetworkInfo(context) | 57 | return AndroidNetworkInfo(context) |
| 52 | } | 58 | } |
| 59 | + | ||
| 60 | + @Provides | ||
| 61 | + fun connectivityManager(context: Context): ConnectivityManager { | ||
| 62 | + return context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + @Provides | ||
| 66 | + fun networkCallbackRegistrar(connectivityManager: ConnectivityManager): NetworkCallbackRegistry { | ||
| 67 | + return NetworkCallbackRegistryImpl(connectivityManager) | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + @Provides | ||
| 71 | + @Reusable | ||
| 72 | + fun networkCallbackManagerFactory(closeableManager: CloseableManager, registrar: NetworkCallbackRegistry): NetworkCallbackManagerFactory { | ||
| 73 | + return { networkCallback: ConnectivityManager.NetworkCallback -> | ||
| 74 | + NetworkCallbackManagerImpl(networkCallback, registrar) | ||
| 75 | + .apply { closeableManager.registerClosable(this) } | ||
| 76 | + } | ||
| 77 | + } | ||
| 53 | } | 78 | } |
| @@ -232,7 +232,10 @@ enum class DisconnectReason { | @@ -232,7 +232,10 @@ enum class DisconnectReason { | ||
| 232 | JOIN_FAILURE, | 232 | JOIN_FAILURE, |
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | -internal fun LivekitModels.DisconnectReason?.convert(): DisconnectReason { | 235 | +/** |
| 236 | + * @suppress | ||
| 237 | + */ | ||
| 238 | +fun LivekitModels.DisconnectReason?.convert(): DisconnectReason { | ||
| 236 | return when (this) { | 239 | return when (this) { |
| 237 | LivekitModels.DisconnectReason.CLIENT_INITIATED -> DisconnectReason.CLIENT_INITIATED | 240 | LivekitModels.DisconnectReason.CLIENT_INITIATED -> DisconnectReason.CLIENT_INITIATED |
| 238 | LivekitModels.DisconnectReason.DUPLICATE_IDENTITY -> DisconnectReason.DUPLICATE_IDENTITY | 241 | LivekitModels.DisconnectReason.DUPLICATE_IDENTITY -> DisconnectReason.DUPLICATE_IDENTITY |
| @@ -354,7 +354,11 @@ constructor( | @@ -354,7 +354,11 @@ constructor( | ||
| 354 | 354 | ||
| 355 | private const val DD_EXTENSION_URI = "https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension" | 355 | private const val DD_EXTENSION_URI = "https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension" |
| 356 | 356 | ||
| 357 | -internal fun ensureVideoDDExtensionForSVC(mediaDesc: MediaDescription) { | 357 | +/** |
| 358 | + * @suppress | ||
| 359 | + */ | ||
| 360 | +@VisibleForTesting | ||
| 361 | +fun ensureVideoDDExtensionForSVC(mediaDesc: MediaDescription) { | ||
| 358 | val codec = mediaDesc.getRtps() | 362 | val codec = mediaDesc.getRtps() |
| 359 | .firstOrNull() | 363 | .firstOrNull() |
| 360 | ?.second | 364 | ?.second |
| @@ -397,7 +401,11 @@ eliminate this issue. | @@ -397,7 +401,11 @@ eliminate this issue. | ||
| 397 | */ | 401 | */ |
| 398 | private const val startBitrateForSVC = 0.7 | 402 | private const val startBitrateForSVC = 0.7 |
| 399 | 403 | ||
| 400 | -internal fun ensureCodecBitrates( | 404 | +/** |
| 405 | + * @suppress | ||
| 406 | + */ | ||
| 407 | +@VisibleForTesting | ||
| 408 | +fun ensureCodecBitrates( | ||
| 401 | media: MediaDescription, | 409 | media: MediaDescription, |
| 402 | trackBitrates: Map<TrackBitrateInfoKey, TrackBitrateInfo>, | 410 | trackBitrates: Map<TrackBitrateInfoKey, TrackBitrateInfo>, |
| 403 | ) { | 411 | ) { |
| @@ -454,12 +462,20 @@ internal fun isSVCCodec(codec: String?): Boolean { | @@ -454,12 +462,20 @@ internal fun isSVCCodec(codec: String?): Boolean { | ||
| 454 | "vp9".equals(codec, ignoreCase = true)) | 462 | "vp9".equals(codec, ignoreCase = true)) |
| 455 | } | 463 | } |
| 456 | 464 | ||
| 457 | -internal data class TrackBitrateInfo( | 465 | +/** |
| 466 | + * @suppress | ||
| 467 | + */ | ||
| 468 | +@VisibleForTesting | ||
| 469 | +data class TrackBitrateInfo( | ||
| 458 | val codec: String, | 470 | val codec: String, |
| 459 | val maxBitrate: Long, | 471 | val maxBitrate: Long, |
| 460 | ) | 472 | ) |
| 461 | 473 | ||
| 462 | -internal sealed class TrackBitrateInfoKey { | 474 | +/** |
| 475 | + * @suppress | ||
| 476 | + */ | ||
| 477 | +@VisibleForTesting | ||
| 478 | +sealed class TrackBitrateInfoKey { | ||
| 463 | data class Cid(val value: String) : TrackBitrateInfoKey() | 479 | data class Cid(val value: String) : TrackBitrateInfoKey() |
| 464 | data class Transceiver(val value: RtpTransceiver) : TrackBitrateInfoKey() | 480 | data class Transceiver(val value: RtpTransceiver) : TrackBitrateInfoKey() |
| 465 | } | 481 | } |
| @@ -80,7 +80,8 @@ internal constructor( | @@ -80,7 +80,8 @@ internal constructor( | ||
| 80 | * Reflects the combined connection state of SignalClient and primary PeerConnection. | 80 | * Reflects the combined connection state of SignalClient and primary PeerConnection. |
| 81 | */ | 81 | */ |
| 82 | @FlowObservable | 82 | @FlowObservable |
| 83 | - internal var connectionState: ConnectionState by flowDelegate(ConnectionState.DISCONNECTED) { newVal, oldVal -> | 83 | + @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) |
| 84 | + var connectionState: ConnectionState by flowDelegate(ConnectionState.DISCONNECTED) { newVal, oldVal -> | ||
| 84 | if (newVal == oldVal) { | 85 | if (newVal == oldVal) { |
| 85 | return@flowDelegate | 86 | return@flowDelegate |
| 86 | } | 87 | } |
| @@ -383,7 +384,8 @@ internal constructor( | @@ -383,7 +384,8 @@ internal constructor( | ||
| 383 | * reconnect Signal and PeerConnections | 384 | * reconnect Signal and PeerConnections |
| 384 | */ | 385 | */ |
| 385 | @Synchronized | 386 | @Synchronized |
| 386 | - internal fun reconnect() { | 387 | + @VisibleForTesting |
| 388 | + fun reconnect() { | ||
| 387 | if (reconnectingJob?.isActive == true) { | 389 | if (reconnectingJob?.isActive == true) { |
| 388 | LKLog.d { "Reconnection is already in progress" } | 390 | LKLog.d { "Reconnection is already in progress" } |
| 389 | return | 391 | return |
| @@ -740,11 +742,18 @@ internal constructor( | @@ -740,11 +742,18 @@ internal constructor( | ||
| 740 | } | 742 | } |
| 741 | 743 | ||
| 742 | companion object { | 744 | companion object { |
| 745 | + | ||
| 746 | + /** | ||
| 747 | + * @suppress | ||
| 748 | + */ | ||
| 743 | @VisibleForTesting | 749 | @VisibleForTesting |
| 744 | - internal const val RELIABLE_DATA_CHANNEL_LABEL = "_reliable" | 750 | + const val RELIABLE_DATA_CHANNEL_LABEL = "_reliable" |
| 745 | 751 | ||
| 752 | + /** | ||
| 753 | + * @suppress | ||
| 754 | + */ | ||
| 746 | @VisibleForTesting | 755 | @VisibleForTesting |
| 747 | - internal const val LOSSY_DATA_CHANNEL_LABEL = "_lossy" | 756 | + const val LOSSY_DATA_CHANNEL_LABEL = "_lossy" |
| 748 | internal const val MAX_DATA_PACKET_SIZE = 15000 | 757 | internal const val MAX_DATA_PACKET_SIZE = 15000 |
| 749 | private const val MAX_RECONNECT_RETRIES = 10 | 758 | private const val MAX_RECONNECT_RETRIES = 10 |
| 750 | private const val MAX_RECONNECT_TIMEOUT = 60 * 1000 | 759 | private const val MAX_RECONNECT_TIMEOUT = 60 * 1000 |
| @@ -1056,11 +1065,11 @@ internal constructor( | @@ -1056,11 +1065,11 @@ internal constructor( | ||
| 1056 | } | 1065 | } |
| 1057 | 1066 | ||
| 1058 | @VisibleForTesting | 1067 | @VisibleForTesting |
| 1059 | - internal fun getPublisherPeerConnection() = | 1068 | + fun getPublisherPeerConnection() = |
| 1060 | publisher!!.peerConnection | 1069 | publisher!!.peerConnection |
| 1061 | 1070 | ||
| 1062 | @VisibleForTesting | 1071 | @VisibleForTesting |
| 1063 | - internal fun getSubscriberPeerConnection() = | 1072 | + fun getSubscriberPeerConnection() = |
| 1064 | subscriber!!.peerConnection | 1073 | subscriber!!.peerConnection |
| 1065 | } | 1074 | } |
| 1066 | 1075 | ||
| @@ -1073,7 +1082,7 @@ enum class ReconnectType { | @@ -1073,7 +1082,7 @@ enum class ReconnectType { | ||
| 1073 | FORCE_FULL_RECONNECT, | 1082 | FORCE_FULL_RECONNECT, |
| 1074 | } | 1083 | } |
| 1075 | 1084 | ||
| 1076 | -internal fun LivekitRtc.ICEServer.toWebrtc() = PeerConnection.IceServer.builder(urlsList) | 1085 | +fun LivekitRtc.ICEServer.toWebrtc(): PeerConnection.IceServer = PeerConnection.IceServer.builder(urlsList) |
| 1077 | .setUsername(username ?: "") | 1086 | .setUsername(username ?: "") |
| 1078 | .setPassword(credential ?: "") | 1087 | .setPassword(credential ?: "") |
| 1079 | .setTlsAlpnProtocols(emptyList()) | 1088 | .setTlsAlpnProtocols(emptyList()) |
| @@ -19,7 +19,6 @@ | @@ -19,7 +19,6 @@ | ||
| 19 | package io.livekit.android.room | 19 | package io.livekit.android.room |
| 20 | 20 | ||
| 21 | import android.content.Context | 21 | import android.content.Context |
| 22 | -import android.net.ConnectivityManager | ||
| 23 | import android.net.ConnectivityManager.NetworkCallback | 22 | import android.net.ConnectivityManager.NetworkCallback |
| 24 | import android.net.Network | 23 | import android.net.Network |
| 25 | import androidx.annotation.VisibleForTesting | 24 | import androidx.annotation.VisibleForTesting |
| @@ -39,7 +38,7 @@ import io.livekit.android.e2ee.E2EEOptions | @@ -39,7 +38,7 @@ import io.livekit.android.e2ee.E2EEOptions | ||
| 39 | import io.livekit.android.events.* | 38 | import io.livekit.android.events.* |
| 40 | import io.livekit.android.memory.CloseableManager | 39 | import io.livekit.android.memory.CloseableManager |
| 41 | import io.livekit.android.renderer.TextureViewRenderer | 40 | import io.livekit.android.renderer.TextureViewRenderer |
| 42 | -import io.livekit.android.room.network.NetworkCallbackManager | 41 | +import io.livekit.android.room.network.NetworkCallbackManagerFactory |
| 43 | import io.livekit.android.room.participant.* | 42 | import io.livekit.android.room.participant.* |
| 44 | import io.livekit.android.room.provisions.LKObjects | 43 | import io.livekit.android.room.provisions.LKObjects |
| 45 | import io.livekit.android.room.track.* | 44 | import io.livekit.android.room.track.* |
| @@ -78,6 +77,7 @@ constructor( | @@ -78,6 +77,7 @@ constructor( | ||
| 78 | private val communicationWorkaround: CommunicationWorkaround, | 77 | private val communicationWorkaround: CommunicationWorkaround, |
| 79 | val audioProcessingController: AudioProcessingController, | 78 | val audioProcessingController: AudioProcessingController, |
| 80 | val lkObjects: LKObjects, | 79 | val lkObjects: LKObjects, |
| 80 | + networkCallbackManagerFactory: NetworkCallbackManagerFactory, | ||
| 81 | ) : RTCEngine.Listener, ParticipantListener { | 81 | ) : RTCEngine.Listener, ParticipantListener { |
| 82 | 82 | ||
| 83 | private lateinit var coroutineScope: CoroutineScope | 83 | private lateinit var coroutineScope: CoroutineScope |
| @@ -753,7 +753,7 @@ constructor( | @@ -753,7 +753,7 @@ constructor( | ||
| 753 | } | 753 | } |
| 754 | 754 | ||
| 755 | // ------------------------------------- NetworkCallback -------------------------------------// | 755 | // ------------------------------------- NetworkCallback -------------------------------------// |
| 756 | - private val networkCallbackManager = NetworkCallbackManager( | 756 | + private val networkCallbackManager = networkCallbackManagerFactory.invoke( |
| 757 | object : NetworkCallback() { | 757 | object : NetworkCallback() { |
| 758 | override fun onLost(network: Network) { | 758 | override fun onLost(network: Network) { |
| 759 | // lost connection, flip to reconnecting | 759 | // lost connection, flip to reconnecting |
| @@ -770,8 +770,7 @@ constructor( | @@ -770,8 +770,7 @@ constructor( | ||
| 770 | hasLostConnectivity = false | 770 | hasLostConnectivity = false |
| 771 | } | 771 | } |
| 772 | }, | 772 | }, |
| 773 | - connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager, | ||
| 774 | - ).apply { closeableManager.registerClosable(this) } | 773 | + ) |
| 775 | 774 | ||
| 776 | // ----------------------------------- RTCEngine.Listener ------------------------------------// | 775 | // ----------------------------------- RTCEngine.Listener ------------------------------------// |
| 777 | 776 |
| @@ -16,6 +16,7 @@ | @@ -16,6 +16,7 @@ | ||
| 16 | 16 | ||
| 17 | package io.livekit.android.room | 17 | package io.livekit.android.room |
| 18 | 18 | ||
| 19 | +import androidx.annotation.VisibleForTesting | ||
| 19 | import com.vdurmont.semver4j.Semver | 20 | import com.vdurmont.semver4j.Semver |
| 20 | import io.livekit.android.ConnectOptions | 21 | import io.livekit.android.ConnectOptions |
| 21 | import io.livekit.android.RoomOptions | 22 | import io.livekit.android.RoomOptions |
| @@ -122,7 +123,8 @@ constructor( | @@ -122,7 +123,8 @@ constructor( | ||
| 122 | /** | 123 | /** |
| 123 | * @throws Exception if fails to connect. | 124 | * @throws Exception if fails to connect. |
| 124 | */ | 125 | */ |
| 125 | - internal suspend fun reconnect(url: String, token: String, participantSid: String?): Either<ReconnectResponse, Unit> { | 126 | + @VisibleForTesting |
| 127 | + suspend fun reconnect(url: String, token: String, participantSid: String?): Either<ReconnectResponse, Unit> { | ||
| 126 | val reconnectResponse = connect( | 128 | val reconnectResponse = connect( |
| 127 | url, | 129 | url, |
| 128 | token, | 130 | token, |
| @@ -17,12 +17,40 @@ | @@ -17,12 +17,40 @@ | ||
| 17 | package io.livekit.android.room.network | 17 | package io.livekit.android.room.network |
| 18 | 18 | ||
| 19 | import android.net.ConnectivityManager | 19 | import android.net.ConnectivityManager |
| 20 | +import android.net.ConnectivityManager.NetworkCallback | ||
| 20 | import android.net.NetworkCapabilities | 21 | import android.net.NetworkCapabilities |
| 21 | import android.net.NetworkRequest | 22 | import android.net.NetworkRequest |
| 22 | import io.livekit.android.util.LKLog | 23 | import io.livekit.android.util.LKLog |
| 23 | import java.io.Closeable | 24 | import java.io.Closeable |
| 24 | import java.util.concurrent.atomic.AtomicBoolean | 25 | import java.util.concurrent.atomic.AtomicBoolean |
| 25 | 26 | ||
| 27 | +typealias NetworkCallbackManagerFactory = @JvmSuppressWildcards ( | ||
| 28 | + networkCallback: NetworkCallback, | ||
| 29 | +) -> NetworkCallbackManager | ||
| 30 | + | ||
| 31 | +/** | ||
| 32 | + * @suppress | ||
| 33 | + */ | ||
| 34 | +interface NetworkCallbackRegistry { | ||
| 35 | + fun registerNetworkCallback(networkRequest: NetworkRequest, networkCallback: NetworkCallback) | ||
| 36 | + fun unregisterNetworkCallback(networkCallback: NetworkCallback) | ||
| 37 | +} | ||
| 38 | + | ||
| 39 | +internal class NetworkCallbackRegistryImpl(val connectivityManager: ConnectivityManager) : NetworkCallbackRegistry { | ||
| 40 | + override fun registerNetworkCallback(networkRequest: NetworkRequest, networkCallback: NetworkCallback) { | ||
| 41 | + connectivityManager.registerNetworkCallback(networkRequest, networkCallback) | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + override fun unregisterNetworkCallback(networkCallback: NetworkCallback) { | ||
| 45 | + connectivityManager.unregisterNetworkCallback(networkCallback) | ||
| 46 | + } | ||
| 47 | +} | ||
| 48 | + | ||
| 49 | +interface NetworkCallbackManager : Closeable { | ||
| 50 | + fun registerCallback() | ||
| 51 | + fun unregisterCallback() | ||
| 52 | +} | ||
| 53 | + | ||
| 26 | /** | 54 | /** |
| 27 | * Manages a [ConnectivityManager.NetworkCallback] so that it is never | 55 | * Manages a [ConnectivityManager.NetworkCallback] so that it is never |
| 28 | * registered multiple times. A NetworkCallback is allowed to be registered | 56 | * registered multiple times. A NetworkCallback is allowed to be registered |
| @@ -30,16 +58,18 @@ import java.util.concurrent.atomic.AtomicBoolean | @@ -30,16 +58,18 @@ import java.util.concurrent.atomic.AtomicBoolean | ||
| 30 | * requests will leak on 8.0 and earlier. | 58 | * requests will leak on 8.0 and earlier. |
| 31 | * | 59 | * |
| 32 | * There's a 100 request hard limit, so leaks here are particularly dangerous. | 60 | * There's a 100 request hard limit, so leaks here are particularly dangerous. |
| 61 | + * | ||
| 62 | + * @suppress | ||
| 33 | */ | 63 | */ |
| 34 | -class NetworkCallbackManager( | ||
| 35 | - private val networkCallback: ConnectivityManager.NetworkCallback, | ||
| 36 | - private val connectivityManager: ConnectivityManager, | ||
| 37 | -) : Closeable { | 64 | +class NetworkCallbackManagerImpl( |
| 65 | + private val networkCallback: NetworkCallback, | ||
| 66 | + private val connectivityManager: NetworkCallbackRegistry, | ||
| 67 | +) : NetworkCallbackManager { | ||
| 38 | private val isRegistered = AtomicBoolean(false) | 68 | private val isRegistered = AtomicBoolean(false) |
| 39 | private val isClosed = AtomicBoolean(false) | 69 | private val isClosed = AtomicBoolean(false) |
| 40 | 70 | ||
| 41 | @Synchronized | 71 | @Synchronized |
| 42 | - fun registerCallback() { | 72 | + override fun registerCallback() { |
| 43 | if (!isClosed.get() && isRegistered.compareAndSet(false, true)) { | 73 | if (!isClosed.get() && isRegistered.compareAndSet(false, true)) { |
| 44 | try { | 74 | try { |
| 45 | val networkRequest = NetworkRequest.Builder() | 75 | val networkRequest = NetworkRequest.Builder() |
| @@ -53,7 +83,7 @@ class NetworkCallbackManager( | @@ -53,7 +83,7 @@ class NetworkCallbackManager( | ||
| 53 | } | 83 | } |
| 54 | 84 | ||
| 55 | @Synchronized | 85 | @Synchronized |
| 56 | - fun unregisterCallback() { | 86 | + override fun unregisterCallback() { |
| 57 | if (!isClosed.get() && isRegistered.compareAndSet(true, false)) { | 87 | if (!isClosed.get() && isRegistered.compareAndSet(true, false)) { |
| 58 | try { | 88 | try { |
| 59 | connectivityManager.unregisterNetworkCallback(networkCallback) | 89 | connectivityManager.unregisterNetworkCallback(networkCallback) |
| @@ -16,6 +16,7 @@ | @@ -16,6 +16,7 @@ | ||
| 16 | 16 | ||
| 17 | package io.livekit.android.room.participant | 17 | package io.livekit.android.room.participant |
| 18 | 18 | ||
| 19 | +import androidx.annotation.VisibleForTesting | ||
| 19 | import io.livekit.android.dagger.InjectionNames | 20 | import io.livekit.android.dagger.InjectionNames |
| 20 | import io.livekit.android.events.BroadcastEventBus | 21 | import io.livekit.android.events.BroadcastEventBus |
| 21 | import io.livekit.android.events.ParticipantEvent | 22 | import io.livekit.android.events.ParticipantEvent |
| @@ -75,7 +76,7 @@ open class Participant( | @@ -75,7 +76,7 @@ open class Participant( | ||
| 75 | @FlowObservable | 76 | @FlowObservable |
| 76 | @get:FlowObservable | 77 | @get:FlowObservable |
| 77 | var identity: Identity? by flowDelegate(identity) | 78 | var identity: Identity? by flowDelegate(identity) |
| 78 | - internal set | 79 | + @VisibleForTesting set |
| 79 | 80 | ||
| 80 | /** | 81 | /** |
| 81 | * Changes can be observed by using [io.livekit.android.util.flow] | 82 | * Changes can be observed by using [io.livekit.android.util.flow] |
| @@ -83,7 +84,7 @@ open class Participant( | @@ -83,7 +84,7 @@ open class Participant( | ||
| 83 | @FlowObservable | 84 | @FlowObservable |
| 84 | @get:FlowObservable | 85 | @get:FlowObservable |
| 85 | var audioLevel: Float by flowDelegate(0f) | 86 | var audioLevel: Float by flowDelegate(0f) |
| 86 | - internal set | 87 | + @VisibleForTesting set |
| 87 | 88 | ||
| 88 | /** | 89 | /** |
| 89 | * Changes can be observed by using [io.livekit.android.util.flow] | 90 | * Changes can be observed by using [io.livekit.android.util.flow] |
| @@ -99,7 +100,7 @@ open class Participant( | @@ -99,7 +100,7 @@ open class Participant( | ||
| 99 | } | 100 | } |
| 100 | } | 101 | } |
| 101 | } | 102 | } |
| 102 | - internal set | 103 | + @VisibleForTesting set |
| 103 | 104 | ||
| 104 | @FlowObservable | 105 | @FlowObservable |
| 105 | @get:FlowObservable | 106 | @get:FlowObservable |
| @@ -108,7 +109,7 @@ open class Participant( | @@ -108,7 +109,7 @@ open class Participant( | ||
| 108 | eventBus.postEvent(ParticipantEvent.NameChanged(this, newValue), scope) | 109 | eventBus.postEvent(ParticipantEvent.NameChanged(this, newValue), scope) |
| 109 | } | 110 | } |
| 110 | } | 111 | } |
| 111 | - internal set | 112 | + @VisibleForTesting set |
| 112 | 113 | ||
| 113 | /** | 114 | /** |
| 114 | * Changes can be observed by using [io.livekit.android.util.flow] | 115 | * Changes can be observed by using [io.livekit.android.util.flow] |
| @@ -121,7 +122,7 @@ open class Participant( | @@ -121,7 +122,7 @@ open class Participant( | ||
| 121 | eventBus.postEvent(ParticipantEvent.MetadataChanged(this, oldMetadata), scope) | 122 | eventBus.postEvent(ParticipantEvent.MetadataChanged(this, oldMetadata), scope) |
| 122 | } | 123 | } |
| 123 | } | 124 | } |
| 124 | - internal set | 125 | + @VisibleForTesting set |
| 125 | 126 | ||
| 126 | /** | 127 | /** |
| 127 | * | 128 | * |
| @@ -168,7 +169,8 @@ open class Participant( | @@ -168,7 +169,8 @@ open class Participant( | ||
| 168 | * @suppress | 169 | * @suppress |
| 169 | */ | 170 | */ |
| 170 | @Deprecated("Use events instead") | 171 | @Deprecated("Use events instead") |
| 171 | - internal var internalListener: ParticipantListener? = null | 172 | + @VisibleForTesting |
| 173 | + var internalListener: ParticipantListener? = null | ||
| 172 | 174 | ||
| 173 | val hasInfo | 175 | val hasInfo |
| 174 | get() = participantInfo != null | 176 | get() = participantInfo != null |
| @@ -300,7 +302,8 @@ open class Participant( | @@ -300,7 +302,8 @@ open class Participant( | ||
| 300 | /** | 302 | /** |
| 301 | * @suppress | 303 | * @suppress |
| 302 | */ | 304 | */ |
| 303 | - internal open fun updateFromInfo(info: LivekitModels.ParticipantInfo) { | 305 | + @VisibleForTesting |
| 306 | + open fun updateFromInfo(info: LivekitModels.ParticipantInfo) { | ||
| 304 | sid = Sid(info.sid) | 307 | sid = Sid(info.sid) |
| 305 | identity = Identity(info.identity) | 308 | identity = Identity(info.identity) |
| 306 | participantInfo = info | 309 | participantInfo = info |
| @@ -351,7 +354,11 @@ open class Participant( | @@ -351,7 +354,11 @@ open class Participant( | ||
| 351 | } | 354 | } |
| 352 | } | 355 | } |
| 353 | 356 | ||
| 354 | - internal open fun dispose() { | 357 | + /** |
| 358 | + * @suppress | ||
| 359 | + */ | ||
| 360 | + @VisibleForTesting | ||
| 361 | + open fun dispose() { | ||
| 355 | scope.cancel() | 362 | scope.cancel() |
| 356 | 363 | ||
| 357 | sid = Sid("") | 364 | sid = Sid("") |
| @@ -17,6 +17,7 @@ | @@ -17,6 +17,7 @@ | ||
| 17 | package io.livekit.android.room.track | 17 | package io.livekit.android.room.track |
| 18 | 18 | ||
| 19 | import android.view.View | 19 | import android.view.View |
| 20 | +import androidx.annotation.VisibleForTesting | ||
| 20 | import io.livekit.android.dagger.InjectionNames | 21 | import io.livekit.android.dagger.InjectionNames |
| 21 | import io.livekit.android.events.TrackEvent | 22 | import io.livekit.android.events.TrackEvent |
| 22 | import io.livekit.android.room.track.video.VideoSinkVisibility | 23 | import io.livekit.android.room.track.video.VideoSinkVisibility |
| @@ -41,9 +42,18 @@ class RemoteVideoTrack( | @@ -41,9 +42,18 @@ class RemoteVideoTrack( | ||
| 41 | private val sinkVisibilityMap = mutableMapOf<VideoSink, VideoSinkVisibility>() | 42 | private val sinkVisibilityMap = mutableMapOf<VideoSink, VideoSinkVisibility>() |
| 42 | private val visibilities = sinkVisibilityMap.values | 43 | private val visibilities = sinkVisibilityMap.values |
| 43 | 44 | ||
| 44 | - internal var lastVisibility = false | 45 | + /** |
| 46 | + * @suppress | ||
| 47 | + */ | ||
| 48 | + @VisibleForTesting | ||
| 49 | + var lastVisibility = false | ||
| 45 | private set | 50 | private set |
| 46 | - internal var lastDimensions: Dimensions = Dimensions(0, 0) | 51 | + |
| 52 | + /** | ||
| 53 | + * @suppress | ||
| 54 | + */ | ||
| 55 | + @VisibleForTesting | ||
| 56 | + var lastDimensions: Dimensions = Dimensions(0, 0) | ||
| 47 | private set | 57 | private set |
| 48 | 58 | ||
| 49 | internal var receiver: RtpReceiver | 59 | internal var receiver: RtpReceiver |
| @@ -16,7 +16,10 @@ | @@ -16,7 +16,10 @@ | ||
| 16 | 16 | ||
| 17 | package io.livekit.android.util | 17 | package io.livekit.android.util |
| 18 | 18 | ||
| 19 | -internal sealed class Either<out A, out B> { | 19 | +/** |
| 20 | + * @suppress | ||
| 21 | + */ | ||
| 22 | +sealed class Either<out A, out B> { | ||
| 20 | class Left<out A>(val value: A) : Either<A, Nothing>() | 23 | class Left<out A>(val value: A) : Either<A, Nothing>() |
| 21 | class Right<out B>(val value: B) : Either<Nothing, B>() | 24 | class Right<out B>(val value: B) : Either<Nothing, B>() |
| 22 | } | 25 | } |
| @@ -20,7 +20,7 @@ import com.google.protobuf.MessageLite | @@ -20,7 +20,7 @@ import com.google.protobuf.MessageLite | ||
| 20 | import okio.ByteString | 20 | import okio.ByteString |
| 21 | import okio.ByteString.Companion.toByteString | 21 | import okio.ByteString.Companion.toByteString |
| 22 | 22 | ||
| 23 | -internal fun MessageLite.toOkioByteString(): ByteString { | 23 | +fun MessageLite.toOkioByteString(): ByteString { |
| 24 | val byteArray = toByteArray() | 24 | val byteArray = toByteArray() |
| 25 | return byteArray.toByteString(0, byteArray.size) | 25 | return byteArray.toByteString(0, byteArray.size) |
| 26 | } | 26 | } |
| @@ -20,9 +20,15 @@ import android.gov.nist.javax.sdp.fields.AttributeField | @@ -20,9 +20,15 @@ import android.gov.nist.javax.sdp.fields.AttributeField | ||
| 20 | import android.javax.sdp.MediaDescription | 20 | import android.javax.sdp.MediaDescription |
| 21 | import io.livekit.android.util.LKLog | 21 | import io.livekit.android.util.LKLog |
| 22 | 22 | ||
| 23 | -internal data class SdpRtp(val payload: Long, val codec: String, val rate: Long?, val encoding: String?) | 23 | +/** |
| 24 | + * @suppress | ||
| 25 | + */ | ||
| 26 | +data class SdpRtp(val payload: Long, val codec: String, val rate: Long?, val encoding: String?) | ||
| 24 | 27 | ||
| 25 | -internal fun MediaDescription.getRtps(): List<Pair<AttributeField, SdpRtp>> { | 28 | +/** |
| 29 | + * @suppress | ||
| 30 | + */ | ||
| 31 | +fun MediaDescription.getRtps(): List<Pair<AttributeField, SdpRtp>> { | ||
| 26 | return getAttributes(true) | 32 | return getAttributes(true) |
| 27 | .filterIsInstance<AttributeField>() | 33 | .filterIsInstance<AttributeField>() |
| 28 | .filter { it.attribute.name == "rtpmap" } | 34 | .filter { it.attribute.name == "rtpmap" } |
| @@ -43,17 +49,26 @@ internal fun tryParseRtp(string: String): SdpRtp? { | @@ -43,17 +49,26 @@ internal fun tryParseRtp(string: String): SdpRtp? { | ||
| 43 | return SdpRtp(payload.toLong(), codec, toOptionalLong(rate), toOptionalString(encoding)) | 49 | return SdpRtp(payload.toLong(), codec, toOptionalLong(rate), toOptionalString(encoding)) |
| 44 | } | 50 | } |
| 45 | 51 | ||
| 46 | -internal data class SdpMsid( | 52 | +/** |
| 53 | + * @suppress | ||
| 54 | + */ | ||
| 55 | +data class SdpMsid( | ||
| 47 | /** holds the msid-id (and msid-appdata if available) */ | 56 | /** holds the msid-id (and msid-appdata if available) */ |
| 48 | val value: String, | 57 | val value: String, |
| 49 | ) | 58 | ) |
| 50 | 59 | ||
| 51 | -internal fun MediaDescription.getMsid(): SdpMsid? { | 60 | +/** |
| 61 | + * @suppress | ||
| 62 | + */ | ||
| 63 | +fun MediaDescription.getMsid(): SdpMsid? { | ||
| 52 | val attribute = getAttribute("msid") ?: return null | 64 | val attribute = getAttribute("msid") ?: return null |
| 53 | return SdpMsid(attribute) | 65 | return SdpMsid(attribute) |
| 54 | } | 66 | } |
| 55 | 67 | ||
| 56 | -internal data class SdpFmtp(val payload: Long, val config: String) { | 68 | +/** |
| 69 | + * @suppress | ||
| 70 | + */ | ||
| 71 | +data class SdpFmtp(val payload: Long, val config: String) { | ||
| 57 | fun toAttributeField(): AttributeField { | 72 | fun toAttributeField(): AttributeField { |
| 58 | return AttributeField().apply { | 73 | return AttributeField().apply { |
| 59 | name = "fmtp" | 74 | name = "fmtp" |
| @@ -62,7 +77,10 @@ internal data class SdpFmtp(val payload: Long, val config: String) { | @@ -62,7 +77,10 @@ internal data class SdpFmtp(val payload: Long, val config: String) { | ||
| 62 | } | 77 | } |
| 63 | } | 78 | } |
| 64 | 79 | ||
| 65 | -internal fun MediaDescription.getFmtps(): List<Pair<AttributeField, SdpFmtp>> { | 80 | +/** |
| 81 | + * @suppress | ||
| 82 | + */ | ||
| 83 | +fun MediaDescription.getFmtps(): List<Pair<AttributeField, SdpFmtp>> { | ||
| 66 | return getAttributes(true) | 84 | return getAttributes(true) |
| 67 | .filterIsInstance<AttributeField>() | 85 | .filterIsInstance<AttributeField>() |
| 68 | .filter { it.attribute.name == "fmtp" } | 86 | .filter { it.attribute.name == "fmtp" } |
| @@ -83,7 +101,10 @@ internal fun tryParseFmtp(string: String): SdpFmtp? { | @@ -83,7 +101,10 @@ internal fun tryParseFmtp(string: String): SdpFmtp? { | ||
| 83 | return SdpFmtp(payload.toLong(), config) | 101 | return SdpFmtp(payload.toLong(), config) |
| 84 | } | 102 | } |
| 85 | 103 | ||
| 86 | -internal data class SdpExt(val value: Long, val direction: String?, val encryptUri: String?, val uri: String, val config: String?) { | 104 | +/** |
| 105 | + * @suppress | ||
| 106 | + */ | ||
| 107 | +data class SdpExt(val value: Long, val direction: String?, val encryptUri: String?, val uri: String, val config: String?) { | ||
| 87 | fun toAttributeField(): AttributeField { | 108 | fun toAttributeField(): AttributeField { |
| 88 | return AttributeField().apply { | 109 | return AttributeField().apply { |
| 89 | name = "extmap" | 110 | name = "extmap" |
| @@ -104,7 +125,10 @@ internal data class SdpExt(val value: Long, val direction: String?, val encryptU | @@ -104,7 +125,10 @@ internal data class SdpExt(val value: Long, val direction: String?, val encryptU | ||
| 104 | } | 125 | } |
| 105 | } | 126 | } |
| 106 | 127 | ||
| 107 | -internal fun MediaDescription.getExts(): List<Pair<AttributeField, SdpExt>> { | 128 | +/** |
| 129 | + * @suppress | ||
| 130 | + */ | ||
| 131 | +fun MediaDescription.getExts(): List<Pair<AttributeField, SdpExt>> { | ||
| 108 | return getAttributes(true) | 132 | return getAttributes(true) |
| 109 | .filterIsInstance<AttributeField>() | 133 | .filterIsInstance<AttributeField>() |
| 110 | .filter { it.attribute.name == "extmap" } | 134 | .filter { it.attribute.name == "extmap" } |
| @@ -43,13 +43,13 @@ internal fun PeerConnection.PeerConnectionState.isDisconnected(): Boolean { | @@ -43,13 +43,13 @@ internal fun PeerConnection.PeerConnectionState.isDisconnected(): Boolean { | ||
| 43 | } | 43 | } |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | -internal fun RTCConfiguration.copy(): RTCConfiguration { | 46 | +fun RTCConfiguration.copy(): RTCConfiguration { |
| 47 | val newConfig = RTCConfiguration(emptyList()) | 47 | val newConfig = RTCConfiguration(emptyList()) |
| 48 | newConfig.copyFrom(this) | 48 | newConfig.copyFrom(this) |
| 49 | return newConfig | 49 | return newConfig |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | -internal fun RTCConfiguration.copyFrom(config: RTCConfiguration) { | 52 | +fun RTCConfiguration.copyFrom(config: RTCConfiguration) { |
| 53 | iceTransportsType = config.iceTransportsType | 53 | iceTransportsType = config.iceTransportsType |
| 54 | iceServers = config.iceServers | 54 | iceServers = config.iceServers |
| 55 | bundlePolicy = config.bundlePolicy | 55 | bundlePolicy = config.bundlePolicy |
| @@ -46,8 +46,14 @@ private val threadFactory = object : ThreadFactory { | @@ -46,8 +46,14 @@ private val threadFactory = object : ThreadFactory { | ||
| 46 | private var executor = Executors.newSingleThreadExecutor(threadFactory) | 46 | private var executor = Executors.newSingleThreadExecutor(threadFactory) |
| 47 | private var rtcDispatcher: CoroutineDispatcher = executor.asCoroutineDispatcher() | 47 | private var rtcDispatcher: CoroutineDispatcher = executor.asCoroutineDispatcher() |
| 48 | 48 | ||
| 49 | +/** | ||
| 50 | + * Overrides how RTC thread calls are executed and dispatched. | ||
| 51 | + * | ||
| 52 | + * This should absolutely not be used in production environments and is | ||
| 53 | + * only to be used for testing. | ||
| 54 | + */ | ||
| 49 | @VisibleForTesting | 55 | @VisibleForTesting |
| 50 | -internal fun overrideExecutorAndDispatcher(executorService: ExecutorService, dispatcher: CoroutineDispatcher) { | 56 | +fun overrideExecutorAndDispatcher(executorService: ExecutorService, dispatcher: CoroutineDispatcher) { |
| 51 | executor = executorService | 57 | executor = executorService |
| 52 | rtcDispatcher = dispatcher | 58 | rtcDispatcher = dispatcher |
| 53 | } | 59 | } |
| @@ -56,8 +62,10 @@ internal fun overrideExecutorAndDispatcher(executorService: ExecutorService, dis | @@ -56,8 +62,10 @@ internal fun overrideExecutorAndDispatcher(executorService: ExecutorService, dis | ||
| 56 | * Execute [action] on the RTC thread. The PeerConnection API | 62 | * Execute [action] on the RTC thread. The PeerConnection API |
| 57 | * is generally not thread safe, so all actions relating to | 63 | * is generally not thread safe, so all actions relating to |
| 58 | * peer connection objects should go through the RTC thread. | 64 | * peer connection objects should go through the RTC thread. |
| 65 | + * | ||
| 66 | + * @suppress | ||
| 59 | */ | 67 | */ |
| 60 | -fun <T> executeOnRTCThread(action: () -> T) { | 68 | +internal fun <T> executeOnRTCThread(action: () -> T) { |
| 61 | if (Thread.currentThread().name.startsWith(EXECUTOR_THREADNAME_PREFIX)) { | 69 | if (Thread.currentThread().name.startsWith(EXECUTOR_THREADNAME_PREFIX)) { |
| 62 | action() | 70 | action() |
| 63 | } else { | 71 | } else { |
| @@ -69,8 +77,10 @@ fun <T> executeOnRTCThread(action: () -> T) { | @@ -69,8 +77,10 @@ fun <T> executeOnRTCThread(action: () -> T) { | ||
| 69 | * Execute [action] synchronously on the RTC thread. The PeerConnection API | 77 | * Execute [action] synchronously on the RTC thread. The PeerConnection API |
| 70 | * is generally not thread safe, so all actions relating to | 78 | * is generally not thread safe, so all actions relating to |
| 71 | * peer connection objects should go through the RTC thread. | 79 | * peer connection objects should go through the RTC thread. |
| 80 | + * | ||
| 81 | + * @suppress | ||
| 72 | */ | 82 | */ |
| 73 | -fun <T> executeBlockingOnRTCThread(action: () -> T): T { | 83 | +internal fun <T> executeBlockingOnRTCThread(action: () -> T): T { |
| 74 | return if (Thread.currentThread().name.startsWith(EXECUTOR_THREADNAME_PREFIX)) { | 84 | return if (Thread.currentThread().name.startsWith(EXECUTOR_THREADNAME_PREFIX)) { |
| 75 | action() | 85 | action() |
| 76 | } else { | 86 | } else { |
| @@ -83,7 +93,7 @@ fun <T> executeBlockingOnRTCThread(action: () -> T): T { | @@ -83,7 +93,7 @@ fun <T> executeBlockingOnRTCThread(action: () -> T): T { | ||
| 83 | * is generally not thread safe, so all actions relating to | 93 | * is generally not thread safe, so all actions relating to |
| 84 | * peer connection objects should go through the RTC thread. | 94 | * peer connection objects should go through the RTC thread. |
| 85 | */ | 95 | */ |
| 86 | -suspend fun <T> launchBlockingOnRTCThread(action: suspend CoroutineScope.() -> T): T = coroutineScope { | 96 | +internal suspend fun <T> launchBlockingOnRTCThread(action: suspend CoroutineScope.() -> T): T = coroutineScope { |
| 87 | return@coroutineScope if (Thread.currentThread().name.startsWith(EXECUTOR_THREADNAME_PREFIX)) { | 97 | return@coroutineScope if (Thread.currentThread().name.startsWith(EXECUTOR_THREADNAME_PREFIX)) { |
| 88 | this.action() | 98 | this.action() |
| 89 | } else { | 99 | } else { |
livekit-android-sdk/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
已删除
100644 → 0
| 1 | -mock-maker-inline |
| 1 | -sdk=30 |
livekit-android-test/.gitignore
0 → 100644
| 1 | +/build |
livekit-android-test/build.gradle
0 → 100644
| 1 | +plugins { | ||
| 2 | + id "org.jetbrains.dokka" | ||
| 3 | + id 'com.android.library' | ||
| 4 | + id 'kotlin-android' | ||
| 5 | + id 'kotlin-kapt' | ||
| 6 | +} | ||
| 7 | + | ||
| 8 | +android { | ||
| 9 | + namespace 'io.livekit.android.test' | ||
| 10 | + compileSdkVersion androidSdk.compileVersion | ||
| 11 | + | ||
| 12 | + defaultConfig { | ||
| 13 | + minSdkVersion androidSdk.minVersion | ||
| 14 | + targetSdkVersion androidSdk.targetVersion | ||
| 15 | + | ||
| 16 | + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" | ||
| 17 | + consumerProguardFiles "consumer-rules.pro" | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + lintOptions { | ||
| 21 | + disable 'VisibleForTests' | ||
| 22 | + } | ||
| 23 | + buildTypes { | ||
| 24 | + release { | ||
| 25 | + minifyEnabled false | ||
| 26 | + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' | ||
| 27 | + } | ||
| 28 | + } | ||
| 29 | + compileOptions { | ||
| 30 | + sourceCompatibility java_version | ||
| 31 | + targetCompatibility java_version | ||
| 32 | + } | ||
| 33 | + kotlinOptions { | ||
| 34 | + freeCompilerArgs = ["-Xinline-classes", "-opt-in=kotlin.RequiresOptIn"] | ||
| 35 | + jvmTarget = java_version | ||
| 36 | + } | ||
| 37 | + testOptions { | ||
| 38 | + unitTests { | ||
| 39 | + includeAndroidResources = true | ||
| 40 | + } | ||
| 41 | + } | ||
| 42 | +} | ||
| 43 | + | ||
| 44 | +dokkaHtml { | ||
| 45 | + moduleName.set("livekit-android-test") | ||
| 46 | + dokkaSourceSets { | ||
| 47 | + configureEach { | ||
| 48 | + skipEmptyPackages.set(true) | ||
| 49 | + includeNonPublic.set(false) | ||
| 50 | + includes.from("module.md") | ||
| 51 | + displayName.set("LiveKit Mocks") | ||
| 52 | + sourceLink { | ||
| 53 | + localDirectory.set(file("src/main/java")) | ||
| 54 | + | ||
| 55 | + // URL showing where the source code can be accessed through the web browser | ||
| 56 | + remoteUrl.set(new URL( | ||
| 57 | + "https://github.com/livekit/client-sdk-android/tree/master/livekit-android-test/src/main/java")) | ||
| 58 | + // Suffix which is used to append the line number to the URL. Use #L for GitHub | ||
| 59 | + remoteLineSuffix.set("#L") | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + perPackageOption { | ||
| 63 | + matchingRegex.set(".*\\.dagger.*") | ||
| 64 | + suppress.set(true) | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + perPackageOption { | ||
| 68 | + matchingRegex.set(".*\\.util.*") | ||
| 69 | + suppress.set(true) | ||
| 70 | + } | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | +dependencies { | ||
| 76 | + | ||
| 77 | + implementation(project(":livekit-android-sdk")) | ||
| 78 | + implementation libs.timber | ||
| 79 | + implementation libs.coroutines.lib | ||
| 80 | + implementation libs.kotlinx.serialization.json | ||
| 81 | + api libs.webrtc | ||
| 82 | + api libs.okhttp | ||
| 83 | + api libs.audioswitch | ||
| 84 | + implementation libs.androidx.annotation | ||
| 85 | + api libs.protobuf.javalite | ||
| 86 | + implementation libs.android.jain.sip.ri | ||
| 87 | + implementation libs.junit | ||
| 88 | + implementation libs.robolectric | ||
| 89 | + implementation libs.mockito.core | ||
| 90 | + implementation libs.mockito.kotlin | ||
| 91 | + implementation libs.mockito.inline | ||
| 92 | + implementation libs.androidx.test.core | ||
| 93 | + implementation libs.coroutines.test | ||
| 94 | + implementation libs.dagger.lib | ||
| 95 | + kapt libs.dagger.compiler | ||
| 96 | + | ||
| 97 | + testImplementation libs.junit | ||
| 98 | + testImplementation libs.robolectric | ||
| 99 | + kaptTest libs.dagger.compiler | ||
| 100 | + | ||
| 101 | + androidTestImplementation libs.androidx.test.junit | ||
| 102 | + androidTestImplementation libs.espresso | ||
| 103 | +} | ||
| 104 | +tasks.withType(Test).configureEach { | ||
| 105 | + systemProperty "robolectric.logging.enabled", true | ||
| 106 | +} | ||
| 107 | + | ||
| 108 | +apply from: rootProject.file('gradle/gradle-mvn-push.gradle') | ||
| 109 | + | ||
| 110 | +afterEvaluate { | ||
| 111 | + publishing { | ||
| 112 | + publications { | ||
| 113 | + // Creates a Maven publication called "release". | ||
| 114 | + release(MavenPublication) { | ||
| 115 | + // Applies the component for the release build variant. | ||
| 116 | + from components.release | ||
| 117 | + | ||
| 118 | + // You can then customize attributes of the publication as shown below. | ||
| 119 | + groupId = GROUP | ||
| 120 | + artifactId = POM_ARTIFACT_ID | ||
| 121 | + version = VERSION_NAME | ||
| 122 | + } | ||
| 123 | + } | ||
| 124 | + } | ||
| 125 | +} |
livekit-android-test/consumer-rules.pro
0 → 100644
livekit-android-test/gradle.properties
0 → 100644
livekit-android-test/module.md
0 → 100644
| 1 | + |
livekit-android-test/proguard-rules.pro
0 → 100644
| 1 | +# Add project specific ProGuard rules here. | ||
| 2 | +# You can control the set of applied configuration files using the | ||
| 3 | +# proguardFiles setting in build.gradle. | ||
| 4 | +# | ||
| 5 | +# For more details, see | ||
| 6 | +# http://developer.android.com/guide/developing/tools/proguard.html | ||
| 7 | + | ||
| 8 | +# If your project uses WebView with JS, uncomment the following | ||
| 9 | +# and specify the fully qualified class name to the JavaScript interface | ||
| 10 | +# class: | ||
| 11 | +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||
| 12 | +# public *; | ||
| 13 | +#} | ||
| 14 | + | ||
| 15 | +# Uncomment this to preserve the line number information for | ||
| 16 | +# debugging stack traces. | ||
| 17 | +#-keepattributes SourceFile,LineNumberTable | ||
| 18 | + | ||
| 19 | +# If you keep the line number information, uncomment this to | ||
| 20 | +# hide the original source file name. | ||
| 21 | +#-renamesourcefileattribute SourceFile |
| 1 | /* | 1 | /* |
| 2 | - * Copyright 2023 LiveKit, Inc. | 2 | + * Copyright 2023-2024 LiveKit, Inc. |
| 3 | * | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
| @@ -14,11 +14,11 @@ | @@ -14,11 +14,11 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android | 17 | +package io.livekit.android.test |
| 18 | 18 | ||
| 19 | import com.google.common.util.concurrent.MoreExecutors | 19 | import com.google.common.util.concurrent.MoreExecutors |
| 20 | -import io.livekit.android.coroutines.TestCoroutineRule | ||
| 21 | -import io.livekit.android.util.LoggingRule | 20 | +import io.livekit.android.test.coroutines.TestCoroutineRule |
| 21 | +import io.livekit.android.test.util.LoggingRule | ||
| 22 | import io.livekit.android.webrtc.peerconnection.overrideExecutorAndDispatcher | 22 | import io.livekit.android.webrtc.peerconnection.overrideExecutorAndDispatcher |
| 23 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 23 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 24 | import kotlinx.coroutines.test.TestScope | 24 | import kotlinx.coroutines.test.TestScope |
| @@ -14,18 +14,18 @@ | @@ -14,18 +14,18 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android | 17 | +package io.livekit.android.test |
| 18 | 18 | ||
| 19 | import android.content.Context | 19 | import android.content.Context |
| 20 | import androidx.test.core.app.ApplicationProvider | 20 | import androidx.test.core.app.ApplicationProvider |
| 21 | import com.google.protobuf.MessageLite | 21 | import com.google.protobuf.MessageLite |
| 22 | -import io.livekit.android.mock.MockPeerConnection | ||
| 23 | -import io.livekit.android.mock.MockWebSocketFactory | ||
| 24 | -import io.livekit.android.mock.dagger.DaggerTestLiveKitComponent | ||
| 25 | -import io.livekit.android.mock.dagger.TestCoroutinesModule | ||
| 26 | -import io.livekit.android.mock.dagger.TestLiveKitComponent | ||
| 27 | import io.livekit.android.room.Room | 22 | import io.livekit.android.room.Room |
| 28 | -import io.livekit.android.room.SignalClientTest | 23 | +import io.livekit.android.test.mock.MockPeerConnection |
| 24 | +import io.livekit.android.test.mock.MockWebSocketFactory | ||
| 25 | +import io.livekit.android.test.mock.TestData | ||
| 26 | +import io.livekit.android.test.mock.dagger.DaggerTestLiveKitComponent | ||
| 27 | +import io.livekit.android.test.mock.dagger.TestCoroutinesModule | ||
| 28 | +import io.livekit.android.test.mock.dagger.TestLiveKitComponent | ||
| 29 | import io.livekit.android.util.toOkioByteString | 29 | import io.livekit.android.util.toOkioByteString |
| 30 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 30 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 31 | import kotlinx.coroutines.launch | 31 | import kotlinx.coroutines.launch |
| @@ -44,10 +44,10 @@ import org.robolectric.RobolectricTestRunner | @@ -44,10 +44,10 @@ import org.robolectric.RobolectricTestRunner | ||
| 44 | @RunWith(RobolectricTestRunner::class) | 44 | @RunWith(RobolectricTestRunner::class) |
| 45 | abstract class MockE2ETest : BaseTest() { | 45 | abstract class MockE2ETest : BaseTest() { |
| 46 | 46 | ||
| 47 | - internal lateinit var component: TestLiveKitComponent | ||
| 48 | - internal lateinit var context: Context | ||
| 49 | - internal lateinit var room: Room | ||
| 50 | - internal lateinit var wsFactory: MockWebSocketFactory | 47 | + lateinit var component: TestLiveKitComponent |
| 48 | + lateinit var context: Context | ||
| 49 | + lateinit var room: Room | ||
| 50 | + lateinit var wsFactory: MockWebSocketFactory | ||
| 51 | 51 | ||
| 52 | @Before | 52 | @Before |
| 53 | fun mocksSetup() { | 53 | fun mocksSetup() { |
| @@ -66,7 +66,7 @@ abstract class MockE2ETest : BaseTest() { | @@ -66,7 +66,7 @@ abstract class MockE2ETest : BaseTest() { | ||
| 66 | room.release() | 66 | room.release() |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | - suspend fun connect(joinResponse: LivekitRtc.SignalResponse = SignalClientTest.JOIN) { | 69 | + suspend fun connect(joinResponse: LivekitRtc.SignalResponse = TestData.JOIN) { |
| 70 | connectSignal(joinResponse) | 70 | connectSignal(joinResponse) |
| 71 | connectPeerConnection() | 71 | connectPeerConnection() |
| 72 | } | 72 | } |
| @@ -74,7 +74,7 @@ abstract class MockE2ETest : BaseTest() { | @@ -74,7 +74,7 @@ abstract class MockE2ETest : BaseTest() { | ||
| 74 | suspend fun connectSignal(joinResponse: LivekitRtc.SignalResponse) { | 74 | suspend fun connectSignal(joinResponse: LivekitRtc.SignalResponse) { |
| 75 | val job = coroutineRule.scope.launch { | 75 | val job = coroutineRule.scope.launch { |
| 76 | room.connect( | 76 | room.connect( |
| 77 | - url = SignalClientTest.EXAMPLE_URL, | 77 | + url = TestData.EXAMPLE_URL, |
| 78 | token = "", | 78 | token = "", |
| 79 | ) | 79 | ) |
| 80 | } | 80 | } |
| @@ -84,23 +84,23 @@ abstract class MockE2ETest : BaseTest() { | @@ -84,23 +84,23 @@ abstract class MockE2ETest : BaseTest() { | ||
| 84 | job.join() | 84 | job.join() |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | - suspend fun getSubscriberPeerConnection() = | 87 | + fun getSubscriberPeerConnection() = |
| 88 | component | 88 | component |
| 89 | .rtcEngine() | 89 | .rtcEngine() |
| 90 | .getSubscriberPeerConnection() as MockPeerConnection | 90 | .getSubscriberPeerConnection() as MockPeerConnection |
| 91 | 91 | ||
| 92 | - suspend fun getPublisherPeerConnection() = | 92 | + fun getPublisherPeerConnection() = |
| 93 | component | 93 | component |
| 94 | .rtcEngine() | 94 | .rtcEngine() |
| 95 | .getPublisherPeerConnection() as MockPeerConnection | 95 | .getPublisherPeerConnection() as MockPeerConnection |
| 96 | 96 | ||
| 97 | - suspend fun connectPeerConnection() { | ||
| 98 | - simulateMessageFromServer(SignalClientTest.OFFER) | 97 | + fun connectPeerConnection() { |
| 98 | + simulateMessageFromServer(TestData.OFFER) | ||
| 99 | val subPeerConnection = getSubscriberPeerConnection() | 99 | val subPeerConnection = getSubscriberPeerConnection() |
| 100 | subPeerConnection.moveToIceConnectionState(PeerConnection.IceConnectionState.CONNECTED) | 100 | subPeerConnection.moveToIceConnectionState(PeerConnection.IceConnectionState.CONNECTED) |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | - suspend fun disconnectPeerConnection() { | 103 | + fun disconnectPeerConnection() { |
| 104 | val subPeerConnection = component | 104 | val subPeerConnection = component |
| 105 | .rtcEngine() | 105 | .rtcEngine() |
| 106 | .getSubscriberPeerConnection() as MockPeerConnection | 106 | .getSubscriberPeerConnection() as MockPeerConnection |
| 1 | /* | 1 | /* |
| 2 | - * Copyright 2023 LiveKit, Inc. | 2 | + * Copyright 2023-2024 LiveKit, Inc. |
| 3 | * | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
| @@ -14,12 +14,16 @@ | @@ -14,12 +14,16 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.assert | 17 | +package io.livekit.android.test.assert |
| 18 | 18 | ||
| 19 | import org.junit.Assert | 19 | import org.junit.Assert |
| 20 | 20 | ||
| 21 | -fun assertIsClass(expectedClass: Class<*>, actual: Any) { | ||
| 22 | - val klazz = actual::class.java | 21 | +fun assertIsClass(expectedClass: Class<*>, actual: Any?) { |
| 22 | + val klazz = if (actual == null) { | ||
| 23 | + Nothing::class.java | ||
| 24 | + } else { | ||
| 25 | + actual::class.java | ||
| 26 | + } | ||
| 23 | 27 | ||
| 24 | Assert.assertEquals(expectedClass, klazz) | 28 | Assert.assertEquals(expectedClass, klazz) |
| 25 | } | 29 | } |
| 1 | /* | 1 | /* |
| 2 | - * Copyright 2023 LiveKit, Inc. | 2 | + * Copyright 2023-2024 LiveKit, Inc. |
| 3 | * | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.coroutines | 17 | +package io.livekit.android.test.coroutines |
| 18 | 18 | ||
| 19 | import kotlinx.coroutines.CancellationException | 19 | import kotlinx.coroutines.CancellationException |
| 20 | import kotlinx.coroutines.cancel | 20 | import kotlinx.coroutines.cancel |
| 1 | /* | 1 | /* |
| 2 | - * Copyright 2023 LiveKit, Inc. | 2 | + * Copyright 2023-2024 LiveKit, Inc. |
| 3 | * | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.coroutines | 17 | +package io.livekit.android.test.coroutines |
| 18 | 18 | ||
| 19 | import kotlinx.coroutines.Dispatchers | 19 | import kotlinx.coroutines.Dispatchers |
| 20 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 20 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 1 | /* | 1 | /* |
| 2 | - * Copyright 2023 LiveKit, Inc. | 2 | + * Copyright 2023-2024 LiveKit, Inc. |
| 3 | * | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
| @@ -14,8 +14,10 @@ | @@ -14,8 +14,10 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.events | 17 | +package io.livekit.android.test.events |
| 18 | 18 | ||
| 19 | +import io.livekit.android.events.Event | ||
| 20 | +import io.livekit.android.events.EventListenable | ||
| 19 | import kotlinx.coroutines.CoroutineScope | 21 | import kotlinx.coroutines.CoroutineScope |
| 20 | 22 | ||
| 21 | class EventCollector<T : Event>( | 23 | class EventCollector<T : Event>( |
| 1 | /* | 1 | /* |
| 2 | - * Copyright 2023 LiveKit, Inc. | 2 | + * Copyright 2023-2024 LiveKit, Inc. |
| 3 | * | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
| @@ -14,11 +14,10 @@ | @@ -14,11 +14,10 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.events | 17 | +package io.livekit.android.test.events |
| 18 | 18 | ||
| 19 | -import io.livekit.android.coroutines.toListUntilSignal | 19 | +import io.livekit.android.test.coroutines.toListUntilSignal |
| 20 | import kotlinx.coroutines.CoroutineScope | 20 | import kotlinx.coroutines.CoroutineScope |
| 21 | -import kotlinx.coroutines.ExperimentalCoroutinesApi | ||
| 22 | import kotlinx.coroutines.async | 21 | import kotlinx.coroutines.async |
| 23 | import kotlinx.coroutines.flow.Flow | 22 | import kotlinx.coroutines.flow.Flow |
| 24 | import kotlinx.coroutines.flow.MutableStateFlow | 23 | import kotlinx.coroutines.flow.MutableStateFlow |
| @@ -35,7 +34,6 @@ open class FlowCollector<T>( | @@ -35,7 +34,6 @@ open class FlowCollector<T>( | ||
| 35 | /** | 34 | /** |
| 36 | * Stop collecting events. returns the events collected. | 35 | * Stop collecting events. returns the events collected. |
| 37 | */ | 36 | */ |
| 38 | - @OptIn(ExperimentalCoroutinesApi::class) | ||
| 39 | suspend fun stopCollecting(): List<T> { | 37 | suspend fun stopCollecting(): List<T> { |
| 40 | signal.compareAndSet(null, Unit) | 38 | signal.compareAndSet(null, Unit) |
| 41 | return collectEventsDeferred.await() | 39 | return collectEventsDeferred.await() |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock | 17 | +package io.livekit.android.test.mock |
| 18 | 18 | ||
| 19 | import io.livekit.android.audio.AudioProcessingController | 19 | import io.livekit.android.audio.AudioProcessingController |
| 20 | import io.livekit.android.audio.AudioProcessorInterface | 20 | import io.livekit.android.audio.AudioProcessorInterface |
| @@ -14,13 +14,14 @@ | @@ -14,13 +14,14 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock | 17 | +package io.livekit.android.test.mock |
| 18 | 18 | ||
| 19 | import livekit.org.webrtc.DataChannel | 19 | import livekit.org.webrtc.DataChannel |
| 20 | 20 | ||
| 21 | class MockDataChannel(private val label: String?) : DataChannel(1L) { | 21 | class MockDataChannel(private val label: String?) : DataChannel(1L) { |
| 22 | 22 | ||
| 23 | - var observer: DataChannel.Observer? = null | 23 | + var observer: Observer? = null |
| 24 | + var sentBuffers = mutableListOf<Buffer?>() | ||
| 24 | override fun registerObserver(observer: Observer?) { | 25 | override fun registerObserver(observer: Observer?) { |
| 25 | this.observer = observer | 26 | this.observer = observer |
| 26 | } | 27 | } |
| @@ -46,6 +47,7 @@ class MockDataChannel(private val label: String?) : DataChannel(1L) { | @@ -46,6 +47,7 @@ class MockDataChannel(private val label: String?) : DataChannel(1L) { | ||
| 46 | } | 47 | } |
| 47 | 48 | ||
| 48 | override fun send(buffer: Buffer?): Boolean { | 49 | override fun send(buffer: Buffer?): Boolean { |
| 50 | + sentBuffers.add(buffer) | ||
| 49 | return true | 51 | return true |
| 50 | } | 52 | } |
| 51 | 53 |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock | 17 | +package io.livekit.android.test.mock |
| 18 | 18 | ||
| 19 | import android.graphics.SurfaceTexture | 19 | import android.graphics.SurfaceTexture |
| 20 | import android.view.Surface | 20 | import android.view.Surface |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock | 17 | +package io.livekit.android.test.mock |
| 18 | 18 | ||
| 19 | import io.livekit.android.room.provisions.LKObjects | 19 | import io.livekit.android.room.provisions.LKObjects |
| 20 | 20 |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock | 17 | +package io.livekit.android.test.mock |
| 18 | 18 | ||
| 19 | import livekit.org.webrtc.AudioTrack | 19 | import livekit.org.webrtc.AudioTrack |
| 20 | import livekit.org.webrtc.MediaStream | 20 | import livekit.org.webrtc.MediaStream |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock | 17 | +package io.livekit.android.test.mock |
| 18 | 18 | ||
| 19 | import livekit.org.webrtc.MediaStreamTrack | 19 | import livekit.org.webrtc.MediaStreamTrack |
| 20 | 20 |
| 1 | /* | 1 | /* |
| 2 | - * Copyright 2023 LiveKit, Inc. | 2 | + * Copyright 2024 LiveKit, Inc. |
| 3 | * | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
| @@ -14,25 +14,19 @@ | @@ -14,25 +14,19 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android | 17 | +package io.livekit.android.test.mock |
| 18 | 18 | ||
| 19 | -import androidx.test.ext.junit.runners.AndroidJUnit4 | ||
| 20 | -import androidx.test.platform.app.InstrumentationRegistry | ||
| 21 | -import org.junit.Assert.assertEquals | ||
| 22 | -import org.junit.Test | ||
| 23 | -import org.junit.runner.RunWith | 19 | +import android.net.ConnectivityManager.NetworkCallback |
| 20 | +import android.net.NetworkRequest | ||
| 21 | +import io.livekit.android.room.network.NetworkCallbackRegistry | ||
| 24 | 22 | ||
| 25 | -/** | ||
| 26 | - * Instrumented test, which will execute on an Android device. | ||
| 27 | - * | ||
| 28 | - * See [testing documentation](http://d.android.com/tools/testing). | ||
| 29 | - */ | ||
| 30 | -@RunWith(AndroidJUnit4::class) | ||
| 31 | -class ExampleInstrumentedTest { | ||
| 32 | - @Test | ||
| 33 | - fun useAppContext() { | ||
| 34 | - // Context of the app under test. | ||
| 35 | - val appContext = InstrumentationRegistry.getInstrumentation().targetContext | ||
| 36 | - assertEquals("io.livekit.android.test", appContext.packageName) | 23 | +class MockNetworkCallbackRegistry : NetworkCallbackRegistry { |
| 24 | + val networkCallbacks = mutableSetOf<NetworkCallback>() | ||
| 25 | + override fun registerNetworkCallback(networkRequest: NetworkRequest, networkCallback: NetworkCallback) { | ||
| 26 | + networkCallbacks.add(networkCallback) | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + override fun unregisterNetworkCallback(networkCallback: NetworkCallback) { | ||
| 30 | + networkCallbacks.remove(networkCallback) | ||
| 37 | } | 31 | } |
| 38 | } | 32 | } |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock | 17 | +package io.livekit.android.test.mock |
| 18 | 18 | ||
| 19 | import livekit.org.webrtc.DataChannel | 19 | import livekit.org.webrtc.DataChannel |
| 20 | import livekit.org.webrtc.IceCandidate | 20 | import livekit.org.webrtc.IceCandidate |
| @@ -64,8 +64,13 @@ class MockPeerConnection( | @@ -64,8 +64,13 @@ class MockPeerConnection( | ||
| 64 | return null | 64 | return null |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | + val dataChannels = mutableMapOf<String, DataChannel>() | ||
| 67 | override fun createDataChannel(label: String?, init: DataChannel.Init?): DataChannel { | 68 | override fun createDataChannel(label: String?, init: DataChannel.Init?): DataChannel { |
| 68 | - return MockDataChannel(label) | 69 | + val dataChannel = MockDataChannel(label) |
| 70 | + if (label != null) { | ||
| 71 | + dataChannels[label] = dataChannel | ||
| 72 | + } | ||
| 73 | + return dataChannel | ||
| 69 | } | 74 | } |
| 70 | 75 | ||
| 71 | override fun createOffer(observer: SdpObserver?, constraints: MediaConstraints?) { | 76 | override fun createOffer(observer: SdpObserver?, constraints: MediaConstraints?) { |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock | 17 | +package io.livekit.android.test.mock |
| 18 | 18 | ||
| 19 | import livekit.org.webrtc.RtpReceiver | 19 | import livekit.org.webrtc.RtpReceiver |
| 20 | import org.mockito.Mockito | 20 | import org.mockito.Mockito |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock | 17 | +package io.livekit.android.test.mock |
| 18 | 18 | ||
| 19 | import livekit.org.webrtc.RtpSender | 19 | import livekit.org.webrtc.RtpSender |
| 20 | import org.mockito.Mockito | 20 | import org.mockito.Mockito |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock | 17 | +package io.livekit.android.test.mock |
| 18 | 18 | ||
| 19 | import android.content.Context | 19 | import android.content.Context |
| 20 | import livekit.org.webrtc.CapturerObserver | 20 | import livekit.org.webrtc.CapturerObserver |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock | 17 | +package io.livekit.android.test.mock |
| 18 | 18 | ||
| 19 | import livekit.org.webrtc.VideoSink | 19 | import livekit.org.webrtc.VideoSink |
| 20 | import livekit.org.webrtc.VideoTrack | 20 | import livekit.org.webrtc.VideoTrack |
| 1 | /* | 1 | /* |
| 2 | - * Copyright 2023 LiveKit, Inc. | 2 | + * Copyright 2023-2024 LiveKit, Inc. |
| 3 | * | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock | 17 | +package io.livekit.android.test.mock |
| 18 | 18 | ||
| 19 | import okhttp3.Request | 19 | import okhttp3.Request |
| 20 | import okhttp3.WebSocket | 20 | import okhttp3.WebSocket |
| @@ -14,11 +14,12 @@ | @@ -14,11 +14,12 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock | 17 | +package io.livekit.android.test.mock |
| 18 | 18 | ||
| 19 | import com.google.protobuf.MessageLite | 19 | import com.google.protobuf.MessageLite |
| 20 | +import io.livekit.android.test.util.toOkioByteString | ||
| 21 | +import io.livekit.android.test.util.toPBByteString | ||
| 20 | import io.livekit.android.util.toOkioByteString | 22 | import io.livekit.android.util.toOkioByteString |
| 21 | -import io.livekit.android.util.toPBByteString | ||
| 22 | import livekit.LivekitModels | 23 | import livekit.LivekitModels |
| 23 | import livekit.LivekitRtc.LeaveRequest | 24 | import livekit.LivekitRtc.LeaveRequest |
| 24 | import livekit.LivekitRtc.SignalRequest | 25 | import livekit.LivekitRtc.SignalRequest |
| @@ -14,32 +14,39 @@ | @@ -14,32 +14,39 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock | 17 | +package io.livekit.android.test.mock |
| 18 | 18 | ||
| 19 | import livekit.LivekitModels | 19 | import livekit.LivekitModels |
| 20 | +import livekit.LivekitRtc | ||
| 20 | 21 | ||
| 21 | object TestData { | 22 | object TestData { |
| 22 | 23 | ||
| 24 | + const val EXAMPLE_URL = "ws://www.example.com" | ||
| 25 | + | ||
| 23 | val LOCAL_AUDIO_TRACK = with(LivekitModels.TrackInfo.newBuilder()) { | 26 | val LOCAL_AUDIO_TRACK = with(LivekitModels.TrackInfo.newBuilder()) { |
| 24 | sid = "TR_local_audio_track_sid" | 27 | sid = "TR_local_audio_track_sid" |
| 25 | type = LivekitModels.TrackType.AUDIO | 28 | type = LivekitModels.TrackType.AUDIO |
| 29 | + source = LivekitModels.TrackSource.MICROPHONE | ||
| 26 | build() | 30 | build() |
| 27 | } | 31 | } |
| 28 | val LOCAL_VIDEO_TRACK = with(LivekitModels.TrackInfo.newBuilder()) { | 32 | val LOCAL_VIDEO_TRACK = with(LivekitModels.TrackInfo.newBuilder()) { |
| 29 | sid = "TR_local_video_track_sid" | 33 | sid = "TR_local_video_track_sid" |
| 30 | type = LivekitModels.TrackType.VIDEO | 34 | type = LivekitModels.TrackType.VIDEO |
| 35 | + source = LivekitModels.TrackSource.CAMERA | ||
| 31 | build() | 36 | build() |
| 32 | } | 37 | } |
| 33 | 38 | ||
| 34 | val REMOTE_AUDIO_TRACK = with(LivekitModels.TrackInfo.newBuilder()) { | 39 | val REMOTE_AUDIO_TRACK = with(LivekitModels.TrackInfo.newBuilder()) { |
| 35 | sid = "TR_remote_audio_track_sid" | 40 | sid = "TR_remote_audio_track_sid" |
| 36 | type = LivekitModels.TrackType.AUDIO | 41 | type = LivekitModels.TrackType.AUDIO |
| 42 | + source = LivekitModels.TrackSource.MICROPHONE | ||
| 37 | build() | 43 | build() |
| 38 | } | 44 | } |
| 39 | 45 | ||
| 40 | val REMOTE_VIDEO_TRACK = with(LivekitModels.TrackInfo.newBuilder()) { | 46 | val REMOTE_VIDEO_TRACK = with(LivekitModels.TrackInfo.newBuilder()) { |
| 41 | sid = "TR_remote_video_track_sid" | 47 | sid = "TR_remote_video_track_sid" |
| 42 | type = LivekitModels.TrackType.VIDEO | 48 | type = LivekitModels.TrackType.VIDEO |
| 49 | + source = LivekitModels.TrackSource.CAMERA | ||
| 43 | build() | 50 | build() |
| 44 | } | 51 | } |
| 45 | 52 | ||
| @@ -81,4 +88,218 @@ object TestData { | @@ -81,4 +88,218 @@ object TestData { | ||
| 81 | active = true | 88 | active = true |
| 82 | build() | 89 | build() |
| 83 | } | 90 | } |
| 91 | + | ||
| 92 | + // Signal Responses | ||
| 93 | + // ///////////////////////////////// | ||
| 94 | + | ||
| 95 | + val JOIN = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 96 | + join = with(LivekitRtc.JoinResponse.newBuilder()) { | ||
| 97 | + room = with(LivekitModels.Room.newBuilder()) { | ||
| 98 | + name = "roomname" | ||
| 99 | + build() | ||
| 100 | + } | ||
| 101 | + participant = LOCAL_PARTICIPANT | ||
| 102 | + subscriberPrimary = true | ||
| 103 | + addIceServers( | ||
| 104 | + with(LivekitRtc.ICEServer.newBuilder()) { | ||
| 105 | + addUrls("stun:stun.join.com:19302") | ||
| 106 | + username = "username" | ||
| 107 | + credential = "credential" | ||
| 108 | + build() | ||
| 109 | + }, | ||
| 110 | + ) | ||
| 111 | + serverVersion = "0.15.2" | ||
| 112 | + build() | ||
| 113 | + } | ||
| 114 | + build() | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + val RECONNECT = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 118 | + reconnect = with(LivekitRtc.ReconnectResponse.newBuilder()) { | ||
| 119 | + addIceServers( | ||
| 120 | + with(LivekitRtc.ICEServer.newBuilder()) { | ||
| 121 | + addUrls("stun:stun.reconnect.com:19302") | ||
| 122 | + username = "username" | ||
| 123 | + credential = "credential" | ||
| 124 | + build() | ||
| 125 | + }, | ||
| 126 | + ) | ||
| 127 | + clientConfiguration = with(LivekitModels.ClientConfiguration.newBuilder()) { | ||
| 128 | + forceRelay = LivekitModels.ClientConfigSetting.ENABLED | ||
| 129 | + build() | ||
| 130 | + } | ||
| 131 | + build() | ||
| 132 | + } | ||
| 133 | + build() | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + val OFFER = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 137 | + offer = with(LivekitRtc.SessionDescription.newBuilder()) { | ||
| 138 | + sdp = "remote_offer" | ||
| 139 | + type = "offer" | ||
| 140 | + build() | ||
| 141 | + } | ||
| 142 | + build() | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + val ROOM_UPDATE = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 146 | + roomUpdate = with(LivekitRtc.RoomUpdate.newBuilder()) { | ||
| 147 | + room = with(LivekitModels.Room.newBuilder()) { | ||
| 148 | + sid = "room_sid" | ||
| 149 | + metadata = "metadata" | ||
| 150 | + activeRecording = true | ||
| 151 | + build() | ||
| 152 | + } | ||
| 153 | + build() | ||
| 154 | + } | ||
| 155 | + build() | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + val LOCAL_TRACK_PUBLISHED = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 159 | + trackPublished = with(LivekitRtc.TrackPublishedResponse.newBuilder()) { | ||
| 160 | + cid = "local_cid" | ||
| 161 | + track = LOCAL_AUDIO_TRACK | ||
| 162 | + build() | ||
| 163 | + } | ||
| 164 | + build() | ||
| 165 | + } | ||
| 166 | + | ||
| 167 | + val LOCAL_TRACK_UNPUBLISHED = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 168 | + trackUnpublished = with(LivekitRtc.TrackUnpublishedResponse.newBuilder()) { | ||
| 169 | + trackSid = LOCAL_AUDIO_TRACK.sid | ||
| 170 | + build() | ||
| 171 | + } | ||
| 172 | + build() | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + val PERMISSION_CHANGE = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 176 | + update = with(LivekitRtc.ParticipantUpdate.newBuilder()) { | ||
| 177 | + addParticipants( | ||
| 178 | + LOCAL_PARTICIPANT.toBuilder() | ||
| 179 | + .setPermission( | ||
| 180 | + LivekitModels.ParticipantPermission.newBuilder() | ||
| 181 | + .setCanPublish(false) | ||
| 182 | + .setCanSubscribe(false) | ||
| 183 | + .setCanPublishData(false) | ||
| 184 | + .setHidden(false) | ||
| 185 | + .setRecorder(false) | ||
| 186 | + .build(), | ||
| 187 | + ) | ||
| 188 | + .build(), | ||
| 189 | + ) | ||
| 190 | + build() | ||
| 191 | + } | ||
| 192 | + build() | ||
| 193 | + } | ||
| 194 | + | ||
| 195 | + val PARTICIPANT_JOIN = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 196 | + update = with(LivekitRtc.ParticipantUpdate.newBuilder()) { | ||
| 197 | + addParticipants(REMOTE_PARTICIPANT) | ||
| 198 | + build() | ||
| 199 | + } | ||
| 200 | + build() | ||
| 201 | + } | ||
| 202 | + | ||
| 203 | + val PARTICIPANT_DISCONNECT = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 204 | + update = with(LivekitRtc.ParticipantUpdate.newBuilder()) { | ||
| 205 | + val disconnectedParticipant = REMOTE_PARTICIPANT.toBuilder() | ||
| 206 | + .setState(LivekitModels.ParticipantInfo.State.DISCONNECTED) | ||
| 207 | + .build() | ||
| 208 | + | ||
| 209 | + addParticipants(disconnectedParticipant) | ||
| 210 | + build() | ||
| 211 | + } | ||
| 212 | + build() | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + val ACTIVE_SPEAKER_UPDATE = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 216 | + speakersChanged = with(LivekitRtc.SpeakersChanged.newBuilder()) { | ||
| 217 | + addSpeakers(REMOTE_SPEAKER_INFO) | ||
| 218 | + build() | ||
| 219 | + } | ||
| 220 | + build() | ||
| 221 | + } | ||
| 222 | + | ||
| 223 | + val LOCAL_PARTICIPANT_METADATA_CHANGED = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 224 | + update = with(LivekitRtc.ParticipantUpdate.newBuilder()) { | ||
| 225 | + val participantMetadataChanged = LOCAL_PARTICIPANT.toBuilder() | ||
| 226 | + .setMetadata("changed_metadata") | ||
| 227 | + .setName("changed_name") | ||
| 228 | + .build() | ||
| 229 | + | ||
| 230 | + addParticipants(participantMetadataChanged) | ||
| 231 | + build() | ||
| 232 | + } | ||
| 233 | + build() | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + val REMOTE_PARTICIPANT_METADATA_CHANGED = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 237 | + update = with(LivekitRtc.ParticipantUpdate.newBuilder()) { | ||
| 238 | + val participantMetadataChanged = REMOTE_PARTICIPANT.toBuilder() | ||
| 239 | + .setMetadata("changed_metadata") | ||
| 240 | + .setName("changed_name") | ||
| 241 | + .build() | ||
| 242 | + | ||
| 243 | + addParticipants(participantMetadataChanged) | ||
| 244 | + build() | ||
| 245 | + } | ||
| 246 | + build() | ||
| 247 | + } | ||
| 248 | + | ||
| 249 | + val CONNECTION_QUALITY = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 250 | + connectionQuality = with(LivekitRtc.ConnectionQualityUpdate.newBuilder()) { | ||
| 251 | + addUpdates( | ||
| 252 | + with(LivekitRtc.ConnectionQualityInfo.newBuilder()) { | ||
| 253 | + participantSid = JOIN.join.participant.sid | ||
| 254 | + quality = LivekitModels.ConnectionQuality.EXCELLENT | ||
| 255 | + build() | ||
| 256 | + }, | ||
| 257 | + ) | ||
| 258 | + build() | ||
| 259 | + } | ||
| 260 | + build() | ||
| 261 | + } | ||
| 262 | + | ||
| 263 | + val STREAM_STATE_UPDATE = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 264 | + streamStateUpdate = with(LivekitRtc.StreamStateUpdate.newBuilder()) { | ||
| 265 | + addStreamStates( | ||
| 266 | + with(LivekitRtc.StreamStateInfo.newBuilder()) { | ||
| 267 | + participantSid = REMOTE_PARTICIPANT.sid | ||
| 268 | + trackSid = REMOTE_AUDIO_TRACK.sid | ||
| 269 | + state = LivekitRtc.StreamState.ACTIVE | ||
| 270 | + build() | ||
| 271 | + }, | ||
| 272 | + ) | ||
| 273 | + build() | ||
| 274 | + } | ||
| 275 | + build() | ||
| 276 | + } | ||
| 277 | + | ||
| 278 | + val SUBSCRIPTION_PERMISSION_UPDATE = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 279 | + subscriptionPermissionUpdate = with(LivekitRtc.SubscriptionPermissionUpdate.newBuilder()) { | ||
| 280 | + participantSid = REMOTE_PARTICIPANT.sid | ||
| 281 | + trackSid = REMOTE_AUDIO_TRACK.sid | ||
| 282 | + allowed = false | ||
| 283 | + build() | ||
| 284 | + } | ||
| 285 | + build() | ||
| 286 | + } | ||
| 287 | + | ||
| 288 | + val REFRESH_TOKEN = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 289 | + refreshToken = "refresh_token" | ||
| 290 | + build() | ||
| 291 | + } | ||
| 292 | + | ||
| 293 | + val PONG = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 294 | + pong = 1L | ||
| 295 | + build() | ||
| 296 | + } | ||
| 297 | + | ||
| 298 | + val LEAVE = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 299 | + leave = with(LivekitRtc.LeaveRequest.newBuilder()) { | ||
| 300 | + reason = LivekitModels.DisconnectReason.SERVER_SHUTDOWN | ||
| 301 | + build() | ||
| 302 | + } | ||
| 303 | + build() | ||
| 304 | + } | ||
| 84 | } | 305 | } |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock.dagger | 17 | +package io.livekit.android.test.mock.dagger |
| 18 | 18 | ||
| 19 | import dagger.Binds | 19 | import dagger.Binds |
| 20 | import dagger.Module | 20 | import dagger.Module |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock.dagger | 17 | +package io.livekit.android.test.mock.dagger |
| 18 | 18 | ||
| 19 | import dagger.Module | 19 | import dagger.Module |
| 20 | import dagger.Provides | 20 | import dagger.Provides |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock.dagger | 17 | +package io.livekit.android.test.mock.dagger |
| 18 | 18 | ||
| 19 | import android.content.Context | 19 | import android.content.Context |
| 20 | import dagger.BindsInstance | 20 | import dagger.BindsInstance |
| @@ -22,8 +22,9 @@ import dagger.Component | @@ -22,8 +22,9 @@ import dagger.Component | ||
| 22 | import io.livekit.android.dagger.JsonFormatModule | 22 | import io.livekit.android.dagger.JsonFormatModule |
| 23 | import io.livekit.android.dagger.LiveKitComponent | 23 | import io.livekit.android.dagger.LiveKitComponent |
| 24 | import io.livekit.android.dagger.MemoryModule | 24 | import io.livekit.android.dagger.MemoryModule |
| 25 | -import io.livekit.android.mock.MockWebSocketFactory | ||
| 26 | import io.livekit.android.room.RTCEngine | 25 | import io.livekit.android.room.RTCEngine |
| 26 | +import io.livekit.android.test.mock.MockNetworkCallbackRegistry | ||
| 27 | +import io.livekit.android.test.mock.MockWebSocketFactory | ||
| 27 | import javax.inject.Singleton | 28 | import javax.inject.Singleton |
| 28 | 29 | ||
| 29 | @Singleton | 30 | @Singleton |
| @@ -37,12 +38,14 @@ import javax.inject.Singleton | @@ -37,12 +38,14 @@ import javax.inject.Singleton | ||
| 37 | MemoryModule::class, | 38 | MemoryModule::class, |
| 38 | ], | 39 | ], |
| 39 | ) | 40 | ) |
| 40 | -internal interface TestLiveKitComponent : LiveKitComponent { | 41 | +interface TestLiveKitComponent : LiveKitComponent { |
| 41 | 42 | ||
| 42 | fun websocketFactory(): MockWebSocketFactory | 43 | fun websocketFactory(): MockWebSocketFactory |
| 43 | 44 | ||
| 44 | fun rtcEngine(): RTCEngine | 45 | fun rtcEngine(): RTCEngine |
| 45 | 46 | ||
| 47 | + fun networkCallbackRegistry(): MockNetworkCallbackRegistry | ||
| 48 | + | ||
| 46 | @Component.Factory | 49 | @Component.Factory |
| 47 | interface Factory { | 50 | interface Factory { |
| 48 | fun create( | 51 | fun create( |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock.dagger | 17 | +package io.livekit.android.test.mock.dagger |
| 18 | 18 | ||
| 19 | import android.content.Context | 19 | import android.content.Context |
| 20 | import android.javax.sdp.SdpFactory | 20 | import android.javax.sdp.SdpFactory |
| @@ -23,8 +23,8 @@ import dagger.Provides | @@ -23,8 +23,8 @@ import dagger.Provides | ||
| 23 | import io.livekit.android.audio.AudioProcessingController | 23 | import io.livekit.android.audio.AudioProcessingController |
| 24 | import io.livekit.android.dagger.CapabilitiesGetter | 24 | import io.livekit.android.dagger.CapabilitiesGetter |
| 25 | import io.livekit.android.dagger.InjectionNames | 25 | import io.livekit.android.dagger.InjectionNames |
| 26 | -import io.livekit.android.mock.MockAudioProcessingController | ||
| 27 | -import io.livekit.android.mock.MockEglBase | 26 | +import io.livekit.android.test.mock.MockAudioProcessingController |
| 27 | +import io.livekit.android.test.mock.MockEglBase | ||
| 28 | import livekit.org.webrtc.* | 28 | import livekit.org.webrtc.* |
| 29 | import javax.inject.Named | 29 | import javax.inject.Named |
| 30 | import javax.inject.Singleton | 30 | import javax.inject.Singleton |
| 1 | /* | 1 | /* |
| 2 | - * Copyright 2023 LiveKit, Inc. | 2 | + * Copyright 2023-2024 LiveKit, Inc. |
| 3 | * | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
| @@ -14,14 +14,19 @@ | @@ -14,14 +14,19 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.mock.dagger | 17 | +package io.livekit.android.test.mock.dagger |
| 18 | 18 | ||
| 19 | +import android.net.ConnectivityManager | ||
| 19 | import dagger.Module | 20 | import dagger.Module |
| 20 | import dagger.Provides | 21 | import dagger.Provides |
| 21 | import dagger.Reusable | 22 | import dagger.Reusable |
| 22 | -import io.livekit.android.mock.MockWebSocketFactory | 23 | +import io.livekit.android.memory.CloseableManager |
| 24 | +import io.livekit.android.room.network.NetworkCallbackManagerFactory | ||
| 25 | +import io.livekit.android.room.network.NetworkCallbackManagerImpl | ||
| 23 | import io.livekit.android.stats.NetworkInfo | 26 | import io.livekit.android.stats.NetworkInfo |
| 24 | import io.livekit.android.stats.NetworkType | 27 | import io.livekit.android.stats.NetworkType |
| 28 | +import io.livekit.android.test.mock.MockNetworkCallbackRegistry | ||
| 29 | +import io.livekit.android.test.mock.MockWebSocketFactory | ||
| 25 | import okhttp3.OkHttpClient | 30 | import okhttp3.OkHttpClient |
| 26 | import okhttp3.Response | 31 | import okhttp3.Response |
| 27 | import okhttp3.WebSocket | 32 | import okhttp3.WebSocket |
| @@ -62,4 +67,22 @@ object TestWebModule { | @@ -62,4 +67,22 @@ object TestWebModule { | ||
| 62 | override fun getNetworkType() = NetworkType.WIFI | 67 | override fun getNetworkType() = NetworkType.WIFI |
| 63 | } | 68 | } |
| 64 | } | 69 | } |
| 70 | + | ||
| 71 | + @Provides | ||
| 72 | + @Singleton | ||
| 73 | + fun networkCallbackRegistrar(): MockNetworkCallbackRegistry { | ||
| 74 | + return MockNetworkCallbackRegistry() | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + @Provides | ||
| 78 | + @Reusable | ||
| 79 | + fun networkCallbackManagerFactory( | ||
| 80 | + closeableManager: CloseableManager, | ||
| 81 | + registrar: MockNetworkCallbackRegistry, | ||
| 82 | + ): NetworkCallbackManagerFactory { | ||
| 83 | + return { networkCallback: ConnectivityManager.NetworkCallback -> | ||
| 84 | + NetworkCallbackManagerImpl(networkCallback, registrar) | ||
| 85 | + .apply { closeableManager.registerClosable(this) } | ||
| 86 | + } | ||
| 87 | + } | ||
| 65 | } | 88 | } |
| 1 | /* | 1 | /* |
| 2 | - * Copyright 2023 LiveKit, Inc. | 2 | + * Copyright 2023-2024 LiveKit, Inc. |
| 3 | * | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.util | 17 | +package io.livekit.android.test.util |
| 18 | 18 | ||
| 19 | import com.google.protobuf.ByteString | 19 | import com.google.protobuf.ByteString |
| 20 | import okio.ByteString.Companion.toByteString | 20 | import okio.ByteString.Companion.toByteString |
| 1 | /* | 1 | /* |
| 2 | - * Copyright 2023 LiveKit, Inc. | 2 | + * Copyright 2023-2024 LiveKit, Inc. |
| 3 | * | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
| @@ -14,10 +14,11 @@ | @@ -14,10 +14,11 @@ | ||
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package io.livekit.android.util | 17 | +package io.livekit.android.test.util |
| 18 | 18 | ||
| 19 | import android.util.Log | 19 | import android.util.Log |
| 20 | import io.livekit.android.LiveKit | 20 | import io.livekit.android.LiveKit |
| 21 | +import io.livekit.android.util.LoggingLevel | ||
| 21 | import org.junit.rules.TestRule | 22 | import org.junit.rules.TestRule |
| 22 | import org.junit.runner.Description | 23 | import org.junit.runner.Description |
| 23 | import org.junit.runners.model.Statement | 24 | import org.junit.runners.model.Statement |
| @@ -16,9 +16,9 @@ | @@ -16,9 +16,9 @@ | ||
| 16 | 16 | ||
| 17 | package livekit.org.webrtc | 17 | package livekit.org.webrtc |
| 18 | 18 | ||
| 19 | -import io.livekit.android.mock.MockPeerConnection | ||
| 20 | -import io.livekit.android.mock.MockVideoSource | ||
| 21 | -import io.livekit.android.mock.MockVideoStreamTrack | 19 | +import io.livekit.android.test.mock.MockPeerConnection |
| 20 | +import io.livekit.android.test.mock.MockVideoSource | ||
| 21 | +import io.livekit.android.test.mock.MockVideoStreamTrack | ||
| 22 | 22 | ||
| 23 | class MockPeerConnectionFactory : PeerConnectionFactory(1L) { | 23 | class MockPeerConnectionFactory : PeerConnectionFactory(1L) { |
| 24 | override fun createPeerConnectionInternal( | 24 | override fun createPeerConnectionInternal( |
| @@ -16,8 +16,8 @@ | @@ -16,8 +16,8 @@ | ||
| 16 | 16 | ||
| 17 | package livekit.org.webrtc | 17 | package livekit.org.webrtc |
| 18 | 18 | ||
| 19 | -import io.livekit.android.mock.MockRtpReceiver | ||
| 20 | -import io.livekit.android.mock.MockRtpSender | 19 | +import io.livekit.android.test.mock.MockRtpReceiver |
| 20 | +import io.livekit.android.test.mock.MockRtpSender | ||
| 21 | import livekit.org.webrtc.RtpTransceiver.RtpTransceiverDirection | 21 | import livekit.org.webrtc.RtpTransceiver.RtpTransceiverDirection |
| 22 | import org.mockito.Mockito | 22 | import org.mockito.Mockito |
| 23 | 23 |
| @@ -16,9 +16,11 @@ | @@ -16,9 +16,11 @@ | ||
| 16 | 16 | ||
| 17 | package io.livekit.android.room | 17 | package io.livekit.android.room |
| 18 | 18 | ||
| 19 | -import io.livekit.android.MockE2ETest | 19 | +import io.livekit.android.test.MockE2ETest |
| 20 | +import io.livekit.android.test.mock.TestData | ||
| 21 | +import io.livekit.android.test.util.toOkioByteString | ||
| 22 | +import io.livekit.android.test.util.toPBByteString | ||
| 20 | import io.livekit.android.util.toOkioByteString | 23 | import io.livekit.android.util.toOkioByteString |
| 21 | -import io.livekit.android.util.toPBByteString | ||
| 22 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 24 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 23 | import livekit.LivekitModels | 25 | import livekit.LivekitModels |
| 24 | import livekit.LivekitRtc | 26 | import livekit.LivekitRtc |
| @@ -44,7 +46,7 @@ class RTCEngineMockE2ETest : MockE2ETest() { | @@ -44,7 +46,7 @@ class RTCEngineMockE2ETest : MockE2ETest() { | ||
| 44 | @Test | 46 | @Test |
| 45 | fun iceServersSetOnJoin() = runTest { | 47 | fun iceServersSetOnJoin() = runTest { |
| 46 | connect() | 48 | connect() |
| 47 | - val sentIceServers = SignalClientTest.JOIN.join.iceServersList | 49 | + val sentIceServers = TestData.JOIN.join.iceServersList |
| 48 | .map { it.toWebrtc() } | 50 | .map { it.toWebrtc() } |
| 49 | val subPeerConnection = getSubscriberPeerConnection() | 51 | val subPeerConnection = getSubscriberPeerConnection() |
| 50 | 52 | ||
| @@ -55,7 +57,7 @@ class RTCEngineMockE2ETest : MockE2ETest() { | @@ -55,7 +57,7 @@ class RTCEngineMockE2ETest : MockE2ETest() { | ||
| 55 | fun iceSubscriberConnect() = runTest { | 57 | fun iceSubscriberConnect() = runTest { |
| 56 | connect() | 58 | connect() |
| 57 | assertEquals( | 59 | assertEquals( |
| 58 | - SignalClientTest.OFFER.offer.sdp, | 60 | + TestData.OFFER.offer.sdp, |
| 59 | getSubscriberPeerConnection().remoteDescription?.description, | 61 | getSubscriberPeerConnection().remoteDescription?.description, |
| 60 | ) | 62 | ) |
| 61 | 63 | ||
| @@ -113,19 +115,19 @@ class RTCEngineMockE2ETest : MockE2ETest() { | @@ -113,19 +115,19 @@ class RTCEngineMockE2ETest : MockE2ETest() { | ||
| 113 | connect() | 115 | connect() |
| 114 | 116 | ||
| 115 | val oldToken = wsFactory.request.url.queryParameter(SignalClient.CONNECT_QUERY_TOKEN) | 117 | val oldToken = wsFactory.request.url.queryParameter(SignalClient.CONNECT_QUERY_TOKEN) |
| 116 | - wsFactory.listener.onMessage(wsFactory.ws, SignalClientTest.REFRESH_TOKEN.toOkioByteString()) | 118 | + wsFactory.listener.onMessage(wsFactory.ws, TestData.REFRESH_TOKEN.toOkioByteString()) |
| 117 | wsFactory.listener.onFailure(wsFactory.ws, Exception(), null) | 119 | wsFactory.listener.onFailure(wsFactory.ws, Exception(), null) |
| 118 | 120 | ||
| 119 | testScheduler.advanceUntilIdle() | 121 | testScheduler.advanceUntilIdle() |
| 120 | val newToken = wsFactory.request.url.queryParameter(SignalClient.CONNECT_QUERY_TOKEN) | 122 | val newToken = wsFactory.request.url.queryParameter(SignalClient.CONNECT_QUERY_TOKEN) |
| 121 | Assert.assertNotEquals(oldToken, newToken) | 123 | Assert.assertNotEquals(oldToken, newToken) |
| 122 | - assertEquals(SignalClientTest.REFRESH_TOKEN.refreshToken, newToken) | 124 | + assertEquals(TestData.REFRESH_TOKEN.refreshToken, newToken) |
| 123 | } | 125 | } |
| 124 | 126 | ||
| 125 | @Test | 127 | @Test |
| 126 | fun relayConfiguration() = runTest { | 128 | fun relayConfiguration() = runTest { |
| 127 | connect( | 129 | connect( |
| 128 | - with(SignalClientTest.JOIN.toBuilder()) { | 130 | + with(TestData.JOIN.toBuilder()) { |
| 129 | join = with(join.toBuilder()) { | 131 | join = with(join.toBuilder()) { |
| 130 | clientConfiguration = with(LivekitModels.ClientConfiguration.newBuilder()) { | 132 | clientConfiguration = with(LivekitModels.ClientConfiguration.newBuilder()) { |
| 131 | forceRelay = LivekitModels.ClientConfigSetting.ENABLED | 133 | forceRelay = LivekitModels.ClientConfigSetting.ENABLED |
| @@ -147,6 +149,6 @@ class RTCEngineMockE2ETest : MockE2ETest() { | @@ -147,6 +149,6 @@ class RTCEngineMockE2ETest : MockE2ETest() { | ||
| 147 | 149 | ||
| 148 | testScheduler.advanceUntilIdle() | 150 | testScheduler.advanceUntilIdle() |
| 149 | val sid = wsFactory.request.url.queryParameter(SignalClient.CONNECT_QUERY_PARTICIPANT_SID) | 151 | val sid = wsFactory.request.url.queryParameter(SignalClient.CONNECT_QUERY_PARTICIPANT_SID) |
| 150 | - assertEquals(SignalClientTest.JOIN.join.participant.sid, sid) | 152 | + assertEquals(TestData.JOIN.join.participant.sid, sid) |
| 151 | } | 153 | } |
| 152 | } | 154 | } |
| 1 | /* | 1 | /* |
| 2 | - * Copyright 2023 LiveKit, Inc. | 2 | + * Copyright 2023-2024 LiveKit, Inc. |
| 3 | * | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
| @@ -17,12 +17,12 @@ | @@ -17,12 +17,12 @@ | ||
| 17 | package io.livekit.android.room | 17 | package io.livekit.android.room |
| 18 | 18 | ||
| 19 | import com.google.protobuf.ByteString | 19 | import com.google.protobuf.ByteString |
| 20 | -import io.livekit.android.MockE2ETest | ||
| 21 | -import io.livekit.android.assert.assertIsClass | ||
| 22 | -import io.livekit.android.events.EventCollector | ||
| 23 | import io.livekit.android.events.RoomEvent | 20 | import io.livekit.android.events.RoomEvent |
| 24 | -import io.livekit.android.mock.MockDataChannel | ||
| 25 | -import io.livekit.android.mock.MockPeerConnection | 21 | +import io.livekit.android.test.MockE2ETest |
| 22 | +import io.livekit.android.test.assert.assertIsClass | ||
| 23 | +import io.livekit.android.test.events.EventCollector | ||
| 24 | +import io.livekit.android.test.mock.MockDataChannel | ||
| 25 | +import io.livekit.android.test.mock.MockPeerConnection | ||
| 26 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 26 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 27 | import livekit.LivekitModels.DataPacket | 27 | import livekit.LivekitModels.DataPacket |
| 28 | import livekit.LivekitModels.UserPacket | 28 | import livekit.LivekitModels.UserPacket |
| @@ -16,21 +16,20 @@ | @@ -16,21 +16,20 @@ | ||
| 16 | 16 | ||
| 17 | package io.livekit.android.room | 17 | package io.livekit.android.room |
| 18 | 18 | ||
| 19 | -import android.content.Context | ||
| 20 | -import android.net.ConnectivityManager | ||
| 21 | import android.net.Network | 19 | import android.net.Network |
| 22 | -import androidx.test.platform.app.InstrumentationRegistry | ||
| 23 | -import io.livekit.android.MockE2ETest | ||
| 24 | -import io.livekit.android.assert.assertIsClassList | ||
| 25 | import io.livekit.android.events.* | 20 | import io.livekit.android.events.* |
| 26 | -import io.livekit.android.mock.MockAudioStreamTrack | ||
| 27 | -import io.livekit.android.mock.MockMediaStream | ||
| 28 | -import io.livekit.android.mock.MockRtpReceiver | ||
| 29 | -import io.livekit.android.mock.TestData | ||
| 30 | -import io.livekit.android.mock.createMediaStreamId | ||
| 31 | import io.livekit.android.room.participant.ConnectionQuality | 21 | import io.livekit.android.room.participant.ConnectionQuality |
| 32 | import io.livekit.android.room.track.LocalAudioTrack | 22 | import io.livekit.android.room.track.LocalAudioTrack |
| 33 | import io.livekit.android.room.track.Track | 23 | import io.livekit.android.room.track.Track |
| 24 | +import io.livekit.android.test.MockE2ETest | ||
| 25 | +import io.livekit.android.test.assert.assertIsClassList | ||
| 26 | +import io.livekit.android.test.events.EventCollector | ||
| 27 | +import io.livekit.android.test.events.FlowCollector | ||
| 28 | +import io.livekit.android.test.mock.MockAudioStreamTrack | ||
| 29 | +import io.livekit.android.test.mock.MockMediaStream | ||
| 30 | +import io.livekit.android.test.mock.MockRtpReceiver | ||
| 31 | +import io.livekit.android.test.mock.TestData | ||
| 32 | +import io.livekit.android.test.mock.createMediaStreamId | ||
| 34 | import io.livekit.android.util.flow | 33 | import io.livekit.android.util.flow |
| 35 | import io.livekit.android.util.toOkioByteString | 34 | import io.livekit.android.util.toOkioByteString |
| 36 | import junit.framework.Assert.assertEquals | 35 | import junit.framework.Assert.assertEquals |
| @@ -45,8 +44,6 @@ import org.junit.Test | @@ -45,8 +44,6 @@ import org.junit.Test | ||
| 45 | import org.junit.runner.RunWith | 44 | import org.junit.runner.RunWith |
| 46 | import org.mockito.Mockito | 45 | import org.mockito.Mockito |
| 47 | import org.robolectric.RobolectricTestRunner | 46 | import org.robolectric.RobolectricTestRunner |
| 48 | -import org.robolectric.Shadows.shadowOf | ||
| 49 | -import org.robolectric.shadows.ShadowConnectivityManager | ||
| 50 | 47 | ||
| 51 | @ExperimentalCoroutinesApi | 48 | @ExperimentalCoroutinesApi |
| 52 | @RunWith(RobolectricTestRunner::class) | 49 | @RunWith(RobolectricTestRunner::class) |
| @@ -79,8 +76,8 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -79,8 +76,8 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 79 | 76 | ||
| 80 | @Test | 77 | @Test |
| 81 | fun connectNoEventsWithRemoteParticipant() = runTest { | 78 | fun connectNoEventsWithRemoteParticipant() = runTest { |
| 82 | - val joinResponse = with(SignalClientTest.JOIN.toBuilder()) { | ||
| 83 | - join = with(SignalClientTest.JOIN.join.toBuilder()) { | 79 | + val joinResponse = with(TestData.JOIN.toBuilder()) { |
| 80 | + join = with(TestData.JOIN.join.toBuilder()) { | ||
| 84 | addOtherParticipants(TestData.REMOTE_PARTICIPANT) | 81 | addOtherParticipants(TestData.REMOTE_PARTICIPANT) |
| 85 | build() | 82 | build() |
| 86 | } | 83 | } |
| @@ -104,7 +101,7 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -104,7 +101,7 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 104 | val job = coroutineRule.scope.launch { | 101 | val job = coroutineRule.scope.launch { |
| 105 | try { | 102 | try { |
| 106 | room.connect( | 103 | room.connect( |
| 107 | - url = SignalClientTest.EXAMPLE_URL, | 104 | + url = TestData.EXAMPLE_URL, |
| 108 | token = "", | 105 | token = "", |
| 109 | ) | 106 | ) |
| 110 | } catch (e: Throwable) { | 107 | } catch (e: Throwable) { |
| @@ -123,8 +120,8 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -123,8 +120,8 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 123 | fun roomUpdateTest() = runTest { | 120 | fun roomUpdateTest() = runTest { |
| 124 | connect() | 121 | connect() |
| 125 | val eventCollector = EventCollector(room.events, coroutineRule.scope) | 122 | val eventCollector = EventCollector(room.events, coroutineRule.scope) |
| 126 | - val roomUpdate = SignalClientTest.ROOM_UPDATE | ||
| 127 | - wsFactory.listener.onMessage(wsFactory.ws, SignalClientTest.ROOM_UPDATE.toOkioByteString()) | 123 | + val roomUpdate = TestData.ROOM_UPDATE |
| 124 | + wsFactory.listener.onMessage(wsFactory.ws, TestData.ROOM_UPDATE.toOkioByteString()) | ||
| 128 | val events = eventCollector.stopCollecting() | 125 | val events = eventCollector.stopCollecting() |
| 129 | 126 | ||
| 130 | assertEquals( | 127 | assertEquals( |
| @@ -150,7 +147,7 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -150,7 +147,7 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 150 | val eventCollector = EventCollector(room.events, coroutineRule.scope) | 147 | val eventCollector = EventCollector(room.events, coroutineRule.scope) |
| 151 | wsFactory.listener.onMessage( | 148 | wsFactory.listener.onMessage( |
| 152 | wsFactory.ws, | 149 | wsFactory.ws, |
| 153 | - SignalClientTest.CONNECTION_QUALITY.toOkioByteString(), | 150 | + TestData.CONNECTION_QUALITY.toOkioByteString(), |
| 154 | ) | 151 | ) |
| 155 | val events = eventCollector.stopCollecting() | 152 | val events = eventCollector.stopCollecting() |
| 156 | 153 | ||
| @@ -164,7 +161,7 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -164,7 +161,7 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 164 | connect() | 161 | connect() |
| 165 | 162 | ||
| 166 | val eventCollector = EventCollector(room.events, coroutineRule.scope) | 163 | val eventCollector = EventCollector(room.events, coroutineRule.scope) |
| 167 | - simulateMessageFromServer(SignalClientTest.PARTICIPANT_JOIN) | 164 | + simulateMessageFromServer(TestData.PARTICIPANT_JOIN) |
| 168 | val events = eventCollector.stopCollecting() | 165 | val events = eventCollector.stopCollecting() |
| 169 | 166 | ||
| 170 | assertIsClassList( | 167 | assertIsClassList( |
| @@ -182,13 +179,13 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -182,13 +179,13 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 182 | connect() | 179 | connect() |
| 183 | wsFactory.listener.onMessage( | 180 | wsFactory.listener.onMessage( |
| 184 | wsFactory.ws, | 181 | wsFactory.ws, |
| 185 | - SignalClientTest.PARTICIPANT_JOIN.toOkioByteString(), | 182 | + TestData.PARTICIPANT_JOIN.toOkioByteString(), |
| 186 | ) | 183 | ) |
| 187 | 184 | ||
| 188 | val eventCollector = EventCollector(room.events, coroutineRule.scope) | 185 | val eventCollector = EventCollector(room.events, coroutineRule.scope) |
| 189 | wsFactory.listener.onMessage( | 186 | wsFactory.listener.onMessage( |
| 190 | wsFactory.ws, | 187 | wsFactory.ws, |
| 191 | - SignalClientTest.PARTICIPANT_DISCONNECT.toOkioByteString(), | 188 | + TestData.PARTICIPANT_DISCONNECT.toOkioByteString(), |
| 192 | ) | 189 | ) |
| 193 | val events = eventCollector.stopCollecting() | 190 | val events = eventCollector.stopCollecting() |
| 194 | 191 | ||
| @@ -209,7 +206,7 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -209,7 +206,7 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 209 | val eventCollector = EventCollector(room.events, coroutineRule.scope) | 206 | val eventCollector = EventCollector(room.events, coroutineRule.scope) |
| 210 | wsFactory.listener.onMessage( | 207 | wsFactory.listener.onMessage( |
| 211 | wsFactory.ws, | 208 | wsFactory.ws, |
| 212 | - SignalClientTest.ACTIVE_SPEAKER_UPDATE.toOkioByteString(), | 209 | + TestData.ACTIVE_SPEAKER_UPDATE.toOkioByteString(), |
| 213 | ) | 210 | ) |
| 214 | val events = eventCollector.stopCollecting() | 211 | val events = eventCollector.stopCollecting() |
| 215 | 212 | ||
| @@ -223,7 +220,7 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -223,7 +220,7 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 223 | 220 | ||
| 224 | wsFactory.listener.onMessage( | 221 | wsFactory.listener.onMessage( |
| 225 | wsFactory.ws, | 222 | wsFactory.ws, |
| 226 | - SignalClientTest.PARTICIPANT_JOIN.toOkioByteString(), | 223 | + TestData.PARTICIPANT_JOIN.toOkioByteString(), |
| 227 | ) | 224 | ) |
| 228 | 225 | ||
| 229 | // We intentionally don't emit if the track isn't subscribed, so need to | 226 | // We intentionally don't emit if the track isn't subscribed, so need to |
| @@ -243,7 +240,7 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -243,7 +240,7 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 243 | val eventCollector = EventCollector(room.events, coroutineRule.scope) | 240 | val eventCollector = EventCollector(room.events, coroutineRule.scope) |
| 244 | wsFactory.listener.onMessage( | 241 | wsFactory.listener.onMessage( |
| 245 | wsFactory.ws, | 242 | wsFactory.ws, |
| 246 | - SignalClientTest.STREAM_STATE_UPDATE.toOkioByteString(), | 243 | + TestData.STREAM_STATE_UPDATE.toOkioByteString(), |
| 247 | ) | 244 | ) |
| 248 | val events = eventCollector.stopCollecting() | 245 | val events = eventCollector.stopCollecting() |
| 249 | 246 | ||
| @@ -260,7 +257,7 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -260,7 +257,7 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 260 | 257 | ||
| 261 | wsFactory.listener.onMessage( | 258 | wsFactory.listener.onMessage( |
| 262 | wsFactory.ws, | 259 | wsFactory.ws, |
| 263 | - SignalClientTest.PARTICIPANT_JOIN.toOkioByteString(), | 260 | + TestData.PARTICIPANT_JOIN.toOkioByteString(), |
| 264 | ) | 261 | ) |
| 265 | room.onAddTrack( | 262 | room.onAddTrack( |
| 266 | MockRtpReceiver.create(), | 263 | MockRtpReceiver.create(), |
| @@ -277,7 +274,7 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -277,7 +274,7 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 277 | val eventCollector = EventCollector(room.events, coroutineRule.scope) | 274 | val eventCollector = EventCollector(room.events, coroutineRule.scope) |
| 278 | wsFactory.listener.onMessage( | 275 | wsFactory.listener.onMessage( |
| 279 | wsFactory.ws, | 276 | wsFactory.ws, |
| 280 | - SignalClientTest.SUBSCRIPTION_PERMISSION_UPDATE.toOkioByteString(), | 277 | + TestData.SUBSCRIPTION_PERMISSION_UPDATE.toOkioByteString(), |
| 281 | ) | 278 | ) |
| 282 | val events = eventCollector.stopCollecting() | 279 | val events = eventCollector.stopCollecting() |
| 283 | 280 | ||
| @@ -297,15 +294,12 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -297,15 +294,12 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 297 | val eventCollector = FlowCollector(engine::connectionState.flow, coroutineRule.scope) | 294 | val eventCollector = FlowCollector(engine::connectionState.flow, coroutineRule.scope) |
| 298 | val network = Mockito.mock(Network::class.java) | 295 | val network = Mockito.mock(Network::class.java) |
| 299 | 296 | ||
| 300 | - val connectivityManager = InstrumentationRegistry.getInstrumentation() | ||
| 301 | - .context | ||
| 302 | - .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager | ||
| 303 | - val shadowConnectivityManager: ShadowConnectivityManager = shadowOf(connectivityManager) | 297 | + val networkCallbackRegistry = component.networkCallbackRegistry() |
| 304 | 298 | ||
| 305 | - shadowConnectivityManager.networkCallbacks.forEach { callback -> | 299 | + networkCallbackRegistry.networkCallbacks.forEach { callback -> |
| 306 | callback.onLost(network) | 300 | callback.onLost(network) |
| 307 | } | 301 | } |
| 308 | - shadowConnectivityManager.networkCallbacks.forEach { callback -> | 302 | + networkCallbackRegistry.networkCallbacks.forEach { callback -> |
| 309 | callback.onAvailable(network) | 303 | callback.onAvailable(network) |
| 310 | } | 304 | } |
| 311 | 305 | ||
| @@ -327,7 +321,7 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -327,7 +321,7 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 327 | val eventCollector = EventCollector(room.events, coroutineRule.scope) | 321 | val eventCollector = EventCollector(room.events, coroutineRule.scope) |
| 328 | wsFactory.listener.onMessage( | 322 | wsFactory.listener.onMessage( |
| 329 | wsFactory.ws, | 323 | wsFactory.ws, |
| 330 | - SignalClientTest.LEAVE.toOkioByteString(), | 324 | + TestData.LEAVE.toOkioByteString(), |
| 331 | ) | 325 | ) |
| 332 | val events = eventCollector.stopCollecting() | 326 | val events = eventCollector.stopCollecting() |
| 333 | 327 | ||
| @@ -342,7 +336,7 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -342,7 +336,7 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 342 | room.localParticipant.publishAudioTrack( | 336 | room.localParticipant.publishAudioTrack( |
| 343 | LocalAudioTrack( | 337 | LocalAudioTrack( |
| 344 | "", | 338 | "", |
| 345 | - MockAudioStreamTrack(id = SignalClientTest.LOCAL_TRACK_PUBLISHED.trackPublished.cid), | 339 | + MockAudioStreamTrack(id = TestData.LOCAL_TRACK_PUBLISHED.trackPublished.cid), |
| 346 | ), | 340 | ), |
| 347 | ) | 341 | ) |
| 348 | 342 | ||
| @@ -350,7 +344,7 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -350,7 +344,7 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 350 | 344 | ||
| 351 | wsFactory.listener.onMessage( | 345 | wsFactory.listener.onMessage( |
| 352 | wsFactory.ws, | 346 | wsFactory.ws, |
| 353 | - SignalClientTest.LEAVE.toOkioByteString(), | 347 | + TestData.LEAVE.toOkioByteString(), |
| 354 | ) | 348 | ) |
| 355 | room.disconnect() | 349 | room.disconnect() |
| 356 | val events = eventCollector.stopCollecting() | 350 | val events = eventCollector.stopCollecting() |
| @@ -388,7 +382,7 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -388,7 +382,7 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 388 | room.localParticipant.publishAudioTrack( | 382 | room.localParticipant.publishAudioTrack( |
| 389 | LocalAudioTrack( | 383 | LocalAudioTrack( |
| 390 | "", | 384 | "", |
| 391 | - MockAudioStreamTrack(id = SignalClientTest.LOCAL_TRACK_PUBLISHED.trackPublished.cid), | 385 | + MockAudioStreamTrack(id = TestData.LOCAL_TRACK_PUBLISHED.trackPublished.cid), |
| 392 | ), | 386 | ), |
| 393 | ) | 387 | ) |
| 394 | 388 | ||
| @@ -405,7 +399,7 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -405,7 +399,7 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 405 | fun disconnectCleansUpParticipants() = runTest { | 399 | fun disconnectCleansUpParticipants() = runTest { |
| 406 | connect() | 400 | connect() |
| 407 | 401 | ||
| 408 | - room.onUpdateParticipants(SignalClientTest.PARTICIPANT_JOIN.update.participantsList) | 402 | + room.onUpdateParticipants(TestData.PARTICIPANT_JOIN.update.participantsList) |
| 409 | room.onAddTrack( | 403 | room.onAddTrack( |
| 410 | MockRtpReceiver.create(), | 404 | MockRtpReceiver.create(), |
| 411 | MockAudioStreamTrack(), | 405 | MockAudioStreamTrack(), |
| @@ -441,11 +435,11 @@ class RoomMockE2ETest : MockE2ETest() { | @@ -441,11 +435,11 @@ class RoomMockE2ETest : MockE2ETest() { | ||
| 441 | connect() | 435 | connect() |
| 442 | 436 | ||
| 443 | val eventCollector = EventCollector(room.events, coroutineRule.scope) | 437 | val eventCollector = EventCollector(room.events, coroutineRule.scope) |
| 444 | - wsFactory.listener.onMessage(wsFactory.ws, SignalClientTest.LEAVE.toOkioByteString()) | 438 | + wsFactory.listener.onMessage(wsFactory.ws, TestData.LEAVE.toOkioByteString()) |
| 445 | val events = eventCollector.stopCollecting() | 439 | val events = eventCollector.stopCollecting() |
| 446 | assertEquals(1, events.size) | 440 | assertEquals(1, events.size) |
| 447 | assertEquals(true, events[0] is RoomEvent.Disconnected) | 441 | assertEquals(true, events[0] is RoomEvent.Disconnected) |
| 448 | - assertEquals(SignalClientTest.LEAVE.leave.reason.convert(), (events[0] as RoomEvent.Disconnected).reason) | 442 | + assertEquals(TestData.LEAVE.leave.reason.convert(), (events[0] as RoomEvent.Disconnected).reason) |
| 449 | } | 443 | } |
| 450 | 444 | ||
| 451 | @Test | 445 | @Test |
| @@ -16,10 +16,11 @@ | @@ -16,10 +16,11 @@ | ||
| 16 | 16 | ||
| 17 | package io.livekit.android.room | 17 | package io.livekit.android.room |
| 18 | 18 | ||
| 19 | -import io.livekit.android.MockE2ETest | ||
| 20 | -import io.livekit.android.mock.MockAudioStreamTrack | ||
| 21 | import io.livekit.android.room.track.LocalAudioTrack | 19 | import io.livekit.android.room.track.LocalAudioTrack |
| 22 | -import io.livekit.android.util.toPBByteString | 20 | +import io.livekit.android.test.MockE2ETest |
| 21 | +import io.livekit.android.test.mock.MockAudioStreamTrack | ||
| 22 | +import io.livekit.android.test.mock.TestData | ||
| 23 | +import io.livekit.android.test.util.toPBByteString | ||
| 23 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 24 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 24 | import livekit.LivekitRtc | 25 | import livekit.LivekitRtc |
| 25 | import livekit.org.webrtc.PeerConnection | 26 | import livekit.org.webrtc.PeerConnection |
| @@ -46,9 +47,9 @@ class RoomReconnectionMockE2ETest : MockE2ETest() { | @@ -46,9 +47,9 @@ class RoomReconnectionMockE2ETest : MockE2ETest() { | ||
| 46 | ?: 0 | 47 | ?: 0 |
| 47 | 48 | ||
| 48 | if (softReconnectParam == 0) { | 49 | if (softReconnectParam == 0) { |
| 49 | - simulateMessageFromServer(SignalClientTest.JOIN) | 50 | + simulateMessageFromServer(TestData.JOIN) |
| 50 | } else { | 51 | } else { |
| 51 | - simulateMessageFromServer(SignalClientTest.RECONNECT) | 52 | + simulateMessageFromServer(TestData.RECONNECT) |
| 52 | } | 53 | } |
| 53 | } | 54 | } |
| 54 | 55 | ||
| @@ -89,7 +90,7 @@ class RoomReconnectionMockE2ETest : MockE2ETest() { | @@ -89,7 +90,7 @@ class RoomReconnectionMockE2ETest : MockE2ETest() { | ||
| 89 | val rtcConfig = getSubscriberPeerConnection().rtcConfig | 90 | val rtcConfig = getSubscriberPeerConnection().rtcConfig |
| 90 | assertEquals(PeerConnection.IceTransportsType.RELAY, rtcConfig.iceTransportsType) | 91 | assertEquals(PeerConnection.IceTransportsType.RELAY, rtcConfig.iceTransportsType) |
| 91 | 92 | ||
| 92 | - val sentIceServers = SignalClientTest.RECONNECT.reconnect.iceServersList | 93 | + val sentIceServers = TestData.RECONNECT.reconnect.iceServersList |
| 93 | .map { server -> server.toWebrtc() } | 94 | .map { server -> server.toWebrtc() } |
| 94 | assertEquals(sentIceServers, rtcConfig.iceServers) | 95 | assertEquals(sentIceServers, rtcConfig.iceServers) |
| 95 | } | 96 | } |
| @@ -103,7 +104,7 @@ class RoomReconnectionMockE2ETest : MockE2ETest() { | @@ -103,7 +104,7 @@ class RoomReconnectionMockE2ETest : MockE2ETest() { | ||
| 103 | room.localParticipant.publishAudioTrack( | 104 | room.localParticipant.publishAudioTrack( |
| 104 | LocalAudioTrack( | 105 | LocalAudioTrack( |
| 105 | "", | 106 | "", |
| 106 | - MockAudioStreamTrack(id = SignalClientTest.LOCAL_TRACK_PUBLISHED.trackPublished.cid), | 107 | + MockAudioStreamTrack(id = TestData.LOCAL_TRACK_PUBLISHED.trackPublished.cid), |
| 107 | ), | 108 | ), |
| 108 | ) | 109 | ) |
| 109 | 110 |
| @@ -16,11 +16,12 @@ | @@ -16,11 +16,12 @@ | ||
| 16 | 16 | ||
| 17 | package io.livekit.android.room | 17 | package io.livekit.android.room |
| 18 | 18 | ||
| 19 | -import io.livekit.android.MockE2ETest | ||
| 20 | -import io.livekit.android.assert.assertIsClassList | ||
| 21 | -import io.livekit.android.events.EventCollector | ||
| 22 | -import io.livekit.android.events.FlowCollector | ||
| 23 | import io.livekit.android.events.RoomEvent | 19 | import io.livekit.android.events.RoomEvent |
| 20 | +import io.livekit.android.test.MockE2ETest | ||
| 21 | +import io.livekit.android.test.assert.assertIsClassList | ||
| 22 | +import io.livekit.android.test.events.EventCollector | ||
| 23 | +import io.livekit.android.test.events.FlowCollector | ||
| 24 | +import io.livekit.android.test.mock.TestData | ||
| 24 | import io.livekit.android.util.flow | 25 | import io.livekit.android.util.flow |
| 25 | import junit.framework.Assert.assertEquals | 26 | import junit.framework.Assert.assertEquals |
| 26 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 27 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| @@ -53,9 +54,9 @@ class RoomReconnectionTypesMockE2ETest( | @@ -53,9 +54,9 @@ class RoomReconnectionTypesMockE2ETest( | ||
| 53 | ?: 0 | 54 | ?: 0 |
| 54 | 55 | ||
| 55 | if (softReconnectParam == 0) { | 56 | if (softReconnectParam == 0) { |
| 56 | - simulateMessageFromServer(SignalClientTest.JOIN) | 57 | + simulateMessageFromServer(TestData.JOIN) |
| 57 | } else { | 58 | } else { |
| 58 | - simulateMessageFromServer(SignalClientTest.RECONNECT) | 59 | + simulateMessageFromServer(TestData.RECONNECT) |
| 59 | } | 60 | } |
| 60 | } | 61 | } |
| 61 | 62 |
| @@ -17,19 +17,24 @@ | @@ -17,19 +17,24 @@ | ||
| 17 | package io.livekit.android.room | 17 | package io.livekit.android.room |
| 18 | 18 | ||
| 19 | import android.content.Context | 19 | import android.content.Context |
| 20 | -import android.net.ConnectivityManager | 20 | +import android.net.ConnectivityManager.NetworkCallback |
| 21 | import android.net.Network | 21 | import android.net.Network |
| 22 | import androidx.test.core.app.ApplicationProvider | 22 | import androidx.test.core.app.ApplicationProvider |
| 23 | -import androidx.test.platform.app.InstrumentationRegistry | ||
| 24 | -import io.livekit.android.assert.assertIsClassList | ||
| 25 | import io.livekit.android.audio.NoAudioHandler | 23 | import io.livekit.android.audio.NoAudioHandler |
| 26 | import io.livekit.android.audio.NoopCommunicationWorkaround | 24 | import io.livekit.android.audio.NoopCommunicationWorkaround |
| 27 | -import io.livekit.android.coroutines.TestCoroutineRule | ||
| 28 | import io.livekit.android.e2ee.E2EEManager | 25 | import io.livekit.android.e2ee.E2EEManager |
| 29 | import io.livekit.android.events.* | 26 | import io.livekit.android.events.* |
| 30 | import io.livekit.android.memory.CloseableManager | 27 | import io.livekit.android.memory.CloseableManager |
| 31 | -import io.livekit.android.mock.* | 28 | +import io.livekit.android.room.network.NetworkCallbackManagerImpl |
| 32 | import io.livekit.android.room.participant.LocalParticipant | 29 | import io.livekit.android.room.participant.LocalParticipant |
| 30 | +import io.livekit.android.test.assert.assertIsClassList | ||
| 31 | +import io.livekit.android.test.coroutines.TestCoroutineRule | ||
| 32 | +import io.livekit.android.test.events.EventCollector | ||
| 33 | +import io.livekit.android.test.mock.MockAudioProcessingController | ||
| 34 | +import io.livekit.android.test.mock.MockEglBase | ||
| 35 | +import io.livekit.android.test.mock.MockLKObjects | ||
| 36 | +import io.livekit.android.test.mock.MockNetworkCallbackRegistry | ||
| 37 | +import io.livekit.android.test.mock.TestData | ||
| 33 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 38 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 34 | import kotlinx.coroutines.async | 39 | import kotlinx.coroutines.async |
| 35 | import kotlinx.coroutines.flow.MutableSharedFlow | 40 | import kotlinx.coroutines.flow.MutableSharedFlow |
| @@ -48,8 +53,6 @@ import org.mockito.Mockito | @@ -48,8 +53,6 @@ import org.mockito.Mockito | ||
| 48 | import org.mockito.junit.MockitoJUnit | 53 | import org.mockito.junit.MockitoJUnit |
| 49 | import org.mockito.kotlin.* | 54 | import org.mockito.kotlin.* |
| 50 | import org.robolectric.RobolectricTestRunner | 55 | import org.robolectric.RobolectricTestRunner |
| 51 | -import org.robolectric.Shadows | ||
| 52 | -import org.robolectric.shadows.ShadowConnectivityManager | ||
| 53 | 56 | ||
| 54 | @ExperimentalCoroutinesApi | 57 | @ExperimentalCoroutinesApi |
| 55 | @RunWith(RobolectricTestRunner::class) | 58 | @RunWith(RobolectricTestRunner::class) |
| @@ -69,6 +72,8 @@ class RoomTest { | @@ -69,6 +72,8 @@ class RoomTest { | ||
| 69 | @Mock | 72 | @Mock |
| 70 | lateinit var e2EEManagerFactory: E2EEManager.Factory | 73 | lateinit var e2EEManagerFactory: E2EEManager.Factory |
| 71 | 74 | ||
| 75 | + lateinit var networkCallbackRegistry: MockNetworkCallbackRegistry | ||
| 76 | + | ||
| 72 | var eglBase: EglBase = MockEglBase() | 77 | var eglBase: EglBase = MockEglBase() |
| 73 | 78 | ||
| 74 | val localParticipantFactory = object : LocalParticipant.Factory { | 79 | val localParticipantFactory = object : LocalParticipant.Factory { |
| @@ -89,6 +94,7 @@ class RoomTest { | @@ -89,6 +94,7 @@ class RoomTest { | ||
| 89 | @Before | 94 | @Before |
| 90 | fun setup() { | 95 | fun setup() { |
| 91 | context = ApplicationProvider.getApplicationContext() | 96 | context = ApplicationProvider.getApplicationContext() |
| 97 | + networkCallbackRegistry = MockNetworkCallbackRegistry() | ||
| 92 | room = Room( | 98 | room = Room( |
| 93 | context = context, | 99 | context = context, |
| 94 | engine = rtcEngine, | 100 | engine = rtcEngine, |
| @@ -103,10 +109,13 @@ class RoomTest { | @@ -103,10 +109,13 @@ class RoomTest { | ||
| 103 | communicationWorkaround = NoopCommunicationWorkaround(), | 109 | communicationWorkaround = NoopCommunicationWorkaround(), |
| 104 | audioProcessingController = MockAudioProcessingController(), | 110 | audioProcessingController = MockAudioProcessingController(), |
| 105 | lkObjects = MockLKObjects.get(), | 111 | lkObjects = MockLKObjects.get(), |
| 112 | + networkCallbackManagerFactory = { networkCallback: NetworkCallback -> | ||
| 113 | + NetworkCallbackManagerImpl(networkCallback, networkCallbackRegistry) | ||
| 114 | + }, | ||
| 106 | ) | 115 | ) |
| 107 | } | 116 | } |
| 108 | 117 | ||
| 109 | - suspend fun connect(joinResponse: JoinResponse = SignalClientTest.JOIN.join) { | 118 | + suspend fun connect(joinResponse: JoinResponse = TestData.JOIN.join) { |
| 110 | rtcEngine.stub { | 119 | rtcEngine.stub { |
| 111 | onBlocking { rtcEngine.join(any(), any(), anyOrNull(), anyOrNull()) } | 120 | onBlocking { rtcEngine.join(any(), any(), anyOrNull(), anyOrNull()) } |
| 112 | .doSuspendableAnswer { | 121 | .doSuspendableAnswer { |
| @@ -120,7 +129,7 @@ class RoomTest { | @@ -120,7 +129,7 @@ class RoomTest { | ||
| 120 | } | 129 | } |
| 121 | 130 | ||
| 122 | room.connect( | 131 | room.connect( |
| 123 | - url = SignalClientTest.EXAMPLE_URL, | 132 | + url = TestData.EXAMPLE_URL, |
| 124 | token = "", | 133 | token = "", |
| 125 | ) | 134 | ) |
| 126 | } | 135 | } |
| @@ -128,7 +137,7 @@ class RoomTest { | @@ -128,7 +137,7 @@ class RoomTest { | ||
| 128 | @Test | 137 | @Test |
| 129 | fun connectTest() = runTest { | 138 | fun connectTest() = runTest { |
| 130 | connect() | 139 | connect() |
| 131 | - val roomInfo = SignalClientTest.JOIN.join.room | 140 | + val roomInfo = TestData.JOIN.join.room |
| 132 | 141 | ||
| 133 | assertEquals(roomInfo.name, room.name) | 142 | assertEquals(roomInfo.name, room.name) |
| 134 | assertEquals(Room.Sid(roomInfo.sid), room.sid) | 143 | assertEquals(Room.Sid(roomInfo.sid), room.sid) |
| @@ -139,7 +148,7 @@ class RoomTest { | @@ -139,7 +148,7 @@ class RoomTest { | ||
| 139 | @Test | 148 | @Test |
| 140 | fun roomUpdate() = runTest { | 149 | fun roomUpdate() = runTest { |
| 141 | connect() | 150 | connect() |
| 142 | - val update = SignalClientTest.ROOM_UPDATE.roomUpdate.room | 151 | + val update = TestData.ROOM_UPDATE.roomUpdate.room |
| 143 | 152 | ||
| 144 | val eventCollector = EventCollector(room.events, coroutineRule.scope) | 153 | val eventCollector = EventCollector(room.events, coroutineRule.scope) |
| 145 | room.onRoomUpdate(update) | 154 | room.onRoomUpdate(update) |
| @@ -164,15 +173,10 @@ class RoomTest { | @@ -164,15 +173,10 @@ class RoomTest { | ||
| 164 | 173 | ||
| 165 | val network = Mockito.mock(Network::class.java) | 174 | val network = Mockito.mock(Network::class.java) |
| 166 | 175 | ||
| 167 | - val connectivityManager = InstrumentationRegistry.getInstrumentation() | ||
| 168 | - .context | ||
| 169 | - .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager | ||
| 170 | - val shadowConnectivityManager: ShadowConnectivityManager = Shadows.shadowOf(connectivityManager) | ||
| 171 | - | ||
| 172 | - shadowConnectivityManager.networkCallbacks.forEach { callback -> | 176 | + networkCallbackRegistry.networkCallbacks.forEach { callback -> |
| 173 | callback.onLost(network) | 177 | callback.onLost(network) |
| 174 | } | 178 | } |
| 175 | - shadowConnectivityManager.networkCallbacks.forEach { callback -> | 179 | + networkCallbackRegistry.networkCallbacks.forEach { callback -> |
| 176 | callback.onAvailable(network) | 180 | callback.onAvailable(network) |
| 177 | } | 181 | } |
| 178 | 182 | ||
| @@ -227,7 +231,7 @@ class RoomTest { | @@ -227,7 +231,7 @@ class RoomTest { | ||
| 227 | assertFalse(job.isCompleted) | 231 | assertFalse(job.isCompleted) |
| 228 | connect() | 232 | connect() |
| 229 | assertFalse(job.isCompleted) | 233 | assertFalse(job.isCompleted) |
| 230 | - val update = SignalClientTest.ROOM_UPDATE.roomUpdate.room | 234 | + val update = TestData.ROOM_UPDATE.roomUpdate.room |
| 231 | room.onRoomUpdate(update) | 235 | room.onRoomUpdate(update) |
| 232 | 236 | ||
| 233 | advanceUntilIdle() | 237 | advanceUntilIdle() |
| 1 | /* | 1 | /* |
| 2 | - * Copyright 2023 LiveKit, Inc. | 2 | + * Copyright 2023-2024 LiveKit, Inc. |
| 3 | * | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
| @@ -16,20 +16,22 @@ | @@ -16,20 +16,22 @@ | ||
| 16 | 16 | ||
| 17 | package io.livekit.android.room | 17 | package io.livekit.android.room |
| 18 | 18 | ||
| 19 | -import io.livekit.android.BaseTest | ||
| 20 | -import io.livekit.android.mock.MockWebSocketFactory | ||
| 21 | -import io.livekit.android.mock.TestData | ||
| 22 | import io.livekit.android.stats.NetworkInfo | 19 | import io.livekit.android.stats.NetworkInfo |
| 23 | import io.livekit.android.stats.NetworkType | 20 | import io.livekit.android.stats.NetworkType |
| 21 | +import io.livekit.android.test.BaseTest | ||
| 22 | +import io.livekit.android.test.mock.MockWebSocketFactory | ||
| 23 | +import io.livekit.android.test.mock.TestData.EXAMPLE_URL | ||
| 24 | +import io.livekit.android.test.mock.TestData.JOIN | ||
| 25 | +import io.livekit.android.test.mock.TestData.OFFER | ||
| 26 | +import io.livekit.android.test.mock.TestData.PONG | ||
| 27 | +import io.livekit.android.test.mock.TestData.RECONNECT | ||
| 28 | +import io.livekit.android.test.mock.TestData.ROOM_UPDATE | ||
| 29 | +import io.livekit.android.test.util.toPBByteString | ||
| 24 | import io.livekit.android.util.toOkioByteString | 30 | import io.livekit.android.util.toOkioByteString |
| 25 | -import io.livekit.android.util.toPBByteString | ||
| 26 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 31 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 27 | import kotlinx.coroutines.async | 32 | import kotlinx.coroutines.async |
| 28 | import kotlinx.serialization.json.Json | 33 | import kotlinx.serialization.json.Json |
| 29 | -import livekit.LivekitModels | ||
| 30 | -import livekit.LivekitModels.ClientConfiguration | ||
| 31 | import livekit.LivekitRtc | 34 | import livekit.LivekitRtc |
| 32 | -import livekit.LivekitRtc.ICEServer | ||
| 33 | import livekit.org.webrtc.SessionDescription | 35 | import livekit.org.webrtc.SessionDescription |
| 34 | import okhttp3.OkHttpClient | 36 | import okhttp3.OkHttpClient |
| 35 | import okhttp3.Protocol | 37 | import okhttp3.Protocol |
| @@ -43,9 +45,9 @@ import org.junit.Before | @@ -43,9 +45,9 @@ import org.junit.Before | ||
| 43 | import org.junit.Test | 45 | import org.junit.Test |
| 44 | import org.mockito.Mock | 46 | import org.mockito.Mock |
| 45 | import org.mockito.Mockito | 47 | import org.mockito.Mockito |
| 48 | +import org.mockito.Mockito.inOrder | ||
| 46 | import org.mockito.kotlin.any | 49 | import org.mockito.kotlin.any |
| 47 | import org.mockito.kotlin.argThat | 50 | import org.mockito.kotlin.argThat |
| 48 | -import org.mockito.kotlin.inOrder | ||
| 49 | import org.mockito.kotlin.times | 51 | import org.mockito.kotlin.times |
| 50 | 52 | ||
| 51 | @ExperimentalCoroutinesApi | 53 | @ExperimentalCoroutinesApi |
| @@ -329,218 +331,5 @@ class SignalClientTest : BaseTest() { | @@ -329,218 +331,5 @@ class SignalClientTest : BaseTest() { | ||
| 329 | } | 331 | } |
| 330 | 332 | ||
| 331 | // mock data | 333 | // mock data |
| 332 | - companion object { | ||
| 333 | - const val EXAMPLE_URL = "ws://www.example.com" | ||
| 334 | - | ||
| 335 | - val JOIN = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 336 | - join = with(LivekitRtc.JoinResponse.newBuilder()) { | ||
| 337 | - room = with(LivekitModels.Room.newBuilder()) { | ||
| 338 | - name = "roomname" | ||
| 339 | - build() | ||
| 340 | - } | ||
| 341 | - participant = TestData.LOCAL_PARTICIPANT | ||
| 342 | - subscriberPrimary = true | ||
| 343 | - addIceServers( | ||
| 344 | - with(ICEServer.newBuilder()) { | ||
| 345 | - addUrls("stun:stun.join.com:19302") | ||
| 346 | - username = "username" | ||
| 347 | - credential = "credential" | ||
| 348 | - build() | ||
| 349 | - }, | ||
| 350 | - ) | ||
| 351 | - serverVersion = "0.15.2" | ||
| 352 | - build() | ||
| 353 | - } | ||
| 354 | - build() | ||
| 355 | - } | ||
| 356 | - | ||
| 357 | - val RECONNECT = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 358 | - reconnect = with(LivekitRtc.ReconnectResponse.newBuilder()) { | ||
| 359 | - addIceServers( | ||
| 360 | - with(ICEServer.newBuilder()) { | ||
| 361 | - addUrls("stun:stun.reconnect.com:19302") | ||
| 362 | - username = "username" | ||
| 363 | - credential = "credential" | ||
| 364 | - build() | ||
| 365 | - }, | ||
| 366 | - ) | ||
| 367 | - clientConfiguration = with(ClientConfiguration.newBuilder()) { | ||
| 368 | - forceRelay = LivekitModels.ClientConfigSetting.ENABLED | ||
| 369 | - build() | ||
| 370 | - } | ||
| 371 | - build() | ||
| 372 | - } | ||
| 373 | - build() | ||
| 374 | - } | ||
| 375 | - | ||
| 376 | - val OFFER = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 377 | - offer = with(LivekitRtc.SessionDescription.newBuilder()) { | ||
| 378 | - sdp = "remote_offer" | ||
| 379 | - type = "offer" | ||
| 380 | - build() | ||
| 381 | - } | ||
| 382 | - build() | ||
| 383 | - } | ||
| 384 | - | ||
| 385 | - val ROOM_UPDATE = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 386 | - roomUpdate = with(LivekitRtc.RoomUpdate.newBuilder()) { | ||
| 387 | - room = with(LivekitModels.Room.newBuilder()) { | ||
| 388 | - sid = "room_sid" | ||
| 389 | - metadata = "metadata" | ||
| 390 | - activeRecording = true | ||
| 391 | - build() | ||
| 392 | - } | ||
| 393 | - build() | ||
| 394 | - } | ||
| 395 | - build() | ||
| 396 | - } | ||
| 397 | - | ||
| 398 | - val LOCAL_TRACK_PUBLISHED = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 399 | - trackPublished = with(LivekitRtc.TrackPublishedResponse.newBuilder()) { | ||
| 400 | - cid = "local_cid" | ||
| 401 | - track = TestData.LOCAL_AUDIO_TRACK | ||
| 402 | - build() | ||
| 403 | - } | ||
| 404 | - build() | ||
| 405 | - } | ||
| 406 | - | ||
| 407 | - val LOCAL_TRACK_UNPUBLISHED = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 408 | - trackUnpublished = with(LivekitRtc.TrackUnpublishedResponse.newBuilder()) { | ||
| 409 | - trackSid = TestData.LOCAL_AUDIO_TRACK.sid | ||
| 410 | - build() | ||
| 411 | - } | ||
| 412 | - build() | ||
| 413 | - } | ||
| 414 | - | ||
| 415 | - val PERMISSION_CHANGE = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 416 | - update = with(LivekitRtc.ParticipantUpdate.newBuilder()) { | ||
| 417 | - addParticipants( | ||
| 418 | - TestData.LOCAL_PARTICIPANT.toBuilder() | ||
| 419 | - .setPermission( | ||
| 420 | - LivekitModels.ParticipantPermission.newBuilder() | ||
| 421 | - .setCanPublish(false) | ||
| 422 | - .setCanSubscribe(false) | ||
| 423 | - .setCanPublishData(false) | ||
| 424 | - .setHidden(false) | ||
| 425 | - .setRecorder(false) | ||
| 426 | - .build(), | ||
| 427 | - ) | ||
| 428 | - .build(), | ||
| 429 | - ) | ||
| 430 | - build() | ||
| 431 | - } | ||
| 432 | - build() | ||
| 433 | - } | ||
| 434 | - | ||
| 435 | - val PARTICIPANT_JOIN = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 436 | - update = with(LivekitRtc.ParticipantUpdate.newBuilder()) { | ||
| 437 | - addParticipants(TestData.REMOTE_PARTICIPANT) | ||
| 438 | - build() | ||
| 439 | - } | ||
| 440 | - build() | ||
| 441 | - } | ||
| 442 | - | ||
| 443 | - val PARTICIPANT_DISCONNECT = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 444 | - update = with(LivekitRtc.ParticipantUpdate.newBuilder()) { | ||
| 445 | - val disconnectedParticipant = TestData.REMOTE_PARTICIPANT.toBuilder() | ||
| 446 | - .setState(LivekitModels.ParticipantInfo.State.DISCONNECTED) | ||
| 447 | - .build() | ||
| 448 | - | ||
| 449 | - addParticipants(disconnectedParticipant) | ||
| 450 | - build() | ||
| 451 | - } | ||
| 452 | - build() | ||
| 453 | - } | ||
| 454 | - | ||
| 455 | - val ACTIVE_SPEAKER_UPDATE = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 456 | - speakersChanged = with(LivekitRtc.SpeakersChanged.newBuilder()) { | ||
| 457 | - addSpeakers(TestData.REMOTE_SPEAKER_INFO) | ||
| 458 | - build() | ||
| 459 | - } | ||
| 460 | - build() | ||
| 461 | - } | ||
| 462 | - | ||
| 463 | - val LOCAL_PARTICIPANT_METADATA_CHANGED = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 464 | - update = with(LivekitRtc.ParticipantUpdate.newBuilder()) { | ||
| 465 | - val participantMetadataChanged = TestData.LOCAL_PARTICIPANT.toBuilder() | ||
| 466 | - .setMetadata("changed_metadata") | ||
| 467 | - .setName("changed_name") | ||
| 468 | - .build() | ||
| 469 | - | ||
| 470 | - addParticipants(participantMetadataChanged) | ||
| 471 | - build() | ||
| 472 | - } | ||
| 473 | - build() | ||
| 474 | - } | ||
| 475 | - | ||
| 476 | - val REMOTE_PARTICIPANT_METADATA_CHANGED = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 477 | - update = with(LivekitRtc.ParticipantUpdate.newBuilder()) { | ||
| 478 | - val participantMetadataChanged = TestData.REMOTE_PARTICIPANT.toBuilder() | ||
| 479 | - .setMetadata("changed_metadata") | ||
| 480 | - .setName("changed_name") | ||
| 481 | - .build() | ||
| 482 | - | ||
| 483 | - addParticipants(participantMetadataChanged) | ||
| 484 | - build() | ||
| 485 | - } | ||
| 486 | - build() | ||
| 487 | - } | ||
| 488 | - | ||
| 489 | - val CONNECTION_QUALITY = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 490 | - connectionQuality = with(LivekitRtc.ConnectionQualityUpdate.newBuilder()) { | ||
| 491 | - addUpdates( | ||
| 492 | - with(LivekitRtc.ConnectionQualityInfo.newBuilder()) { | ||
| 493 | - participantSid = JOIN.join.participant.sid | ||
| 494 | - quality = LivekitModels.ConnectionQuality.EXCELLENT | ||
| 495 | - build() | ||
| 496 | - }, | ||
| 497 | - ) | ||
| 498 | - build() | ||
| 499 | - } | ||
| 500 | - build() | ||
| 501 | - } | ||
| 502 | - | ||
| 503 | - val STREAM_STATE_UPDATE = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 504 | - streamStateUpdate = with(LivekitRtc.StreamStateUpdate.newBuilder()) { | ||
| 505 | - addStreamStates( | ||
| 506 | - with(LivekitRtc.StreamStateInfo.newBuilder()) { | ||
| 507 | - participantSid = TestData.REMOTE_PARTICIPANT.sid | ||
| 508 | - trackSid = TestData.REMOTE_AUDIO_TRACK.sid | ||
| 509 | - state = LivekitRtc.StreamState.ACTIVE | ||
| 510 | - build() | ||
| 511 | - }, | ||
| 512 | - ) | ||
| 513 | - build() | ||
| 514 | - } | ||
| 515 | - build() | ||
| 516 | - } | ||
| 517 | - | ||
| 518 | - val SUBSCRIPTION_PERMISSION_UPDATE = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 519 | - subscriptionPermissionUpdate = with(LivekitRtc.SubscriptionPermissionUpdate.newBuilder()) { | ||
| 520 | - participantSid = TestData.REMOTE_PARTICIPANT.sid | ||
| 521 | - trackSid = TestData.REMOTE_AUDIO_TRACK.sid | ||
| 522 | - allowed = false | ||
| 523 | - build() | ||
| 524 | - } | ||
| 525 | - build() | ||
| 526 | - } | ||
| 527 | - | ||
| 528 | - val REFRESH_TOKEN = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 529 | - refreshToken = "refresh_token" | ||
| 530 | - build() | ||
| 531 | - } | ||
| 532 | - | ||
| 533 | - val PONG = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 534 | - pong = 1L | ||
| 535 | - build() | ||
| 536 | - } | ||
| 537 | - | ||
| 538 | - val LEAVE = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 539 | - leave = with(LivekitRtc.LeaveRequest.newBuilder()) { | ||
| 540 | - reason = LivekitModels.DisconnectReason.SERVER_SHUTDOWN | ||
| 541 | - build() | ||
| 542 | - } | ||
| 543 | - build() | ||
| 544 | - } | ||
| 545 | - } | 334 | + companion object |
| 546 | } | 335 | } |
| @@ -16,25 +16,25 @@ | @@ -16,25 +16,25 @@ | ||
| 16 | 16 | ||
| 17 | package io.livekit.android.room.participant | 17 | package io.livekit.android.room.participant |
| 18 | 18 | ||
| 19 | -import io.livekit.android.MockE2ETest | ||
| 20 | -import io.livekit.android.assert.assertIsClassList | ||
| 21 | -import io.livekit.android.events.EventCollector | ||
| 22 | import io.livekit.android.events.ParticipantEvent | 19 | import io.livekit.android.events.ParticipantEvent |
| 23 | import io.livekit.android.events.RoomEvent | 20 | import io.livekit.android.events.RoomEvent |
| 24 | -import io.livekit.android.mock.MockAudioStreamTrack | ||
| 25 | -import io.livekit.android.mock.MockEglBase | ||
| 26 | -import io.livekit.android.mock.MockVideoCapturer | ||
| 27 | -import io.livekit.android.mock.MockVideoStreamTrack | ||
| 28 | import io.livekit.android.room.DefaultsManager | 21 | import io.livekit.android.room.DefaultsManager |
| 29 | -import io.livekit.android.room.SignalClientTest | ||
| 30 | import io.livekit.android.room.track.LocalAudioTrack | 22 | import io.livekit.android.room.track.LocalAudioTrack |
| 31 | import io.livekit.android.room.track.LocalVideoTrack | 23 | import io.livekit.android.room.track.LocalVideoTrack |
| 32 | import io.livekit.android.room.track.LocalVideoTrackOptions | 24 | import io.livekit.android.room.track.LocalVideoTrackOptions |
| 33 | import io.livekit.android.room.track.Track | 25 | import io.livekit.android.room.track.Track |
| 34 | import io.livekit.android.room.track.VideoCaptureParameter | 26 | import io.livekit.android.room.track.VideoCaptureParameter |
| 35 | import io.livekit.android.room.track.VideoCodec | 27 | import io.livekit.android.room.track.VideoCodec |
| 28 | +import io.livekit.android.test.MockE2ETest | ||
| 29 | +import io.livekit.android.test.assert.assertIsClassList | ||
| 30 | +import io.livekit.android.test.events.EventCollector | ||
| 31 | +import io.livekit.android.test.mock.MockAudioStreamTrack | ||
| 32 | +import io.livekit.android.test.mock.MockEglBase | ||
| 33 | +import io.livekit.android.test.mock.MockVideoCapturer | ||
| 34 | +import io.livekit.android.test.mock.MockVideoStreamTrack | ||
| 35 | +import io.livekit.android.test.mock.TestData | ||
| 36 | +import io.livekit.android.test.util.toPBByteString | ||
| 36 | import io.livekit.android.util.toOkioByteString | 37 | import io.livekit.android.util.toOkioByteString |
| 37 | -import io.livekit.android.util.toPBByteString | ||
| 38 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 38 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 39 | import livekit.LivekitModels | 39 | import livekit.LivekitModels |
| 40 | import livekit.LivekitRtc | 40 | import livekit.LivekitRtc |
| @@ -60,7 +60,7 @@ class LocalParticipantMockE2ETest : MockE2ETest() { | @@ -60,7 +60,7 @@ class LocalParticipantMockE2ETest : MockE2ETest() { | ||
| 60 | room.localParticipant.publishAudioTrack( | 60 | room.localParticipant.publishAudioTrack( |
| 61 | LocalAudioTrack( | 61 | LocalAudioTrack( |
| 62 | "", | 62 | "", |
| 63 | - MockAudioStreamTrack(id = SignalClientTest.LOCAL_TRACK_PUBLISHED.trackPublished.cid), | 63 | + MockAudioStreamTrack(id = TestData.LOCAL_TRACK_PUBLISHED.trackPublished.cid), |
| 64 | ), | 64 | ), |
| 65 | ) | 65 | ) |
| 66 | 66 | ||
| @@ -147,14 +147,14 @@ class LocalParticipantMockE2ETest : MockE2ETest() { | @@ -147,14 +147,14 @@ class LocalParticipantMockE2ETest : MockE2ETest() { | ||
| 147 | 147 | ||
| 148 | wsFactory.listener.onMessage( | 148 | wsFactory.listener.onMessage( |
| 149 | wsFactory.ws, | 149 | wsFactory.ws, |
| 150 | - SignalClientTest.LOCAL_PARTICIPANT_METADATA_CHANGED.toOkioByteString(), | 150 | + TestData.LOCAL_PARTICIPANT_METADATA_CHANGED.toOkioByteString(), |
| 151 | ) | 151 | ) |
| 152 | 152 | ||
| 153 | val roomEvents = roomEventsCollector.stopCollecting() | 153 | val roomEvents = roomEventsCollector.stopCollecting() |
| 154 | val participantEvents = participantEventsCollector.stopCollecting() | 154 | val participantEvents = participantEventsCollector.stopCollecting() |
| 155 | 155 | ||
| 156 | val localParticipant = room.localParticipant | 156 | val localParticipant = room.localParticipant |
| 157 | - val updateData = SignalClientTest.REMOTE_PARTICIPANT_METADATA_CHANGED.update.getParticipants(0) | 157 | + val updateData = TestData.REMOTE_PARTICIPANT_METADATA_CHANGED.update.getParticipants(0) |
| 158 | assertEquals(updateData.metadata, localParticipant.metadata) | 158 | assertEquals(updateData.metadata, localParticipant.metadata) |
| 159 | assertEquals(updateData.name, localParticipant.name) | 159 | assertEquals(updateData.name, localParticipant.name) |
| 160 | 160 |
| @@ -16,14 +16,15 @@ | @@ -16,14 +16,15 @@ | ||
| 16 | 16 | ||
| 17 | package io.livekit.android.room.participant | 17 | package io.livekit.android.room.participant |
| 18 | 18 | ||
| 19 | -import io.livekit.android.MockE2ETest | ||
| 20 | -import io.livekit.android.assert.assertIsClassList | ||
| 21 | -import io.livekit.android.events.EventCollector | ||
| 22 | import io.livekit.android.events.ParticipantEvent | 19 | import io.livekit.android.events.ParticipantEvent |
| 23 | import io.livekit.android.events.RoomEvent | 20 | import io.livekit.android.events.RoomEvent |
| 24 | -import io.livekit.android.mock.MockAudioStreamTrack | ||
| 25 | -import io.livekit.android.room.SignalClientTest | ||
| 26 | import io.livekit.android.room.track.LocalAudioTrack | 21 | import io.livekit.android.room.track.LocalAudioTrack |
| 22 | +import io.livekit.android.test.MockE2ETest | ||
| 23 | +import io.livekit.android.test.assert.assertIsClassList | ||
| 24 | +import io.livekit.android.test.events.EventCollector | ||
| 25 | +import io.livekit.android.test.mock.MockAudioStreamTrack | ||
| 26 | +import io.livekit.android.test.mock.TestData | ||
| 27 | +import io.livekit.android.test.util.toOkioByteString | ||
| 27 | import io.livekit.android.util.toOkioByteString | 28 | import io.livekit.android.util.toOkioByteString |
| 28 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 29 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 29 | import org.junit.Assert.assertEquals | 30 | import org.junit.Assert.assertEquals |
| @@ -43,13 +44,13 @@ class ParticipantMockE2ETest : MockE2ETest() { | @@ -43,13 +44,13 @@ class ParticipantMockE2ETest : MockE2ETest() { | ||
| 43 | room.localParticipant.publishAudioTrack( | 44 | room.localParticipant.publishAudioTrack( |
| 44 | LocalAudioTrack( | 45 | LocalAudioTrack( |
| 45 | "", | 46 | "", |
| 46 | - MockAudioStreamTrack(id = SignalClientTest.LOCAL_TRACK_PUBLISHED.trackPublished.cid), | 47 | + MockAudioStreamTrack(id = TestData.LOCAL_TRACK_PUBLISHED.trackPublished.cid), |
| 47 | ), | 48 | ), |
| 48 | ) | 49 | ) |
| 49 | 50 | ||
| 50 | val eventCollector = EventCollector(room.events, coroutineRule.scope) | 51 | val eventCollector = EventCollector(room.events, coroutineRule.scope) |
| 51 | // remote unpublish | 52 | // remote unpublish |
| 52 | - simulateMessageFromServer(SignalClientTest.LOCAL_TRACK_UNPUBLISHED) | 53 | + simulateMessageFromServer(TestData.LOCAL_TRACK_UNPUBLISHED) |
| 53 | val events = eventCollector.stopCollecting() | 54 | val events = eventCollector.stopCollecting() |
| 54 | 55 | ||
| 55 | assertEquals(1, events.size) | 56 | assertEquals(1, events.size) |
| @@ -62,7 +63,7 @@ class ParticipantMockE2ETest : MockE2ETest() { | @@ -62,7 +63,7 @@ class ParticipantMockE2ETest : MockE2ETest() { | ||
| 62 | connect() | 63 | connect() |
| 63 | 64 | ||
| 64 | val eventCollector = EventCollector(room.events, coroutineRule.scope) | 65 | val eventCollector = EventCollector(room.events, coroutineRule.scope) |
| 65 | - simulateMessageFromServer(SignalClientTest.PERMISSION_CHANGE) | 66 | + simulateMessageFromServer(TestData.PERMISSION_CHANGE) |
| 66 | val events = eventCollector.stopCollecting() | 67 | val events = eventCollector.stopCollecting() |
| 67 | 68 | ||
| 68 | assertEquals(1, events.size) | 69 | assertEquals(1, events.size) |
| @@ -75,7 +76,7 @@ class ParticipantMockE2ETest : MockE2ETest() { | @@ -75,7 +76,7 @@ class ParticipantMockE2ETest : MockE2ETest() { | ||
| 75 | 76 | ||
| 76 | wsFactory.listener.onMessage( | 77 | wsFactory.listener.onMessage( |
| 77 | wsFactory.ws, | 78 | wsFactory.ws, |
| 78 | - SignalClientTest.PARTICIPANT_JOIN.toOkioByteString(), | 79 | + TestData.PARTICIPANT_JOIN.toOkioByteString(), |
| 79 | ) | 80 | ) |
| 80 | 81 | ||
| 81 | val remoteParticipant = room.remoteParticipants.values.first() | 82 | val remoteParticipant = room.remoteParticipants.values.first() |
| @@ -83,12 +84,12 @@ class ParticipantMockE2ETest : MockE2ETest() { | @@ -83,12 +84,12 @@ class ParticipantMockE2ETest : MockE2ETest() { | ||
| 83 | val participantEventsCollector = EventCollector(remoteParticipant.events, coroutineRule.scope) | 84 | val participantEventsCollector = EventCollector(remoteParticipant.events, coroutineRule.scope) |
| 84 | wsFactory.listener.onMessage( | 85 | wsFactory.listener.onMessage( |
| 85 | wsFactory.ws, | 86 | wsFactory.ws, |
| 86 | - SignalClientTest.REMOTE_PARTICIPANT_METADATA_CHANGED.toOkioByteString(), | 87 | + TestData.REMOTE_PARTICIPANT_METADATA_CHANGED.toOkioByteString(), |
| 87 | ) | 88 | ) |
| 88 | val roomEvents = roomEventsCollector.stopCollecting() | 89 | val roomEvents = roomEventsCollector.stopCollecting() |
| 89 | val participantEvents = participantEventsCollector.stopCollecting() | 90 | val participantEvents = participantEventsCollector.stopCollecting() |
| 90 | 91 | ||
| 91 | - val updateData = SignalClientTest.REMOTE_PARTICIPANT_METADATA_CHANGED.update.getParticipants(0) | 92 | + val updateData = TestData.REMOTE_PARTICIPANT_METADATA_CHANGED.update.getParticipants(0) |
| 92 | assertEquals(updateData.metadata, remoteParticipant.metadata) | 93 | assertEquals(updateData.metadata, remoteParticipant.metadata) |
| 93 | assertEquals(updateData.name, remoteParticipant.name) | 94 | assertEquals(updateData.name, remoteParticipant.name) |
| 94 | 95 |
| @@ -16,10 +16,10 @@ | @@ -16,10 +16,10 @@ | ||
| 16 | 16 | ||
| 17 | package io.livekit.android.room.participant | 17 | package io.livekit.android.room.participant |
| 18 | 18 | ||
| 19 | -import io.livekit.android.coroutines.TestCoroutineRule | ||
| 20 | -import io.livekit.android.events.EventCollector | ||
| 21 | import io.livekit.android.events.ParticipantEvent | 19 | import io.livekit.android.events.ParticipantEvent |
| 22 | import io.livekit.android.room.track.TrackPublication | 20 | import io.livekit.android.room.track.TrackPublication |
| 21 | +import io.livekit.android.test.coroutines.TestCoroutineRule | ||
| 22 | +import io.livekit.android.test.events.EventCollector | ||
| 23 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 23 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 24 | import kotlinx.coroutines.test.runTest | 24 | import kotlinx.coroutines.test.runTest |
| 25 | import livekit.LivekitModels | 25 | import livekit.LivekitModels |
| 1 | /* | 1 | /* |
| 2 | - * Copyright 2023 LiveKit, Inc. | 2 | + * Copyright 2023-2024 LiveKit, Inc. |
| 3 | * | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
| @@ -16,12 +16,12 @@ | @@ -16,12 +16,12 @@ | ||
| 16 | 16 | ||
| 17 | package io.livekit.android.room.participant | 17 | package io.livekit.android.room.participant |
| 18 | 18 | ||
| 19 | -import io.livekit.android.BaseTest | ||
| 20 | -import io.livekit.android.events.EventCollector | ||
| 21 | -import io.livekit.android.events.FlowCollector | ||
| 22 | import io.livekit.android.events.ParticipantEvent | 19 | import io.livekit.android.events.ParticipantEvent |
| 23 | import io.livekit.android.room.SignalClient | 20 | import io.livekit.android.room.SignalClient |
| 24 | import io.livekit.android.room.track.TrackPublication | 21 | import io.livekit.android.room.track.TrackPublication |
| 22 | +import io.livekit.android.test.BaseTest | ||
| 23 | +import io.livekit.android.test.events.EventCollector | ||
| 24 | +import io.livekit.android.test.events.FlowCollector | ||
| 25 | import io.livekit.android.util.flow | 25 | import io.livekit.android.util.flow |
| 26 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 26 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 27 | import livekit.LivekitModels | 27 | import livekit.LivekitModels |
| @@ -16,11 +16,14 @@ | @@ -16,11 +16,14 @@ | ||
| 16 | 16 | ||
| 17 | package io.livekit.android.room.track | 17 | package io.livekit.android.room.track |
| 18 | 18 | ||
| 19 | -import io.livekit.android.MockE2ETest | ||
| 20 | -import io.livekit.android.mock.* | ||
| 21 | -import io.livekit.android.room.SignalClientTest | 19 | +import io.livekit.android.test.MockE2ETest |
| 20 | +import io.livekit.android.test.mock.MockMediaStream | ||
| 21 | +import io.livekit.android.test.mock.MockRtpReceiver | ||
| 22 | +import io.livekit.android.test.mock.MockVideoStreamTrack | ||
| 23 | +import io.livekit.android.test.mock.TestData | ||
| 24 | +import io.livekit.android.test.mock.createMediaStreamId | ||
| 25 | +import io.livekit.android.test.util.toPBByteString | ||
| 22 | import io.livekit.android.util.toOkioByteString | 26 | import io.livekit.android.util.toOkioByteString |
| 23 | -import io.livekit.android.util.toPBByteString | ||
| 24 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 27 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 25 | import kotlinx.coroutines.test.advanceUntilIdle | 28 | import kotlinx.coroutines.test.advanceUntilIdle |
| 26 | import livekit.LivekitModels.VideoQuality | 29 | import livekit.LivekitModels.VideoQuality |
| @@ -43,7 +46,7 @@ class RemoteTrackPublicationTest : MockE2ETest() { | @@ -43,7 +46,7 @@ class RemoteTrackPublicationTest : MockE2ETest() { | ||
| 43 | 46 | ||
| 44 | wsFactory.listener.onMessage( | 47 | wsFactory.listener.onMessage( |
| 45 | wsFactory.ws, | 48 | wsFactory.ws, |
| 46 | - SignalClientTest.PARTICIPANT_JOIN.toOkioByteString(), | 49 | + TestData.PARTICIPANT_JOIN.toOkioByteString(), |
| 47 | ) | 50 | ) |
| 48 | 51 | ||
| 49 | room.onAddTrack( | 52 | room.onAddTrack( |
| @@ -16,12 +16,12 @@ | @@ -16,12 +16,12 @@ | ||
| 16 | 16 | ||
| 17 | package io.livekit.android.room.track | 17 | package io.livekit.android.room.track |
| 18 | 18 | ||
| 19 | -import io.livekit.android.BaseTest | ||
| 20 | -import io.livekit.android.events.EventCollector | ||
| 21 | import io.livekit.android.events.TrackEvent | 19 | import io.livekit.android.events.TrackEvent |
| 22 | -import io.livekit.android.mock.MockRtpReceiver | ||
| 23 | -import io.livekit.android.mock.MockVideoStreamTrack | ||
| 24 | import io.livekit.android.room.track.video.VideoSinkVisibility | 20 | import io.livekit.android.room.track.video.VideoSinkVisibility |
| 21 | +import io.livekit.android.test.BaseTest | ||
| 22 | +import io.livekit.android.test.events.EventCollector | ||
| 23 | +import io.livekit.android.test.mock.MockRtpReceiver | ||
| 24 | +import io.livekit.android.test.mock.MockVideoStreamTrack | ||
| 25 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 25 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 26 | import livekit.org.webrtc.VideoFrame | 26 | import livekit.org.webrtc.VideoFrame |
| 27 | import livekit.org.webrtc.VideoSink | 27 | import livekit.org.webrtc.VideoSink |
| 1 | /* | 1 | /* |
| 2 | - * Copyright 2023 LiveKit, Inc. | 2 | + * Copyright 2023-2024 LiveKit, Inc. |
| 3 | * | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
| 1 | /* | 1 | /* |
| 2 | - * Copyright 2023 LiveKit, Inc. | 2 | + * Copyright 2023-2024 LiveKit, Inc. |
| 3 | * | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
| 1 | /* | 1 | /* |
| 2 | - * Copyright 2023 LiveKit, Inc. | 2 | + * Copyright 2023-2024 LiveKit, Inc. |
| 3 | * | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
| @@ -16,7 +16,7 @@ | @@ -16,7 +16,7 @@ | ||
| 16 | 16 | ||
| 17 | package io.livekit.android.webrtc | 17 | package io.livekit.android.webrtc |
| 18 | 18 | ||
| 19 | -import io.livekit.android.BaseTest | 19 | +import io.livekit.android.test.BaseTest |
| 20 | import livekit.org.webrtc.PeerConnection.RTCConfiguration | 20 | import livekit.org.webrtc.PeerConnection.RTCConfiguration |
| 21 | import org.junit.Assert.assertEquals | 21 | import org.junit.Assert.assertEquals |
| 22 | import org.junit.Assert.assertTrue | 22 | import org.junit.Assert.assertTrue |
| @@ -25,6 +25,9 @@ import org.mockito.Mockito | @@ -25,6 +25,9 @@ import org.mockito.Mockito | ||
| 25 | 25 | ||
| 26 | class RTCConfigurationTest : BaseTest() { | 26 | class RTCConfigurationTest : BaseTest() { |
| 27 | 27 | ||
| 28 | + /** | ||
| 29 | + * Make sure that copy handles every declared field. | ||
| 30 | + */ | ||
| 28 | @Test | 31 | @Test |
| 29 | fun copyTest() { | 32 | fun copyTest() { |
| 30 | val originalConfig = RTCConfiguration(mutableListOf()) | 33 | val originalConfig = RTCConfiguration(mutableListOf()) |
| @@ -40,7 +43,9 @@ class RTCConfigurationTest : BaseTest() { | @@ -40,7 +43,9 @@ class RTCConfigurationTest : BaseTest() { | ||
| 40 | } | 43 | } |
| 41 | } | 44 | } |
| 42 | 45 | ||
| 43 | - // Test to make sure the copy test is actually checking properly | 46 | + /** |
| 47 | + * Make sure the copy test is actually checking properly | ||
| 48 | + */ | ||
| 44 | @Test | 49 | @Test |
| 45 | fun copyFailureCheckTest() { | 50 | fun copyFailureCheckTest() { |
| 46 | val originalConfig = RTCConfiguration(mutableListOf()) | 51 | val originalConfig = RTCConfiguration(mutableListOf()) |
| @@ -11,3 +11,4 @@ include ':video-encode-decode-test' | @@ -11,3 +11,4 @@ include ':video-encode-decode-test' | ||
| 11 | include ':sample-app-basic' | 11 | include ':sample-app-basic' |
| 12 | include ':sample-app-record-local' | 12 | include ':sample-app-record-local' |
| 13 | include ':examples:selfie-segmentation' | 13 | include ':examples:selfie-segmentation' |
| 14 | +include ':livekit-android-test' |
-
请 注册 或 登录 后发表评论