openvidu-test-e2e: KMS reconnection test
This commit is contained in:
parent
3bc39ed448
commit
e0b1f118eb
@ -62,6 +62,18 @@
|
||||
<org-seleniumhq-selenium.version>3.141.59</org-seleniumhq-selenium.version>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0-M3</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
|
||||
@ -95,12 +95,27 @@ public class OpenViduEventManager {
|
||||
|
||||
Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() {
|
||||
public void uncaughtException(Thread th, Throwable ex) {
|
||||
if (ex.getClass().getSimpleName().equals("UnhandledAlertException")
|
||||
&& ex.getMessage().contains("unexpected alert open")) {
|
||||
stopPolling(false);
|
||||
System.err.println("Alert opened. Waiting 1 second and restarting polling");
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
startPolling();
|
||||
}
|
||||
if (ex.getClass().getSimpleName().equals("NoSuchSessionException")) {
|
||||
System.err.println("Disposing driver when running 'executeScript'");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (this.pollingThread != null) {
|
||||
this.pollingThread.interrupt();
|
||||
}
|
||||
|
||||
this.pollingThread = new Thread(() -> {
|
||||
while (!this.isInterrupted.get()) {
|
||||
this.getEventsFromBrowser();
|
||||
@ -116,12 +131,15 @@ public class OpenViduEventManager {
|
||||
this.pollingThread.start();
|
||||
}
|
||||
|
||||
public void stopPolling() {
|
||||
public void stopPolling(boolean stopThread) {
|
||||
this.eventCallbacks.clear();
|
||||
this.eventCountdowns.clear();
|
||||
this.eventNumbers.clear();
|
||||
this.isInterrupted.set(true);
|
||||
this.pollingThread.interrupt();
|
||||
|
||||
if (stopThread) {
|
||||
this.isInterrupted.set(true);
|
||||
this.pollingThread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
public void on(String eventName, Consumer<JsonObject> callback) {
|
||||
|
||||
@ -60,6 +60,7 @@ import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.platform.runner.JUnitPlatform;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.openqa.selenium.Alert;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.Dimension;
|
||||
import org.openqa.selenium.Keys;
|
||||
@ -99,7 +100,7 @@ import io.openvidu.test.e2e.browser.ChromeAndroidUser;
|
||||
import io.openvidu.test.e2e.browser.ChromeUser;
|
||||
import io.openvidu.test.e2e.browser.FirefoxUser;
|
||||
import io.openvidu.test.e2e.browser.OperaUser;
|
||||
import io.openvidu.test.e2e.utils.CommandLineExecuter;
|
||||
import io.openvidu.test.e2e.utils.CommandLineExecutor;
|
||||
import io.openvidu.test.e2e.utils.CustomHttpClient;
|
||||
import io.openvidu.test.e2e.utils.MultimediaFileMetadata;
|
||||
import io.openvidu.test.e2e.utils.Unzipper;
|
||||
@ -126,12 +127,13 @@ public class OpenViduTestAppE2eTest {
|
||||
BrowserUser user;
|
||||
Collection<BrowserUser> otherUsers = new ArrayList<>();
|
||||
volatile static boolean isRecordingTest;
|
||||
volatile static boolean isKurentoRestartTest;
|
||||
private static OpenVidu OV;
|
||||
|
||||
@BeforeAll()
|
||||
static void setupAll() {
|
||||
|
||||
String ffmpegOutput = new CommandLineExecuter().executeCommand("which ffmpeg");
|
||||
String ffmpegOutput = new CommandLineExecutor().executeCommand("which ffmpeg");
|
||||
if (ffmpegOutput == null || ffmpegOutput.isEmpty()) {
|
||||
log.error("ffmpeg package is not installed in the host machine");
|
||||
Assert.fail();
|
||||
@ -186,7 +188,10 @@ public class OpenViduTestAppE2eTest {
|
||||
this.user = new ChromeAndroidUser("TestUser", 50);
|
||||
break;
|
||||
case "chromeAlternateScreenShare":
|
||||
this.user = new ChromeUser("TestUser", 50, "OpenVidu TestApp");
|
||||
this.user = new ChromeUser("TestUser", 50, "OpenVidu TestApp", false);
|
||||
break;
|
||||
case "chromeAsRoot":
|
||||
this.user = new ChromeUser("TestUser", 50, "Entire screen", true);
|
||||
break;
|
||||
default:
|
||||
this.user = new ChromeUser("TestUser", 50);
|
||||
@ -250,6 +255,9 @@ public class OpenViduTestAppE2eTest {
|
||||
}
|
||||
isRecordingTest = false;
|
||||
}
|
||||
if (isKurentoRestartTest) {
|
||||
new CommandLineExecutor().executeCommand("sudo service kurento-media-server restart");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -2558,6 +2566,150 @@ public class OpenViduTestAppE2eTest {
|
||||
+ "'openviduRecordingVersion':'STR','openviduRecordingPath':'STR','openviduRecordingPublicAccess':false,'openviduRecordingNotification':'STR','openviduRecordingCustomLayout':'STR','openviduRecordingAutostopTimeout':0}");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Kurento reconnect test")
|
||||
void kurentoReconnectTest() throws Exception {
|
||||
isRecordingTest = true;
|
||||
isKurentoRestartTest = true;
|
||||
|
||||
log.info("Kurento reconnect test");
|
||||
|
||||
List<Session> sessions = OV.getActiveSessions();
|
||||
Assert.assertEquals("Expected no active sessions but found " + sessions.size(), 0, sessions.size());
|
||||
|
||||
final CommandLineExecutor exec = new CommandLineExecutor();
|
||||
|
||||
exec.executeCommand("sudo service kurento-media-server stop");
|
||||
|
||||
OV.fetch();
|
||||
|
||||
setupBrowser("chromeAsRoot");
|
||||
|
||||
// Connect one publisher with no connection to KMS
|
||||
|
||||
user.getDriver().findElement(By.id("add-user-btn")).click();
|
||||
user.getDriver().findElement(By.className("subscribe-remote-check")).click();
|
||||
user.getDriver().findElement(By.className("join-btn")).click();
|
||||
|
||||
user.getWaiter().until(ExpectedConditions.alertIsPresent());
|
||||
Alert alert = user.getDriver().switchTo().alert();
|
||||
|
||||
final String alertMessage = "Exception connecting to WebSocket server ws://localhost:8888/kurento";
|
||||
Assert.assertTrue("Alert message wrong. Expected to contain: \"" + alertMessage + "\". Actual message: \""
|
||||
+ alert.getText() + "\"", alert.getText().contains(alertMessage));
|
||||
alert.accept();
|
||||
|
||||
user.getDriver().findElement(By.id("remove-user-btn")).sendKeys(Keys.ENTER);
|
||||
|
||||
exec.executeCommand("sudo service kurento-media-server start");
|
||||
Thread.sleep(3000);
|
||||
|
||||
// Connect one subscriber with connection to KMS -> restart KMS -> connect a
|
||||
// publisher -> restart KMS -> check streamDestroyed events
|
||||
|
||||
user.getDriver().findElement(By.id("add-user-btn")).click();
|
||||
user.getDriver().findElements(By.className("publish-checkbox")).forEach(el -> el.click());
|
||||
user.getDriver().findElement(By.className("join-btn")).click();
|
||||
|
||||
user.getEventManager().waitUntilEventReaches("connectionCreated", 1);
|
||||
|
||||
OV.fetch();
|
||||
sessions = OV.getActiveSessions();
|
||||
Assert.assertEquals("Expected 1 active sessions but found " + sessions.size(), 1, sessions.size());
|
||||
|
||||
exec.executeCommand("sudo service kurento-media-server restart");
|
||||
Thread.sleep(3000);
|
||||
|
||||
OV.fetch();
|
||||
sessions = OV.getActiveSessions();
|
||||
Assert.assertEquals("Expected 1 active sessions but found " + sessions.size(), 1, sessions.size());
|
||||
|
||||
user.getDriver().findElement(By.id("add-user-btn")).click();
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .join-btn")).click();
|
||||
|
||||
user.getEventManager().waitUntilEventReaches("connectionCreated", 4);
|
||||
user.getEventManager().waitUntilEventReaches("accessAllowed", 1);
|
||||
user.getEventManager().waitUntilEventReaches("streamCreated", 2);
|
||||
user.getEventManager().waitUntilEventReaches("streamPlaying", 2);
|
||||
|
||||
final int numberOfVideos = user.getDriver().findElements(By.tagName("video")).size();
|
||||
Assert.assertEquals("Expected 2 videos but found " + numberOfVideos, 2, numberOfVideos);
|
||||
Assert.assertTrue("Videos were expected to have audio and video tracks", user.getEventManager()
|
||||
.assertMediaTracks(user.getDriver().findElements(By.tagName("video")), true, true));
|
||||
|
||||
OV.fetch();
|
||||
Session session = OV.getActiveSessions().get(0);
|
||||
Assert.assertEquals("Expected 2 active connections but found " + session.getActiveConnections(), 2,
|
||||
session.getActiveConnections().size());
|
||||
int pubs = session.getActiveConnections().stream().mapToInt(con -> con.getPublishers().size()).sum();
|
||||
int subs = session.getActiveConnections().stream().mapToInt(con -> con.getSubscribers().size()).sum();
|
||||
Assert.assertEquals("Expected 1 active publisher but found " + pubs, 1, pubs);
|
||||
Assert.assertEquals("Expected 1 active subscriber but found " + subs, 1, subs);
|
||||
|
||||
OV.startRecording(session.getSessionId(),
|
||||
new RecordingProperties.Builder().outputMode(OutputMode.INDIVIDUAL).build());
|
||||
user.getEventManager().waitUntilEventReaches("recordingStarted", 2);
|
||||
|
||||
long recStartTime = System.currentTimeMillis();
|
||||
|
||||
final CountDownLatch latch = new CountDownLatch(4);
|
||||
|
||||
user.getEventManager().on("recordingStopped", (event) -> {
|
||||
String reason = event.get("reason").getAsString();
|
||||
Assert.assertEquals("Expected 'recordingStopped' reason 'mediaServerDisconnect'", "mediaServerDisconnect",
|
||||
reason);
|
||||
latch.countDown();
|
||||
});
|
||||
user.getEventManager().on("streamDestroyed", (event) -> {
|
||||
String reason = event.get("reason").getAsString();
|
||||
Assert.assertEquals("Expected 'streamDestroyed' reason 'mediaServerDisconnect'", "mediaServerDisconnect",
|
||||
reason);
|
||||
latch.countDown();
|
||||
});
|
||||
exec.executeCommand("sudo service kurento-media-server restart");
|
||||
long recEndTime = System.currentTimeMillis();
|
||||
user.getEventManager().waitUntilEventReaches("recordingStopped", 2);
|
||||
user.getEventManager().waitUntilEventReaches("streamDestroyed", 2);
|
||||
if (!latch.await(5000, TimeUnit.MILLISECONDS)) {
|
||||
gracefullyLeaveParticipants(2);
|
||||
fail("Waiting for 2 streamDestroyed events with reason 'mediaServerDisconnect' to happen in total");
|
||||
return;
|
||||
}
|
||||
user.getEventManager().off("streamDestroyed");
|
||||
|
||||
session.fetch();
|
||||
Assert.assertEquals("Expected 2 active connections but found " + session.getActiveConnections(), 2,
|
||||
session.getActiveConnections().size());
|
||||
pubs = session.getActiveConnections().stream().mapToInt(con -> con.getPublishers().size()).sum();
|
||||
subs = session.getActiveConnections().stream().mapToInt(con -> con.getSubscribers().size()).sum();
|
||||
Assert.assertEquals("Expected no active publishers but found " + pubs, 0, pubs);
|
||||
Assert.assertEquals("Expected no active subscribers but found " + subs, 0, subs);
|
||||
|
||||
Recording rec = OV.getRecording("TestSession");
|
||||
double differenceInDuration = Math.abs(rec.getDuration() - ((recEndTime - recStartTime) / 1000));
|
||||
Assert.assertTrue("Recording duration exceeds valid value. Expected no more than 0.2 seconds, got "
|
||||
+ differenceInDuration, differenceInDuration < 0.2);
|
||||
|
||||
this.checkIndividualRecording("/opt/openvidu/recordings/TestSession/", rec, 1, "opus", "vp8", true);
|
||||
|
||||
WebElement pubBtn = user.getDriver().findElements(By.cssSelector("#openvidu-instance-1 .pub-btn")).get(0);
|
||||
pubBtn.click();
|
||||
user.getEventManager().waitUntilEventReaches("streamDestroyed", 3); // This is not real, only in testapp
|
||||
pubBtn.click();
|
||||
user.getEventManager().waitUntilEventReaches("streamCreated", 4);
|
||||
user.getEventManager().waitUntilEventReaches("streamPlaying", 4);
|
||||
|
||||
session.fetch();
|
||||
Assert.assertEquals("Expected 2 active connections but found " + session.getActiveConnections(), 2,
|
||||
session.getActiveConnections().size());
|
||||
pubs = session.getActiveConnections().stream().mapToInt(con -> con.getPublishers().size()).sum();
|
||||
subs = session.getActiveConnections().stream().mapToInt(con -> con.getSubscribers().size()).sum();
|
||||
Assert.assertEquals("Expected 1 active publisher but found " + pubs, 1, pubs);
|
||||
Assert.assertEquals("Expected 1 active subscriber but found " + subs, 1, subs);
|
||||
|
||||
gracefullyLeaveParticipants(2);
|
||||
}
|
||||
|
||||
private void listEmptyRecordings() {
|
||||
// List existing recordings (empty)
|
||||
user.getDriver().findElement(By.id("list-recording-btn")).click();
|
||||
|
||||
@ -73,7 +73,7 @@ public class BrowserUser {
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
this.eventManager.stopPolling();
|
||||
this.eventManager.stopPolling(true);
|
||||
this.driver.quit();
|
||||
}
|
||||
|
||||
|
||||
@ -32,11 +32,11 @@ import org.springframework.core.io.ClassPathResource;
|
||||
public class ChromeUser extends BrowserUser {
|
||||
|
||||
public ChromeUser(String userName, int timeOfWaitInSeconds) {
|
||||
this(userName, timeOfWaitInSeconds, "Entire screen");
|
||||
this(userName, timeOfWaitInSeconds, "Entire screen", false);
|
||||
}
|
||||
|
||||
public ChromeUser(String userName, int timeOfWaitInSeconds, String screenToCapture) {
|
||||
this(userName, timeOfWaitInSeconds, generateScreenChromeOptions(screenToCapture));
|
||||
public ChromeUser(String userName, int timeOfWaitInSeconds, String screenToCapture, boolean runningAsRoot) {
|
||||
this(userName, timeOfWaitInSeconds, generateScreenChromeOptions(screenToCapture, runningAsRoot));
|
||||
}
|
||||
|
||||
public ChromeUser(String userName, int timeOfWaitInSeconds, Path fakeVideoLocation) {
|
||||
@ -66,7 +66,7 @@ public class ChromeUser extends BrowserUser {
|
||||
this.configureDriver();
|
||||
}
|
||||
|
||||
private static ChromeOptions generateScreenChromeOptions(String screenToCapture) {
|
||||
private static ChromeOptions generateScreenChromeOptions(String screenToCapture, boolean runningAsRoot) {
|
||||
ChromeOptions options = new ChromeOptions();
|
||||
// This flag avoids to grant the user media
|
||||
options.addArguments("--use-fake-ui-for-media-stream");
|
||||
@ -80,6 +80,11 @@ public class ChromeUser extends BrowserUser {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (runningAsRoot) {
|
||||
options.addArguments("--no-sandbox");
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ package io.openvidu.test.e2e.utils;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class CommandLineExecuter {
|
||||
public class CommandLineExecutor {
|
||||
|
||||
public String executeCommand(String command) {
|
||||
String output = "";
|
||||
@ -28,7 +28,7 @@ public class MultimediaFileMetadata {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MultimediaFileMetadata.class);
|
||||
|
||||
private CommandLineExecuter executer = new CommandLineExecuter();
|
||||
private CommandLineExecutor executer = new CommandLineExecutor();
|
||||
private JsonParser parser = new JsonParser();
|
||||
|
||||
private JsonObject json;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user