From ae08286d601eb6f2502b0caf0018679446a48b56 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 23 Sep 2026 17:47:42 +0200 Subject: [PATCH] openvidu-test-e2e: add connectionQualityLostPublisherSubscriberNotLostTest When a publisher's network dies, only that publisher should be reported LOST. With the mediasoup engine every subscriber of its tracks was reported LOST too, because the subscriber's quality is the minimum over the tracks it publishes and subscribes to. Since livekit-client 2.22 a participant that has been LOST for 10 s while publishing does a full reconnect, so a healthy participant publishing in the same room would reconnect because of someone else's outage. No existing test covered this. connectionQualityLostPublisherTest only checks the quality of the publisher whose network is cut. The ramp-up test does check the subscriber's own quality, but by the time it blacks out the publisher, mediasoup's frozen producer score is already degraded, which hides the bug. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../test/e2e/OpenViduTestAppE2eTest.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 271938992..3aef5f841 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -1187,6 +1187,47 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest { gracefullyLeaveParticipants(punchbagUser, 1); } + @Test + @DisplayName("ConnectionQuality LOST publisher does not make its subscriber LOST") + void connectionQualityLostPublisherSubscriberNotLostTest() throws Exception { + + log.info("ConnectionQuality LOST publisher does not make its subscriber LOST"); + + // PunchbagUser publishes audio and video, RegularUser only subscribes to them + Pair users = connectionQualityTest(true, false, null, null); + OpenViduTestappUser punchbagUser = users.getLeft(); + OpenViduTestappUser regularUser = users.getRight(); + + // Cut the publisher's media uplink at once while its quality is EXCELLENT, + // keeping its signaling up: a sudden network outage on the publisher's side + NetworkConditioner.blackoutOutbound(getNetemContainerName(punchbagUser), "7900-7999", 120); + 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); + + // 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 + // ParticipantEvents ("lost") and the RoomEvents of every participant + // (" (lost)"), PunchbagUser's included: only RegularUser's count + List qualities = new ArrayList<>(); + for (WebElement el : getConnectionQualityEventContents(regularUser, 0, "RegularUser")) { + String text = el.getAttribute("textContent"); + if (text != null) { + qualities.add(text.toLowerCase().trim()); + } + } + Assertions.assertFalse(qualities.stream().anyMatch(q -> q.equals("lost") || q.equals("regularuser (lost)")), + "RegularUser only subscribes to the LOST publisher and its own network is not impaired, " + + "so its own connection quality must never be LOST. Observed: " + qualities); + } finally { + NetworkConditioner.clear(); + } + + gracefullyLeaveParticipants(punchbagUser, 1); + } + @Test @DisplayName("ConnectionQuality POOR subscriber test") void connectionQualityPoorSubscriberTest() throws Exception {