mirror of https://github.com/OpenVidu/openvidu.git
openvidu-test-e2e: add iceCandidateTypeSwitchTest
parent
0625275964
commit
64f2ab4563
|
|
@ -65,6 +65,7 @@ import org.openqa.selenium.StaleElementReferenceException;
|
|||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
import org.opentest4j.AssertionFailedError;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
|
@ -1637,6 +1638,110 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch the ICE candidates of a connected participant mid-call, the way
|
||||
* LiveKit itself does after an ICE failure: livekit-client's
|
||||
* room.simulateScenario("force-tcp" / "force-tls") makes LiveKit store an ICE
|
||||
* preference for the participant, and then makes the client reconnect from
|
||||
* scratch (new PeerConnections) with it. "force-tcp" drops every non-TCP
|
||||
* candidate of the SFU, and "force-tls" forces a relay over TURN/TLS. The
|
||||
* local deployment has no TURN/TLS, so LiveKit hands out its TURN/UDP servers
|
||||
* for it instead.
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("ICE candidate type switch")
|
||||
void iceCandidateTypeSwitchTest() throws Exception {
|
||||
|
||||
log.info("ICE candidate type switch");
|
||||
|
||||
// mediasoup transports listen for ICE-TCP on the RTC port range, which the
|
||||
// deployment only publishes over UDP
|
||||
setSfuTcpPortRangePublished(true);
|
||||
try {
|
||||
final String secureLivekitUrl = prepareNetemBrowsers();
|
||||
// A room of its own: LiveKit keeps the forced ICE preference of a room name
|
||||
// and identity for a while
|
||||
final String roomName = "IceCandidateTypeSwitch" + System.currentTimeMillis();
|
||||
|
||||
// Both users publish audio and video and subscribe to each other's
|
||||
OpenViduTestappUser punchbagUser = setupNetemBrowserUser(secureLivekitUrl);
|
||||
this.addPublisher(punchbagUser, true, false, false, false, true, true, null, null, null);
|
||||
setParticipantAndRoomName(punchbagUser, "PunchbagUser", roomName);
|
||||
punchbagUser.getDriver().findElement(By.cssSelector(".connect-btn")).sendKeys(Keys.ENTER);
|
||||
punchbagUser.getEventManager().waitUntilEventReaches("connected", "RoomEvent", 1);
|
||||
punchbagUser.getEventManager().waitUntilEventReaches("localTrackPublished", "RoomEvent", 2);
|
||||
|
||||
OpenViduTestappUser regularUser = setupNetemBrowserUser(secureLivekitUrl);
|
||||
this.addPublisher(regularUser, true, false, false, false, true, true, null, null, null);
|
||||
setParticipantAndRoomName(regularUser, "RegularUser", roomName);
|
||||
regularUser.getDriver().findElement(By.cssSelector(".connect-btn")).sendKeys(Keys.ENTER);
|
||||
regularUser.getEventManager().waitUntilEventReaches("connected", "RoomEvent", 1);
|
||||
|
||||
// UDP first: the candidates ICE prefers
|
||||
assertMediaThroughIceCandidateType(punchbagUser, regularUser, IceCandidateType.HOST_UDP, 1);
|
||||
|
||||
simulateIceCandidateProtocolSwitch(punchbagUser, "force-tcp", 1);
|
||||
assertMediaThroughIceCandidateType(punchbagUser, regularUser, IceCandidateType.HOST_TCP, 2);
|
||||
|
||||
simulateIceCandidateProtocolSwitch(punchbagUser, "force-tls", 2);
|
||||
assertMediaThroughIceCandidateType(punchbagUser, regularUser, IceCandidateType.RELAY_UDP, 3);
|
||||
|
||||
gracefullyLeaveParticipants(punchbagUser, 1);
|
||||
} finally {
|
||||
setSfuTcpPortRangePublished(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run room.simulateScenario(scenario) in the user's livekit-client and wait
|
||||
* for the reconnection it triggers, the given one since the user connected.
|
||||
*/
|
||||
private void simulateIceCandidateProtocolSwitch(OpenViduTestappUser user, String scenario, int reconnection)
|
||||
throws Exception {
|
||||
log.info("Simulating scenario {} in livekit-client", scenario);
|
||||
((JavascriptExecutor) user.getDriver()).executeScript("window['room_0'].simulateScenario(arguments[0]);",
|
||||
scenario);
|
||||
user.getEventManager().waitUntilEventReaches("reconnected", "RoomEvent", reconnection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the media of PunchbagUser, a participant that has just
|
||||
* connected or reconnected for the given time, goes both ways through
|
||||
* {@code iceCandidateType} with nothing lost on the way.
|
||||
*/
|
||||
private void assertMediaThroughIceCandidateType(OpenViduTestappUser punchbagUser, OpenViduTestappUser regularUser,
|
||||
IceCandidateType iceCandidateType, int connection) throws Exception {
|
||||
// Every connection subscribes both users again to the other's audio and video
|
||||
punchbagUser.getEventManager().waitUntilEventReaches("trackSubscribed", "RoomEvent", 2 * connection);
|
||||
regularUser.getEventManager().waitUntilEventReaches("trackSubscribed", "RoomEvent", 2 * connection);
|
||||
|
||||
// The PeerConnections of a reconnection are new: give them time to connect
|
||||
final long deadline = System.currentTimeMillis() + 30000;
|
||||
while (true) {
|
||||
try {
|
||||
assertConnectedThroughIceCandidateType(readPcTransportsInfoJson(punchbagUser, 0), iceCandidateType);
|
||||
break;
|
||||
} catch (AssertionFailedError e) {
|
||||
if (System.currentTimeMillis() > deadline) {
|
||||
throw e;
|
||||
}
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
for (OpenViduTestappUser user : List.of(punchbagUser, regularUser)) {
|
||||
user.getWaiter().until(
|
||||
ExpectedConditions.numberOfElementsToBe(By.cssSelector("#openvidu-instance-0 video.remote"), 1));
|
||||
waitUntilSubscriberFramesDecodedIncrease(user,
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 video.remote")));
|
||||
}
|
||||
waitUntilConnectionQuality(punchbagUser, 0, "PunchbagUser", q -> q.contains("excellent"), 20,
|
||||
"Expected PunchbagUser's own connection quality to be EXCELLENT through " + iceCandidateType);
|
||||
waitUntilConnectionQuality(regularUser, 0, "PunchbagUser", q -> q.contains("excellent"), 20,
|
||||
"Expected PunchbagUser's connection quality seen by RegularUser to be EXCELLENT through "
|
||||
+ iceCandidateType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add/Remove the TCP port range from the "openvidu" container in the
|
||||
* openvidu-local-deployment. It replicates the declared UDP port range.
|
||||
|
|
|
|||
Loading…
Reference in New Issue