mirror of
https://github.com/nextcloud/talk-android
synced 2025-03-07 06:39:45 +00:00
Send state also through signaling messages
The speaking state is still sent only through data channels, as it is not currently handled by other clients when sent through signaling messages. Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
This commit is contained in:
parent
73105515bd
commit
512b320015
@ -7,6 +7,8 @@
|
||||
package com.nextcloud.talk.call;
|
||||
|
||||
import com.nextcloud.talk.models.json.signaling.DataChannelMessage;
|
||||
import com.nextcloud.talk.models.json.signaling.NCMessagePayload;
|
||||
import com.nextcloud.talk.models.json.signaling.NCSignalingMessage;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@ -48,6 +50,7 @@ public abstract class LocalStateBroadcaster {
|
||||
audioEnabled = localCallParticipantModel.isAudioEnabled();
|
||||
|
||||
messageSender.sendToAll(getDataChannelMessageForAudioState());
|
||||
messageSender.sendToAll(getSignalingMessageForAudioState());
|
||||
}
|
||||
|
||||
if (!Objects.equals(speaking, localCallParticipantModel.isSpeaking())) {
|
||||
@ -60,6 +63,7 @@ public abstract class LocalStateBroadcaster {
|
||||
videoEnabled = localCallParticipantModel.isVideoEnabled();
|
||||
|
||||
messageSender.sendToAll(getDataChannelMessageForVideoState());
|
||||
messageSender.sendToAll(getSignalingMessageForVideoState());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -106,4 +110,61 @@ public abstract class LocalStateBroadcaster {
|
||||
|
||||
return new DataChannelMessage(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a signaling message with the common fields set (type and room type).
|
||||
*
|
||||
* @param type the type of the signaling message
|
||||
* @return the signaling message
|
||||
*/
|
||||
private NCSignalingMessage createBaseSignalingMessage(String type) {
|
||||
NCSignalingMessage ncSignalingMessage = new NCSignalingMessage();
|
||||
// "roomType" is not really relevant without a peer or when referring to the whole participant, but it is
|
||||
// nevertheless expected in the message. As most of the signaling messages currently sent to all participants
|
||||
// are related to audio/video state "video" is used as the room type.
|
||||
ncSignalingMessage.setRoomType("video");
|
||||
ncSignalingMessage.setType(type);
|
||||
|
||||
return ncSignalingMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a signaling message to notify current audio state.
|
||||
*
|
||||
* @return the signaling message
|
||||
*/
|
||||
protected NCSignalingMessage getSignalingMessageForAudioState() {
|
||||
String type = "mute";
|
||||
if (localCallParticipantModel.isAudioEnabled() != null && localCallParticipantModel.isAudioEnabled()) {
|
||||
type = "unmute";
|
||||
}
|
||||
|
||||
NCSignalingMessage ncSignalingMessage = createBaseSignalingMessage(type);
|
||||
|
||||
NCMessagePayload ncMessagePayload = new NCMessagePayload();
|
||||
ncMessagePayload.setName("audio");
|
||||
ncSignalingMessage.setPayload(ncMessagePayload);
|
||||
|
||||
return ncSignalingMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a signaling message to notify current video state.
|
||||
*
|
||||
* @return the signaling message
|
||||
*/
|
||||
protected NCSignalingMessage getSignalingMessageForVideoState() {
|
||||
String type = "mute";
|
||||
if (localCallParticipantModel.isVideoEnabled() != null && localCallParticipantModel.isVideoEnabled()) {
|
||||
type = "unmute";
|
||||
}
|
||||
|
||||
NCSignalingMessage ncSignalingMessage = createBaseSignalingMessage(type);
|
||||
|
||||
NCMessagePayload ncMessagePayload = new NCMessagePayload();
|
||||
ncMessagePayload.setName("video");
|
||||
ncSignalingMessage.setPayload(ncMessagePayload);
|
||||
|
||||
return ncSignalingMessage;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
*/
|
||||
package com.nextcloud.talk.call;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
@ -26,11 +28,30 @@ import io.reactivex.schedulers.Schedulers;
|
||||
* initial state when the local participant joins the call, as all the remote participants joined from the point of
|
||||
* view of the local participant). If the state was already being sent the sending is restarted with each new
|
||||
* participant that joins.
|
||||
* <p>
|
||||
* Similarly, in the case of signaling messages it is not possible either to know when the remote participants have
|
||||
* "seen" the local participant and thus are ready to handle signaling messages about the state. However, in the case
|
||||
* of signaling messages it is possible to send them to a specific participant, so the initial state is sent several
|
||||
* times with an increasing delay directly to the participant that was added. Moreover, if the participant is removed
|
||||
* the state is no longer directly sent.
|
||||
* <p>
|
||||
* In any case, note that the state is sent only when the remote participant joins the call. Even in case of
|
||||
* temporary disconnections the normal state updates sent when the state changes are expected to be received by the
|
||||
* other participant, as signaling messages are sent through a WebSocket and are therefore reliable. Moreover, even
|
||||
* if the WebSocket is restarted and the connection resumed (rather than joining with a new session ID) the messages
|
||||
* would be also received, as in that case they would be queued until the WebSocket is connected again.
|
||||
* <p>
|
||||
* Data channel messages, on the other hand, could be lost if the remote participant restarts the peer receiver
|
||||
* connection (although they would be received in case of temporary disconnections, as data channels use a reliable
|
||||
* transport by default). Therefore, as the speaking state is sent only through data channels, updates of the speaking
|
||||
* state could be not received by remote participants.
|
||||
*/
|
||||
public class LocalStateBroadcasterMcu extends LocalStateBroadcaster {
|
||||
|
||||
private final MessageSender messageSender;
|
||||
|
||||
private final Map<String, Disposable> sendStateWithRepetitionByParticipant = new HashMap<>();
|
||||
|
||||
private Disposable sendStateWithRepetition;
|
||||
|
||||
public LocalStateBroadcasterMcu(LocalCallParticipantModel localCallParticipantModel,
|
||||
@ -46,6 +67,10 @@ public class LocalStateBroadcasterMcu extends LocalStateBroadcaster {
|
||||
if (sendStateWithRepetition != null) {
|
||||
sendStateWithRepetition.dispose();
|
||||
}
|
||||
|
||||
for (Disposable sendStateWithRepetitionForParticipant: sendStateWithRepetitionByParticipant.values()) {
|
||||
sendStateWithRepetitionForParticipant.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -58,10 +83,26 @@ public class LocalStateBroadcasterMcu extends LocalStateBroadcaster {
|
||||
.fromArray(new Integer[]{0, 1, 2, 4, 8, 16})
|
||||
.concatMap(i -> Observable.just(i).delay(i, TimeUnit.SECONDS, Schedulers.io()))
|
||||
.subscribe(value -> sendState());
|
||||
|
||||
String sessionId = callParticipantModel.getSessionId();
|
||||
Disposable sendStateWithRepetitionForParticipant = sendStateWithRepetitionByParticipant.get(sessionId);
|
||||
if (sendStateWithRepetitionForParticipant != null) {
|
||||
sendStateWithRepetitionForParticipant.dispose();
|
||||
}
|
||||
|
||||
sendStateWithRepetitionByParticipant.put(sessionId, Observable
|
||||
.fromArray(new Integer[]{0, 1, 2, 4, 8, 16})
|
||||
.concatMap(i -> Observable.just(i).delay(i, TimeUnit.SECONDS, Schedulers.io()))
|
||||
.subscribe(value -> sendState(sessionId)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCallParticipantRemoved(CallParticipantModel callParticipantModel) {
|
||||
String sessionId = callParticipantModel.getSessionId();
|
||||
Disposable sendStateWithRepetitionForParticipant = sendStateWithRepetitionByParticipant.get(sessionId);
|
||||
if (sendStateWithRepetitionForParticipant != null) {
|
||||
sendStateWithRepetitionForParticipant.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void sendState() {
|
||||
@ -69,4 +110,9 @@ public class LocalStateBroadcasterMcu extends LocalStateBroadcaster {
|
||||
messageSender.sendToAll(getDataChannelMessageForSpeakingState());
|
||||
messageSender.sendToAll(getDataChannelMessageForVideoState());
|
||||
}
|
||||
|
||||
private void sendState(String sessionId) {
|
||||
messageSender.send(getSignalingMessageForAudioState(), sessionId);
|
||||
messageSender.send(getSignalingMessageForVideoState(), sessionId);
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,12 @@ import java.util.Objects;
|
||||
* after a temporary disconnection; data channels use a reliable transport by default, so even if the state changes
|
||||
* while the connection is temporarily interrupted the normal state update messages should be received by the other
|
||||
* participant once the connection is restored.
|
||||
* <p>
|
||||
* Nevertheless, in case of a failed connection and an ICE restart it is unclear whether the data channel messages
|
||||
* would be received or not (as the data channel transport may be the one that failed and needs to be restarted).
|
||||
* However, the state (except the speaking state) is also sent through signaling messages, which need to be
|
||||
* explicitly fetched from the internal signaling server, so even in case of a failed connection they will be
|
||||
* eventually received once the remote participant connects again.
|
||||
*/
|
||||
public class LocalStateBroadcasterNoMcu extends LocalStateBroadcaster {
|
||||
|
||||
@ -115,5 +121,8 @@ public class LocalStateBroadcasterNoMcu extends LocalStateBroadcaster {
|
||||
messageSender.send(getDataChannelMessageForAudioState(), sessionId);
|
||||
messageSender.send(getDataChannelMessageForSpeakingState(), sessionId);
|
||||
messageSender.send(getDataChannelMessageForVideoState(), sessionId);
|
||||
|
||||
messageSender.send(getSignalingMessageForAudioState(), sessionId);
|
||||
messageSender.send(getSignalingMessageForVideoState(), sessionId);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
package com.nextcloud.talk.call
|
||||
|
||||
import com.nextcloud.talk.models.json.signaling.DataChannelMessage
|
||||
import com.nextcloud.talk.models.json.signaling.NCMessagePayload
|
||||
import com.nextcloud.talk.models.json.signaling.NCSignalingMessage
|
||||
import io.reactivex.plugins.RxJavaPlugins
|
||||
import io.reactivex.schedulers.TestScheduler
|
||||
import org.junit.Before
|
||||
@ -32,6 +34,54 @@ class LocalStateBroadcasterMcuTest {
|
||||
mockedMessageSender = Mockito.mock(MessageSender::class.java)
|
||||
}
|
||||
|
||||
private fun getExpectedUnmuteAudio(): NCSignalingMessage {
|
||||
val expectedUnmuteAudio = NCSignalingMessage()
|
||||
expectedUnmuteAudio.roomType = "video"
|
||||
expectedUnmuteAudio.type = "unmute"
|
||||
|
||||
val payload = NCMessagePayload()
|
||||
payload.name = "audio"
|
||||
expectedUnmuteAudio.payload = payload
|
||||
|
||||
return expectedUnmuteAudio
|
||||
}
|
||||
|
||||
private fun getExpectedMuteAudio(): NCSignalingMessage {
|
||||
val expectedMuteAudio = NCSignalingMessage()
|
||||
expectedMuteAudio.roomType = "video"
|
||||
expectedMuteAudio.type = "mute"
|
||||
|
||||
val payload = NCMessagePayload()
|
||||
payload.name = "audio"
|
||||
expectedMuteAudio.payload = payload
|
||||
|
||||
return expectedMuteAudio
|
||||
}
|
||||
|
||||
private fun getExpectedUnmuteVideo(): NCSignalingMessage {
|
||||
val expectedUnmuteVideo = NCSignalingMessage()
|
||||
expectedUnmuteVideo.roomType = "video"
|
||||
expectedUnmuteVideo.type = "unmute"
|
||||
|
||||
val payload = NCMessagePayload()
|
||||
payload.name = "video"
|
||||
expectedUnmuteVideo.payload = payload
|
||||
|
||||
return expectedUnmuteVideo
|
||||
}
|
||||
|
||||
private fun getExpectedMuteVideo(): NCSignalingMessage {
|
||||
val expectedMuteVideo = NCSignalingMessage()
|
||||
expectedMuteVideo.roomType = "video"
|
||||
expectedMuteVideo.type = "mute"
|
||||
|
||||
val payload = NCMessagePayload()
|
||||
payload.name = "video"
|
||||
expectedMuteVideo.payload = payload
|
||||
|
||||
return expectedMuteVideo
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStateSentWithExponentialBackoffWhenParticipantAdded() {
|
||||
val testScheduler = TestScheduler()
|
||||
@ -54,12 +104,17 @@ class LocalStateBroadcasterMcuTest {
|
||||
val expectedSpeaking = DataChannelMessage("speaking")
|
||||
val expectedVideoOn = DataChannelMessage("videoOn")
|
||||
|
||||
val expectedUnmuteAudio = getExpectedUnmuteAudio()
|
||||
val expectedUnmuteVideo = getExpectedUnmuteVideo()
|
||||
|
||||
testScheduler.advanceTimeBy(0, TimeUnit.SECONDS)
|
||||
|
||||
var messageCount = 1
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(1, TimeUnit.SECONDS)
|
||||
@ -68,6 +123,8 @@ class LocalStateBroadcasterMcuTest {
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS)
|
||||
@ -76,6 +133,8 @@ class LocalStateBroadcasterMcuTest {
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(4, TimeUnit.SECONDS)
|
||||
@ -84,6 +143,8 @@ class LocalStateBroadcasterMcuTest {
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(8, TimeUnit.SECONDS)
|
||||
@ -92,6 +153,8 @@ class LocalStateBroadcasterMcuTest {
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(16, TimeUnit.SECONDS)
|
||||
@ -100,6 +163,8 @@ class LocalStateBroadcasterMcuTest {
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(100, TimeUnit.SECONDS)
|
||||
@ -132,11 +197,16 @@ class LocalStateBroadcasterMcuTest {
|
||||
val expectedSpeaking = DataChannelMessage("speaking")
|
||||
val expectedVideoOn = DataChannelMessage("videoOn")
|
||||
|
||||
val expectedUnmuteAudio = getExpectedUnmuteAudio()
|
||||
val expectedUnmuteVideo = getExpectedUnmuteVideo()
|
||||
|
||||
testScheduler.advanceTimeBy(0, TimeUnit.SECONDS)
|
||||
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
localCallParticipantModel!!.isSpeaking = false
|
||||
@ -151,51 +221,73 @@ class LocalStateBroadcasterMcuTest {
|
||||
Mockito.verify(mockedMessageSender!!, times(2)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(2)).sendToAll(expectedStoppedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(2)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(2)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(2)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
localCallParticipantModel!!.isAudioEnabled = false
|
||||
|
||||
val expectedAudioOff = DataChannelMessage("audioOff")
|
||||
val expectedMuteAudio = getExpectedMuteAudio()
|
||||
|
||||
// Changing the state causes the normal state update to be sent, independently of the initial state
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedAudioOff)
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedMuteAudio)
|
||||
|
||||
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS)
|
||||
|
||||
Mockito.verify(mockedMessageSender!!, times(2)).sendToAll(expectedAudioOff)
|
||||
Mockito.verify(mockedMessageSender!!, times(3)).sendToAll(expectedStoppedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(3)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedMuteAudio)
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).send(expectedMuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(3)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
localCallParticipantModel!!.isVideoEnabled = false
|
||||
|
||||
val expectedVideoOff = DataChannelMessage("videoOff")
|
||||
val expectedMuteVideo = getExpectedMuteVideo()
|
||||
|
||||
// Changing the state causes the normal state update to be sent, independently of the initial state
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedVideoOff)
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedMuteVideo)
|
||||
|
||||
testScheduler.advanceTimeBy(4, TimeUnit.SECONDS)
|
||||
|
||||
Mockito.verify(mockedMessageSender!!, times(3)).sendToAll(expectedAudioOff)
|
||||
Mockito.verify(mockedMessageSender!!, times(4)).sendToAll(expectedStoppedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(2)).sendToAll(expectedVideoOff)
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedMuteAudio)
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedMuteVideo)
|
||||
Mockito.verify(mockedMessageSender!!, times(2)).send(expectedMuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).send(expectedMuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
localCallParticipantModel!!.isVideoEnabled = true
|
||||
|
||||
// Changing the state causes the normal state update to be sent, independently of the initial state
|
||||
Mockito.verify(mockedMessageSender!!, times(4)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedUnmuteVideo)
|
||||
|
||||
testScheduler.advanceTimeBy(8, TimeUnit.SECONDS)
|
||||
|
||||
Mockito.verify(mockedMessageSender!!, times(4)).sendToAll(expectedAudioOff)
|
||||
Mockito.verify(mockedMessageSender!!, times(5)).sendToAll(expectedStoppedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(5)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedMuteAudio)
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedMuteVideo)
|
||||
Mockito.verify(mockedMessageSender!!, times(1)).sendToAll(expectedUnmuteVideo)
|
||||
Mockito.verify(mockedMessageSender!!, times(3)).send(expectedMuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(4)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStateSentWithExponentialBackoffRestartedWhenAnotherParticipantAdded() {
|
||||
fun testStateSentWithExponentialBackoffWhenAnotherParticipantAdded() {
|
||||
// The state sent through data channels should be restarted, although the state sent through signaling
|
||||
// messages should be independent for each participant.
|
||||
|
||||
val testScheduler = TestScheduler()
|
||||
RxJavaPlugins.setIoSchedulerHandler { testScheduler }
|
||||
|
||||
@ -216,36 +308,51 @@ class LocalStateBroadcasterMcuTest {
|
||||
val expectedSpeaking = DataChannelMessage("speaking")
|
||||
val expectedVideoOn = DataChannelMessage("videoOn")
|
||||
|
||||
val expectedUnmuteAudio = getExpectedUnmuteAudio()
|
||||
val expectedUnmuteVideo = getExpectedUnmuteVideo()
|
||||
|
||||
testScheduler.advanceTimeBy(0, TimeUnit.SECONDS)
|
||||
|
||||
var dataChannelMessageCount = 1
|
||||
var signalingMessageCount1 = 1
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(1, TimeUnit.SECONDS)
|
||||
|
||||
dataChannelMessageCount = 2
|
||||
signalingMessageCount1 = 2
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS)
|
||||
|
||||
dataChannelMessageCount = 3
|
||||
signalingMessageCount1 = 3
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(4, TimeUnit.SECONDS)
|
||||
|
||||
dataChannelMessageCount = 4
|
||||
signalingMessageCount1 = 4
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
val callParticipantModel2 = MutableCallParticipantModel("theSessionId2")
|
||||
@ -255,49 +362,107 @@ class LocalStateBroadcasterMcuTest {
|
||||
testScheduler.advanceTimeBy(0, TimeUnit.SECONDS)
|
||||
|
||||
dataChannelMessageCount = 5
|
||||
var signalingMessageCount2 = 1
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteAudio, "theSessionId2")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteVideo, "theSessionId2")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(1, TimeUnit.SECONDS)
|
||||
|
||||
dataChannelMessageCount = 6
|
||||
signalingMessageCount2 = 2
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteAudio, "theSessionId2")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteVideo, "theSessionId2")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS)
|
||||
|
||||
dataChannelMessageCount = 7
|
||||
signalingMessageCount2 = 3
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteAudio, "theSessionId2")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteVideo, "theSessionId2")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(4, TimeUnit.SECONDS)
|
||||
|
||||
dataChannelMessageCount = 8
|
||||
signalingMessageCount2 = 4
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteAudio, "theSessionId2")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteVideo, "theSessionId2")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(8, TimeUnit.SECONDS)
|
||||
// 0+1+2+4+1=8 seconds since last signaling messages for participant 1
|
||||
testScheduler.advanceTimeBy(1, TimeUnit.SECONDS)
|
||||
|
||||
signalingMessageCount1 = 5
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteAudio, "theSessionId2")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteVideo, "theSessionId2")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
// 1+7=8 seconds since last data channel messages and signaling messages for participant 2
|
||||
testScheduler.advanceTimeBy(7, TimeUnit.SECONDS)
|
||||
|
||||
dataChannelMessageCount = 9
|
||||
signalingMessageCount2 = 5
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteAudio, "theSessionId2")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteVideo, "theSessionId2")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(16, TimeUnit.SECONDS)
|
||||
// 7+9=16 seconds since last signaling messages for participant 1
|
||||
testScheduler.advanceTimeBy(9, TimeUnit.SECONDS)
|
||||
|
||||
dataChannelMessageCount = 10
|
||||
signalingMessageCount1 = 6
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteAudio, "theSessionId2")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteVideo, "theSessionId2")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
// 9+7=16 seconds since last data channel messages and signaling messages for participant 2
|
||||
testScheduler.advanceTimeBy(7, TimeUnit.SECONDS)
|
||||
|
||||
dataChannelMessageCount = 10
|
||||
signalingMessageCount2 = 6
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount1)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteAudio, "theSessionId2")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount2)).send(expectedUnmuteVideo, "theSessionId2")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(100, TimeUnit.SECONDS)
|
||||
@ -306,8 +471,9 @@ class LocalStateBroadcasterMcuTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStateStillSentWithExponentialBackoffWhenParticipantRemoved() {
|
||||
fun testStateSentWithExponentialBackoffWhenParticipantRemoved() {
|
||||
// For simplicity the exponential backoff is not aborted when the participant that triggered it is removed.
|
||||
// However, the signaling messages are stopped when the participant is removed.
|
||||
|
||||
val testScheduler = TestScheduler()
|
||||
RxJavaPlugins.setIoSchedulerHandler { testScheduler }
|
||||
@ -329,36 +495,51 @@ class LocalStateBroadcasterMcuTest {
|
||||
val expectedSpeaking = DataChannelMessage("speaking")
|
||||
val expectedVideoOn = DataChannelMessage("videoOn")
|
||||
|
||||
val expectedUnmuteAudio = getExpectedUnmuteAudio()
|
||||
val expectedUnmuteVideo = getExpectedUnmuteVideo()
|
||||
|
||||
testScheduler.advanceTimeBy(0, TimeUnit.SECONDS)
|
||||
|
||||
var dataChannelMessageCount = 1
|
||||
var signalingMessageCount = 1
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(1, TimeUnit.SECONDS)
|
||||
|
||||
dataChannelMessageCount = 2
|
||||
signalingMessageCount = 2
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS)
|
||||
|
||||
dataChannelMessageCount = 3
|
||||
signalingMessageCount = 3
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(4, TimeUnit.SECONDS)
|
||||
|
||||
dataChannelMessageCount = 4
|
||||
signalingMessageCount = 4
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
localStateBroadcasterMcu!!.handleCallParticipantRemoved(callParticipantModel)
|
||||
@ -369,6 +550,8 @@ class LocalStateBroadcasterMcuTest {
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(16, TimeUnit.SECONDS)
|
||||
@ -377,6 +560,8 @@ class LocalStateBroadcasterMcuTest {
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(dataChannelMessageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(signalingMessageCount)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(100, TimeUnit.SECONDS)
|
||||
@ -395,8 +580,10 @@ class LocalStateBroadcasterMcuTest {
|
||||
)
|
||||
|
||||
val callParticipantModel = MutableCallParticipantModel("theSessionId")
|
||||
val callParticipantModel2 = MutableCallParticipantModel("theSessionId2")
|
||||
|
||||
localStateBroadcasterMcu!!.handleCallParticipantAdded(callParticipantModel)
|
||||
localStateBroadcasterMcu!!.handleCallParticipantAdded(callParticipantModel2)
|
||||
|
||||
// Sending will be done in another thread, so just adding the participant does not send anything until that
|
||||
// other thread could run.
|
||||
@ -406,12 +593,19 @@ class LocalStateBroadcasterMcuTest {
|
||||
val expectedSpeaking = DataChannelMessage("speaking")
|
||||
val expectedVideoOn = DataChannelMessage("videoOn")
|
||||
|
||||
val expectedUnmuteAudio = getExpectedUnmuteAudio()
|
||||
val expectedUnmuteVideo = getExpectedUnmuteVideo()
|
||||
|
||||
testScheduler.advanceTimeBy(0, TimeUnit.SECONDS)
|
||||
|
||||
var messageCount = 1
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId2")
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId2")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(1, TimeUnit.SECONDS)
|
||||
@ -420,6 +614,10 @@ class LocalStateBroadcasterMcuTest {
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId2")
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId2")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS)
|
||||
@ -428,6 +626,10 @@ class LocalStateBroadcasterMcuTest {
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteAudio, "theSessionId2")
|
||||
Mockito.verify(mockedMessageSender!!, times(messageCount)).send(expectedUnmuteVideo, "theSessionId2")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
|
||||
localStateBroadcasterMcu!!.destroy()
|
||||
|
@ -7,6 +7,8 @@
|
||||
package com.nextcloud.talk.call
|
||||
|
||||
import com.nextcloud.talk.models.json.signaling.DataChannelMessage
|
||||
import com.nextcloud.talk.models.json.signaling.NCMessagePayload
|
||||
import com.nextcloud.talk.models.json.signaling.NCSignalingMessage
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.Mockito
|
||||
@ -28,6 +30,30 @@ class LocalStateBroadcasterNoMcuTest {
|
||||
mockedMessageSenderNoMcu = Mockito.mock(MessageSenderNoMcu::class.java)
|
||||
}
|
||||
|
||||
private fun getExpectedUnmuteAudio(): NCSignalingMessage {
|
||||
val expectedUnmuteAudio = NCSignalingMessage()
|
||||
expectedUnmuteAudio.roomType = "video"
|
||||
expectedUnmuteAudio.type = "unmute"
|
||||
|
||||
val payload = NCMessagePayload()
|
||||
payload.name = "audio"
|
||||
expectedUnmuteAudio.payload = payload
|
||||
|
||||
return expectedUnmuteAudio
|
||||
}
|
||||
|
||||
private fun getExpectedUnmuteVideo(): NCSignalingMessage {
|
||||
val expectedUnmuteVideo = NCSignalingMessage()
|
||||
expectedUnmuteVideo.roomType = "video"
|
||||
expectedUnmuteVideo.type = "unmute"
|
||||
|
||||
val payload = NCMessagePayload()
|
||||
payload.name = "video"
|
||||
expectedUnmuteVideo.payload = payload
|
||||
|
||||
return expectedUnmuteVideo
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStateSentWhenIceConnected() {
|
||||
localStateBroadcasterNoMcu = LocalStateBroadcasterNoMcu(
|
||||
@ -49,9 +75,14 @@ class LocalStateBroadcasterNoMcuTest {
|
||||
val expectedSpeaking = DataChannelMessage("speaking")
|
||||
val expectedVideoOn = DataChannelMessage("videoOn")
|
||||
|
||||
val expectedUnmuteAudio = getExpectedUnmuteAudio()
|
||||
val expectedUnmuteVideo = getExpectedUnmuteVideo()
|
||||
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedAudioOn, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedSpeaking, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedVideoOn, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSenderNoMcu)
|
||||
}
|
||||
|
||||
@ -76,9 +107,14 @@ class LocalStateBroadcasterNoMcuTest {
|
||||
val expectedSpeaking = DataChannelMessage("speaking")
|
||||
val expectedVideoOn = DataChannelMessage("videoOn")
|
||||
|
||||
val expectedUnmuteAudio = getExpectedUnmuteAudio()
|
||||
val expectedUnmuteVideo = getExpectedUnmuteVideo()
|
||||
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedAudioOn, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedSpeaking, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedVideoOn, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSenderNoMcu)
|
||||
}
|
||||
|
||||
@ -103,9 +139,14 @@ class LocalStateBroadcasterNoMcuTest {
|
||||
val expectedSpeaking = DataChannelMessage("speaking")
|
||||
val expectedVideoOn = DataChannelMessage("videoOn")
|
||||
|
||||
val expectedUnmuteAudio = getExpectedUnmuteAudio()
|
||||
val expectedUnmuteVideo = getExpectedUnmuteVideo()
|
||||
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedAudioOn, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedSpeaking, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedVideoOn, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSenderNoMcu)
|
||||
|
||||
callParticipantModel.setIceConnectionState(PeerConnection.IceConnectionState.COMPLETED)
|
||||
@ -134,9 +175,14 @@ class LocalStateBroadcasterNoMcuTest {
|
||||
val expectedSpeaking = DataChannelMessage("speaking")
|
||||
val expectedVideoOn = DataChannelMessage("videoOn")
|
||||
|
||||
val expectedUnmuteAudio = getExpectedUnmuteAudio()
|
||||
val expectedUnmuteVideo = getExpectedUnmuteVideo()
|
||||
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedAudioOn, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedSpeaking, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedVideoOn, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSenderNoMcu)
|
||||
|
||||
callParticipantModel.setIceConnectionState(PeerConnection.IceConnectionState.COMPLETED)
|
||||
@ -191,9 +237,14 @@ class LocalStateBroadcasterNoMcuTest {
|
||||
val expectedSpeaking = DataChannelMessage("speaking")
|
||||
val expectedVideoOn = DataChannelMessage("videoOn")
|
||||
|
||||
val expectedUnmuteAudio = getExpectedUnmuteAudio()
|
||||
val expectedUnmuteVideo = getExpectedUnmuteVideo()
|
||||
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedAudioOn, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedSpeaking, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedVideoOn, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteAudio, "theSessionId")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteVideo, "theSessionId")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSenderNoMcu)
|
||||
|
||||
callParticipantModel2.setIceConnectionState(PeerConnection.IceConnectionState.CONNECTED)
|
||||
@ -201,6 +252,8 @@ class LocalStateBroadcasterNoMcuTest {
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedAudioOn, "theSessionId2")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedSpeaking, "theSessionId2")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedVideoOn, "theSessionId2")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteAudio, "theSessionId2")
|
||||
Mockito.verify(mockedMessageSenderNoMcu!!).send(expectedUnmuteVideo, "theSessionId2")
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSenderNoMcu)
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
package com.nextcloud.talk.call
|
||||
|
||||
import com.nextcloud.talk.models.json.signaling.DataChannelMessage
|
||||
import com.nextcloud.talk.models.json.signaling.NCMessagePayload
|
||||
import com.nextcloud.talk.models.json.signaling.NCSignalingMessage
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.Mockito
|
||||
@ -49,7 +51,15 @@ class LocalStateBroadcasterTest {
|
||||
|
||||
val expectedAudioOn = DataChannelMessage("audioOn")
|
||||
|
||||
val expectedUnmuteAudio = NCSignalingMessage()
|
||||
expectedUnmuteAudio.roomType = "video"
|
||||
expectedUnmuteAudio.type = "unmute"
|
||||
val payload = NCMessagePayload()
|
||||
payload.name = "audio"
|
||||
expectedUnmuteAudio.payload = payload
|
||||
|
||||
Mockito.verify(mockedMessageSender!!).sendToAll(expectedAudioOn)
|
||||
Mockito.verify(mockedMessageSender!!).sendToAll(expectedUnmuteAudio)
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
}
|
||||
|
||||
@ -74,7 +84,15 @@ class LocalStateBroadcasterTest {
|
||||
|
||||
val expectedAudioOff = DataChannelMessage("audioOff")
|
||||
|
||||
val expectedMuteAudio = NCSignalingMessage()
|
||||
expectedMuteAudio.roomType = "video"
|
||||
expectedMuteAudio.type = "mute"
|
||||
val payload = NCMessagePayload()
|
||||
payload.name = "audio"
|
||||
expectedMuteAudio.payload = payload
|
||||
|
||||
Mockito.verify(mockedMessageSender!!).sendToAll(expectedAudioOff)
|
||||
Mockito.verify(mockedMessageSender!!).sendToAll(expectedMuteAudio)
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
}
|
||||
|
||||
@ -141,10 +159,18 @@ class LocalStateBroadcasterTest {
|
||||
val expectedAudioOn = DataChannelMessage("audioOn")
|
||||
val expectedSpeaking = DataChannelMessage("speaking")
|
||||
|
||||
val expectedUnmuteAudio = NCSignalingMessage()
|
||||
expectedUnmuteAudio.roomType = "video"
|
||||
expectedUnmuteAudio.type = "unmute"
|
||||
val payload = NCMessagePayload()
|
||||
payload.name = "audio"
|
||||
expectedUnmuteAudio.payload = payload
|
||||
|
||||
val inOrder = Mockito.inOrder(mockedMessageSender)
|
||||
|
||||
inOrder.verify(mockedMessageSender!!).sendToAll(expectedAudioOn)
|
||||
inOrder.verify(mockedMessageSender!!).sendToAll(expectedSpeaking)
|
||||
Mockito.verify(mockedMessageSender!!).sendToAll(expectedUnmuteAudio)
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
}
|
||||
|
||||
@ -187,10 +213,18 @@ class LocalStateBroadcasterTest {
|
||||
val expectedStoppedSpeaking = DataChannelMessage("stoppedSpeaking")
|
||||
val expectedAudioOff = DataChannelMessage("audioOff")
|
||||
|
||||
val expectedMuteAudio = NCSignalingMessage()
|
||||
expectedMuteAudio.roomType = "video"
|
||||
expectedMuteAudio.type = "mute"
|
||||
val payload = NCMessagePayload()
|
||||
payload.name = "audio"
|
||||
expectedMuteAudio.payload = payload
|
||||
|
||||
val inOrder = Mockito.inOrder(mockedMessageSender)
|
||||
|
||||
inOrder.verify(mockedMessageSender!!).sendToAll(expectedStoppedSpeaking)
|
||||
inOrder.verify(mockedMessageSender!!).sendToAll(expectedAudioOff)
|
||||
Mockito.verify(mockedMessageSender!!).sendToAll(expectedMuteAudio)
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
}
|
||||
|
||||
@ -216,7 +250,15 @@ class LocalStateBroadcasterTest {
|
||||
|
||||
val expectedVideoOn = DataChannelMessage("videoOn")
|
||||
|
||||
val expectedUnmuteVideo = NCSignalingMessage()
|
||||
expectedUnmuteVideo.roomType = "video"
|
||||
expectedUnmuteVideo.type = "unmute"
|
||||
val payload = NCMessagePayload()
|
||||
payload.name = "video"
|
||||
expectedUnmuteVideo.payload = payload
|
||||
|
||||
Mockito.verify(mockedMessageSender!!).sendToAll(expectedVideoOn)
|
||||
Mockito.verify(mockedMessageSender!!).sendToAll(expectedUnmuteVideo)
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
}
|
||||
|
||||
@ -241,7 +283,15 @@ class LocalStateBroadcasterTest {
|
||||
|
||||
val expectedVideoOff = DataChannelMessage("videoOff")
|
||||
|
||||
val expectedMuteVideo = NCSignalingMessage()
|
||||
expectedMuteVideo.roomType = "video"
|
||||
expectedMuteVideo.type = "mute"
|
||||
val payload = NCMessagePayload()
|
||||
payload.name = "video"
|
||||
expectedMuteVideo.payload = payload
|
||||
|
||||
Mockito.verify(mockedMessageSender!!).sendToAll(expectedVideoOff)
|
||||
Mockito.verify(mockedMessageSender!!).sendToAll(expectedMuteVideo)
|
||||
Mockito.verifyNoMoreInteractions(mockedMessageSender)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user