mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-11-22 04:55:29 +03:00
Add helper class to keep track of the participants in a call
For now only the same signaling messages that were already handled are still handled; in the future it could be extended to handle other messages, like the one sent by the external signaling server when a participant leaves the room (in some cases no participants update message is sent if the participant leaves the call and room at the same time, which causes the participants to still be seen as in call until a new update is received). Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
This commit is contained in:
parent
0a3f515bb6
commit
ab72db7a10
5 changed files with 1486 additions and 0 deletions
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Daniel Calviño Sánchez
|
||||||
|
* Copyright (C) 2022 Daniel Calviño Sánchez <danxuliu@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.nextcloud.talk.call;
|
||||||
|
|
||||||
|
import com.nextcloud.talk.models.json.participants.Participant;
|
||||||
|
import com.nextcloud.talk.signaling.SignalingMessageReceiver;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to keep track of the participants in a call based on the signaling messages.
|
||||||
|
*
|
||||||
|
* The CallParticipantList adds a listener for participant list messages as soon as it is created and starts tracking
|
||||||
|
* the call participants until destroyed. Notifications about the changes can be received by adding an observer to the
|
||||||
|
* CallParticipantList; note that no sorting is guaranteed on the participants.
|
||||||
|
*/
|
||||||
|
public class CallParticipantList {
|
||||||
|
|
||||||
|
public interface Observer {
|
||||||
|
void onCallParticipantsChanged(Collection<Participant> joined, Collection<Participant> updated,
|
||||||
|
Collection<Participant> left, Collection<Participant> unchanged);
|
||||||
|
void onCallEndedForAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final SignalingMessageReceiver.ParticipantListMessageListener participantListMessageListener =
|
||||||
|
new SignalingMessageReceiver.ParticipantListMessageListener() {
|
||||||
|
|
||||||
|
private final Map<String, Participant> callParticipants = new HashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUsersInRoom(List<Participant> participants) {
|
||||||
|
processParticipantList(participants);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onParticipantsUpdate(List<Participant> participants) {
|
||||||
|
processParticipantList(participants);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processParticipantList(List<Participant> participants) {
|
||||||
|
Collection<Participant> joined = new ArrayList<>();
|
||||||
|
Collection<Participant> updated = new ArrayList<>();
|
||||||
|
Collection<Participant> left = new ArrayList<>();
|
||||||
|
Collection<Participant> unchanged = new ArrayList<>();
|
||||||
|
|
||||||
|
Collection<Participant> knownCallParticipantsNotFound = new ArrayList<>(callParticipants.values());
|
||||||
|
|
||||||
|
for (Participant participant : participants) {
|
||||||
|
String sessionId = participant.getSessionId();
|
||||||
|
Participant callParticipant = callParticipants.get(sessionId);
|
||||||
|
|
||||||
|
boolean knownCallParticipant = callParticipant != null;
|
||||||
|
if (!knownCallParticipant && participant.getInCall() != Participant.InCallFlags.DISCONNECTED) {
|
||||||
|
callParticipants.put(sessionId, copyParticipant(participant));
|
||||||
|
joined.add(copyParticipant(participant));
|
||||||
|
} else if (knownCallParticipant && participant.getInCall() == Participant.InCallFlags.DISCONNECTED) {
|
||||||
|
callParticipants.remove(sessionId);
|
||||||
|
// No need to copy it, as it will be no longer used.
|
||||||
|
callParticipant.setInCall(Participant.InCallFlags.DISCONNECTED);
|
||||||
|
left.add(callParticipant);
|
||||||
|
} else if (knownCallParticipant && callParticipant.getInCall() != participant.getInCall()) {
|
||||||
|
callParticipant.setInCall(participant.getInCall());
|
||||||
|
updated.add(copyParticipant(participant));
|
||||||
|
} else if (knownCallParticipant) {
|
||||||
|
unchanged.add(copyParticipant(participant));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (knownCallParticipant) {
|
||||||
|
knownCallParticipantsNotFound.remove(callParticipant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Participant callParticipant : knownCallParticipantsNotFound) {
|
||||||
|
callParticipants.remove(callParticipant.getSessionId());
|
||||||
|
// No need to copy it, as it will be no longer used.
|
||||||
|
callParticipant.setInCall(Participant.InCallFlags.DISCONNECTED);
|
||||||
|
left.add(callParticipant);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!joined.isEmpty() || !updated.isEmpty() || !left.isEmpty()) {
|
||||||
|
callParticipantListNotifier.notifyChanged(joined, updated, left, unchanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAllParticipantsUpdate(long inCall) {
|
||||||
|
if (inCall != Participant.InCallFlags.DISCONNECTED) {
|
||||||
|
// Updating all participants is expected to happen only to disconnect them.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
callParticipantListNotifier.notifyCallEndedForAll();
|
||||||
|
|
||||||
|
Collection<Participant> joined = new ArrayList<>();
|
||||||
|
Collection<Participant> updated = new ArrayList<>();
|
||||||
|
Collection<Participant> left = new ArrayList<>(callParticipants.size());
|
||||||
|
Collection<Participant> unchanged = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Participant callParticipant : callParticipants.values()) {
|
||||||
|
// No need to copy it, as it will be no longer used.
|
||||||
|
callParticipant.setInCall(Participant.InCallFlags.DISCONNECTED);
|
||||||
|
left.add(callParticipant);
|
||||||
|
}
|
||||||
|
callParticipants.clear();
|
||||||
|
|
||||||
|
if (!left.isEmpty()) {
|
||||||
|
callParticipantListNotifier.notifyChanged(joined, updated, left, unchanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Participant copyParticipant(Participant participant) {
|
||||||
|
Participant copiedParticipant = new Participant();
|
||||||
|
copiedParticipant.setInCall(participant.getInCall());
|
||||||
|
copiedParticipant.setLastPing(participant.getLastPing());
|
||||||
|
copiedParticipant.setSessionId(participant.getSessionId());
|
||||||
|
copiedParticipant.setType(participant.getType());
|
||||||
|
copiedParticipant.setUserId(participant.getUserId());
|
||||||
|
|
||||||
|
return copiedParticipant;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final CallParticipantListNotifier callParticipantListNotifier = new CallParticipantListNotifier();
|
||||||
|
|
||||||
|
private final SignalingMessageReceiver signalingMessageReceiver;
|
||||||
|
|
||||||
|
public CallParticipantList(SignalingMessageReceiver signalingMessageReceiver) {
|
||||||
|
this.signalingMessageReceiver = signalingMessageReceiver;
|
||||||
|
this.signalingMessageReceiver.addListener(participantListMessageListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy() {
|
||||||
|
signalingMessageReceiver.removeListener(participantListMessageListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addObserver(Observer observer) {
|
||||||
|
callParticipantListNotifier.addObserver(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeObserver(Observer observer) {
|
||||||
|
callParticipantListNotifier.removeObserver(observer);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Daniel Calviño Sánchez
|
||||||
|
* Copyright (C) 2022 Daniel Calviño Sánchez <danxuliu@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.nextcloud.talk.call;
|
||||||
|
|
||||||
|
import com.nextcloud.talk.models.json.participants.Participant;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to register and notify CallParticipantList.Observers.
|
||||||
|
*
|
||||||
|
* This class is only meant for internal use by CallParticipantList; listeners must register themselves against
|
||||||
|
* a CallParticipantList rather than against a CallParticipantListNotifier.
|
||||||
|
*/
|
||||||
|
class CallParticipantListNotifier {
|
||||||
|
|
||||||
|
private final Set<CallParticipantList.Observer> callParticipantListObservers = new LinkedHashSet<>();
|
||||||
|
|
||||||
|
public synchronized void addObserver(CallParticipantList.Observer observer) {
|
||||||
|
if (observer == null) {
|
||||||
|
throw new IllegalArgumentException("CallParticipantList.Observer can not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
callParticipantListObservers.add(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void removeObserver(CallParticipantList.Observer observer) {
|
||||||
|
callParticipantListObservers.remove(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void notifyChanged(Collection<Participant> joined, Collection<Participant> updated,
|
||||||
|
Collection<Participant> left, Collection<Participant> unchanged) {
|
||||||
|
for (CallParticipantList.Observer observer : new ArrayList<>(callParticipantListObservers)) {
|
||||||
|
observer.onCallParticipantsChanged(joined, updated, left, unchanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void notifyCallEndedForAll() {
|
||||||
|
for (CallParticipantList.Observer observer : new ArrayList<>(callParticipantListObservers)) {
|
||||||
|
observer.onCallEndedForAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,663 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Daniel Calviño Sánchez
|
||||||
|
* Copyright (C) 2022 Daniel Calviño Sánchez <danxuliu@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.nextcloud.talk.call;
|
||||||
|
|
||||||
|
import com.nextcloud.talk.models.json.participants.Participant;
|
||||||
|
import com.nextcloud.talk.signaling.SignalingMessageReceiver;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.ArgumentMatcher;
|
||||||
|
import org.mockito.InOrder;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.nextcloud.talk.models.json.participants.Participant.InCallFlags.DISCONNECTED;
|
||||||
|
import static com.nextcloud.talk.models.json.participants.Participant.InCallFlags.IN_CALL;
|
||||||
|
import static com.nextcloud.talk.models.json.participants.Participant.InCallFlags.WITH_AUDIO;
|
||||||
|
import static com.nextcloud.talk.models.json.participants.Participant.InCallFlags.WITH_VIDEO;
|
||||||
|
import static com.nextcloud.talk.models.json.participants.Participant.ParticipantType.GUEST;
|
||||||
|
import static com.nextcloud.talk.models.json.participants.Participant.ParticipantType.GUEST_MODERATOR;
|
||||||
|
import static com.nextcloud.talk.models.json.participants.Participant.ParticipantType.MODERATOR;
|
||||||
|
import static com.nextcloud.talk.models.json.participants.Participant.ParticipantType.OWNER;
|
||||||
|
import static com.nextcloud.talk.models.json.participants.Participant.ParticipantType.USER;
|
||||||
|
import static org.mockito.ArgumentMatchers.argThat;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.inOrder;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.only;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyNoInteractions;
|
||||||
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
|
|
||||||
|
public class CallParticipantListExternalSignalingTest {
|
||||||
|
|
||||||
|
private static class ParticipantsUpdateParticipantBuilder {
|
||||||
|
private Participant newUser(long inCall, long lastPing, String sessionId, Participant.ParticipantType type,
|
||||||
|
String userId) {
|
||||||
|
Participant participant = new Participant();
|
||||||
|
participant.setInCall(inCall);
|
||||||
|
participant.setLastPing(lastPing);
|
||||||
|
participant.setSessionId(sessionId);
|
||||||
|
participant.setType(type);
|
||||||
|
participant.setUserId(userId);
|
||||||
|
|
||||||
|
return participant;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Participant newGuest(long inCall, long lastPing, String sessionId, Participant.ParticipantType type) {
|
||||||
|
Participant participant = new Participant();
|
||||||
|
participant.setInCall(inCall);
|
||||||
|
participant.setLastPing(lastPing);
|
||||||
|
participant.setSessionId(sessionId);
|
||||||
|
participant.setType(type);
|
||||||
|
|
||||||
|
return participant;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ParticipantsUpdateParticipantBuilder builder = new ParticipantsUpdateParticipantBuilder();
|
||||||
|
|
||||||
|
private CallParticipantList callParticipantList;
|
||||||
|
private SignalingMessageReceiver.ParticipantListMessageListener participantListMessageListener;
|
||||||
|
|
||||||
|
private CallParticipantList.Observer mockedCallParticipantListObserver;
|
||||||
|
|
||||||
|
private Collection<Participant> expectedJoined;
|
||||||
|
private Collection<Participant> expectedUpdated;
|
||||||
|
private Collection<Participant> expectedLeft;
|
||||||
|
private Collection<Participant> expectedUnchanged;
|
||||||
|
|
||||||
|
// The order of the left participants in some tests depends on how they are internally sorted by the map, so the
|
||||||
|
// list of left participants needs to be checked ignoring the sorting (or, rather, sorting by session ID as in
|
||||||
|
// expectedLeft).
|
||||||
|
// Other tests can just relay on the not guaranteed, but known internal sorting of the elements.
|
||||||
|
private final ArgumentMatcher<List<Participant>> matchesExpectedLeftIgnoringOrder = left -> {
|
||||||
|
Collections.sort(left, Comparator.comparing(Participant::getSessionId));
|
||||||
|
return expectedLeft.equals(left);
|
||||||
|
};
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
SignalingMessageReceiver mockedSignalingMessageReceiver = mock(SignalingMessageReceiver.class);
|
||||||
|
|
||||||
|
callParticipantList = new CallParticipantList(mockedSignalingMessageReceiver);
|
||||||
|
|
||||||
|
mockedCallParticipantListObserver = mock(CallParticipantList.Observer.class);
|
||||||
|
|
||||||
|
// Get internal ParticipantListMessageListener from callParticipantList set in the
|
||||||
|
// mockedSignalingMessageReceiver.
|
||||||
|
ArgumentCaptor<SignalingMessageReceiver.ParticipantListMessageListener> participantListMessageListenerArgumentCaptor =
|
||||||
|
ArgumentCaptor.forClass(SignalingMessageReceiver.ParticipantListMessageListener.class);
|
||||||
|
|
||||||
|
verify(mockedSignalingMessageReceiver).addListener(participantListMessageListenerArgumentCaptor.capture());
|
||||||
|
|
||||||
|
participantListMessageListener = participantListMessageListenerArgumentCaptor.getValue();
|
||||||
|
|
||||||
|
expectedJoined = new ArrayList<>();
|
||||||
|
expectedUpdated = new ArrayList<>();
|
||||||
|
expectedLeft = new ArrayList<>();
|
||||||
|
expectedUnchanged = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateJoinRoom() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
verifyNoInteractions(mockedCallParticipantListObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateJoinRoomSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 5, "theSessionId5", OWNER, "theUserId5"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
verifyNoInteractions(mockedCallParticipantListObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateJoinRoomThenJoinCall() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
expectedJoined.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateJoinRoomThenJoinCallSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL, 2, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
expectedJoined.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
expectedJoined.add(builder.newGuest(IN_CALL, 2, "theSessionId2", GUEST));
|
||||||
|
expectedUnchanged.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateJoinRoomAndCall() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
expectedJoined.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateJoinRoomAndCallSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL, 2, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
expectedJoined.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
expectedJoined.add(builder.newGuest(IN_CALL, 2, "theSessionId2", GUEST));
|
||||||
|
expectedUnchanged.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateJoinRoomAndCallRepeated() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
expectedJoined.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateChangeCallFlags() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO | WITH_VIDEO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
expectedUpdated.add(builder.newUser(IN_CALL | WITH_AUDIO | WITH_VIDEO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateChangeCallFlagsSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL | WITH_AUDIO | WITH_VIDEO, 2, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL | WITH_AUDIO | WITH_VIDEO, 2, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_VIDEO, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
expectedUpdated.add(builder.newUser(IN_CALL, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
expectedUpdated.add(builder.newUser(IN_CALL | WITH_VIDEO, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
expectedUnchanged.add(builder.newGuest(IN_CALL | WITH_AUDIO | WITH_VIDEO, 2, "theSessionId2", GUEST));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateChangeLastPing() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 42, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
verifyNoInteractions(mockedCallParticipantListObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateChangeLastPingSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL | WITH_AUDIO, 2, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 42, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL | WITH_AUDIO, 108, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 815, "theSessionId3", USER, "theUserId3"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
verifyNoInteractions(mockedCallParticipantListObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateChangeParticipantType() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", USER, "theUserId1"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
verifyNoInteractions(mockedCallParticipantListObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateChangeParticipantTypeeSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL | WITH_AUDIO, 2, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", USER, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL | WITH_AUDIO, 2, "theSessionId2", GUEST_MODERATOR));
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 3, "theSessionId3", MODERATOR, "theUserId3"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
verifyNoInteractions(mockedCallParticipantListObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateLeaveCall() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
expectedLeft.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateLeaveCallSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL, 2, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
expectedLeft.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
expectedLeft.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2", GUEST));
|
||||||
|
expectedUnchanged.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateLeaveCallThenLeaveRoom() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
verifyNoInteractions(mockedCallParticipantListObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateLeaveCallThenLeaveRoomSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL, 2, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
verifyNoInteractions(mockedCallParticipantListObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateLeaveCallAndRoom() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
expectedLeft.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateLeaveCallAndRoomSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL, 2, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
expectedLeft.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
expectedLeft.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2", GUEST));
|
||||||
|
expectedUnchanged.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver).onCallParticipantsChanged(eq(expectedJoined), eq(expectedUpdated),
|
||||||
|
argThat(matchesExpectedLeftIgnoringOrder), eq(expectedUnchanged));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParticipantsUpdateSeveralEventsSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL, 2, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 5, "theSessionId5", OWNER, "theUserId5"));
|
||||||
|
// theSessionId6 has not joined yet.
|
||||||
|
participants.add(builder.newGuest(IN_CALL | WITH_VIDEO, 7, "theSessionId7", GUEST));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 8, "theSessionId8", USER, "theUserId8"));
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 9, "theSessionId9", MODERATOR, "theUserId9"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
// theSessionId1 is gone.
|
||||||
|
participants.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2", GUEST));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO | WITH_VIDEO, 5, "theSessionId5", OWNER, "theUserId5"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL | WITH_AUDIO, 6, "theSessionId6", GUEST));
|
||||||
|
participants.add(builder.newGuest(IN_CALL, 7, "theSessionId7", GUEST));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 8, "theSessionId8", USER, "theUserId8"));
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 42, "theSessionId9", USER, "theUserId9"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
expectedJoined.add(builder.newGuest(IN_CALL | WITH_AUDIO, 6, "theSessionId6", GUEST));
|
||||||
|
expectedJoined.add(builder.newUser(IN_CALL, 8, "theSessionId8", USER, "theUserId8"));
|
||||||
|
expectedUpdated.add(builder.newUser(IN_CALL | WITH_AUDIO | WITH_VIDEO, 5, "theSessionId5", OWNER, "theUserId5"));
|
||||||
|
expectedUpdated.add(builder.newGuest(IN_CALL, 7, "theSessionId7", GUEST));
|
||||||
|
expectedLeft.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
expectedLeft.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2", GUEST));
|
||||||
|
expectedUnchanged.add(builder.newUser(IN_CALL, 4, "theSessionId4", USER, "theUserId4"));
|
||||||
|
// Last ping and participant type are not seen as changed, even if they did.
|
||||||
|
expectedUnchanged.add(builder.newUser(IN_CALL | WITH_AUDIO, 42, "theSessionId9", USER, "theUserId9"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver).onCallParticipantsChanged(eq(expectedJoined), eq(expectedUpdated),
|
||||||
|
argThat(matchesExpectedLeftIgnoringOrder), eq(expectedUnchanged));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllParticipantsUpdateDisconnected() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onAllParticipantsUpdate(DISCONNECTED);
|
||||||
|
|
||||||
|
expectedLeft.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
InOrder inOrder = inOrder(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
inOrder.verify(mockedCallParticipantListObserver).onCallEndedForAll();
|
||||||
|
inOrder.verify(mockedCallParticipantListObserver).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllParticipantsUpdateDisconnectedWithSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 2, "theSessionId2", USER, "theUserId2"));
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL | WITH_AUDIO | WITH_VIDEO, 4, "theSessionId4", GUEST));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onAllParticipantsUpdate(DISCONNECTED);
|
||||||
|
|
||||||
|
expectedLeft.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
expectedLeft.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", USER, "theUserId3"));
|
||||||
|
expectedLeft.add(builder.newGuest(DISCONNECTED, 4, "theSessionId4", GUEST));
|
||||||
|
|
||||||
|
InOrder inOrder = inOrder(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
inOrder.verify(mockedCallParticipantListObserver).onCallEndedForAll();
|
||||||
|
inOrder.verify(mockedCallParticipantListObserver).onCallParticipantsChanged(eq(expectedJoined), eq(expectedUpdated),
|
||||||
|
argThat(matchesExpectedLeftIgnoringOrder), eq(expectedUnchanged));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllParticipantsUpdateDisconnectedNoOneInCall() {
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onAllParticipantsUpdate(DISCONNECTED);
|
||||||
|
|
||||||
|
InOrder inOrder = inOrder(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
inOrder.verify(mockedCallParticipantListObserver).onCallEndedForAll();
|
||||||
|
verifyNoMoreInteractions(mockedCallParticipantListObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllParticipantsUpdateDisconnectedThenJoinCallAgain() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
participantListMessageListener.onAllParticipantsUpdate(DISCONNECTED);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onParticipantsUpdate(participants);
|
||||||
|
|
||||||
|
expectedJoined.add(builder.newUser(IN_CALL, 1, "theSessionId1", MODERATOR, "theUserId1"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,535 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Daniel Calviño Sánchez
|
||||||
|
* Copyright (C) 2022 Daniel Calviño Sánchez <danxuliu@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.nextcloud.talk.call;
|
||||||
|
|
||||||
|
import com.nextcloud.talk.models.json.participants.Participant;
|
||||||
|
import com.nextcloud.talk.signaling.SignalingMessageReceiver;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.ArgumentMatcher;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.nextcloud.talk.models.json.participants.Participant.InCallFlags.DISCONNECTED;
|
||||||
|
import static com.nextcloud.talk.models.json.participants.Participant.InCallFlags.IN_CALL;
|
||||||
|
import static com.nextcloud.talk.models.json.participants.Participant.InCallFlags.WITH_AUDIO;
|
||||||
|
import static com.nextcloud.talk.models.json.participants.Participant.InCallFlags.WITH_VIDEO;
|
||||||
|
import static org.mockito.ArgumentMatchers.argThat;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.only;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyNoInteractions;
|
||||||
|
|
||||||
|
public class CallParticipantListInternalSignalingTest {
|
||||||
|
|
||||||
|
private static class UsersInRoomParticipantBuilder {
|
||||||
|
private Participant newUser(long inCall, long lastPing, String sessionId, String userId) {
|
||||||
|
Participant participant = new Participant();
|
||||||
|
participant.setInCall(inCall);
|
||||||
|
participant.setLastPing(lastPing);
|
||||||
|
participant.setSessionId(sessionId);
|
||||||
|
participant.setUserId(userId);
|
||||||
|
|
||||||
|
return participant;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Participant newGuest(long inCall, long lastPing, String sessionId) {
|
||||||
|
Participant participant = new Participant();
|
||||||
|
participant.setInCall(inCall);
|
||||||
|
participant.setLastPing(lastPing);
|
||||||
|
participant.setSessionId(sessionId);
|
||||||
|
|
||||||
|
return participant;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final UsersInRoomParticipantBuilder builder = new UsersInRoomParticipantBuilder();
|
||||||
|
|
||||||
|
private CallParticipantList callParticipantList;
|
||||||
|
private SignalingMessageReceiver.ParticipantListMessageListener participantListMessageListener;
|
||||||
|
|
||||||
|
private CallParticipantList.Observer mockedCallParticipantListObserver;
|
||||||
|
|
||||||
|
private Collection<Participant> expectedJoined;
|
||||||
|
private Collection<Participant> expectedUpdated;
|
||||||
|
private Collection<Participant> expectedLeft;
|
||||||
|
private Collection<Participant> expectedUnchanged;
|
||||||
|
|
||||||
|
// The order of the left participants in some tests depends on how they are internally sorted by the map, so the
|
||||||
|
// list of left participants needs to be checked ignoring the sorting (or, rather, sorting by session ID as in
|
||||||
|
// expectedLeft).
|
||||||
|
// Other tests can just relay on the not guaranteed, but known internal sorting of the elements.
|
||||||
|
private final ArgumentMatcher<List<Participant>> matchesExpectedLeftIgnoringOrder = left -> {
|
||||||
|
Collections.sort(left, Comparator.comparing(Participant::getSessionId));
|
||||||
|
return expectedLeft.equals(left);
|
||||||
|
};
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
SignalingMessageReceiver mockedSignalingMessageReceiver = mock(SignalingMessageReceiver.class);
|
||||||
|
|
||||||
|
callParticipantList = new CallParticipantList(mockedSignalingMessageReceiver);
|
||||||
|
|
||||||
|
mockedCallParticipantListObserver = mock(CallParticipantList.Observer.class);
|
||||||
|
|
||||||
|
// Get internal ParticipantListMessageListener from callParticipantList set in the
|
||||||
|
// mockedSignalingMessageReceiver.
|
||||||
|
ArgumentCaptor<SignalingMessageReceiver.ParticipantListMessageListener> participantListMessageListenerArgumentCaptor =
|
||||||
|
ArgumentCaptor.forClass(SignalingMessageReceiver.ParticipantListMessageListener.class);
|
||||||
|
|
||||||
|
verify(mockedSignalingMessageReceiver).addListener(participantListMessageListenerArgumentCaptor.capture());
|
||||||
|
|
||||||
|
participantListMessageListener = participantListMessageListenerArgumentCaptor.getValue();
|
||||||
|
|
||||||
|
expectedJoined = new ArrayList<>();
|
||||||
|
expectedUpdated = new ArrayList<>();
|
||||||
|
expectedLeft = new ArrayList<>();
|
||||||
|
expectedUnchanged = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomJoinRoom() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
verifyNoInteractions(mockedCallParticipantListObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomJoinRoomSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 4, "theSessionId4", "theUserId4"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 5, "theSessionId5", "theUserId5"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
verifyNoInteractions(mockedCallParticipantListObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomJoinRoomThenJoinCall() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
expectedJoined.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomJoinRoomThenJoinCallSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL, 2, "theSessionId2"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
expectedJoined.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
expectedJoined.add(builder.newGuest(IN_CALL, 2, "theSessionId2"));
|
||||||
|
expectedUnchanged.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomJoinRoomAndCall() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
expectedJoined.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomJoinRoomAndCallSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL, 2, "theSessionId2"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
expectedJoined.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
expectedJoined.add(builder.newGuest(IN_CALL, 2, "theSessionId2"));
|
||||||
|
expectedUnchanged.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomJoinRoomAndCallRepeated() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
expectedJoined.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomChangeCallFlags() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO | WITH_VIDEO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
expectedUpdated.add(builder.newUser(IN_CALL | WITH_AUDIO | WITH_VIDEO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomChangeCallFlagsSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL | WITH_AUDIO | WITH_VIDEO, 2, "theSessionId2"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL, 1, "theSessionId1", "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL | WITH_AUDIO | WITH_VIDEO, 2, "theSessionId2"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_VIDEO, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
expectedUpdated.add(builder.newUser(IN_CALL, 1, "theSessionId1", "theUserId1"));
|
||||||
|
expectedUpdated.add(builder.newUser(IN_CALL | WITH_VIDEO, 4, "theSessionId4", "theUserId4"));
|
||||||
|
expectedUnchanged.add(builder.newGuest(IN_CALL | WITH_AUDIO | WITH_VIDEO, 2, "theSessionId2"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomChangeLastPing() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 42, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
verifyNoInteractions(mockedCallParticipantListObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomChangeLastPingSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL | WITH_AUDIO, 2, "theSessionId2"));
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 3, "theSessionId3", "theUserId3"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 42, "theSessionId1", "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL | WITH_AUDIO, 108, "theSessionId2"));
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 815, "theSessionId3", "theUserId3"));
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
verifyNoInteractions(mockedCallParticipantListObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomLeaveCall() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
expectedLeft.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomLeaveCallSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL, 2, "theSessionId2"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
expectedLeft.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", "theUserId1"));
|
||||||
|
expectedLeft.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2"));
|
||||||
|
expectedUnchanged.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomLeaveCallThenLeaveRoom() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
verifyNoInteractions(mockedCallParticipantListObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomLeaveCallThenLeaveRoomSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL, 2, "theSessionId2"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
verifyNoInteractions(mockedCallParticipantListObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomLeaveCallAndRoom() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
expectedLeft.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", "theUserId1"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver, only()).onCallParticipantsChanged(expectedJoined, expectedUpdated,
|
||||||
|
expectedLeft, expectedUnchanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomLeaveCallAndRoomSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL, 2, "theSessionId2"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
expectedLeft.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", "theUserId1"));
|
||||||
|
expectedLeft.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2"));
|
||||||
|
expectedUnchanged.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver).onCallParticipantsChanged(eq(expectedJoined), eq(expectedUpdated),
|
||||||
|
argThat(matchesExpectedLeftIgnoringOrder), eq(expectedUnchanged));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersInRoomSeveralEventsSeveralParticipants() {
|
||||||
|
List<Participant> participants = new ArrayList<>();
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 1, "theSessionId1", "theUserId1"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL, 2, "theSessionId2"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 5, "theSessionId5", "theUserId5"));
|
||||||
|
// theSessionId6 has not joined yet.
|
||||||
|
participants.add(builder.newGuest(IN_CALL | WITH_VIDEO, 7, "theSessionId7"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 8, "theSessionId8", "theUserId8"));
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 9, "theSessionId9", "theUserId9"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
callParticipantList.addObserver(mockedCallParticipantListObserver);
|
||||||
|
|
||||||
|
participants = new ArrayList<>();
|
||||||
|
// theSessionId1 is gone.
|
||||||
|
participants.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2"));
|
||||||
|
participants.add(builder.newUser(DISCONNECTED, 3, "theSessionId3", "theUserId3"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO | WITH_VIDEO, 5, "theSessionId5", "theUserId5"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL | WITH_AUDIO, 6, "theSessionId6"));
|
||||||
|
participants.add(builder.newGuest(IN_CALL, 7, "theSessionId7"));
|
||||||
|
participants.add(builder.newUser(IN_CALL, 8, "theSessionId8", "theUserId8"));
|
||||||
|
participants.add(builder.newUser(IN_CALL | WITH_AUDIO, 42, "theSessionId9", "theUserId9"));
|
||||||
|
|
||||||
|
participantListMessageListener.onUsersInRoom(participants);
|
||||||
|
|
||||||
|
expectedJoined.add(builder.newGuest(IN_CALL | WITH_AUDIO, 6, "theSessionId6"));
|
||||||
|
expectedJoined.add(builder.newUser(IN_CALL, 8, "theSessionId8", "theUserId8"));
|
||||||
|
expectedUpdated.add(builder.newUser(IN_CALL | WITH_AUDIO | WITH_VIDEO, 5, "theSessionId5", "theUserId5"));
|
||||||
|
expectedUpdated.add(builder.newGuest(IN_CALL, 7, "theSessionId7"));
|
||||||
|
expectedLeft.add(builder.newUser(DISCONNECTED, 1, "theSessionId1", "theUserId1"));
|
||||||
|
expectedLeft.add(builder.newGuest(DISCONNECTED, 2, "theSessionId2"));
|
||||||
|
expectedUnchanged.add(builder.newUser(IN_CALL, 4, "theSessionId4", "theUserId4"));
|
||||||
|
// Last ping is not seen as changed, even if it did.
|
||||||
|
expectedUnchanged.add(builder.newUser(IN_CALL | WITH_AUDIO, 42, "theSessionId9", "theUserId9"));
|
||||||
|
|
||||||
|
verify(mockedCallParticipantListObserver).onCallParticipantsChanged(eq(expectedJoined), eq(expectedUpdated),
|
||||||
|
argThat(matchesExpectedLeftIgnoringOrder), eq(expectedUnchanged));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Daniel Calviño Sánchez
|
||||||
|
* Copyright (C) 2022 Daniel Calviño Sánchez <danxuliu@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.nextcloud.talk.call;
|
||||||
|
|
||||||
|
import com.nextcloud.talk.signaling.SignalingMessageReceiver;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
|
|
||||||
|
public class CallParticipantListTest {
|
||||||
|
|
||||||
|
private SignalingMessageReceiver mockedSignalingMessageReceiver;
|
||||||
|
|
||||||
|
private CallParticipantList callParticipantList;
|
||||||
|
private SignalingMessageReceiver.ParticipantListMessageListener participantListMessageListener;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mockedSignalingMessageReceiver = mock(SignalingMessageReceiver.class);
|
||||||
|
|
||||||
|
callParticipantList = new CallParticipantList(mockedSignalingMessageReceiver);
|
||||||
|
|
||||||
|
// Get internal ParticipantListMessageListener from callParticipantList set in the
|
||||||
|
// mockedSignalingMessageReceiver.
|
||||||
|
ArgumentCaptor<SignalingMessageReceiver.ParticipantListMessageListener> participantListMessageListenerArgumentCaptor =
|
||||||
|
ArgumentCaptor.forClass(SignalingMessageReceiver.ParticipantListMessageListener.class);
|
||||||
|
|
||||||
|
verify(mockedSignalingMessageReceiver).addListener(participantListMessageListenerArgumentCaptor.capture());
|
||||||
|
|
||||||
|
participantListMessageListener = participantListMessageListenerArgumentCaptor.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDestroy() {
|
||||||
|
callParticipantList.destroy();
|
||||||
|
|
||||||
|
verify(mockedSignalingMessageReceiver).removeListener(participantListMessageListener);
|
||||||
|
verifyNoMoreInteractions(mockedSignalingMessageReceiver);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue