openvidu-test-e2e: init openViduJavaClientTest and REST API test

pull/203/head
pabloFuente 2019-02-08 21:10:23 +01:00
parent a94d9d0497
commit 248539fa42
3 changed files with 384 additions and 1 deletions

View File

@ -163,6 +163,12 @@
<artifactId>openvidu-java-client</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>com.mashape.unirest</groupId>
<artifactId>unirest-java</artifactId>
<version>1.4.9</version>
</dependency>
</dependencies>
</project>

View File

@ -44,6 +44,7 @@ import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
import org.apache.commons.io.FileUtils;
import org.apache.http.HttpStatus;
import org.jcodec.api.FrameGrab;
import org.jcodec.api.JCodecException;
import org.jcodec.common.model.Picture;
@ -75,19 +76,29 @@ import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.stream.JsonReader;
import com.mashape.unirest.http.HttpMethod;
import io.github.bonigarcia.SeleniumExtension;
import io.github.bonigarcia.wdm.WebDriverManager;
import io.openvidu.java.client.KurentoOptions;
import io.openvidu.java.client.MediaMode;
import io.openvidu.java.client.OpenVidu;
import io.openvidu.java.client.OpenViduHttpException;
import io.openvidu.java.client.OpenViduJavaClientException;
import io.openvidu.java.client.OpenViduRole;
import io.openvidu.java.client.Recording;
import io.openvidu.java.client.Recording.OutputMode;
import io.openvidu.java.client.RecordingMode;
import io.openvidu.java.client.Session;
import io.openvidu.java.client.SessionProperties;
import io.openvidu.java.client.TokenOptions;
import io.openvidu.test.e2e.browser.BrowserUser;
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.CustomHttpClient;
import io.openvidu.test.e2e.utils.MultimediaFileMetadata;
import io.openvidu.test.e2e.utils.Unzipper;
@ -206,7 +217,9 @@ public class OpenViduTestAppE2eTest {
@AfterEach
void dispose() {
user.dispose();
if (user != null) {
user.dispose();
}
Iterator<BrowserUser> it = otherUsers.iterator();
while (it.hasNext()) {
BrowserUser other = it.next();
@ -1898,6 +1911,153 @@ public class OpenViduTestAppE2eTest {
gracefullyLeaveParticipants(2);
}
@Test
@DisplayName("openvidu-java-client test")
void openViduJavaClientTest() throws Exception {
setupBrowser("chrome");
log.info("openvidu-java-client test");
user.getDriver().findElement(By.id("one2one-btn")).click();
final String customSessionId = "openviduJavaClientSession";
final String serverData1 = "SERVER_DATA_1";
final String serverData2 = "SERVER_DATA_2";
Assert.assertFalse("OV.fetch() should return false if OV.createSession() has not been called", OV.fetch());
List<Session> sessions = OV.getActiveSessions();
Assert.assertEquals("Expected no active sessions but found " + sessions.size(), sessions.size(), 0);
SessionProperties properties = new SessionProperties.Builder().customSessionId(customSessionId)
.mediaMode(MediaMode.ROUTED).recordingMode(RecordingMode.ALWAYS)
.defaultOutputMode(OutputMode.INDIVIDUAL).build();
Session session = OV.createSession(properties);
Assert.assertFalse("Session.fetch() should return false after OpenVidu.createSession()", session.fetch());
Assert.assertFalse("OpenVidu.fetch() should return false after OpenVidu.createSession()", OV.fetch());
sessions = OV.getActiveSessions();
Assert.assertEquals("Expected 1 active session but found " + sessions.size(), 1, sessions.size());
KurentoOptions kurentoOptions = new KurentoOptions.Builder().videoMaxRecvBandwidth(250)
.allowedFilters(new String[] { "GStreamerFilter" }).build();
TokenOptions tokenOptions1 = new TokenOptions.Builder().role(OpenViduRole.MODERATOR).data(serverData1)
.kurentoOptions(kurentoOptions).build();
String token1 = session.generateToken(tokenOptions1);
TokenOptions tokenOptions2 = new TokenOptions.Builder().role(OpenViduRole.SUBSCRIBER).data(serverData2).build();
String token2 = session.generateToken(tokenOptions2);
Assert.assertFalse("Session.fetch() should return false until a user has connected", session.fetch());
user.getDriver().findElement(By.id("session-settings-btn-0")).click();
Thread.sleep(1000);
// Set token 1
WebElement tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input"));
tokeInput.clear();
tokeInput.sendKeys(token1);
user.getDriver().findElement(By.id("save-btn")).click();
Thread.sleep(1000);
user.getDriver().findElement(By.id("session-settings-btn-1")).click();
Thread.sleep(1000);
// Set token 2
tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input"));
tokeInput.clear();
tokeInput.sendKeys(token2);
user.getDriver().findElement(By.id("save-btn")).click();
Thread.sleep(1000);
user.getDriver().findElements(By.className("join-btn")).forEach(el -> el.sendKeys(Keys.ENTER));
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, numberOfVideos, 2);
Assert.assertTrue("Videos were expected to have audio and video tracks", user.getEventManager()
.assertMediaTracks(user.getDriver().findElements(By.tagName("video")), true, true));
Assert.assertTrue("Session.fetch() should return true after users connected", session.fetch());
// Verify that users have the role and data they were assigned through
// TokenOptions
gracefullyLeaveParticipants(2);
}
@Test
@DisplayName("REST API test")
void restApiTest() throws Exception {
CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, OPENVIDU_SECRET);
// 401
restClient.testAuthorizationError();
// GET /api/sessions before any session created
restClient.rest(HttpMethod.GET, "/api/sessions/NOT_EXISTS", HttpStatus.SC_NOT_FOUND);
Map<String, Object> returnValues = new HashMap<>();
returnValues.put("numberOfElements", new Integer(0));
returnValues.put("content", "[]");
restClient.rest(HttpMethod.GET, "/api/sessions", null, HttpStatus.SC_OK, true, returnValues);
/** POST /api/sessions **/
// 400
String body = "{'mediaMode': 'ROUTED', 'recordingMode': 'ALWAYS', 'customSessionId': 999}";
restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_BAD_REQUEST);
body = "{'mediaMode': 'ROUTED', 'recordingMode': false}";
restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_BAD_REQUEST);
body = "{'mediaMode': 'NOT_EXISTS'}";
restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_BAD_REQUEST);
body = "{'mediaMode': 'ROUTED', 'recordingMode': 'NOT_EXISTS'}";
restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_BAD_REQUEST);
body = "{'mediaMode': 'ROUTED', 'recordingMode': 'ALWAYS', 'defaultOutputMode': 'NOT_EXISTS'}";
restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_BAD_REQUEST);
body = "{'mediaMode': 'ROUTED', 'recordingMode': 'ALWAYS', 'defaultOutputMode': 'INDIVIDUAL', 'defaultRecordingLayout': 'NOT_EXISTS'}";
restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_BAD_REQUEST);
// 200
body = "{'mediaMode': 'ROUTED', 'recordingMode': 'ALWAYS', 'customSessionId': 'CUSTOM_SESSION_ID', 'defaultOutputMode': 'INDIVIDUAL', 'defaultRecordingLayout': 'BEST_FIT'}";
restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_OK, true,
"{'id': 'STR', 'createdAt': 0}");
// 409
body = "{'customSessionId': 'CUSTOM_SESSION_ID'}";
restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_CONFLICT);
// GET /api/sessions after session created
restClient.rest(HttpMethod.GET, "/api/sessions/CUSTOM_SESSION_ID", null, HttpStatus.SC_OK, true,
"{'sessionId':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','customSessionId':'STR','connections':{'numberOfElements':0,'content':[]},'recording':true}");
returnValues = new HashMap<>();
returnValues.put("numberOfElements", new Integer(1));
returnValues.put("content", new org.json.JSONArray());
restClient.rest(HttpMethod.GET, "/api/sessions", null, HttpStatus.SC_OK, true, returnValues);
/** POST /api/tokens **/
// 400
body = "{'session': true}";
restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_BAD_REQUEST);
body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'NOT_EXISTS', 'data': 'DATA'}";
restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_BAD_REQUEST);
body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'MODERATOR', 'data': 999}";
restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_BAD_REQUEST);
body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'MODERATOR', 'data': 'SERVER_DATA', 'kurentoOptions': false}";
restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_BAD_REQUEST);
body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'MODERATOR', 'data': 'SERVER_DATA', 'kurentoOptions': {'allowedFilters': 'NOT_EXISTS'}}";
restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_BAD_REQUEST);
// 200
body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'MODERATOR', 'data': 'SERVER_DATA', 'kurentoOptions': {'allowedFilters': ['GStreamerFilter']}}";
restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_OK);
}
private void listEmptyRecordings() {
// List existing recordings (empty)
user.getDriver().findElement(By.id("list-recording-btn")).click();

View File

@ -0,0 +1,217 @@
/*
* (C) Copyright 2017-2019 OpenVidu (https://openvidu.io/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package io.openvidu.test.e2e.utils;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Map;
import java.util.Map.Entry;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.simple.parser.JSONParser;
import org.junit.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.mashape.unirest.http.HttpMethod;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.mashape.unirest.request.HttpRequest;
import com.mashape.unirest.request.HttpRequestWithBody;
public class CustomHttpClient {
private static final Logger log = LoggerFactory.getLogger(CustomHttpClient.class);
private String openviduUrl;
private String headerAuth;
private JSONParser parser = new JSONParser();
public CustomHttpClient(String openviduUrl, String openviduSecret) {
this.openviduUrl = openviduUrl.replaceFirst("/*$", "");
this.headerAuth = "Basic " + Base64.getEncoder().encodeToString(("OPENVIDUAPP:" + openviduSecret).getBytes());
SSLContext sslContext = null;
try {
sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy() {
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
}).build();
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
Assert.fail("Error building custom HttpClient: " + e.getMessage());
}
HttpClient unsafeHttpClient = HttpClients.custom().setSSLContext(sslContext)
.setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
Unirest.setHttpClient(unsafeHttpClient);
}
public void testAuthorizationError() {
try {
String wrongCredentials = "Basic "
+ Base64.getEncoder().encodeToString(("OPENVIDUAPP:WRONG_SECRET").getBytes());
Assert.assertEquals("Expected 401 status (unauthorized)", HttpStatus.SC_UNAUTHORIZED, Unirest
.get(openviduUrl + "/config").header("Authorization", wrongCredentials).asJson().getStatus());
} catch (UnirestException e) {
Assert.fail("Error testing UNAUTHORIZED rest method: " + e.getMessage());
}
}
public void rest(HttpMethod method, String path, int status) {
this.commonRest(method, path, null, status);
}
public void rest(HttpMethod method, String path, String body, int status) {
this.commonRest(method, path, body, status);
}
public void rest(HttpMethod method, String path, String body, int status, boolean exactFields,
String jsonElmentString) {
JSONObject json = this.commonRest(method, path, body, status);
JSONObject jsonObjExpected = null;
jsonElmentString.replaceAll("'", "\"");
try {
jsonObjExpected = new JSONObject((String) jsonElmentString);
} catch (JSONException e1) {
Assert.fail("Expected json element is a string without a JSON format: " + jsonElmentString);
}
if (exactFields) {
Assert.assertEquals("Error in number of keys in JSON response to POST " + path, jsonObjExpected.length(),
json.length());
}
for (String key : jsonObjExpected.keySet()) {
json.get(key);
}
}
public void rest(HttpMethod method, String path, String body, int status, boolean exactFields,
Map<String, ?> jsonResponse) {
org.json.JSONObject json = this.commonRest(method, path, body, status);
if (exactFields) {
Assert.assertEquals("Error in number of keys in JSON response to POST " + path, jsonResponse.size(),
json.length());
}
for (Entry<String, ?> entry : jsonResponse.entrySet()) {
Object value = entry.getValue();
if (value instanceof String) {
try {
JSONObject jsonObjExpected = new JSONObject((String) value);
JSONObject jsonObjActual = json.getJSONObject(entry.getKey());
// COMPARE
} catch (JSONException e1) {
try {
JSONArray jsonArrayExpected = new JSONArray((String) value);
JSONArray jsonArrayActual = json.getJSONArray(entry.getKey());
// COMPARE
} catch (JSONException e2) {
Assert.assertEquals("JSON field " + entry.getKey() + " has not expected value", (String) value,
json.getInt(entry.getKey()));
}
}
} else if (value instanceof Integer) {
Assert.assertEquals("JSON field " + entry.getKey() + " has not expected value", (int) value,
json.getInt(entry.getKey()));
} else if (value instanceof Long) {
Assert.assertEquals("JSON field " + entry.getKey() + " has not expected value", (long) value,
json.getLong(entry.getKey()));
} else if (value instanceof Double) {
Assert.assertEquals("JSON field " + entry.getKey() + " has not expected value", (double) value,
json.getDouble(entry.getKey()), 0.001);
} else if (value instanceof Boolean) {
Assert.assertEquals("JSON field " + entry.getKey() + " has not expected value", (boolean) value,
json.getBoolean(entry.getKey()));
} else if (value instanceof JSONArray) {
json.getJSONArray(entry.getKey());
} else if (value instanceof JSONObject) {
json.getJSONObject(entry.getKey());
} else {
Assert.fail("JSON response field cannot be parsed: " + entry.toString());
}
}
}
private org.json.JSONObject commonRest(HttpMethod method, String path, String body, int status) {
HttpResponse<JsonNode> jsonResponse = null;
org.json.JSONObject json = null;
path = openviduUrl + (path.startsWith("/") ? path : ("/" + path));
HttpRequest request = null;
if (body != null && !body.isEmpty()) {
switch (method) {
case POST:
request = Unirest.post(path);
break;
case PUT:
request = Unirest.put(path);
break;
default:
break;
}
((HttpRequestWithBody) request).header("Content-Type", "application/json").body(body.replaceAll("'", "\""));
} else {
switch (method) {
case GET:
request = Unirest.get(path);
break;
case POST:
request = Unirest.post(path);
break;
case DELETE:
request = Unirest.delete(path);
break;
default:
break;
}
request.header("Content-Type", "application/x-www-form-urlencoded");
}
try {
jsonResponse = request.header("Authorization", this.headerAuth).asJson();
if (jsonResponse.getBody() != null) {
json = jsonResponse.getBody().getObject();
}
} catch (UnirestException e) {
log.error(e.getMessage());
Assert.fail("Error sending request to " + path + ": " + e.getMessage());
}
Assert.assertEquals(path + " expected to return status " + status, status, jsonResponse.getStatus());
return json;
}
}