正在显示
8 个修改的文件
包含
327 行增加
和
27 行删除
| @@ -35,13 +35,19 @@ sealed class RoomEvent : Event() { | @@ -35,13 +35,19 @@ sealed class RoomEvent : Event() { | ||
| 35 | /** | 35 | /** |
| 36 | * When a [RemoteParticipant] leaves after the local participant has joined. | 36 | * When a [RemoteParticipant] leaves after the local participant has joined. |
| 37 | */ | 37 | */ |
| 38 | - class ParticipantDisconnected(val room: Room, val participant: RemoteParticipant): RoomEvent() | 38 | + class ParticipantDisconnected(val room: Room, val participant: RemoteParticipant) : RoomEvent() |
| 39 | 39 | ||
| 40 | /** | 40 | /** |
| 41 | * Active speakers changed. List of speakers are ordered by their audio level. loudest | 41 | * Active speakers changed. List of speakers are ordered by their audio level. loudest |
| 42 | * speakers first. This will include the [LocalParticipant] too. | 42 | * speakers first. This will include the [LocalParticipant] too. |
| 43 | */ | 43 | */ |
| 44 | - class ActiveSpeakersChanged(val room: Room, val speakers: List<Participant>,): RoomEvent() | 44 | + class ActiveSpeakersChanged(val room: Room, val speakers: List<Participant>) : RoomEvent() |
| 45 | + | ||
| 46 | + class RoomMetadataChanged( | ||
| 47 | + val room: Room, | ||
| 48 | + val newMetadata: String?, | ||
| 49 | + val prevMetadata: String? | ||
| 50 | + ) : RoomEvent() | ||
| 45 | 51 | ||
| 46 | // Participant callbacks | 52 | // Participant callbacks |
| 47 | /** | 53 | /** |
| @@ -49,7 +55,11 @@ sealed class RoomEvent : Event() { | @@ -49,7 +55,11 @@ sealed class RoomEvent : Event() { | ||
| 49 | * When RoomService.UpdateParticipantMetadata is called to change a participant's state, | 55 | * When RoomService.UpdateParticipantMetadata is called to change a participant's state, |
| 50 | * this event will be fired for all clients in the room. | 56 | * this event will be fired for all clients in the room. |
| 51 | */ | 57 | */ |
| 52 | - class MetadataChanged(val room: Room, val participant: Participant, val prevMetadata: String?): RoomEvent() | 58 | + class ParticipantMetadataChanged( |
| 59 | + val room: Room, | ||
| 60 | + val participant: Participant, | ||
| 61 | + val prevMetadata: String? | ||
| 62 | + ) : RoomEvent() | ||
| 53 | 63 | ||
| 54 | /** | 64 | /** |
| 55 | * The participant was muted. | 65 | * The participant was muted. |
| @@ -349,7 +349,10 @@ constructor( | @@ -349,7 +349,10 @@ constructor( | ||
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | override fun onRoomUpdate(update: LivekitModels.Room) { | 351 | override fun onRoomUpdate(update: LivekitModels.Room) { |
| 352 | + val oldMetadata = metadata | ||
| 352 | metadata = update.metadata | 353 | metadata = update.metadata |
| 354 | + | ||
| 355 | + eventBus.postEvent(RoomEvent.RoomMetadataChanged(this, metadata, oldMetadata), coroutineScope) | ||
| 353 | } | 356 | } |
| 354 | 357 | ||
| 355 | override fun onConnectionQuality(updates: List<LivekitRtc.ConnectionQualityInfo>) { | 358 | override fun onConnectionQuality(updates: List<LivekitRtc.ConnectionQualityInfo>) { |
| @@ -403,7 +406,7 @@ constructor( | @@ -403,7 +406,7 @@ constructor( | ||
| 403 | */ | 406 | */ |
| 404 | override fun onMetadataChanged(participant: Participant, prevMetadata: String?) { | 407 | override fun onMetadataChanged(participant: Participant, prevMetadata: String?) { |
| 405 | listener?.onMetadataChanged(participant, prevMetadata, this) | 408 | listener?.onMetadataChanged(participant, prevMetadata, this) |
| 406 | - eventBus.postEvent(RoomEvent.MetadataChanged(this, participant, prevMetadata), coroutineScope) | 409 | + eventBus.postEvent(RoomEvent.ParticipantMetadataChanged(this, participant, prevMetadata), coroutineScope) |
| 407 | } | 410 | } |
| 408 | 411 | ||
| 409 | /** @suppress */ | 412 | /** @suppress */ |
| 1 | +package io.livekit.android.coroutines | ||
| 2 | + | ||
| 3 | +import io.livekit.android.events.EventListenable | ||
| 4 | +import kotlinx.coroutines.CancellationException | ||
| 5 | +import kotlinx.coroutines.cancel | ||
| 6 | +import kotlinx.coroutines.coroutineScope | ||
| 7 | +import kotlinx.coroutines.flow.* | ||
| 8 | +import kotlinx.coroutines.launch | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * Collect events until signal is given. | ||
| 12 | + */ | ||
| 13 | +suspend fun <T> EventListenable<T>.collectEvents(signal: Flow<Unit?>): List<T> { | ||
| 14 | + return events.takeUntilSignal(signal) | ||
| 15 | + .fold(emptyList()) { list, event -> | ||
| 16 | + list.plus(event) | ||
| 17 | + } | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +fun <T> Flow<T>.takeUntilSignal(signal: Flow<Unit?>): Flow<T> = flow { | ||
| 21 | + try { | ||
| 22 | + coroutineScope { | ||
| 23 | + launch { | ||
| 24 | + signal.takeWhile { it == null }.collect() | ||
| 25 | + println("signalled") | ||
| 26 | + this@coroutineScope.cancel() | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + collect { | ||
| 30 | + emit(it) | ||
| 31 | + } | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + } catch (e: CancellationException) { | ||
| 35 | + //ignore | ||
| 36 | + } | ||
| 37 | +} |
| 1 | +package io.livekit.android.events | ||
| 2 | + | ||
| 3 | +import io.livekit.android.coroutines.collectEvents | ||
| 4 | +import kotlinx.coroutines.CoroutineScope | ||
| 5 | +import kotlinx.coroutines.ExperimentalCoroutinesApi | ||
| 6 | +import kotlinx.coroutines.async | ||
| 7 | +import kotlinx.coroutines.flow.MutableStateFlow | ||
| 8 | +import kotlinx.coroutines.test.runBlockingTest | ||
| 9 | + | ||
| 10 | +class EventCollector<T : Event>( | ||
| 11 | + private val eventListenable: EventListenable<T>, | ||
| 12 | + coroutineScope: CoroutineScope | ||
| 13 | +) { | ||
| 14 | + val signal = MutableStateFlow<Unit?>(null) | ||
| 15 | + val collectEventsDeferred = coroutineScope.async { | ||
| 16 | + eventListenable.collectEvents(signal) | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * Stop collecting events. returns the events collected. | ||
| 21 | + */ | ||
| 22 | + @OptIn(ExperimentalCoroutinesApi::class) | ||
| 23 | + fun stopCollectingEvents(): List<T> { | ||
| 24 | + signal.compareAndSet(null, Unit) | ||
| 25 | + var events: List<T> = emptyList() | ||
| 26 | + runBlockingTest { | ||
| 27 | + events = collectEventsDeferred.await() | ||
| 28 | + } | ||
| 29 | + return events | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | +} |
| 1 | +package io.livekit.android.mock | ||
| 2 | + | ||
| 3 | +import livekit.LivekitModels | ||
| 4 | + | ||
| 5 | +object TestData { | ||
| 6 | + | ||
| 7 | + val REMOTE_AUDIO_TRACK = with(LivekitModels.TrackInfo.newBuilder()) { | ||
| 8 | + sid = "remote_audio_track_sid" | ||
| 9 | + type = LivekitModels.TrackType.AUDIO | ||
| 10 | + build() | ||
| 11 | + } | ||
| 12 | + | ||
| 13 | + val LOCAL_PARTICIPANT = with(LivekitModels.ParticipantInfo.newBuilder()) { | ||
| 14 | + sid = "local_participant_sid" | ||
| 15 | + identity = "local_participant_identity" | ||
| 16 | + state = LivekitModels.ParticipantInfo.State.ACTIVE | ||
| 17 | + build() | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + val REMOTE_PARTICIPANT = with(LivekitModels.ParticipantInfo.newBuilder()) { | ||
| 21 | + sid = "remote_participant_sid" | ||
| 22 | + identity = "remote_participant_identity" | ||
| 23 | + state = LivekitModels.ParticipantInfo.State.ACTIVE | ||
| 24 | + addTracks(REMOTE_AUDIO_TRACK) | ||
| 25 | + build() | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + val REMOTE_SPEAKER_INFO = with(LivekitModels.SpeakerInfo.newBuilder()) { | ||
| 30 | + sid = REMOTE_PARTICIPANT.sid | ||
| 31 | + level = 1.0f | ||
| 32 | + active = true | ||
| 33 | + build() | ||
| 34 | + } | ||
| 35 | +} |
| @@ -3,21 +3,20 @@ package io.livekit.android.room | @@ -3,21 +3,20 @@ package io.livekit.android.room | ||
| 3 | import android.content.Context | 3 | import android.content.Context |
| 4 | import androidx.test.core.app.ApplicationProvider | 4 | import androidx.test.core.app.ApplicationProvider |
| 5 | import io.livekit.android.coroutines.TestCoroutineRule | 5 | import io.livekit.android.coroutines.TestCoroutineRule |
| 6 | +import io.livekit.android.events.EventCollector | ||
| 7 | +import io.livekit.android.events.RoomEvent | ||
| 6 | import io.livekit.android.mock.MockWebsocketFactory | 8 | import io.livekit.android.mock.MockWebsocketFactory |
| 7 | import io.livekit.android.mock.dagger.DaggerTestLiveKitComponent | 9 | import io.livekit.android.mock.dagger.DaggerTestLiveKitComponent |
| 8 | import io.livekit.android.room.participant.ConnectionQuality | 10 | import io.livekit.android.room.participant.ConnectionQuality |
| 9 | import io.livekit.android.util.toOkioByteString | 11 | import io.livekit.android.util.toOkioByteString |
| 10 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 12 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 11 | -import kotlinx.coroutines.Job | ||
| 12 | import kotlinx.coroutines.launch | 13 | import kotlinx.coroutines.launch |
| 13 | -import kotlinx.coroutines.test.TestCoroutineScope | ||
| 14 | import kotlinx.coroutines.test.runBlockingTest | 14 | import kotlinx.coroutines.test.runBlockingTest |
| 15 | import org.junit.Assert | 15 | import org.junit.Assert |
| 16 | import org.junit.Before | 16 | import org.junit.Before |
| 17 | import org.junit.Rule | 17 | import org.junit.Rule |
| 18 | import org.junit.Test | 18 | import org.junit.Test |
| 19 | import org.junit.runner.RunWith | 19 | import org.junit.runner.RunWith |
| 20 | -import org.mockito.Mockito | ||
| 21 | import org.mockito.junit.MockitoJUnit | 20 | import org.mockito.junit.MockitoJUnit |
| 22 | import org.robolectric.RobolectricTestRunner | 21 | import org.robolectric.RobolectricTestRunner |
| 23 | 22 | ||
| @@ -71,30 +70,114 @@ class RoomMockE2ETest { | @@ -71,30 +70,114 @@ class RoomMockE2ETest { | ||
| 71 | @Test | 70 | @Test |
| 72 | fun roomUpdateTest() { | 71 | fun roomUpdateTest() { |
| 73 | connect() | 72 | connect() |
| 73 | + val eventCollector = EventCollector(room.events, coroutineRule.scope) | ||
| 74 | wsFactory.listener.onMessage(wsFactory.ws, SignalClientTest.ROOM_UPDATE.toOkioByteString()) | 74 | wsFactory.listener.onMessage(wsFactory.ws, SignalClientTest.ROOM_UPDATE.toOkioByteString()) |
| 75 | + val events = eventCollector.stopCollectingEvents() | ||
| 75 | 76 | ||
| 76 | Assert.assertEquals( | 77 | Assert.assertEquals( |
| 77 | SignalClientTest.ROOM_UPDATE.roomUpdate.room.metadata, | 78 | SignalClientTest.ROOM_UPDATE.roomUpdate.room.metadata, |
| 78 | room.metadata | 79 | room.metadata |
| 79 | ) | 80 | ) |
| 81 | + Assert.assertEquals(1, events.size) | ||
| 82 | + Assert.assertEquals(true, events[0] is RoomEvent.RoomMetadataChanged) | ||
| 80 | } | 83 | } |
| 81 | 84 | ||
| 82 | @Test | 85 | @Test |
| 83 | fun connectionQualityUpdateTest() { | 86 | fun connectionQualityUpdateTest() { |
| 84 | - val roomListener = Mockito.mock(RoomListener::class.java) | ||
| 85 | - room.listener = roomListener | ||
| 86 | - | ||
| 87 | connect() | 87 | connect() |
| 88 | + val eventCollector = EventCollector(room.events, coroutineRule.scope) | ||
| 88 | wsFactory.listener.onMessage( | 89 | wsFactory.listener.onMessage( |
| 89 | wsFactory.ws, | 90 | wsFactory.ws, |
| 90 | SignalClientTest.CONNECTION_QUALITY.toOkioByteString() | 91 | SignalClientTest.CONNECTION_QUALITY.toOkioByteString() |
| 91 | ) | 92 | ) |
| 93 | + val events = eventCollector.stopCollectingEvents() | ||
| 92 | 94 | ||
| 93 | - Assert.assertEquals( | ||
| 94 | - ConnectionQuality.EXCELLENT, | ||
| 95 | - room.localParticipant.connectionQuality | 95 | + Assert.assertEquals(ConnectionQuality.EXCELLENT, room.localParticipant.connectionQuality) |
| 96 | + Assert.assertEquals(1, events.size) | ||
| 97 | + Assert.assertEquals(true, events[0] is RoomEvent.ConnectionQualityChanged) | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + @Test | ||
| 101 | + fun participantConnected() { | ||
| 102 | + connect() | ||
| 103 | + | ||
| 104 | + val eventCollector = EventCollector(room.events, coroutineRule.scope) | ||
| 105 | + wsFactory.listener.onMessage( | ||
| 106 | + wsFactory.ws, | ||
| 107 | + SignalClientTest.PARTICIPANT_JOIN.toOkioByteString() | ||
| 96 | ) | 108 | ) |
| 97 | - Mockito.verify(roomListener) | ||
| 98 | - .onConnectionQualityChanged(room.localParticipant, ConnectionQuality.EXCELLENT) | 109 | + val events = eventCollector.stopCollectingEvents() |
| 110 | + | ||
| 111 | + Assert.assertEquals(1, events.size) | ||
| 112 | + Assert.assertEquals(true, events[0] is RoomEvent.ParticipantConnected) | ||
| 99 | } | 113 | } |
| 114 | + | ||
| 115 | + @Test | ||
| 116 | + fun participantDisconnected() { | ||
| 117 | + connect() | ||
| 118 | + wsFactory.listener.onMessage( | ||
| 119 | + wsFactory.ws, | ||
| 120 | + SignalClientTest.PARTICIPANT_JOIN.toOkioByteString() | ||
| 121 | + ) | ||
| 122 | + | ||
| 123 | + val eventCollector = EventCollector(room.events, coroutineRule.scope) | ||
| 124 | + wsFactory.listener.onMessage( | ||
| 125 | + wsFactory.ws, | ||
| 126 | + SignalClientTest.PARTICIPANT_DISCONNECT.toOkioByteString() | ||
| 127 | + ) | ||
| 128 | + val events = eventCollector.stopCollectingEvents() | ||
| 129 | + | ||
| 130 | + Assert.assertEquals(1, events.size) | ||
| 131 | + Assert.assertEquals(true, events[0] is RoomEvent.ParticipantDisconnected) | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + @Test | ||
| 135 | + fun onActiveSpeakersChanged() { | ||
| 136 | + connect() | ||
| 137 | + | ||
| 138 | + val eventCollector = EventCollector(room.events, coroutineRule.scope) | ||
| 139 | + wsFactory.listener.onMessage( | ||
| 140 | + wsFactory.ws, | ||
| 141 | + SignalClientTest.ACTIVE_SPEAKER_UPDATE.toOkioByteString() | ||
| 142 | + ) | ||
| 143 | + val events = eventCollector.stopCollectingEvents() | ||
| 144 | + | ||
| 145 | + Assert.assertEquals(1, events.size) | ||
| 146 | + Assert.assertEquals(true, events[0] is RoomEvent.ActiveSpeakersChanged) | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + @Test | ||
| 150 | + fun participantMetadataChanged() { | ||
| 151 | + connect() | ||
| 152 | + | ||
| 153 | + wsFactory.listener.onMessage( | ||
| 154 | + wsFactory.ws, | ||
| 155 | + SignalClientTest.PARTICIPANT_JOIN.toOkioByteString() | ||
| 156 | + ) | ||
| 157 | + | ||
| 158 | + val eventCollector = EventCollector(room.events, coroutineRule.scope) | ||
| 159 | + wsFactory.listener.onMessage( | ||
| 160 | + wsFactory.ws, | ||
| 161 | + SignalClientTest.PARTICIPANT_METADATA_CHANGED.toOkioByteString() | ||
| 162 | + ) | ||
| 163 | + val events = eventCollector.stopCollectingEvents() | ||
| 164 | + | ||
| 165 | + Assert.assertEquals(1, events.size) | ||
| 166 | + Assert.assertEquals(true, events[0] is RoomEvent.ParticipantMetadataChanged) | ||
| 167 | + } | ||
| 168 | + | ||
| 169 | + @Test | ||
| 170 | + fun leave() { | ||
| 171 | + connect() | ||
| 172 | + val eventCollector = EventCollector(room.events, coroutineRule.scope) | ||
| 173 | + wsFactory.listener.onMessage( | ||
| 174 | + wsFactory.ws, | ||
| 175 | + SignalClientTest.LEAVE.toOkioByteString() | ||
| 176 | + ) | ||
| 177 | + val events = eventCollector.stopCollectingEvents() | ||
| 178 | + | ||
| 179 | + Assert.assertEquals(1, events.size) | ||
| 180 | + Assert.assertEquals(true, events[0] is RoomEvent.Disconnected) | ||
| 181 | + } | ||
| 182 | + | ||
| 100 | } | 183 | } |
| 1 | package io.livekit.android.room | 1 | package io.livekit.android.room |
| 2 | 2 | ||
| 3 | import android.content.Context | 3 | import android.content.Context |
| 4 | +import android.net.Network | ||
| 4 | import androidx.test.core.app.ApplicationProvider | 5 | import androidx.test.core.app.ApplicationProvider |
| 5 | import io.livekit.android.coroutines.TestCoroutineRule | 6 | import io.livekit.android.coroutines.TestCoroutineRule |
| 7 | +import io.livekit.android.coroutines.collectEvents | ||
| 8 | +import io.livekit.android.events.Event | ||
| 9 | +import io.livekit.android.events.EventCollector | ||
| 10 | +import io.livekit.android.events.EventListenable | ||
| 11 | +import io.livekit.android.events.RoomEvent | ||
| 6 | import io.livekit.android.mock.MockEglBase | 12 | import io.livekit.android.mock.MockEglBase |
| 13 | +import io.livekit.android.mock.TestData | ||
| 7 | import io.livekit.android.room.participant.LocalParticipant | 14 | import io.livekit.android.room.participant.LocalParticipant |
| 8 | -import kotlinx.coroutines.ExperimentalCoroutinesApi | ||
| 9 | -import kotlinx.coroutines.launch | 15 | +import kotlinx.coroutines.* |
| 16 | +import kotlinx.coroutines.flow.MutableStateFlow | ||
| 10 | import kotlinx.coroutines.test.runBlockingTest | 17 | import kotlinx.coroutines.test.runBlockingTest |
| 11 | import livekit.LivekitModels | 18 | import livekit.LivekitModels |
| 19 | +import org.junit.Assert | ||
| 12 | import org.junit.Before | 20 | import org.junit.Before |
| 13 | import org.junit.Rule | 21 | import org.junit.Rule |
| 14 | import org.junit.Test | 22 | import org.junit.Test |
| @@ -56,16 +64,20 @@ class RoomTest { | @@ -56,16 +64,20 @@ class RoomTest { | ||
| 56 | eglBase, | 64 | eglBase, |
| 57 | localParticantFactory, | 65 | localParticantFactory, |
| 58 | DefaultsManager(), | 66 | DefaultsManager(), |
| 59 | - coroutineRule.dispatcher | 67 | + coroutineRule.dispatcher, |
| 68 | + coroutineRule.dispatcher, | ||
| 60 | ) | 69 | ) |
| 61 | } | 70 | } |
| 62 | 71 | ||
| 63 | - @Test | ||
| 64 | - fun connectTest() { | 72 | + fun connect() { |
| 65 | rtcEngine.stub { | 73 | rtcEngine.stub { |
| 66 | onBlocking { rtcEngine.join(any(), any(), anyOrNull()) } | 74 | onBlocking { rtcEngine.join(any(), any(), anyOrNull()) } |
| 67 | .doReturn(SignalClientTest.JOIN.join) | 75 | .doReturn(SignalClientTest.JOIN.join) |
| 68 | } | 76 | } |
| 77 | + rtcEngine.stub { | ||
| 78 | + onBlocking { rtcEngine.client } | ||
| 79 | + .doReturn(Mockito.mock(SignalClient::class.java)) | ||
| 80 | + } | ||
| 69 | val job = coroutineRule.scope.launch { | 81 | val job = coroutineRule.scope.launch { |
| 70 | room.connect( | 82 | room.connect( |
| 71 | url = "http://www.example.com", | 83 | url = "http://www.example.com", |
| @@ -77,4 +89,36 @@ class RoomTest { | @@ -77,4 +89,36 @@ class RoomTest { | ||
| 77 | job.join() | 89 | job.join() |
| 78 | } | 90 | } |
| 79 | } | 91 | } |
| 92 | + | ||
| 93 | + @Test | ||
| 94 | + fun connectTest() { | ||
| 95 | + connect() | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + @Test | ||
| 99 | + fun onConnectionAvailableWillReconnect() { | ||
| 100 | + connect() | ||
| 101 | + | ||
| 102 | + val eventCollector = EventCollector(room.events, coroutineRule.scope) | ||
| 103 | + val network = Mockito.mock(Network::class.java) | ||
| 104 | + room.onLost(network) | ||
| 105 | + room.onAvailable(network) | ||
| 106 | + | ||
| 107 | + val events = eventCollector.stopCollectingEvents() | ||
| 108 | + | ||
| 109 | + Assert.assertEquals(1, events.size) | ||
| 110 | + Assert.assertEquals(true, events[0] is RoomEvent.Reconnecting) | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | + @Test | ||
| 114 | + fun onDisconnect() { | ||
| 115 | + connect() | ||
| 116 | + | ||
| 117 | + val eventCollector = EventCollector(room.events, coroutineRule.scope) | ||
| 118 | + room.onDisconnect("") | ||
| 119 | + val events = eventCollector.stopCollectingEvents() | ||
| 120 | + | ||
| 121 | + Assert.assertEquals(1, events.size) | ||
| 122 | + Assert.assertEquals(true, events[0] is RoomEvent.Disconnected) | ||
| 123 | + } | ||
| 80 | } | 124 | } |
| @@ -2,6 +2,7 @@ package io.livekit.android.room | @@ -2,6 +2,7 @@ package io.livekit.android.room | ||
| 2 | 2 | ||
| 3 | import com.google.protobuf.util.JsonFormat | 3 | import com.google.protobuf.util.JsonFormat |
| 4 | import io.livekit.android.mock.MockWebsocketFactory | 4 | import io.livekit.android.mock.MockWebsocketFactory |
| 5 | +import io.livekit.android.mock.TestData | ||
| 5 | import io.livekit.android.util.toOkioByteString | 6 | import io.livekit.android.util.toOkioByteString |
| 6 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 7 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 7 | import kotlinx.coroutines.async | 8 | import kotlinx.coroutines.async |
| @@ -11,7 +12,10 @@ import kotlinx.coroutines.test.runBlockingTest | @@ -11,7 +12,10 @@ import kotlinx.coroutines.test.runBlockingTest | ||
| 11 | import kotlinx.serialization.json.Json | 12 | import kotlinx.serialization.json.Json |
| 12 | import livekit.LivekitModels | 13 | import livekit.LivekitModels |
| 13 | import livekit.LivekitRtc | 14 | import livekit.LivekitRtc |
| 14 | -import okhttp3.* | 15 | +import okhttp3.OkHttpClient |
| 16 | +import okhttp3.Protocol | ||
| 17 | +import okhttp3.Request | ||
| 18 | +import okhttp3.Response | ||
| 15 | import org.junit.After | 19 | import org.junit.After |
| 16 | import org.junit.Assert | 20 | import org.junit.Assert |
| 17 | import org.junit.Before | 21 | import org.junit.Before |
| @@ -138,11 +142,7 @@ class SignalClientTest { | @@ -138,11 +142,7 @@ class SignalClientTest { | ||
| 138 | sid = "room_sid" | 142 | sid = "room_sid" |
| 139 | build() | 143 | build() |
| 140 | } | 144 | } |
| 141 | - participant = with(participantBuilder) { | ||
| 142 | - sid = "participant_sid" | ||
| 143 | - identity = "participant_identity" | ||
| 144 | - build() | ||
| 145 | - } | 145 | + participant = TestData.LOCAL_PARTICIPANT |
| 146 | build() | 146 | build() |
| 147 | } | 147 | } |
| 148 | build() | 148 | build() |
| @@ -168,9 +168,58 @@ class SignalClientTest { | @@ -168,9 +168,58 @@ class SignalClientTest { | ||
| 168 | build() | 168 | build() |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | + val TRACK_PUBLISHED = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 172 | + trackPublished = with(trackPublishedBuilder) { | ||
| 173 | + track = TestData.REMOTE_AUDIO_TRACK | ||
| 174 | + build() | ||
| 175 | + } | ||
| 176 | + build() | ||
| 177 | + } | ||
| 178 | + | ||
| 179 | + val PARTICIPANT_JOIN = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 180 | + update = with(LivekitRtc.ParticipantUpdate.newBuilder()) { | ||
| 181 | + addParticipants(TestData.REMOTE_PARTICIPANT) | ||
| 182 | + build() | ||
| 183 | + } | ||
| 184 | + build() | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + val PARTICIPANT_DISCONNECT = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 188 | + update = with(LivekitRtc.ParticipantUpdate.newBuilder()) { | ||
| 189 | + val disconnectedParticipant = TestData.REMOTE_PARTICIPANT.toBuilder() | ||
| 190 | + .setState(LivekitModels.ParticipantInfo.State.DISCONNECTED) | ||
| 191 | + .build() | ||
| 192 | + | ||
| 193 | + addParticipants(disconnectedParticipant) | ||
| 194 | + build() | ||
| 195 | + } | ||
| 196 | + build() | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | + val ACTIVE_SPEAKER_UPDATE = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 200 | + speakersChanged = with(LivekitRtc.SpeakersChanged.newBuilder()) { | ||
| 201 | + addSpeakers(TestData.REMOTE_SPEAKER_INFO) | ||
| 202 | + build() | ||
| 203 | + } | ||
| 204 | + build() | ||
| 205 | + } | ||
| 206 | + | ||
| 207 | + val PARTICIPANT_METADATA_CHANGED = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 208 | + update = with(LivekitRtc.ParticipantUpdate.newBuilder()) { | ||
| 209 | + val participantMetadataChanged = TestData.REMOTE_PARTICIPANT.toBuilder() | ||
| 210 | + .setMetadata("changed_metadata") | ||
| 211 | + .build() | ||
| 212 | + | ||
| 213 | + addParticipants(participantMetadataChanged) | ||
| 214 | + build() | ||
| 215 | + } | ||
| 216 | + build() | ||
| 217 | + } | ||
| 218 | + | ||
| 219 | + | ||
| 171 | val CONNECTION_QUALITY = with(LivekitRtc.SignalResponse.newBuilder()) { | 220 | val CONNECTION_QUALITY = with(LivekitRtc.SignalResponse.newBuilder()) { |
| 172 | connectionQuality = with(connectionQualityBuilder) { | 221 | connectionQuality = with(connectionQualityBuilder) { |
| 173 | - addUpdates(with(LivekitRtc.ConnectionQualityInfo.newBuilder()){ | 222 | + addUpdates(with(LivekitRtc.ConnectionQualityInfo.newBuilder()) { |
| 174 | participantSid = JOIN.join.participant.sid | 223 | participantSid = JOIN.join.participant.sid |
| 175 | quality = LivekitModels.ConnectionQuality.EXCELLENT | 224 | quality = LivekitModels.ConnectionQuality.EXCELLENT |
| 176 | build() | 225 | build() |
| @@ -179,5 +228,12 @@ class SignalClientTest { | @@ -179,5 +228,12 @@ class SignalClientTest { | ||
| 179 | } | 228 | } |
| 180 | build() | 229 | build() |
| 181 | } | 230 | } |
| 231 | + | ||
| 232 | + val LEAVE = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 233 | + leave = with(leaveBuilder) { | ||
| 234 | + build() | ||
| 235 | + } | ||
| 236 | + build() | ||
| 237 | + } | ||
| 182 | } | 238 | } |
| 183 | } | 239 | } |
-
请 注册 或 登录 后发表评论