openvidu-test-e2e: add tests for STT load/unloading lang models

pull/771/head
pabloFuente 2022-12-20 01:12:53 +01:00
parent 038d6ccd29
commit 316b14561f
1 changed files with 137 additions and 22 deletions

View File

@ -22,9 +22,9 @@ import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.openqa.selenium.Alert; import org.openqa.selenium.Alert;
@ -56,6 +56,8 @@ import io.openvidu.test.browsers.utils.Unzipper;
public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest { public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
protected volatile static boolean isSttManualTest = false;
@BeforeAll() @BeforeAll()
protected static void setupAll() { protected static void setupAll() {
checkFfmpegInstallation(); checkFfmpegInstallation();
@ -64,6 +66,33 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
cleanFoldersAndSetUpOpenViduJavaClient(); cleanFoldersAndSetUpOpenViduJavaClient();
} }
@AfterEach
protected void dispose() {
// Unload STT models in all running Media Nodes
if (isSttManualTest) {
try {
CustomHttpClient restClient = new CustomHttpClient(OpenViduTestAppE2eTest.OPENVIDU_URL, "OPENVIDUAPP",
OpenViduTestAppE2eTest.OPENVIDU_SECRET);
JsonArray mediaNodes = restClient
.rest(HttpMethod.GET, "/openvidu/api/media-nodes", null, HttpStatus.SC_OK).get("content")
.getAsJsonArray();
mediaNodes.asList().parallelStream().forEach(mediaNode -> {
String containerId = mediaNode.getAsJsonObject().get("environmentId").getAsString();
try {
restartSttContainer(containerId);
} catch (Exception e) {
System.err.println(e);
}
});
} catch (Exception e) {
System.err.println(e);
} finally {
isSttManualTest = false;
}
}
super.dispose();
}
@Test @Test
@DisplayName("Individual dynamic record") @DisplayName("Individual dynamic record")
void individualDynamicRecordTest() throws Exception { void individualDynamicRecordTest() throws Exception {
@ -1611,7 +1640,10 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
latch.countDown(); latch.countDown();
}); });
this.killSttService(); CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET);
String containerId = restClient.rest(HttpMethod.GET, "/openvidu/api/media-nodes", HttpStatus.SC_OK)
.get("content").getAsJsonArray().get(0).getAsJsonObject().get("environmentId").getAsString();
this.killSttService(containerId);
latch.await(); latch.await();
@ -1751,6 +1783,8 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
@DisplayName("REST API STT Test") @DisplayName("REST API STT Test")
void restApiSttTest() throws Exception { void restApiSttTest() throws Exception {
isSttManualTest = true;
log.info("REST API STT"); log.info("REST API STT");
CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET);
@ -1851,21 +1885,87 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
// OK // OK
body = "{'lang':'es-ES', 'mediaNode': {'id': '" + mediaNodeId + "'}}"; body = "{'lang':'es-ES', 'mediaNode': {'id': '" + mediaNodeId + "'}}";
restClient.rest(HttpMethod.POST, "/openvidu/api/speech-to-text/unload", body, HttpStatus.SC_OK); restClient.rest(HttpMethod.POST, "/openvidu/api/speech-to-text/unload", body, HttpStatus.SC_OK);
// // With manual mode
//
// OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chromeFakeAudio");
// user.getDriver().get(APP_URL);
// user.getDriver().findElement(By.id("add-user-btn")).click();
// user.getDriver().findElement(By.className("join-btn")).sendKeys(Keys.ENTER);
// user.getEventManager().waitUntilEventReaches("streamCreated", 1);
// user.getEventManager().waitUntilEventReaches("streamPlaying", 1);
//
// sttSubUser(user, 0, 0, "en-US", true, false, "");
//
// gracefullyLeaveParticipants(user, 1);
} }
@Test
@DisplayName("Load Unload Model Error STT Test")
void loadUnloadModelErrorSttTest() throws Exception {
isSttManualTest = true;
log.info("Load Unload Model Error STT");
restartOpenViduServerIfNecessary(false, null, "vosk", "manual");
CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET);
JsonArray mediaNodes = restClient.rest(HttpMethod.GET, "/openvidu/api/media-nodes", null, HttpStatus.SC_OK)
.get("content").getAsJsonArray();
String mediaNodeId = mediaNodes.get(0).getAsJsonObject().get("id").getAsString();
OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chromeFakeAudio");
user.getDriver().get(APP_URL);
user.getDriver().findElement(By.id("add-user-btn")).click();
user.getDriver().findElement(By.id("add-user-btn")).click();
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .publish-checkbox")).click();
user.getDriver().findElements(By.className("join-btn")).forEach(btn -> btn.sendKeys(Keys.ENTER));
user.getEventManager().waitUntilEventReaches("streamCreated", 2);
user.getEventManager().waitUntilEventReaches("streamPlaying", 2);
sttSubUser(user, 0, 0, "en-US", true, false,
"Vosk model for language 'en-US' is not loaded and OPENVIDU_PRO_SPEECH_TO_TEXT_VOSK_MODEL_LOAD_STRATEGY is manual",
false);
String body = "{'lang':'en-US', 'mediaNode': {'id': '" + mediaNodeId + "'}}";
restClient.rest(HttpMethod.POST, "/openvidu/api/speech-to-text/load", body, HttpStatus.SC_OK);
sttSubUser(user, 0, 0, "en-US", false, true);
user.getEventManager().waitUntilEventReaches("speechToTextMessage", 2);
sttSubUser(user, 1, 0, "es-ES", true, false,
"Vosk model for language 'es-ES' is not loaded and OPENVIDU_PRO_SPEECH_TO_TEXT_VOSK_MODEL_LOAD_STRATEGY is manual",
false);
// First participant still receiving STT events
user.getEventManager().clearAllCurrentEvents(0);
user.getEventManager().waitUntilEventReaches(0, "speechToTextMessage", 4);
body = "{'lang':'es-ES', 'mediaNode': {'id': '" + mediaNodeId + "'}}";
restClient.rest(HttpMethod.POST, "/openvidu/api/speech-to-text/load", body, HttpStatus.SC_OK);
sttSubUser(user, 1, 0, "es-ES", false, true);
user.getEventManager().clearAllCurrentEvents(0);
user.getEventManager().clearAllCurrentEvents(1);
user.getEventManager().waitUntilEventReaches(0, "speechToTextMessage", 4);
user.getEventManager().waitUntilEventReaches(1, "speechToTextMessage", 4);
// Unloading lang in use should not affect current STT subscriptions
body = "{'lang':'es-ES', 'mediaNode': {'id': '" + mediaNodeId + "'}}";
restClient.rest(HttpMethod.POST, "/openvidu/api/speech-to-text/unload", body, HttpStatus.SC_OK);
body = "{'lang':'en-US', 'mediaNode': {'id': '" + mediaNodeId + "'}}";
restClient.rest(HttpMethod.POST, "/openvidu/api/speech-to-text/unload", body, HttpStatus.SC_OK);
user.getEventManager().clearAllCurrentEvents(0);
user.getEventManager().clearAllCurrentEvents(1);
user.getEventManager().waitUntilEventReaches(0, "speechToTextMessage", 4);
user.getEventManager().waitUntilEventReaches(1, "speechToTextMessage", 4);
gracefullyLeaveParticipants(user, 2);
}
// Test de manual con fallo. Pasos, mismo test:
// 1. Intentar usar un idioma que no está cargado
// 2. Cargar el idioma e intentarlo. Ahora todo bien. Se reciben eventos
// 3. Intentar usar un segundo idioma sin carga sobre el mismo stream. Ahora
// fallo. Eventos del primero bien todavia
// 4. Cargar el segundo idioma, intentarlo. Ahora los 2 van bien, cada uno en su
// idioma
// Descarga en uso de un idioma? Qué pasa? Sigue funcionando y enviando eventos?
// Qué pasa si se intenta iniciar
// otro stream con ese idioma descargado pero en uso? Se carga 2 veces?
protected void restartOpenViduServerIfNecessary(Boolean wantedNetworkQuality, Integer wantedNetworkQualityInterval, protected void restartOpenViduServerIfNecessary(Boolean wantedNetworkQuality, Integer wantedNetworkQualityInterval,
String wantedSpeechToText, String wantedVoskModelLoadStrategy) { String wantedSpeechToText, String wantedVoskModelLoadStrategy) {
@ -1980,6 +2080,12 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
private void sttSubUser(OpenViduTestappUser user, int numberOfUser, int numberOfVideo, String language, private void sttSubUser(OpenViduTestappUser user, int numberOfUser, int numberOfVideo, String language,
boolean openDialog, boolean closeDialog, String outputMessage) throws InterruptedException { boolean openDialog, boolean closeDialog, String outputMessage) throws InterruptedException {
this.sttSubUser(user, numberOfUser, numberOfVideo, language, openDialog, closeDialog, outputMessage, true);
}
private void sttSubUser(OpenViduTestappUser user, int numberOfUser, int numberOfVideo, String language,
boolean openDialog, boolean closeDialog, String outputMessage, boolean exactMatchOutputMessage)
throws InterruptedException {
if (openDialog) { if (openDialog) {
List<WebElement> videos = user.getDriver() List<WebElement> videos = user.getDriver()
.findElements(By.cssSelector("#openvidu-instance-" + numberOfUser + " app-video")); .findElements(By.cssSelector("#openvidu-instance-" + numberOfUser + " app-video"));
@ -1991,8 +2097,14 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
langInput.clear(); langInput.clear();
langInput.sendKeys(language); langInput.sendKeys(language);
user.getDriver().findElement(By.cssSelector("#sub-stt-btn")).click(); user.getDriver().findElement(By.cssSelector("#sub-stt-btn")).click();
user.getWaiter() if (exactMatchOutputMessage) {
.until(ExpectedConditions.attributeToBe(By.id("operation-response-text-area"), "value", outputMessage)); user.getWaiter().until(
ExpectedConditions.attributeToBe(By.id("operation-response-text-area"), "value", outputMessage));
} else {
user.getWaiter().until(ExpectedConditions.attributeContains(By.id("operation-response-text-area"), "value",
outputMessage));
}
if (closeDialog) { if (closeDialog) {
user.getDriver().findElement(By.id("close-dialog-btn")).click(); user.getDriver().findElement(By.id("close-dialog-btn")).click();
Thread.sleep(500); Thread.sleep(500);
@ -2017,17 +2129,20 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
} }
} }
private void killSttService() throws Exception { private void killSttService(String mediaNodeContainerId) throws Exception {
// For local run // For local run
// String killCommand = "ps axf | grep \"speech-to-text-service\" | grep -v grep // String killCommand = "ps axf | grep \"speech-to-text-service\" | grep -v grep
// | awk '{print $1}' | xargs -I {} kill -9 {}"; // | awk '{print $1}' | xargs -I {} kill -9 {}";
// For DIND run // For DIND run
CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); String killCommand = "docker exec -i " + mediaNodeContainerId
String containerId = restClient.rest(HttpMethod.GET, "/openvidu/api/media-nodes", HttpStatus.SC_OK)
.get("content").getAsJsonArray().get(0).getAsJsonObject().get("environmentId").getAsString();
String killCommand = "docker exec -i " + containerId
+ " /bin/sh -c \"ps axf | grep \\\"speech-to-text-service\\\" | grep -v grep | awk '{print \\$1}' | xargs -I {} kill -9 {}\""; + " /bin/sh -c \"ps axf | grep \\\"speech-to-text-service\\\" | grep -v grep | awk '{print \\$1}' | xargs -I {} kill -9 {}\"";
commandLine.executeCommand(killCommand, 10); commandLine.executeCommand(killCommand, 10);
} }
private void restartSttContainer(String mediaNodeContainerId) throws Exception {
String restartCommand = "docker exec -i " + mediaNodeContainerId
+ " /bin/sh -c \"docker restart speech-to-text-services\"";
commandLine.executeCommand(restartCommand, 30);
}
} }