From 77a63a8e545913ac8c89649dab5cf3dc783e79a6 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 16 Oct 2020 13:41:19 +0200 Subject: [PATCH] openvidu-server: GET /connection --- .../io/openvidu/server/core/Participant.java | 4 + .../java/io/openvidu/server/core/Session.java | 43 +-- .../server/core/SessionInterface.java | 4 +- .../kurento/core/KurentoParticipant.java | 1 + .../io/openvidu/server/kurento/kms/Kms.java | 2 +- .../server/rest/SessionRestController.java | 75 ++++- ...essionGarbageCollectorIntegrationTest.java | 2 +- .../test/e2e/OpenViduProTestAppE2eTest.java | 18 ++ .../test/e2e/OpenViduTestAppE2eTest.java | 264 ++++++++++++++++-- 9 files changed, 364 insertions(+), 49 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java index ddf1e76a..1c450ff4 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java @@ -316,4 +316,8 @@ public class Participant { return json; } + public JsonObject withStatsToJson() { + return null; + } + } diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Session.java b/openvidu-server/src/main/java/io/openvidu/server/core/Session.java index 1b6e88b5..f40f027f 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Session.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Session.java @@ -29,7 +29,7 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.function.Function; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,7 +43,6 @@ import io.openvidu.client.internal.ProtocolElements; import io.openvidu.java.client.RecordingLayout; import io.openvidu.java.client.SessionProperties; import io.openvidu.server.config.OpenviduConfig; -import io.openvidu.server.kurento.core.KurentoParticipant; import io.openvidu.server.recording.service.RecordingManager; import io.openvidu.server.utils.RecordingUtils; @@ -183,10 +182,6 @@ public class Session implements SessionInterface { return deleted; } - public boolean isTokenValid(String token) { - return this.tokens.containsKey(token); - } - public Token consumeToken(String token) { Token tokenObj = this.tokens.remove(token); return tokenObj; @@ -214,15 +209,30 @@ public class Session implements SessionInterface { } } - public JsonObject toJson() { - return this.sharedJson(KurentoParticipant::toJson); + public JsonArray getSnapshotOfConnectionsAsJsonArray(boolean withPendingConnections, boolean withWebrtcStats) { + + Set snapshotOfActiveConnections = this.getParticipants().stream().collect(Collectors.toSet()); + JsonArray jsonArray = new JsonArray(); + snapshotOfActiveConnections.forEach(participant -> { + // Filter recorder participant + if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(participant.getParticipantPublicId())) { + jsonArray.add(withWebrtcStats ? participant.withStatsToJson() : participant.toJson()); + } + }); + + if (withPendingConnections) { + Set snapshotOfPendingConnections = this.tokens.values().stream().collect(Collectors.toSet()); + // Eliminate duplicates in case some concurrent situation took place + Set activeConnectionIds = snapshotOfActiveConnections.stream() + .map(participant -> participant.getParticipantPublicId()).collect(Collectors.toSet()); + snapshotOfPendingConnections.removeIf(token -> activeConnectionIds.contains(token.getConnectionId())); + snapshotOfPendingConnections.forEach(token -> jsonArray.add(token.toJsonAsParticipant())); + } + + return jsonArray; } - public JsonObject withStatsToJson() { - return this.sharedJson(KurentoParticipant::withStatsToJson); - } - - private JsonObject sharedJson(Function toJsonFunction) { + public JsonObject toJson(boolean withPendingConnections, boolean withWebrtcStats) { JsonObject json = new JsonObject(); json.addProperty("id", this.sessionId); json.addProperty("object", "session"); @@ -241,12 +251,7 @@ public class Session implements SessionInterface { json.addProperty("customSessionId", this.sessionProperties.customSessionId()); } JsonObject connections = new JsonObject(); - JsonArray participants = new JsonArray(); - this.participants.values().forEach(p -> { - if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(p.getParticipantPublicId())) { - participants.add(toJsonFunction.apply((KurentoParticipant) p)); - } - }); + JsonArray participants = this.getSnapshotOfConnectionsAsJsonArray(withPendingConnections, withWebrtcStats); connections.addProperty("numberOfElements", participants.size()); connections.add("content", participants); json.add("connections", connections); diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionInterface.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionInterface.java index fa398f22..08d1d805 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionInterface.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionInterface.java @@ -47,9 +47,7 @@ public interface SessionInterface { String getMediaNodeId(); - JsonObject toJson(); - - JsonObject withStatsToJson(); + JsonObject toJson(boolean withPendingConnections, boolean withWebrtcStats); Long getStartTime(); diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java index 560d8808..68a7008b 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java @@ -568,6 +568,7 @@ public class KurentoParticipant extends Participant { return this.sharedJson(MediaEndpoint::toJson); } + @Override public JsonObject withStatsToJson() { return this.sharedJson(MediaEndpoint::withStatsToJson); } diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java index 31d74da9..d63ec9d9 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java @@ -171,7 +171,7 @@ public class Kms { if (withSessions) { JsonArray sessions = new JsonArray(); for (KurentoSession session : this.kurentoSessions.values()) { - sessions.add(session.toJson()); + sessions.add(session.toJson(false, false)); } json.add("sessions", sessions); } diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index 75539422..7992af8a 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -20,7 +20,9 @@ package io.openvidu.server.rest; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collection; +import java.util.Iterator; import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -177,25 +179,25 @@ public class SessionRestController { log.info("New session {} initialized {}", sessionId, this.sessionManager.getSessionsWithNotActive().stream() .map(Session::getSessionId).collect(Collectors.toList()).toString()); - return new ResponseEntity<>(sessionNotActive.toJson().toString(), RestUtils.getResponseHeaders(), + return new ResponseEntity<>(sessionNotActive.toJson(false, false).toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); } @RequestMapping(value = "/sessions/{sessionId}", method = RequestMethod.GET) public ResponseEntity getSession(@PathVariable("sessionId") String sessionId, + @RequestParam(value = "pendingConnections", defaultValue = "false", required = false) boolean pendingConnections, @RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) { log.info("REST API: GET {}/sessions/{}", RequestMappings.API, sessionId); Session session = this.sessionManager.getSession(sessionId); if (session != null) { - JsonObject response = (webRtcStats == true) ? session.withStatsToJson() : session.toJson(); + JsonObject response = session.toJson(pendingConnections, webRtcStats); return new ResponseEntity<>(response.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); } else { Session sessionNotActive = this.sessionManager.getSessionNotActive(sessionId); if (sessionNotActive != null) { - JsonObject response = (webRtcStats == true) ? sessionNotActive.withStatsToJson() - : sessionNotActive.toJson(); + JsonObject response = sessionNotActive.toJson(pendingConnections, webRtcStats); return new ResponseEntity<>(response.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); } else { return new ResponseEntity<>(HttpStatus.NOT_FOUND); @@ -205,15 +207,16 @@ public class SessionRestController { @RequestMapping(value = "/sessions", method = RequestMethod.GET) public ResponseEntity listSessions( + @RequestParam(value = "pendingConnections", defaultValue = "false", required = false) boolean pendingConnections, @RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) { - log.info("REST API: GET {}/sessions?webRtcStats={}", RequestMappings.API, webRtcStats); + log.info("REST API: GET {}/sessions", RequestMappings.API); Collection sessions = this.sessionManager.getSessionsWithNotActive(); JsonObject json = new JsonObject(); JsonArray jsonArray = new JsonArray(); - sessions.forEach(s -> { - JsonObject sessionJson = (webRtcStats == true) ? s.withStatsToJson() : s.toJson(); + sessions.forEach(session -> { + JsonObject sessionJson = session.toJson(pendingConnections, webRtcStats); jsonArray.add(sessionJson); }); json.addProperty("numberOfElements", sessions.size()); @@ -735,6 +738,51 @@ public class SessionRestController { return new ResponseEntity<>(HttpStatus.OK); } + @RequestMapping(value = "/sessions/{sessionId}/connection/{connectionId}", method = RequestMethod.GET) + public ResponseEntity getConnection(@PathVariable("sessionId") String sessionId, + @PathVariable("connectionId") String connectionId) { + + log.info("REST API: GET {}/sessions/{}/connection/{}", RequestMappings.API, sessionId, connectionId); + + Session session = this.sessionManager.getSessionWithNotActive(sessionId); + if (session != null) { + Participant p = session.getParticipantByPublicId(connectionId); + if (p != null) { + return new ResponseEntity<>(p.toJson().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); + } else { + Token t = getTokenFromConnectionId(connectionId, session.getTokenIterator()); + if (t != null) { + return new ResponseEntity<>(t.toJsonAsParticipant().toString(), RestUtils.getResponseHeaders(), + HttpStatus.OK); + } else { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + } + } else { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + } + + @RequestMapping(value = "/sessions/{sessionId}/connection", method = RequestMethod.GET) + public ResponseEntity listConnections(@PathVariable("sessionId") String sessionId, + @RequestParam(value = "pendingConnections", defaultValue = "true", required = false) boolean pendingConnections, + @RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) { + + log.info("REST API: GET {}/sessions/{}/connection", RequestMappings.API, sessionId); + + Session session = this.sessionManager.getSessionWithNotActive(sessionId); + + if (session != null) { + JsonObject json = new JsonObject(); + JsonArray jsonArray = session.getSnapshotOfConnectionsAsJsonArray(pendingConnections, webRtcStats); + json.addProperty("numberOfElements", jsonArray.size()); + json.add("content", jsonArray); + return new ResponseEntity<>(json.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); + } else { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + } + @RequestMapping(value = "/sessions/{sessionId}/connection", method = RequestMethod.POST) public ResponseEntity publishIpcam(@PathVariable("sessionId") String sessionId, @RequestBody Map params) { @@ -812,6 +860,19 @@ public class SessionRestController { } } + protected Token getTokenFromConnectionId(String connectionId, Iterator> iterator) { + boolean found = false; + Token token = null; + while (iterator.hasNext() && !found) { + Token tAux = iterator.next().getValue(); + found = tAux.getConnectionId().equals(connectionId); + if (found) { + token = tAux; + } + } + return token; + } + protected ResponseEntity generateErrorResponse(String errorMessage, String path, HttpStatus status) { JsonObject responseJson = new JsonObject(); responseJson.addProperty("timestamp", System.currentTimeMillis()); diff --git a/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java b/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java index 7e267ee6..e4abf225 100644 --- a/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java +++ b/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java @@ -110,7 +110,7 @@ public class SessionGarbageCollectorIntegrationTest { } private JsonObject listSessions() { - String stringResponse = (String) sessionRestController.listSessions(false).getBody(); + String stringResponse = (String) sessionRestController.listSessions(false, false).getBody(); return new Gson().fromJson(stringResponse, JsonObject.class); } diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index cc253613..bd14255e 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -31,6 +31,7 @@ import io.openvidu.java.client.OpenViduHttpException; import io.openvidu.java.client.OpenViduRole; import io.openvidu.java.client.Recording; import io.openvidu.java.client.Session; +import io.openvidu.java.client.Token; import io.openvidu.test.browsers.utils.CustomHttpClient; import io.openvidu.test.browsers.utils.Unzipper; @@ -382,4 +383,21 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { "{'status':'UP'}"); } + @Test + @DisplayName("openvidu-java-client PRO test") + void openViduJavaClientProTest() throws Exception { + Session session = OV.createSession(); + Assert.assertFalse(session.fetch()); + Token token = session.createToken(); + Assert.assertTrue(session.fetch()); + Connection connection = session.getConnection(token.getConnectionId()); + Assert.assertEquals("Wrong role property", OpenViduRole.PUBLISHER, connection.getRole()); + Assert.assertTrue("Wrong record property", connection.record()); + session.updateConnection(connection.getConnectionId(), + new ConnectionOptions.Builder().role(OpenViduRole.SUBSCRIBER).record(false).build()); + Assert.assertEquals("Wrong role property", OpenViduRole.SUBSCRIBER, connection.getRole()); + Assert.assertFalse("Wrong record property", connection.record()); + Assert.assertFalse(session.fetch()); + } + } 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 be488351..1ea36adf 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 @@ -42,7 +42,9 @@ import org.openqa.selenium.Alert; import org.openqa.selenium.By; import org.openqa.selenium.Dimension; import org.openqa.selenium.Keys; +import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.ExpectedConditions; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -64,6 +66,7 @@ import io.openvidu.java.client.RecordingMode; import io.openvidu.java.client.RecordingProperties; import io.openvidu.java.client.Session; import io.openvidu.java.client.SessionProperties; +import io.openvidu.java.client.Token; import io.openvidu.java.client.TokenOptions; import io.openvidu.test.browsers.FirefoxUser; import io.openvidu.test.browsers.utils.CustomHttpClient; @@ -2114,8 +2117,6 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { log.info("openvidu-java-client test"); - System.out.println(getBase64Screenshot(user)); - user.getDriver().findElement(By.id("one2one-btn")).click(); final String customSessionId = "openviduJavaClientSession"; @@ -2142,13 +2143,34 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { .allowedFilters(new String[] { "GStreamerFilter" }).build(); TokenOptions tokenOptionsModerator = new TokenOptions.Builder().role(OpenViduRole.MODERATOR) .data(serverDataModerator).kurentoOptions(kurentoOptions).build(); - String tokenModerator = session.generateToken(tokenOptionsModerator); + Token tokenModerator = session.createToken(tokenOptionsModerator); + String tokenModeratorString = tokenModerator.getToken(); + String connectionIdModerator = tokenModerator.getConnectionId(); TokenOptions tokenOptionsSubscriber = new TokenOptions.Builder().role(OpenViduRole.SUBSCRIBER) .data(serverDataSubscriber).build(); - String tokenSubscriber = session.generateToken(tokenOptionsSubscriber); + Token tokenSubscriber = session.createToken(tokenOptionsSubscriber); + String tokenSubscriberString = tokenSubscriber.getToken(); + String connectionIdSubscriber = tokenSubscriber.getConnectionId(); - Assert.assertFalse("Session.fetch() should return false until a user has connected", session.fetch()); + Assert.assertTrue("Session.fetch() should return true if new pending connections", session.fetch()); + Assert.assertFalse("OpenVidu.fetch() should return false after Session.fetch()", OV.fetch()); + + Assert.assertEquals("Wrong number of active connections", 0, session.getActiveConnections().size()); + Assert.assertEquals("Wrong number of connections", 2, session.getConnections().size()); + Connection connectionModerator = session.getConnection(connectionIdModerator); + Connection connectionSubscriber = session.getConnection(connectionIdSubscriber); + Assert.assertEquals("Wrong connectionId property", connectionIdModerator, + connectionModerator.getConnectionId()); + Assert.assertEquals("Wrong status property", "pending", connectionModerator.getStatus()); + Assert.assertEquals("Wrong role property", OpenViduRole.MODERATOR, connectionModerator.getRole()); + Assert.assertTrue("Wrong record property", connectionModerator.record()); + Assert.assertNull("Wrong location property", connectionModerator.getLocation()); + Assert.assertNull("Wrong platform property", connectionModerator.getPlatform()); + Assert.assertEquals("Wrong createdAt property", 0, connectionModerator.createdAt()); + Assert.assertNull("Wrong clientData property", connectionModerator.getClientData()); + Assert.assertEquals("Wrong publishers property", 0, connectionModerator.getPublishers().size()); + Assert.assertEquals("Wrong subscribers property", 0, connectionModerator.getSubscribers().size()); // Set client data 1 WebElement clientDataInput = user.getDriver().findElement(By.cssSelector("#client-data-input-0")); @@ -2160,7 +2182,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Thread.sleep(1000); WebElement tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input")); tokeInput.clear(); - tokeInput.sendKeys(tokenModerator); + tokeInput.sendKeys(tokenModeratorString); user.getDriver().findElement(By.id("save-btn")).click(); Thread.sleep(1000); @@ -2175,7 +2197,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Thread.sleep(1000); tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input")); tokeInput.clear(); - tokeInput.sendKeys(tokenSubscriber); + tokeInput.sendKeys(tokenSubscriberString); user.getDriver().findElement(By.id("save-btn")).click(); Thread.sleep(1000); @@ -2215,17 +2237,9 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertEquals("Expected 2 active connections but found " + session.getActiveConnections().size(), 2, session.getActiveConnections().size()); - Connection connectionModerator; - Connection connectionSubscriber; - if (OpenViduRole.MODERATOR.equals(session.getActiveConnections().get(0).getRole())) { - connectionModerator = session.getActiveConnections().get(0); - connectionSubscriber = session.getActiveConnections().get(1); - } else { - connectionModerator = session.getActiveConnections().get(1); - connectionSubscriber = session.getActiveConnections().get(0); - } - - Assert.assertEquals(OpenViduRole.SUBSCRIBER, connectionSubscriber.getRole()); + // Verify status + Assert.assertEquals("Wrong status for moderator connection", "active", connectionModerator.getStatus()); + Assert.assertEquals("Wrong status for subscriber connection", "active", connectionSubscriber.getStatus()); // Verify platform Assert.assertTrue("Wrong platform for moderator connection", @@ -2579,6 +2593,15 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, true, false, "{'numberOfElements': 1, 'content': []}"); + /** GET /openvidu/api/sessions/ID/connection (with no connections) **/ + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/NOT_EXISTS/connection", HttpStatus.SC_NOT_FOUND); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", null, HttpStatus.SC_OK, + true, true, true, "{'numberOfElements':0,'content':[]}"); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/NOT_EXISTS/connection/NOT_EXISTS", + HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/NOT_EXISTS", + HttpStatus.SC_NOT_FOUND); + /** POST /openvidu/api/tokens **/ // 400 body = "{}"; @@ -2599,6 +2622,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true, "{'id':'STR','object':'STR','connectionId':'STR','session':'STR','role':'STR','data':'STR','record':true,'token':'STR','kurentoOptions':{'videoMaxSendBandwidth':777,'allowedFilters':['STR']}}"); final String token1 = res.get("token").getAsString(); + final String connectionId1 = res.get("connectionId").getAsString(); Assert.assertEquals("JSON return value from /openvidu/api/tokens should have equal srtings in 'id' and 'token'", res.get("id").getAsString(), token1); Assert.assertEquals("Wrong session parameter", "CUSTOM_SESSION_ID", res.get("session").getAsString()); @@ -2608,6 +2632,17 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_TOKEN); final String token2 = res.get("id").getAsString(); + final String connectionId2 = res.get("connectionId").getAsString(); + + /** GET /openvidu/api/sessions/ID/connection (with pending connections) **/ + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", null, HttpStatus.SC_OK, + true, true, false, "{'numberOfElements':2,'content':[]}"); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId1, null, + HttpStatus.SC_OK, true, true, true, + "{'id':'" + connectionId1 + "','connectionId':'" + connectionId1 + + "','object':'connection','status':'pending','sessionId':'CUSTOM_SESSION_ID','token':'" + + token1 + + "','role':'MODERATOR','serverData':'SERVER_DATA','record':true,'createdAt':null,'platform':null,'location':null,'clientData':null,'publishers':null,'subscribers':null}"); /** POST /openvidu/api/signal (NOT ACTIVE SESSION) **/ body = "{}"; @@ -2695,6 +2730,20 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertTrue("Videos were expected to have audio and video tracks", user.getEventManager() .assertMediaTracks(user.getDriver().findElements(By.tagName("video")), true, true)); + /** GET /openvidu/api/sessions/ID/connection (with active connections) **/ + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", null, HttpStatus.SC_OK, + true, true, false, "{'numberOfElements':2,'content':[]}"); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId1, null, + HttpStatus.SC_OK, false, true, false, + "{'id':'" + connectionId1 + "','connectionId':'" + connectionId1 + + "','object':'connection','status':'active','sessionId':'CUSTOM_SESSION_ID','token':'" + token1 + + "','role':'MODERATOR','serverData':'SERVER_DATA','record':true}"); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId2, null, + HttpStatus.SC_OK, false, true, false, + "{'id':'" + connectionId2 + "','connectionId':'" + connectionId2 + + "','object':'connection','status':'active','sessionId':'CUSTOM_SESSION_ID','token':'" + token2 + + "','role':'PUBLISHER','serverData':'','record':true}"); + /** GET /openvidu/api/recordings (before recording started) **/ restClient.rest(HttpMethod.GET, "/openvidu/api/recordings/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); restClient.rest(HttpMethod.GET, "/openvidu/api/recordings", null, HttpStatus.SC_OK, true, true, true, @@ -3434,4 +3483,183 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { } } + @Test + @DisplayName("OpenVidu SDK fetch test") + void openviduSdkFetchTest() throws Exception { + isRecordingTest = true; + + setupBrowser("chrome"); + + log.info("OpenVidu SDK fetch test"); + + user.getDriver().findElement(By.id("add-user-btn")).click(); + user.getDriver().findElement(By.id("session-api-btn-0")).click(); + Thread.sleep(1000); + + Session session = OV.createSession(); + Assert.assertFalse("Java fetch should be false", OV.fetch()); + checkNodeFetchChanged(true, true); + checkNodeFetchChanged(true, false); + + CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", "{'customSessionId':'REST_SESSION'}", + HttpStatus.SC_OK); + Assert.assertTrue("Java fetch should be true", OV.fetch()); + Assert.assertFalse("Java fetch should be false", OV.fetch()); + Assert.assertFalse("Java fetch should be false", session.fetch()); + checkNodeFetchChanged(true, true); + checkNodeFetchChanged(true, false); + + Token token = session.createToken(); + // TODO: when using createConnection this below should be false! + Assert.assertTrue("Java fetch should be true", session.fetch()); + Assert.assertFalse("Java fetch should be false", OV.fetch()); + checkNodeFetchChanged(true, true); + checkNodeFetchChanged(true, false); + + restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", "{'session':'REST_SESSION'}", HttpStatus.SC_OK); + Assert.assertFalse("Fetch should be true", session.fetch()); + Assert.assertTrue("Fetch should be false", OV.fetch()); + checkNodeFetchChanged(true, true); + checkNodeFetchChanged(true, false); + + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/REST_SESSION", HttpStatus.SC_NO_CONTENT); + Assert.assertFalse("Java fetch should be true", session.fetch()); + Assert.assertTrue("Java fetch should be true", OV.fetch()); + Assert.assertFalse("Java fetch should be false", OV.fetch()); + checkNodeFetchChanged(true, true); + checkNodeFetchChanged(true, false); + + // Set token and join session + user.getDriver().findElement(By.id("close-dialog-btn")).click(); + Thread.sleep(1000); + user.getDriver().findElement(By.id("session-settings-btn-0")).click(); + Thread.sleep(1000); + WebElement tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input")); + tokeInput.clear(); + tokeInput.sendKeys(token.getToken()); + user.getDriver().findElement(By.id("save-btn")).click(); + Thread.sleep(1000); + user.getDriver().findElement(By.className("join-btn")).click(); + + user.getEventManager().waitUntilEventReaches("connectionCreated", 1); + user.getEventManager().waitUntilEventReaches("accessAllowed", 1); + user.getEventManager().waitUntilEventReaches("streamCreated", 1); + user.getEventManager().waitUntilEventReaches("streamPlaying", 1); + + user.getDriver().findElement(By.id("session-api-btn-0")).click(); + Thread.sleep(1000); + + Assert.assertTrue("Java fetch should be true", OV.fetch()); + Assert.assertFalse("Java fetch should be false", session.fetch()); + checkNodeFetchChanged(false, true); + checkNodeFetchChanged(true, false); + checkNodeFetchChanged(true, false); + + // RECORD + user.getDriver().findElement(By.id("rec-properties-btn")).click(); + user.getDriver().findElement(By.id("rec-hasvideo-checkbox")).click(); + user.getDriver().findElement(By.id("rec-outputmode-select")).click(); + Thread.sleep(500); + user.getDriver().findElement(By.id("option-INDIVIDUAL")).click(); + Thread.sleep(500); + + user.getDriver().findElement(By.id("start-recording-btn")).click(); + user.getEventManager().waitUntilEventReaches("recordingStarted", 1); + + // Node SDK should return false as the recording has been started with it + checkNodeFetchChanged(false, false); + checkNodeFetchChanged(true, false); + checkNodeFetchChanged(true, false); + // Java SDK should return true as it doesn't know about the recording yet + Assert.assertTrue("Java fetch should be true", session.fetch()); + Assert.assertFalse("Java fetch should be false", OV.fetch()); + + OV.stopRecording(session.getSessionId()); + user.getEventManager().waitUntilEventReaches("recordingStopped", 1); + // Java SDK should return false as the recording has been stopped with it + Assert.assertFalse("Java fetch should be false", session.fetch()); + Assert.assertFalse("Java fetch should be false", OV.fetch()); + // Node SDK should return true as it doesn't know about the recording stooped + checkNodeFetchChanged(false, true); + checkNodeFetchChanged(false, false); + checkNodeFetchChanged(true, false); + + // NEW SUBSCRIBER + user.getDriver().findElement(By.id("close-dialog-btn")).click(); + Thread.sleep(1000); + user.getDriver().findElement(By.id("add-user-btn")).click(); + user.getDriver().findElement(By.id("session-name-input-1")).clear(); + user.getDriver().findElement(By.id("session-name-input-1")).sendKeys(session.getSessionId()); + user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .publish-checkbox")).click(); + user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .join-btn")).click(); + user.getEventManager().waitUntilEventReaches("streamPlaying", 2); + + user.getDriver().findElement(By.id("session-api-btn-0")).click(); + Thread.sleep(1000); + Assert.assertTrue("Java fetch should be true", OV.fetch()); + Assert.assertFalse("Java fetch should be false", session.fetch()); + checkNodeFetchChanged(true, true); + checkNodeFetchChanged(true, false); + checkNodeFetchChanged(false, false); + + // MODIFY STREAM + user.getDriver().findElement(By.id("close-dialog-btn")).click(); + Thread.sleep(1000); + user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 .pub-video-btn")).click(); + user.getEventManager().waitUntilEventReaches("streamPropertyChanged", 2); + user.getDriver().findElement(By.id("session-api-btn-0")).click(); + Thread.sleep(1000); + Assert.assertTrue("Java fetch should be true", session.fetch()); + Assert.assertFalse("Java fetch should be false", OV.fetch()); + checkNodeFetchChanged(false, true); + checkNodeFetchChanged(true, false); + checkNodeFetchChanged(false, false); + + // REMOVE STREAM + user.getDriver().findElement(By.id("close-dialog-btn")).click(); + Thread.sleep(1000); + user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .sub-btn")).click(); + user.getDriver().findElement(By.id("session-api-btn-0")).click(); + Thread.sleep(1000); + Assert.assertTrue("Java fetch should be true", OV.fetch()); + Assert.assertFalse("Java fetch should be false", session.fetch()); + checkNodeFetchChanged(true, true); + checkNodeFetchChanged(true, false); + checkNodeFetchChanged(false, false); + + // REMOVE USER + user.getDriver().findElement(By.id("close-dialog-btn")).click(); + Thread.sleep(1000); + user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .leave-btn")).click(); + user.getEventManager().waitUntilEventReaches("connectionDestroyed", 1); + user.getDriver().findElement(By.id("session-api-btn-0")).click(); + Thread.sleep(1000); + Assert.assertTrue("Java fetch should be true", session.fetch()); + Assert.assertFalse("Java fetch should be false", OV.fetch()); + checkNodeFetchChanged(false, true); + checkNodeFetchChanged(false, false); + checkNodeFetchChanged(true, false); + } + + private void checkNodeFetchChanged(boolean global, boolean hasChanged) { + user.getDriver().findElement(By.id(global ? "list-sessions-btn" : "get-session-btn")).click(); + user.getWaiter().until(new NodeFetchHasChanged(hasChanged)); + } + + private class NodeFetchHasChanged implements ExpectedCondition { + + private boolean hasChanged; + + public NodeFetchHasChanged(boolean hasChanged) { + this.hasChanged = hasChanged; + } + + @Override + public Boolean apply(WebDriver driver) { + return driver.findElement(By.id("api-response-text-area")).getAttribute("value") + .endsWith("Changes: " + hasChanged); + } + } + }