mirror of https://github.com/OpenVidu/openvidu.git
openvidu-test-e2e: add connectionQualityLostMeetPublisherSubscriberNotLostTest
The same check as connectionQualityLostPublisherSubscriberNotLostTest, but with the media OpenVidu Meet publishes. The Meet bundle currently deployed runs its Room with adaptiveStream and dynacast, a 720p camera and livekit-client's publish defaults (simulcast, DTX, RED, VP8). The connection-quality tests turned simulcast, dynacast and adaptiveStream off, so the camera was a single 640x480 layer. connectionQualityTest() gets an overload with a videoOptimizations flag: simulcast, dynacast and adaptiveStream enabled for both users, with a 1280x720 camera published as three VP8 simulcast layers. The existing 4-argument form passes false, so the other connection-quality tests are unchanged. The body of the previous test moves to lostPublisherDoesNotMakeSubscriberLost(videoOptimizations), which both tests call. With a simulcast camera the video track does not trigger the bug. mediasoup zeroes the score of a silent Producer with several layers within 1.5 s, and only the audio track keeps a frozen score. That also makes the publisher LOST two server quality updates earlier than with a single layer, so the subscriber's wrong LOST arrives 10 s after the publisher's. The wait after the publisher is LOST therefore goes from 10 s to 15 s; with 10 s the check ran just as that LOST arrived. Caveat: the publisher's livekit-client (>= 2.22) does its full reconnect in that same update, 10 s after its first LOST. A server with the bug therefore fails this test only while its quality update reaches the subscriber before the publisher's Leave does. It won by 10-15 ms in all 4 runs, but if it ever loses, a buggy server passes; a correct server can never fail. The single-layer test has no such race. Verified against the local Compose deployment: - mediasoup, server image built before the openvidu-pro-livekit fix: the new test failed 4 of 4 times. RegularUser went EXCELLENT -> LOST through its audio consumer, while its video consumer read producer score 0 and stayed EXCELLENT. - mediasoup with the fix, and pion: both tests pass. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>pull/911/head
parent
ae08286d60
commit
86300ec00e
|
|
@ -938,6 +938,22 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
|
||||
private Pair<OpenViduTestappUser, OpenViduTestappUser> connectionQualityTest(boolean isPublisher,
|
||||
boolean isSubscriber, Integer outboundPacketLoss, Integer inboundPacketLoss) throws Exception {
|
||||
return connectionQualityTest(isPublisher, isSubscriber, outboundPacketLoss, inboundPacketLoss, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code videoOptimizations} means simulcast, dynacast and adaptiveStream
|
||||
* enabled for both users, as OpenVidu Meet has them, with a 1280x720 camera, so
|
||||
* the camera is published as three VP8 simulcast layers. Without them the camera
|
||||
* is a single 640x480 layer. Audio is the same in both cases (Opus with the
|
||||
* livekit-client defaults, DTX and RED).
|
||||
*/
|
||||
private Pair<OpenViduTestappUser, OpenViduTestappUser> connectionQualityTest(boolean isPublisher,
|
||||
boolean isSubscriber, Integer outboundPacketLoss, Integer inboundPacketLoss, boolean videoOptimizations)
|
||||
throws Exception {
|
||||
|
||||
final Integer width = videoOptimizations ? 1280 : null;
|
||||
final Integer height = videoOptimizations ? 720 : null;
|
||||
|
||||
// Connect to LiveKit server from a secure URL
|
||||
String secureLivekitUrlFromOpenViduLocalDeployment = getLivekitWssUrlFromReadyCheckContainer();
|
||||
|
|
@ -974,7 +990,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
throw new IllegalArgumentException("At least one of isPublisher or isSubscriber must be true");
|
||||
}
|
||||
if (isPublisher) {
|
||||
this.addPublisher(punchbagUser, isSubscriber, false, false, false, true, true, null, null, null);
|
||||
this.addPublisher(punchbagUser, isSubscriber, videoOptimizations, videoOptimizations, videoOptimizations,
|
||||
true, true, width, height, null);
|
||||
} else {
|
||||
// Publish audio only (and keep subscribing) so the OTHER user subscribes to
|
||||
// PunchbagUser and therefore also receives its connectionQualityChanged events
|
||||
|
|
@ -982,7 +999,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
// subscribed to. PunchbagUser still subscribes to RegularUser's audio+video,
|
||||
// which is the downlink actually impaired in this scenario; the extra audio
|
||||
// uplink stays clean and does not affect its (min-based) quality.
|
||||
this.addPublisher(punchbagUser, true, false, false, false, true, false, null, null, null);
|
||||
this.addPublisher(punchbagUser, true, videoOptimizations, videoOptimizations, videoOptimizations, true,
|
||||
false, null, null, null);
|
||||
}
|
||||
|
||||
WebElement participantNameInput = punchbagUser.getDriver().findElement(By.id("participant-name-input-0"));
|
||||
|
|
@ -1022,9 +1040,10 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
regularUser.getEventManager().startPolling();
|
||||
|
||||
if (isSubscriber) {
|
||||
this.addPublisher(regularUser, true, false, false, false, true, true, null, null, null);
|
||||
this.addPublisher(regularUser, true, videoOptimizations, videoOptimizations, videoOptimizations, true, true,
|
||||
width, height, null);
|
||||
} else {
|
||||
this.addSubscriber(regularUser, false);
|
||||
this.addSubscriber(regularUser, videoOptimizations);
|
||||
}
|
||||
participantNameInput = regularUser.getDriver().findElement(By.id("participant-name-input-0"));
|
||||
participantNameInput.clear();
|
||||
|
|
@ -1193,8 +1212,24 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
|
||||
log.info("ConnectionQuality LOST publisher does not make its subscriber LOST");
|
||||
|
||||
// Single-layer camera: both published tracks keep a frozen score in mediasoup
|
||||
lostPublisherDoesNotMakeSubscriberLost(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("ConnectionQuality LOST publisher with OpenVidu Meet media does not make its subscriber LOST")
|
||||
void connectionQualityLostMeetPublisherSubscriberNotLostTest() throws Exception {
|
||||
|
||||
log.info("ConnectionQuality LOST publisher with OpenVidu Meet media does not make its subscriber LOST");
|
||||
|
||||
lostPublisherDoesNotMakeSubscriberLost(true);
|
||||
}
|
||||
|
||||
private void lostPublisherDoesNotMakeSubscriberLost(boolean videoOptimizations) throws Exception {
|
||||
|
||||
// PunchbagUser publishes audio and video, RegularUser only subscribes to them
|
||||
Pair<OpenViduTestappUser, OpenViduTestappUser> users = connectionQualityTest(true, false, null, null);
|
||||
Pair<OpenViduTestappUser, OpenViduTestappUser> users = connectionQualityTest(true, false, null, null,
|
||||
videoOptimizations);
|
||||
OpenViduTestappUser punchbagUser = users.getLeft();
|
||||
OpenViduTestappUser regularUser = users.getRight();
|
||||
|
||||
|
|
@ -1204,8 +1239,11 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
try {
|
||||
waitUntilConnectionQuality(regularUser, 0, "PunchbagUser", q -> q.contains("lost"), 45,
|
||||
"Expected the publisher's connection quality to reach LOST");
|
||||
// Leave a couple more server quality ticks (every 5 s) to be reported
|
||||
Thread.sleep(10000);
|
||||
// Leave three more server quality ticks (every 5 s) to be reported. With a
|
||||
// single-layer camera the publisher goes LOST when its media is found stale,
|
||||
// in the same tick as a subscriber wrongly would. A silent simulcast camera is
|
||||
// LOST two ticks before that, when mediasoup zeroes its score
|
||||
Thread.sleep(15000);
|
||||
|
||||
// RegularUser's own network is not impaired, so the publisher's outage must
|
||||
// not be reported as LOST for RegularUser itself. Its instance lists its own
|
||||
|
|
|
|||
Loading…
Reference in New Issue