mirror of https://github.com/OpenVidu/openvidu.git
openvidu-test deleted
parent
68dfd4414a
commit
cb382d66b2
|
@ -314,27 +314,6 @@
|
||||||
|
|
||||||
<!-- Test dependencies -->
|
<!-- Test dependencies -->
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.openvidu</groupId>
|
|
||||||
<artifactId>openvidu-test</artifactId>
|
|
||||||
<version>${version.openvidu.test}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-nop</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-api</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>jcl-over-slf4j</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hamcrest</groupId>
|
<groupId>org.hamcrest</groupId>
|
||||||
<artifactId>hamcrest-core</artifactId>
|
<artifactId>hamcrest-core</artifactId>
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
/target/
|
|
||||||
.factorypath
|
|
|
@ -1,202 +0,0 @@
|
||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
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.
|
|
|
@ -1,13 +0,0 @@
|
||||||
(C) Copyright 2016 Kurento (http://kurento.org)
|
|
||||||
|
|
||||||
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.
|
|
|
@ -1,11 +0,0 @@
|
||||||
[](http://www.apache.org/licenses/LICENSE-2.0)
|
|
||||||
[](https://docs.openvidu.io/en/stable/?badge=stable)
|
|
||||||
[](https://hub.docker.com/r/openvidu/)
|
|
||||||
[](https://groups.google.com/forum/#!forum/openvidu)
|
|
||||||
|
|
||||||
[![][OpenViduLogo]](https://openvidu.io)
|
|
||||||
|
|
||||||
openvidu-test
|
|
||||||
===
|
|
||||||
|
|
||||||
[OpenViduLogo]: https://secure.gravatar.com/avatar/5daba1d43042f2e4e85849733c8e5702?s=120
|
|
|
@ -1,94 +0,0 @@
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>io.openvidu</groupId>
|
|
||||||
<artifactId>openvidu-parent</artifactId>
|
|
||||||
<version>2.0.0</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<artifactId>openvidu-test</artifactId>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<name>OpenVidu Test</name>
|
|
||||||
<version>1.1.0</version>
|
|
||||||
<description>
|
|
||||||
OpenVidu Tests Framework
|
|
||||||
|
|
||||||
This project contains the test framework for the openvidu projects
|
|
||||||
</description>
|
|
||||||
<url>https://github.com/OpenVidu/openvidu</url>
|
|
||||||
|
|
||||||
<licenses>
|
|
||||||
<license>
|
|
||||||
<name>Apache 2.0</name>
|
|
||||||
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
|
|
||||||
<distribution>repo</distribution>
|
|
||||||
</license>
|
|
||||||
</licenses>
|
|
||||||
|
|
||||||
<organization>
|
|
||||||
<name>OpenVidu</name>
|
|
||||||
<url>https://github.com/OpenVidu/openvidu</url>
|
|
||||||
</organization>
|
|
||||||
|
|
||||||
<scm>
|
|
||||||
<url>${openvidu.scm.url}</url>
|
|
||||||
<connection>scm:git:${openvidu.scm.connection}</connection>
|
|
||||||
<developerConnection>scm:git:${openvidu.scm.connection}</developerConnection>
|
|
||||||
<tag>develop</tag>
|
|
||||||
</scm>
|
|
||||||
|
|
||||||
<developers>
|
|
||||||
<developer>
|
|
||||||
<id>openvidu.io</id>
|
|
||||||
<name>-openvidu.io Community</name>
|
|
||||||
<organization>OpenVidu</organization>
|
|
||||||
<organizationUrl>https://openvidu.io</organizationUrl>
|
|
||||||
</developer>
|
|
||||||
</developers>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<version>${version.junit}</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.openvidu</groupId>
|
|
||||||
<artifactId>openvidu-client</artifactId>
|
|
||||||
<version>${version.openvidu.client}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.kurento</groupId>
|
|
||||||
<artifactId>kurento-commons</artifactId>
|
|
||||||
<version>${version.kurento}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.kurento</groupId>
|
|
||||||
<artifactId>kurento-test</artifactId>
|
|
||||||
<version>${version.kurento}</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-logging</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<!-- <exclusion>
|
|
||||||
<groupId>org.kurento</groupId>
|
|
||||||
<artifactId>kurento-repository-internal</artifactId>
|
|
||||||
</exclusion>-->
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<!--<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
|
||||||
</dependency>-->
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
|
@ -1,635 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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;
|
|
||||||
|
|
||||||
import static io.openvidu.test.config.RoomTestConfiguration.ROOM_APP_CLASSNAME_DEFAULT;
|
|
||||||
import static io.openvidu.test.config.RoomTestConfiguration.ROOM_APP_CLASSNAME_PROP;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
import static org.kurento.commons.PropertiesManager.getProperty;
|
|
||||||
import static org.kurento.test.config.TestConfiguration.SELENIUM_SCOPE_PROPERTY;
|
|
||||||
import static org.kurento.test.config.TestConfiguration.TEST_URL_TIMEOUT_DEFAULT;
|
|
||||||
import static org.kurento.test.config.TestConfiguration.TEST_URL_TIMEOUT_PROPERTY;
|
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.ExecutorCompletionService;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.kurento.commons.PropertiesManager;
|
|
||||||
import org.kurento.jsonrpc.JsonUtils;
|
|
||||||
import org.kurento.test.base.BrowserTest;
|
|
||||||
import org.kurento.test.browser.Browser;
|
|
||||||
import org.kurento.test.browser.BrowserType;
|
|
||||||
import org.kurento.test.browser.WebPage;
|
|
||||||
import org.kurento.test.browser.WebPageType;
|
|
||||||
import org.kurento.test.config.BrowserScope;
|
|
||||||
import org.kurento.test.config.TestScenario;
|
|
||||||
import org.kurento.test.services.KmsService;
|
|
||||||
import org.kurento.test.services.Service;
|
|
||||||
import org.kurento.test.services.TestService;
|
|
||||||
import org.kurento.test.services.WebServerService;
|
|
||||||
import org.openqa.selenium.By;
|
|
||||||
import org.openqa.selenium.Dimension;
|
|
||||||
import org.openqa.selenium.ElementNotVisibleException;
|
|
||||||
import org.openqa.selenium.NoSuchElementException;
|
|
||||||
import org.openqa.selenium.Point;
|
|
||||||
import org.openqa.selenium.TimeoutException;
|
|
||||||
import org.openqa.selenium.WebDriver;
|
|
||||||
import org.openqa.selenium.WebElement;
|
|
||||||
import org.openqa.selenium.interactions.Actions;
|
|
||||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
|
||||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base for Kurento Room tests with browsers.
|
|
||||||
*
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 6.2.1
|
|
||||||
*/
|
|
||||||
public abstract class OpenViduClientBrowserTest<W extends WebPage> extends BrowserTest<W> {
|
|
||||||
|
|
||||||
public interface UserLifecycle {
|
|
||||||
public void run(int numUser, int iteration) throws Exception;
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Task {
|
|
||||||
public void exec(int numTask) throws Exception;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class KmsUriSetterService extends TestService {
|
|
||||||
|
|
||||||
private KmsService kms;
|
|
||||||
|
|
||||||
public KmsUriSetterService(KmsService kms) {
|
|
||||||
this.kms = kms;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TestServiceScope getScope() {
|
|
||||||
return kms.getScope();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void start() {
|
|
||||||
super.start();
|
|
||||||
String uri = kms.getWsUri();
|
|
||||||
System.setProperty("kms.uris", "[\"" + uri + "\"]");
|
|
||||||
System.setProperty("kms.uri", uri);
|
|
||||||
log.debug("Set system properties 'kms.uri' to {} & 'kms.uris' to [{}] ", uri, uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long TASKS_TIMEOUT_IN_MINUTES = 15 * 60;
|
|
||||||
|
|
||||||
public static int POLLING_LATENCY = 100;
|
|
||||||
public static int WEB_TEST_MAX_WIDTH = 1200;
|
|
||||||
public static int WEB_TEST_LEFT_BAR_WIDTH = 60;
|
|
||||||
public static int WEB_TEST_TOP_BAR_WIDTH = 30;
|
|
||||||
public static int WEB_TEST_BROWSER_WIDTH = 500;
|
|
||||||
public static int WEB_TEST_BROWSER_HEIGHT = 400;
|
|
||||||
|
|
||||||
public static String ROOM_PREFIX = "room";
|
|
||||||
public static String USER_BROWSER_PREFIX = "browser";
|
|
||||||
public static String USER_FAKE_PREFIX = "user";
|
|
||||||
|
|
||||||
public static @Service(1) KmsService kms = new KmsService();
|
|
||||||
public static @Service(2) KmsUriSetterService kmsUriSetter = new KmsUriSetterService(kms);
|
|
||||||
|
|
||||||
public static BrowserScope testScope = BrowserScope.LOCAL;
|
|
||||||
public static Class<?> webServerClass;
|
|
||||||
|
|
||||||
static {
|
|
||||||
loadWebServerClass();
|
|
||||||
if (webServerClass == null) {
|
|
||||||
Assert.fail("Unable to load any of the provided classnames for the web server test service");
|
|
||||||
}
|
|
||||||
|
|
||||||
String scopeProp = PropertiesManager.getProperty(SELENIUM_SCOPE_PROPERTY);
|
|
||||||
if (scopeProp != null) {
|
|
||||||
testScope = BrowserScope.valueOf(scopeProp.toUpperCase());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static @Service(99) WebServerService webServer = new WebServerService(webServerClass);
|
|
||||||
|
|
||||||
public static int testTimeout;
|
|
||||||
|
|
||||||
public static SecureRandom random = new SecureRandom();
|
|
||||||
|
|
||||||
public WebPageType webPageType = WebPageType.ROOM;
|
|
||||||
|
|
||||||
public int PLAY_TIME = 5; // seconds
|
|
||||||
|
|
||||||
public int ITERATIONS = 2;
|
|
||||||
|
|
||||||
public Object browsersLock = new Object();
|
|
||||||
|
|
||||||
public String roomName = ROOM_PREFIX;
|
|
||||||
|
|
||||||
public Map<String, Exception> execExceptions = new HashMap<String, Exception>();
|
|
||||||
|
|
||||||
public boolean failed = false;
|
|
||||||
|
|
||||||
public OpenViduClientBrowserTest() {
|
|
||||||
setDeleteLogsIfSuccess(false); // always keep the logs
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
public static void beforeClass() {
|
|
||||||
testTimeout = getProperty(TEST_URL_TIMEOUT_PROPERTY, TEST_URL_TIMEOUT_DEFAULT);
|
|
||||||
log.debug("Test timeout: {}", testTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setupBrowserTest() throws InterruptedException {
|
|
||||||
super.setupBrowserTest();
|
|
||||||
|
|
||||||
execExceptions.clear();
|
|
||||||
|
|
||||||
if (testScenario != null && testScenario.getBrowserMap() != null
|
|
||||||
&& testScenario.getBrowserMap().size() > 0) {
|
|
||||||
int row = 0;
|
|
||||||
int col = 0;
|
|
||||||
for (final String browserKey : testScenario.getBrowserMap().keySet()) {
|
|
||||||
Browser browser = getPage(browserKey).getBrowser();
|
|
||||||
browser.getWebDriver().manage().window()
|
|
||||||
.setSize(new Dimension(WEB_TEST_BROWSER_WIDTH, WEB_TEST_BROWSER_HEIGHT));
|
|
||||||
browser
|
|
||||||
.getWebDriver()
|
|
||||||
.manage()
|
|
||||||
.window()
|
|
||||||
.setPosition(
|
|
||||||
new Point(col * WEB_TEST_BROWSER_WIDTH + WEB_TEST_LEFT_BAR_WIDTH, row
|
|
||||||
* WEB_TEST_BROWSER_HEIGHT + WEB_TEST_TOP_BAR_WIDTH));
|
|
||||||
col++;
|
|
||||||
if (col * WEB_TEST_BROWSER_WIDTH + WEB_TEST_LEFT_BAR_WIDTH > WEB_TEST_MAX_WIDTH) {
|
|
||||||
col = 0;
|
|
||||||
row++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void teardownBrowserTest() {
|
|
||||||
super.teardownBrowserTest();
|
|
||||||
failWithExceptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Collection<Object[]> localChromes(String caller, int browsers, WebPageType pageType) {
|
|
||||||
TestScenario test = new TestScenario();
|
|
||||||
for (int i = 0; i < browsers; i++) {
|
|
||||||
Browser browser = new Browser.Builder().webPageType(pageType).browserType(BrowserType.CHROME)
|
|
||||||
.scope(BrowserScope.LOCAL).build();
|
|
||||||
test.addBrowser(getBrowserKey(i), browser);
|
|
||||||
}
|
|
||||||
log.debug("{}: Web browsers: {}, webPageType: {}, test scope: {}, Browsers map keySet: {}",
|
|
||||||
caller, browsers, pageType, testScope.toString(), test.getBrowserMap().keySet());
|
|
||||||
return Arrays.asList(new Object[][] { { test } });
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void loadWebServerClass() {
|
|
||||||
try {
|
|
||||||
List<String> auxList = JsonUtils.toStringList(PropertiesManager.getPropertyJson(
|
|
||||||
ROOM_APP_CLASSNAME_PROP, ROOM_APP_CLASSNAME_DEFAULT, JsonArray.class));
|
|
||||||
|
|
||||||
for (String aux : auxList) {
|
|
||||||
log.info("Loading class '{}' as the test's web server service", aux);
|
|
||||||
try {
|
|
||||||
webServerClass = Class.forName(aux);
|
|
||||||
break;
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("Couldn't load web server class '{}': {}", aux, e.getMessage());
|
|
||||||
log.debug("Couldn't load web server class '{}'", aux, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Incorrect value for property '{}'", ROOM_APP_CLASSNAME_PROP, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void sleep(long seconds) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(seconds * 1000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
log.warn("Interrupted while sleeping {}seconds", seconds, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getBrowserKey(int index) {
|
|
||||||
return USER_BROWSER_PREFIX + index;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getBrowserStreamName(int index) {
|
|
||||||
return getBrowserKey(index) + "_webcam";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getBrowserVideoStreamName(int index) {
|
|
||||||
return "video-" + getBrowserStreamName(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getBrowserNativeStreamName(int index) {
|
|
||||||
return "native-" + getBrowserVideoStreamName(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getFakeKey(int index) {
|
|
||||||
return USER_FAKE_PREFIX + index;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getFakeStreamName(int index) {
|
|
||||||
return getFakeKey(index) + "_webcam";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getFakeStreamName(String userName) {
|
|
||||||
return userName + "_webcam";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getFakeVideoStreamName(int index) {
|
|
||||||
return "video-" + getFakeStreamName(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getFakeNativeStreamName(int index) {
|
|
||||||
return "native-" + getFakeVideoStreamName(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CountDownLatch[] createCdl(int numLatches, int numUsers) {
|
|
||||||
final CountDownLatch[] cdl = new CountDownLatch[numLatches];
|
|
||||||
for (int i = 0; i < numLatches; i++) {
|
|
||||||
cdl[i] = new CountDownLatch(numUsers);
|
|
||||||
}
|
|
||||||
return cdl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void iterParallelUsers(int numUsers, int iterations, final UserLifecycle user)
|
|
||||||
throws InterruptedException, ExecutionException, TimeoutException {
|
|
||||||
|
|
||||||
int totalExecutions = iterations * numUsers;
|
|
||||||
ExecutorService threadPool = Executors.newFixedThreadPool(totalExecutions);
|
|
||||||
ExecutorCompletionService<Void> exec = new ExecutorCompletionService<>(threadPool);
|
|
||||||
List<Future<Void>> futures = new ArrayList<>();
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (int j = 0; j < iterations; j++) {
|
|
||||||
final int it = j;
|
|
||||||
log.info("it#{}: Starting execution of {} users", it, numUsers);
|
|
||||||
for (int i = 0; i < numUsers; i++) {
|
|
||||||
final int numUser = i;
|
|
||||||
final Browser browser = getPage(getBrowserKey(i)).getBrowser();
|
|
||||||
futures.add(exec.submit(new Callable<Void>() {
|
|
||||||
@Override
|
|
||||||
public Void call() throws Exception {
|
|
||||||
Thread.currentThread().setName("it" + it + "|browser" + numUser);
|
|
||||||
if (it > 0) {
|
|
||||||
log.debug("Page reloaded");
|
|
||||||
browser.reload();
|
|
||||||
}
|
|
||||||
user.run(numUser, it);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < numUsers; i++) {
|
|
||||||
try {
|
|
||||||
exec.take().get();
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
log.error("Execution exception", e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.info("it#{}: Finished execution of {} users", it, numUsers);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
threadPool.shutdownNow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parallelTasks(int numThreads, final String thPrefix, String taskName, final Task task) {
|
|
||||||
ExecutorService threadPool = Executors.newFixedThreadPool(numThreads);
|
|
||||||
ExecutorCompletionService<Void> exec = new ExecutorCompletionService<>(threadPool);
|
|
||||||
try {
|
|
||||||
for (int i = 0; i < numThreads; i++) {
|
|
||||||
final int numTask = i;
|
|
||||||
exec.submit(new Callable<Void>() {
|
|
||||||
@Override
|
|
||||||
public Void call() throws Exception {
|
|
||||||
String thname = Thread.currentThread().getName();
|
|
||||||
Thread.currentThread().setName(thPrefix + numTask);
|
|
||||||
task.exec(numTask);
|
|
||||||
Thread.currentThread().setName(thname);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
for (int i = 0; i < numThreads; i++) {
|
|
||||||
String thTask = taskName + "-" + thPrefix + i;
|
|
||||||
try {
|
|
||||||
log.debug("Waiting for the {} execution to complete ({}/{})", thTask, i + 1, numThreads);
|
|
||||||
exec.take().get();
|
|
||||||
log.debug("Job {} completed ({}/{})", thTask, i + 1, numThreads);
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
log.debug("Execution exception of {} ({}/{})", thTask, i + 1, numThreads, e);
|
|
||||||
execExceptions.put(taskName + "-" + thPrefix + i, e);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
log.error("Interrupted while waiting for execution of task{}", i, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
threadPool.shutdown();
|
|
||||||
try {
|
|
||||||
threadPool.awaitTermination(TASKS_TIMEOUT_IN_MINUTES, TimeUnit.MINUTES);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
log.warn("Tasks were executed more than {} minutes. Stopping it", TASKS_TIMEOUT_IN_MINUTES);
|
|
||||||
threadPool.shutdownNow();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void joinToRoom(int pageIndex, String userName, String roomName) {
|
|
||||||
Browser userBrowser = getPage(getBrowserKey(pageIndex)).getBrowser();
|
|
||||||
WebElement nameInput = findElement(userName, userBrowser, "name");
|
|
||||||
nameInput.clear();
|
|
||||||
nameInput.sendKeys(userName);
|
|
||||||
WebElement roomInput = findElement(userName, userBrowser, "roomName");
|
|
||||||
roomInput.clear();
|
|
||||||
roomInput.sendKeys(roomName);
|
|
||||||
findElement(userName, userBrowser, "joinBtn").submit();
|
|
||||||
log.debug("Clicked on 'joinBtn' in {}", userName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void exitFromRoom(int pageIndex, String userName) {
|
|
||||||
Browser userBrowser = getPage(getBrowserKey(pageIndex)).getBrowser();
|
|
||||||
try {
|
|
||||||
Actions actions = new Actions(userBrowser.getWebDriver());
|
|
||||||
actions.click(findElement(userName, userBrowser, "buttonLeaveRoom")).perform();
|
|
||||||
log.debug("'buttonLeaveRoom' clicked on in {}", userName);
|
|
||||||
} catch (ElementNotVisibleException e) {
|
|
||||||
log.warn("Button 'buttonLeaveRoom' is not visible. Session can't be closed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unsubscribe(int pageIndex, int unsubscribeFromIndex) {
|
|
||||||
String clickableVideoTagId = getBrowserVideoStreamName(unsubscribeFromIndex);
|
|
||||||
selectVideoTag(pageIndex, clickableVideoTagId);
|
|
||||||
|
|
||||||
WebDriver userWebDriver = getPage(getBrowserKey(pageIndex)).getBrowser().getWebDriver();
|
|
||||||
try {
|
|
||||||
userWebDriver.findElement(By.id("buttonDisconnect")).click();
|
|
||||||
} catch (ElementNotVisibleException e) {
|
|
||||||
String msg = "Button 'buttonDisconnect' is not visible. Can't unsubscribe from media.";
|
|
||||||
log.warn(msg);
|
|
||||||
fail(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void selectVideoTag(int pageIndex, String targetVideoTagId) {
|
|
||||||
WebDriver userWebDriver = getPage(getBrowserKey(pageIndex)).getBrowser().getWebDriver();
|
|
||||||
try {
|
|
||||||
WebElement element = userWebDriver.findElement(By.id(targetVideoTagId));
|
|
||||||
Actions actions = new Actions(userWebDriver);
|
|
||||||
actions.moveToElement(element).click().perform();
|
|
||||||
} catch (ElementNotVisibleException e) {
|
|
||||||
String msg = "Video tag '" + targetVideoTagId + "' is not visible, thus not selectable.";
|
|
||||||
log.warn(msg);
|
|
||||||
fail(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void unpublish(int pageIndex) {
|
|
||||||
WebDriver userWebDriver = getPage(getBrowserKey(pageIndex)).getBrowser().getWebDriver();
|
|
||||||
try {
|
|
||||||
userWebDriver.findElement(By.id("buttonDisconnect")).click();
|
|
||||||
} catch (ElementNotVisibleException e) {
|
|
||||||
log.warn("Button 'buttonDisconnect' is not visible. Can't unpublish media.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public WebElement findElement(String label, Browser browser, String id) {
|
|
||||||
try {
|
|
||||||
return new WebDriverWait(browser.getWebDriver(), testTimeout, POLLING_LATENCY)
|
|
||||||
.until(ExpectedConditions.presenceOfElementLocated(By.id(id)));
|
|
||||||
} catch (TimeoutException e) {
|
|
||||||
log.warn("Timeout when waiting for element {} to exist in browser {}", id, label);
|
|
||||||
int originalTimeout = 60;
|
|
||||||
try {
|
|
||||||
originalTimeout = browser.getTimeout();
|
|
||||||
log.debug("Original browser timeout (s): {}, set to 10", originalTimeout);
|
|
||||||
browser.setTimeout(10);
|
|
||||||
browser.changeTimeout(10);
|
|
||||||
WebElement elem = browser.getWebDriver().findElement(By.id(id));
|
|
||||||
log.info("Additional findElement call was able to locate {} in browser {}", id, label);
|
|
||||||
return elem;
|
|
||||||
} catch (NoSuchElementException e1) {
|
|
||||||
log.debug("Additional findElement call couldn't locate {} in browser {} ({})", id, label,
|
|
||||||
e1.getMessage());
|
|
||||||
throw new NoSuchElementException("Element with id='" + id + "' not found after "
|
|
||||||
+ testTimeout + " seconds in browser " + label);
|
|
||||||
} finally {
|
|
||||||
browser.setTimeout(originalTimeout);
|
|
||||||
browser.changeTimeout(originalTimeout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void waitWhileElement(String label, Browser browser, String id) throws TimeoutException {
|
|
||||||
int originalTimeout = 60;
|
|
||||||
try {
|
|
||||||
originalTimeout = browser.getTimeout();
|
|
||||||
log.debug("Original browser timeout (s): {}, set to 1", originalTimeout);
|
|
||||||
browser.setTimeout(1);
|
|
||||||
browser.changeTimeout(1);
|
|
||||||
new WebDriverWait(browser.getWebDriver(), testTimeout, POLLING_LATENCY)
|
|
||||||
.until(ExpectedConditions.invisibilityOfElementLocated(By.id(id)));
|
|
||||||
} catch (org.openqa.selenium.TimeoutException e) {
|
|
||||||
log.warn("Timeout when waiting for element {} to disappear in browser {}", id, label, e);
|
|
||||||
throw new TimeoutException("Element with id='" + id + "' is present in page after "
|
|
||||||
+ testTimeout + " seconds");
|
|
||||||
} finally {
|
|
||||||
browser.setTimeout(originalTimeout);
|
|
||||||
browser.changeTimeout(originalTimeout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for stream of another browser user.
|
|
||||||
*
|
|
||||||
* @param index
|
|
||||||
* own user index
|
|
||||||
* @param label
|
|
||||||
* browser name (user name)
|
|
||||||
* @param targetIndex
|
|
||||||
* the target user index
|
|
||||||
*/
|
|
||||||
public void waitForStream(int index, String label, int targetIndex) {
|
|
||||||
waitForStream(index, label, getBrowserNativeStreamName(targetIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for stream of a fake user.
|
|
||||||
*
|
|
||||||
* @param index
|
|
||||||
* own user index
|
|
||||||
* @param label
|
|
||||||
* browser name (user name)
|
|
||||||
* @param targetIndex
|
|
||||||
* the target user index
|
|
||||||
*/
|
|
||||||
public void waitForStreamFake(int index, String label, int targetIndex) {
|
|
||||||
waitForStream(index, label, getFakeNativeStreamName(targetIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for stream of user whose video tag has already been generated.
|
|
||||||
*
|
|
||||||
* @param index
|
|
||||||
* own user index
|
|
||||||
* @param label
|
|
||||||
* browser name (user name)
|
|
||||||
* @param targetVideoTagId
|
|
||||||
* expected video tag id
|
|
||||||
*/
|
|
||||||
public void waitForStream(int index, String label, String targetVideoTagId) {
|
|
||||||
String hostKey = getBrowserKey(index);
|
|
||||||
Browser browser = getPage(hostKey).getBrowser();
|
|
||||||
int i = 0;
|
|
||||||
for (; i < testTimeout; i++) {
|
|
||||||
WebElement video = findElement(label, browser, targetVideoTagId);
|
|
||||||
String srcAtt = video.getAttribute("src");
|
|
||||||
if (srcAtt != null && srcAtt.startsWith("blob")) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Thread.sleep(1000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == testTimeout) {
|
|
||||||
Assert.fail("Video tag '" + targetVideoTagId + "' is not playing media after " + testTimeout
|
|
||||||
+ " seconds in '" + hostKey + "'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void verify(boolean[] activeBrowserUsers) {
|
|
||||||
verify(activeBrowserUsers, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void verify(boolean[] activeBrowserUsers, Map<String, Boolean> activeFakeUsers) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (int i = 0; i < activeBrowserUsers.length; i++) {
|
|
||||||
if (activeBrowserUsers[i]) {
|
|
||||||
sb.append(USER_BROWSER_PREFIX + i + ": active, ");
|
|
||||||
} else {
|
|
||||||
sb.append(USER_BROWSER_PREFIX + i + ": not, ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.debug("Checking Browser users (active or not): [{}]", sb);
|
|
||||||
if (activeFakeUsers != null && !activeFakeUsers.isEmpty()) {
|
|
||||||
log.debug("Checking Fake users (active or not): {}", activeFakeUsers);
|
|
||||||
}
|
|
||||||
|
|
||||||
long startTime = System.nanoTime();
|
|
||||||
|
|
||||||
for (int i = 0; i < activeBrowserUsers.length; i++) {
|
|
||||||
|
|
||||||
if (activeBrowserUsers[i]) {
|
|
||||||
Browser browser = getPage(getBrowserKey(i)).getBrowser();
|
|
||||||
String browserLabel = getBrowserStreamName(i);
|
|
||||||
String browserUsername = USER_BROWSER_PREFIX + i;
|
|
||||||
|
|
||||||
for (int j = 0; j < activeBrowserUsers.length; j++) {
|
|
||||||
String videoElementId = "video-" + getBrowserStreamName(j);
|
|
||||||
verifyVideoInBrowser(browser, browserLabel, browserUsername, videoElementId,
|
|
||||||
activeBrowserUsers[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (activeFakeUsers != null) {
|
|
||||||
for (Entry<String, Boolean> fakeEntry : activeFakeUsers.entrySet()) {
|
|
||||||
String videoElementId = "video-" + getFakeStreamName(fakeEntry.getKey());
|
|
||||||
verifyVideoInBrowser(browser, browserLabel, browserUsername, videoElementId,
|
|
||||||
fakeEntry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
long endTime = System.nanoTime();
|
|
||||||
double duration = ((double) endTime - startTime) / 1_000_000;
|
|
||||||
log.debug("Checked active users: [{}] {} - in {} millis", sb, activeFakeUsers != null
|
|
||||||
&& !activeFakeUsers.isEmpty() ? "& " + activeFakeUsers : "", duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void verifyVideoInBrowser(Browser browser, String browserLabel, String chromeName,
|
|
||||||
String videoElementId, boolean isActive) {
|
|
||||||
if (isActive) {
|
|
||||||
log.debug("Verifing element {} exists in browser of {}", videoElementId, chromeName);
|
|
||||||
try {
|
|
||||||
WebElement video = findElement(browserLabel, browser, videoElementId);
|
|
||||||
if (video == null) {
|
|
||||||
fail("Video element " + videoElementId + " was not found in browser of " + chromeName);
|
|
||||||
}
|
|
||||||
} catch (NoSuchElementException e) {
|
|
||||||
fail(e.getMessage());
|
|
||||||
}
|
|
||||||
log.debug("OK - element {} found in browser of {}", videoElementId, chromeName);
|
|
||||||
} else {
|
|
||||||
log.debug("Verifing element {} is missing from browser of {}", videoElementId, chromeName);
|
|
||||||
try {
|
|
||||||
waitWhileElement(browserLabel, browser, videoElementId);
|
|
||||||
} catch (TimeoutException e) {
|
|
||||||
fail(e.getMessage());
|
|
||||||
}
|
|
||||||
log.debug("OK - element {} is missing from browser of {}", videoElementId, chromeName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void failWithExceptions() {
|
|
||||||
if (!failed && !execExceptions.isEmpty()) {
|
|
||||||
failed = true;
|
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
log.warn("\n+-------------------------------------------------------+\n"
|
|
||||||
+ "| Failing because of the following test errors: |\n"
|
|
||||||
+ "+-------------------------------------------------------+");
|
|
||||||
for (String exKey : execExceptions.keySet()) {
|
|
||||||
Exception e = execExceptions.get(exKey);
|
|
||||||
log.warn("Error on '{}'", exKey, e);
|
|
||||||
sb.append(exKey).append(" - ").append(e.getMessage()).append("\n");
|
|
||||||
}
|
|
||||||
sb.append("Check logs for more details");
|
|
||||||
log.warn("\n+-------------------------------------------------------+\n"
|
|
||||||
+ "| End of errors list |\n"
|
|
||||||
+ "+-------------------------------------------------------+");
|
|
||||||
Assert.fail(sb.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,350 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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;
|
|
||||||
|
|
||||||
import static org.kurento.commons.PropertiesManager.getProperty;
|
|
||||||
import static org.kurento.test.config.TestConfiguration.TEST_HOST_PROPERTY;
|
|
||||||
import static org.kurento.test.config.TestConfiguration.TEST_PORT_PROPERTY;
|
|
||||||
import static org.kurento.test.config.TestConfiguration.TEST_PROTOCOL_DEFAULT;
|
|
||||||
import static org.kurento.test.config.TestConfiguration.TEST_PROTOCOL_PROPERTY;
|
|
||||||
import static org.kurento.test.config.TestConfiguration.TEST_PUBLIC_IP_DEFAULT;
|
|
||||||
import static org.kurento.test.config.TestConfiguration.TEST_PUBLIC_IP_PROPERTY;
|
|
||||||
import static org.kurento.test.config.TestConfiguration.TEST_PUBLIC_PORT_PROPERTY;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.kurento.client.KurentoClient;
|
|
||||||
import org.kurento.commons.PropertiesManager;
|
|
||||||
import org.kurento.commons.exception.KurentoException;
|
|
||||||
import org.kurento.test.base.KurentoTest;
|
|
||||||
import org.kurento.test.browser.WebPage;
|
|
||||||
import org.kurento.test.config.BrowserScope;
|
|
||||||
import org.kurento.test.config.Protocol;
|
|
||||||
import org.kurento.test.docker.Docker;
|
|
||||||
import org.kurento.test.services.FakeKmsService;
|
|
||||||
import org.kurento.test.services.KmsService;
|
|
||||||
import org.kurento.test.services.Service;
|
|
||||||
import org.kurento.test.services.WebServerService;
|
|
||||||
import org.kurento.test.utils.Shell;
|
|
||||||
|
|
||||||
import io.openvidu.test.fake.util.FakeSession;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base for Kurento Room tests with browsers and fake clients.
|
|
||||||
*
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 6.2.1
|
|
||||||
*/
|
|
||||||
public abstract class RoomClientFakeTest<W extends WebPage> extends OpenViduClientBrowserTest<W> {
|
|
||||||
|
|
||||||
public static @Service(3) KmsService fakeKms = new FakeKmsService();
|
|
||||||
|
|
||||||
public static String testFiles = KurentoTest.getTestFilesDiskPath();
|
|
||||||
|
|
||||||
// overwritten if running in Docker
|
|
||||||
public static String serverAddress = PropertiesManager.getProperty(TEST_HOST_PROPERTY,
|
|
||||||
getProperty(TEST_PUBLIC_IP_PROPERTY, TEST_PUBLIC_IP_DEFAULT));
|
|
||||||
public static int serverPort = getProperty(TEST_PORT_PROPERTY,
|
|
||||||
getProperty(TEST_PUBLIC_PORT_PROPERTY, WebServerService.getAppHttpsPort()));
|
|
||||||
public static Protocol protocol = Protocol.valueOf(getProperty(TEST_PROTOCOL_PROPERTY,
|
|
||||||
TEST_PROTOCOL_DEFAULT).toUpperCase());
|
|
||||||
|
|
||||||
// might get overwritten by custom room apps
|
|
||||||
public static String appWsPath = "/openvidu";
|
|
||||||
|
|
||||||
public long JOIN_ROOM_TOTAL_TIMEOUT_IN_SECONDS = 30;
|
|
||||||
public long ACTIVE_LIVE_TOTAL_TIMEOUT_IN_SECONDS = 180;
|
|
||||||
public long ROOM_ACTIVITY_IN_SECONDS = 30;
|
|
||||||
public long LEAVE_ROOM_TOTAL_TIMEOUT_IN_SECONDS = 10;
|
|
||||||
|
|
||||||
public URI appWsUrl;
|
|
||||||
public URI appBaseUrl;
|
|
||||||
public URI appUrl;
|
|
||||||
|
|
||||||
public ConcurrentMap<String, FakeSession> sessions = new ConcurrentHashMap<String, FakeSession>();
|
|
||||||
|
|
||||||
public KurentoClient fakeKurentoClient;
|
|
||||||
|
|
||||||
public RoomClientFakeTest() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setupBrowserTest() throws InterruptedException {
|
|
||||||
super.setupBrowserTest();
|
|
||||||
|
|
||||||
calculateUrl();
|
|
||||||
|
|
||||||
String wsProtocol = "ws";
|
|
||||||
if (protocol.equals(Protocol.HTTPS)) {
|
|
||||||
wsProtocol = "wss";
|
|
||||||
}
|
|
||||||
String hostName = appUrl.getHost();
|
|
||||||
try {
|
|
||||||
appWsUrl = new URI(wsProtocol, null, hostName, serverPort, appWsPath, null, null);
|
|
||||||
} catch (URISyntaxException e) {
|
|
||||||
throw new KurentoException("Exception generating WS URI from " + wsProtocol + ", " + hostName
|
|
||||||
+ ", server port " + serverPort + " and WS path " + appWsPath);
|
|
||||||
}
|
|
||||||
log.debug("Protocol: {}, Hostname: {}, Port: {}, Path: {}", wsProtocol, hostName, serverPort,
|
|
||||||
appWsPath);
|
|
||||||
|
|
||||||
fakeKurentoClient = fakeKms.getKurentoClient();
|
|
||||||
Assert.assertNotNull("Fake Kurento Client is null", fakeKurentoClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void teardownBrowserTest() {
|
|
||||||
for (FakeSession s : sessions.values()) {
|
|
||||||
try {
|
|
||||||
s.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.warn("Error closing session", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fakeKms.closeKurentoClient();
|
|
||||||
super.teardownBrowserTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void calculateUrl() {
|
|
||||||
if (appUrl == null) {
|
|
||||||
String hostName = serverAddress;
|
|
||||||
|
|
||||||
if (BrowserScope.DOCKER.equals(testScope)) {
|
|
||||||
Docker docker = Docker.getSingleton();
|
|
||||||
if (docker.isRunningInContainer()) {
|
|
||||||
hostName = docker.getContainerIpAddress();
|
|
||||||
} else {
|
|
||||||
hostName = docker.getHostIpForContainers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.debug("Protocol: {}, Hostname: {}, Port: {}, Web page type: {}", protocol, hostName,
|
|
||||||
serverPort, webPageType);
|
|
||||||
|
|
||||||
try {
|
|
||||||
appUrl = new URI(protocol.toString(), null, hostName, serverPort, webPageType.toString(),
|
|
||||||
null, null);
|
|
||||||
} catch (URISyntaxException e) {
|
|
||||||
throw new KurentoException("Exception generating URI from " + protocol + ", " + hostName
|
|
||||||
+ ", server port " + serverPort + " and webpage type " + webPageType);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
appBaseUrl = new URI(protocol.toString(), null, hostName, serverPort, null, null, null);
|
|
||||||
} catch (URISyntaxException e) {
|
|
||||||
throw new KurentoException("Exception generating URI from " + protocol + ", " + hostName
|
|
||||||
+ ", server port " + serverPort);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public FakeSession getSession(String room) {
|
|
||||||
return sessions.get(room);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FakeSession createSession(String room) {
|
|
||||||
if (sessions.containsKey(room)) {
|
|
||||||
return sessions.get(room);
|
|
||||||
}
|
|
||||||
FakeSession s = new FakeSession(appWsUrl.toString(), room, fakeKurentoClient);
|
|
||||||
FakeSession old = sessions.putIfAbsent(room, s);
|
|
||||||
if (old != null) {
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void closeSession(String room) {
|
|
||||||
FakeSession session = sessions.get(room);
|
|
||||||
if (session != null) {
|
|
||||||
try {
|
|
||||||
session.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.warn("Error closing session", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public FakeSession removeSession(String room) {
|
|
||||||
return sessions.remove(room);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CountDownLatch parallelJoinFakeUsers(final List<String> relativePaths, final String room,
|
|
||||||
final KurentoClient kurento) {
|
|
||||||
if (relativePaths == null || relativePaths.isEmpty()) {
|
|
||||||
execExceptions.put("parallelJoinFakeUsers-" + room, new Exception(
|
|
||||||
"Null or empty play paths list"));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
int userThreads = relativePaths.size();
|
|
||||||
log.info("Joining room '{}': {} fake users with relative play paths:\n{}", room, userThreads,
|
|
||||||
relativePaths);
|
|
||||||
|
|
||||||
final CountDownLatch joinLatch = new CountDownLatch(userThreads);
|
|
||||||
parallelTasks(userThreads, USER_FAKE_PREFIX, "parallelJoinFakeUsers-" + room, new Task() {
|
|
||||||
@Override
|
|
||||||
public void exec(int numTask) throws Exception {
|
|
||||||
try {
|
|
||||||
String userName = getFakeKey(numTask);
|
|
||||||
FakeSession s = createSession(room);
|
|
||||||
String fullPlayPath = getPlaySourcePath(userName, relativePaths.get(numTask));
|
|
||||||
if (kurento == null) {
|
|
||||||
s.newParticipant(userName, fullPlayPath, true, true);
|
|
||||||
} else {
|
|
||||||
s.newParticipant(userName, fullPlayPath, true, true, kurento);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
joinLatch.countDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return joinLatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected CountDownLatch parallelLeaveFakeUsers(final String room, int userThreads) {
|
|
||||||
final CountDownLatch leaveLatch = new CountDownLatch(userThreads);
|
|
||||||
parallelTasks(userThreads, USER_FAKE_PREFIX, "parallelLeaveFakeUsers-" + room, new Task() {
|
|
||||||
@Override
|
|
||||||
public void exec(int numTask) throws Exception {
|
|
||||||
try {
|
|
||||||
getSession(room).getParticipant(getFakeKey(numTask)).leaveRoom();
|
|
||||||
} finally {
|
|
||||||
leaveLatch.countDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return leaveLatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected CountDownLatch parallelWaitActiveLive(final String room, int userThreads) {
|
|
||||||
final CountDownLatch waitForLatch = new CountDownLatch(userThreads);
|
|
||||||
parallelTasks(userThreads, USER_FAKE_PREFIX, "parallelWaitForActiveLive-" + room, new Task() {
|
|
||||||
@Override
|
|
||||||
public void exec(int numTask) throws Exception {
|
|
||||||
getSession(room).getParticipant(getFakeKey(numTask)).waitForActiveLive(waitForLatch);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return waitForLatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void await(CountDownLatch waitLatch, long actionTimeoutInSeconds, String action,
|
|
||||||
int userThreads) {
|
|
||||||
failWithExceptions();
|
|
||||||
try {
|
|
||||||
if (!waitLatch.await(actionTimeoutInSeconds, TimeUnit.SECONDS)) {
|
|
||||||
execExceptions.put(action, new Exception("Timeout waiting for '" + action + "' of "
|
|
||||||
+ userThreads + " tasks (max " + actionTimeoutInSeconds + "s)"));
|
|
||||||
} else {
|
|
||||||
log.debug("Finished waiting for {}", action);
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
log.warn("Interrupted when waiting for {} of {} tasks (max {}s)", action, userThreads,
|
|
||||||
actionTimeoutInSeconds, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void idlePeriod() {
|
|
||||||
idlePeriod("ACTIVE_LIVE", "LEAVE_ROOM", roomName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void idlePeriod(String room) {
|
|
||||||
idlePeriod("ACTIVE_LIVE", "LEAVE_ROOM", room);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void idlePeriod(String previousAction, String nextAction, String room) {
|
|
||||||
failWithExceptions();
|
|
||||||
log.info("\n-----------------\n" + "Wait for {} concluded in '{}'" + "\n-----------------\n"
|
|
||||||
+ "Waiting {} seconds", previousAction, room, ROOM_ACTIVITY_IN_SECONDS);
|
|
||||||
sleep(ROOM_ACTIVITY_IN_SECONDS);
|
|
||||||
log.info("\n-----------------\n" + "{} in '{}'" + "\n-----------------\n", nextAction, room);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getPlaySourcePath(String userName, String relativePath) throws Exception {
|
|
||||||
return getPlaySourcePath(userName, relativePath, testFiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getPlaySourcePath(String userName, String relativePath, String basePath)
|
|
||||||
throws Exception {
|
|
||||||
if (relativePath == null) {
|
|
||||||
throw new Exception("Null play path for user " + userName);
|
|
||||||
}
|
|
||||||
if (!basePath.startsWith("http://") && !basePath.startsWith("https://")
|
|
||||||
&& !basePath.startsWith("file://")) {
|
|
||||||
basePath = "file://" + basePath;
|
|
||||||
}
|
|
||||||
URI playerUri = null;
|
|
||||||
try {
|
|
||||||
playerUri = new URI(basePath + relativePath);
|
|
||||||
} catch (URISyntaxException e) {
|
|
||||||
throw new Exception("Unable to construct player URI for user " + userName
|
|
||||||
+ " from base path " + basePath + " and file " + relativePath);
|
|
||||||
}
|
|
||||||
String fullPlayPath = playerUri.toString();
|
|
||||||
log.debug("Fake user '{}': using play URI {}", userName, fullPlayPath);
|
|
||||||
return fullPlayPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
// use fake.kms.ws.uri instead
|
|
||||||
@Deprecated
|
|
||||||
public static String getFreePort(String wsUri) {
|
|
||||||
if (BrowserScope.DOCKER.equals(testScope)) {
|
|
||||||
log.info("Test is dockerized, returning the same WS for the KMS: {}", wsUri);
|
|
||||||
return wsUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
URI url;
|
|
||||||
try {
|
|
||||||
url = new URI(wsUri);
|
|
||||||
} catch (URISyntaxException e) {
|
|
||||||
log.warn("WebSocket URI {} is malformed: " + e.getMessage(), wsUri);
|
|
||||||
throw new KurentoException("WebSocket URI " + wsUri + " is malformed");
|
|
||||||
}
|
|
||||||
|
|
||||||
int c = 0;
|
|
||||||
do {
|
|
||||||
try {
|
|
||||||
c++;
|
|
||||||
int newPort = url.getPort() + c * c * c;
|
|
||||||
url = new URI(url.getScheme(), null, url.getHost(), newPort, url.getPath(), null, null);
|
|
||||||
String updatedWsUri = url.toString();
|
|
||||||
log.debug("try#{} Is port available for running (fake) KMS using this URI? {}", c,
|
|
||||||
updatedWsUri);
|
|
||||||
String result = Shell.runAndWait("/bin/bash", "-c",
|
|
||||||
"nc -z " + url.getHost() + " " + url.getPort() + "; echo $?");
|
|
||||||
if (result.trim().equals("0")) {
|
|
||||||
log.warn("Port " + url.getPort()
|
|
||||||
+ " is used. Maybe another KMS instance is running in this port");
|
|
||||||
} else {
|
|
||||||
log.debug("URI is available: {}", updatedWsUri);
|
|
||||||
return updatedWsUri;
|
|
||||||
}
|
|
||||||
} catch (URISyntaxException e) {
|
|
||||||
log.warn("WebSocket URI {} is malformed: " + e.getMessage(), wsUri);
|
|
||||||
}
|
|
||||||
} while (c < 3);
|
|
||||||
|
|
||||||
log.warn("Giving up, will return the original URI: {}", wsUri);
|
|
||||||
return wsUri;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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;
|
|
||||||
|
|
||||||
import org.junit.experimental.categories.Category;
|
|
||||||
import org.kurento.commons.testing.SystemFunctionalTests;
|
|
||||||
import org.kurento.test.browser.WebPage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Functional Kurento Room tests (using browser clients).
|
|
||||||
*
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 6.2.1
|
|
||||||
*/
|
|
||||||
@Category(SystemFunctionalTests.class)
|
|
||||||
public class RoomFunctionalBrowserTest<W extends WebPage> extends OpenViduClientBrowserTest<W> {
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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;
|
|
||||||
|
|
||||||
import org.junit.experimental.categories.Category;
|
|
||||||
import org.kurento.commons.testing.SystemFunctionalTests;
|
|
||||||
import org.kurento.test.browser.WebPage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Functional Kurento Room tests (using browser and fake clients).
|
|
||||||
*
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 6.2.1
|
|
||||||
*/
|
|
||||||
@Category(SystemFunctionalTests.class)
|
|
||||||
public class RoomFunctionalFakeTest<W extends WebPage> extends RoomClientFakeTest<W> {
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.browser;
|
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.kurento.test.browser.WebPage;
|
|
||||||
|
|
||||||
import io.openvidu.test.RoomFunctionalBrowserTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Room demo integration test (basic version).
|
|
||||||
*
|
|
||||||
* @author Micael Gallego (micael.gallego@gmail.com)
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 5.0.0
|
|
||||||
*/
|
|
||||||
public class AddRemoveUsers extends RoomFunctionalBrowserTest<WebPage> {
|
|
||||||
|
|
||||||
public static final int NUM_USERS = 2;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() throws Exception {
|
|
||||||
final boolean[] activeUsers = new boolean[NUM_USERS];
|
|
||||||
|
|
||||||
final CountDownLatch[] joinCdl = createCdl(ITERATIONS, NUM_USERS);
|
|
||||||
final CountDownLatch[] leaveCdl = createCdl(ITERATIONS, NUM_USERS);
|
|
||||||
|
|
||||||
iterParallelUsers(NUM_USERS, ITERATIONS, new UserLifecycle() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run(int numUser, int iteration) throws Exception {
|
|
||||||
String userName = getBrowserKey(numUser);
|
|
||||||
log.info("User '{}' is joining room '{}'", userName, roomName);
|
|
||||||
synchronized (browsersLock) {
|
|
||||||
joinToRoom(numUser, userName, roomName);
|
|
||||||
activeUsers[numUser] = true;
|
|
||||||
verify(activeUsers);
|
|
||||||
joinCdl[iteration].countDown();
|
|
||||||
}
|
|
||||||
log.info("User '{}' joined room '{}'", userName, roomName);
|
|
||||||
|
|
||||||
joinCdl[iteration].await(PLAY_TIME * 5000L, TimeUnit.MILLISECONDS);
|
|
||||||
sleep(PLAY_TIME);
|
|
||||||
|
|
||||||
log.info("User '{}' is exiting from room '{}'", userName, roomName);
|
|
||||||
synchronized (browsersLock) {
|
|
||||||
exitFromRoom(numUser, userName);
|
|
||||||
activeUsers[numUser] = false;
|
|
||||||
verify(activeUsers);
|
|
||||||
leaveCdl[iteration].countDown();
|
|
||||||
}
|
|
||||||
log.info("User '{}' exited from room '{}'", userName, roomName);
|
|
||||||
leaveCdl[iteration].await(PLAY_TIME * 5000L, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.browser;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.kurento.test.browser.WebPage;
|
|
||||||
|
|
||||||
import io.openvidu.test.RoomFunctionalBrowserTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Room integration test (basic version).
|
|
||||||
*
|
|
||||||
* @author Micael Gallego (micael.gallego@gmail.com)
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 5.0.0
|
|
||||||
*/
|
|
||||||
public class AddRemoveUsersNoSinkVerify extends RoomFunctionalBrowserTest<WebPage> {
|
|
||||||
|
|
||||||
public static final int NUM_USERS = 4;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() throws Exception {
|
|
||||||
iterParallelUsers(NUM_USERS, ITERATIONS, new UserLifecycle() {
|
|
||||||
@Override
|
|
||||||
public void run(int numUser, int iteration) throws Exception {
|
|
||||||
String userName = getBrowserKey(numUser);
|
|
||||||
|
|
||||||
log.info("User '{}' is joining room '{}'", userName, roomName);
|
|
||||||
joinToRoom(numUser, userName, roomName);
|
|
||||||
log.info("User '{}' joined room '{}'", userName, roomName);
|
|
||||||
|
|
||||||
sleep(PLAY_TIME);
|
|
||||||
|
|
||||||
log.info("User '{}' is exiting from room '{}'", userName, roomName);
|
|
||||||
exitFromRoom(numUser, userName);
|
|
||||||
log.info("User '{}' exited from room '{}'", userName, roomName);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,97 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.browser;
|
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.kurento.test.browser.WebPage;
|
|
||||||
|
|
||||||
import io.openvidu.test.RoomFunctionalBrowserTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Room demo integration test (basic version).
|
|
||||||
*
|
|
||||||
* @author Micael Gallego (micael.gallego@gmail.com)
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 5.0.0
|
|
||||||
*/
|
|
||||||
public class NUsersEqualLifetime extends RoomFunctionalBrowserTest<WebPage> {
|
|
||||||
|
|
||||||
public static final int NUM_USERS = 4;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() throws Exception {
|
|
||||||
ITERATIONS = 1;
|
|
||||||
|
|
||||||
final boolean[] activeUsers = new boolean[NUM_USERS];
|
|
||||||
|
|
||||||
final CountDownLatch[] joinCdl = createCdl(ITERATIONS, NUM_USERS);
|
|
||||||
final CountDownLatch[] publishCdl = createCdl(ITERATIONS, NUM_USERS * NUM_USERS);
|
|
||||||
final CountDownLatch[] leaveCdl = createCdl(ITERATIONS, NUM_USERS);
|
|
||||||
|
|
||||||
iterParallelUsers(NUM_USERS, ITERATIONS, new UserLifecycle() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run(final int numUser, final int iteration) throws Exception {
|
|
||||||
final String userName = getBrowserKey(numUser);
|
|
||||||
log.info("User '{}' is joining room '{}'", userName, roomName);
|
|
||||||
synchronized (browsersLock) {
|
|
||||||
joinToRoom(numUser, userName, roomName);
|
|
||||||
activeUsers[numUser] = true;
|
|
||||||
verify(activeUsers);
|
|
||||||
joinCdl[iteration].countDown();
|
|
||||||
}
|
|
||||||
log.info("User '{}' joined room '{}'", userName, roomName);
|
|
||||||
|
|
||||||
joinCdl[iteration].await(PLAY_TIME * 5000L, TimeUnit.MILLISECONDS);
|
|
||||||
|
|
||||||
final long start = System.currentTimeMillis();
|
|
||||||
|
|
||||||
parallelTasks(NUM_USERS, USER_BROWSER_PREFIX, "parallelWaitForStream", new Task() {
|
|
||||||
@Override
|
|
||||||
public void exec(int numTask) throws Exception {
|
|
||||||
String videoUserName = getBrowserKey(numTask);
|
|
||||||
synchronized (browsersLock) {
|
|
||||||
waitForStream(numUser, userName, numTask);
|
|
||||||
}
|
|
||||||
long duration = System.currentTimeMillis() - start;
|
|
||||||
log.info("Video received in browser of user '{}' for user '{}' in {} millis", userName,
|
|
||||||
videoUserName, duration);
|
|
||||||
publishCdl[iteration].countDown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
publishCdl[iteration].await(PLAY_TIME * 5000L, TimeUnit.MILLISECONDS);
|
|
||||||
|
|
||||||
sleep(PLAY_TIME);
|
|
||||||
|
|
||||||
log.info("User '{}' is exiting from room '{}'", userName, roomName);
|
|
||||||
synchronized (browsersLock) {
|
|
||||||
exitFromRoom(numUser, userName);
|
|
||||||
activeUsers[numUser] = false;
|
|
||||||
verify(activeUsers);
|
|
||||||
leaveCdl[iteration].countDown();
|
|
||||||
}
|
|
||||||
log.info("User '{}' exited from room '{}'", userName, roomName);
|
|
||||||
leaveCdl[iteration].await(PLAY_TIME * 5000L, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.browser;
|
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.kurento.test.browser.WebPage;
|
|
||||||
|
|
||||||
import io.openvidu.test.RoomFunctionalBrowserTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Room demo integration test (basic version).
|
|
||||||
*
|
|
||||||
* @author Micael Gallego (micael.gallego@gmail.com)
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 5.0.0
|
|
||||||
*/
|
|
||||||
public class OneUserQuickReentry extends RoomFunctionalBrowserTest<WebPage> {
|
|
||||||
|
|
||||||
public static final int NUM_USERS = 1;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() throws Exception {
|
|
||||||
ITERATIONS = 5;
|
|
||||||
|
|
||||||
final boolean[] activeUsers = new boolean[NUM_USERS];
|
|
||||||
|
|
||||||
final CountDownLatch[] joinCdl = createCdl(ITERATIONS, NUM_USERS);
|
|
||||||
final CountDownLatch[] leaveCdl = createCdl(ITERATIONS, NUM_USERS);
|
|
||||||
|
|
||||||
iterParallelUsers(NUM_USERS, ITERATIONS, new UserLifecycle() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run(int numUser, int iteration) throws Exception {
|
|
||||||
String userName = getBrowserKey(numUser);
|
|
||||||
log.info("User '{}' is joining room '{}'", userName, roomName);
|
|
||||||
synchronized (browsersLock) {
|
|
||||||
joinToRoom(numUser, userName, roomName);
|
|
||||||
activeUsers[numUser] = true;
|
|
||||||
verify(activeUsers);
|
|
||||||
joinCdl[iteration].countDown();
|
|
||||||
}
|
|
||||||
log.info("User '{}' joined room '{}'", userName, roomName);
|
|
||||||
|
|
||||||
joinCdl[iteration].await(PLAY_TIME * 5000L, TimeUnit.MILLISECONDS);
|
|
||||||
sleep(0);
|
|
||||||
|
|
||||||
log.info("User '{}' is exiting from room '{}'", userName, roomName);
|
|
||||||
synchronized (browsersLock) {
|
|
||||||
exitFromRoom(numUser, userName);
|
|
||||||
activeUsers[numUser] = false;
|
|
||||||
verify(activeUsers);
|
|
||||||
leaveCdl[iteration].countDown();
|
|
||||||
}
|
|
||||||
log.info("User '{}' exited from room '{}'", userName, roomName);
|
|
||||||
leaveCdl[iteration].await(PLAY_TIME * 5000L, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.browser;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.kurento.test.browser.WebPage;
|
|
||||||
|
|
||||||
import io.openvidu.test.RoomFunctionalBrowserTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Room demo integration test (basic version).
|
|
||||||
*
|
|
||||||
* @author Micael Gallego (micael.gallego@gmail.com)
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 5.0.0
|
|
||||||
*/
|
|
||||||
public class SeqAddRemoveUser extends RoomFunctionalBrowserTest<WebPage> {
|
|
||||||
|
|
||||||
private static final int WAIT_TIME = 1;
|
|
||||||
|
|
||||||
public static final int NUM_USERS = 2;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() throws Exception {
|
|
||||||
|
|
||||||
boolean[] activeUsers = new boolean[NUM_USERS];
|
|
||||||
|
|
||||||
for (int cycle = 0; cycle < ITERATIONS; cycle++) {
|
|
||||||
|
|
||||||
for (int i = 0; i < NUM_USERS; i++) {
|
|
||||||
String userName = getBrowserKey(i);
|
|
||||||
log.info("User '{}' joining room '{}'", userName, roomName);
|
|
||||||
joinToRoom(i, userName, roomName);
|
|
||||||
activeUsers[i] = true;
|
|
||||||
sleep(WAIT_TIME);
|
|
||||||
verify(activeUsers);
|
|
||||||
log.info("User '{}' joined to room '{}'", userName, roomName);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < NUM_USERS; i++) {
|
|
||||||
for (int j = 0; j < NUM_USERS; j++) {
|
|
||||||
waitForStream(i, getBrowserKey(i), j);
|
|
||||||
log.debug("Received media from '{}' in browser of '{}'", getBrowserKey(j),
|
|
||||||
getBrowserKey(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Guard time to see application in action
|
|
||||||
sleep(PLAY_TIME);
|
|
||||||
|
|
||||||
// Stop application by caller
|
|
||||||
for (int i = 0; i < NUM_USERS; i++) {
|
|
||||||
String userName = getBrowserKey(i);
|
|
||||||
log.info("User '{}' is exiting from room '{}'", userName, roomName);
|
|
||||||
exitFromRoom(i, userName);
|
|
||||||
activeUsers[i] = false;
|
|
||||||
sleep(WAIT_TIME);
|
|
||||||
verify(activeUsers);
|
|
||||||
log.info("User '{}' exited from room '{}'", userName, roomName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.browser;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.kurento.test.browser.WebPage;
|
|
||||||
|
|
||||||
import io.openvidu.test.RoomFunctionalBrowserTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Room demo integration test (basic version).
|
|
||||||
*
|
|
||||||
* @author Micael Gallego (micael.gallego@gmail.com)
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 5.0.0
|
|
||||||
*/
|
|
||||||
public class SeqNUsersEqualLifetime extends RoomFunctionalBrowserTest<WebPage> {
|
|
||||||
|
|
||||||
public static final int NUM_USERS = 4;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() throws Exception {
|
|
||||||
|
|
||||||
for (int i = 0; i < NUM_USERS; i++) {
|
|
||||||
String userName = getBrowserKey(i);
|
|
||||||
joinToRoom(i, userName, roomName);
|
|
||||||
log.info("User '{}' joined to room '{}'", userName, roomName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME it fails sporadically (could be the TrickleICE mechanism)
|
|
||||||
|
|
||||||
for (int i = 0; i < NUM_USERS; i++) {
|
|
||||||
String userName = getBrowserKey(i);
|
|
||||||
for (int j = 0; j < NUM_USERS; j++) {
|
|
||||||
if (i != j) {
|
|
||||||
waitForStream(i, userName, j);
|
|
||||||
log.debug("Received media from '{}' in '{}'", getBrowserKey(j), userName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Guard time to see application in action
|
|
||||||
sleep(PLAY_TIME);
|
|
||||||
|
|
||||||
for (int i = 0; i < NUM_USERS; i++) {
|
|
||||||
String userName = getBrowserKey(i);
|
|
||||||
exitFromRoom(i, userName);
|
|
||||||
log.info("User '{}' exited from room '{}'", userName, roomName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.browser;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.kurento.test.browser.WebPage;
|
|
||||||
|
|
||||||
import io.openvidu.test.RoomFunctionalBrowserTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Room demo integration test (basic version).
|
|
||||||
*
|
|
||||||
* @author Micael Gallego (micael.gallego@gmail.com)
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 5.0.0
|
|
||||||
*/
|
|
||||||
public class TwoUsersEqualLifetime extends RoomFunctionalBrowserTest<WebPage> {
|
|
||||||
|
|
||||||
public static final int NUM_USERS = 2;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() throws Exception {
|
|
||||||
|
|
||||||
String user0Name = getBrowserKey(0);
|
|
||||||
String user1Name = getBrowserKey(1);
|
|
||||||
|
|
||||||
joinToRoom(0, user0Name, roomName);
|
|
||||||
log.info("User '{}' joined to room '{}'", user0Name, roomName);
|
|
||||||
|
|
||||||
joinToRoom(1, user1Name, roomName);
|
|
||||||
log.info("User '{}' joined to room '{}'", user1Name, roomName);
|
|
||||||
|
|
||||||
// FIXME it fails sporadically (could be the TrickleICE mechanism)
|
|
||||||
|
|
||||||
waitForStream(0, user0Name, 0);
|
|
||||||
log.debug("Received media from '{}' in '{}'", user0Name, user0Name);
|
|
||||||
waitForStream(0, user0Name, 1);
|
|
||||||
log.debug("Received media from '{}' in '{}'", user1Name, user0Name);
|
|
||||||
|
|
||||||
waitForStream(1, user1Name, 0);
|
|
||||||
log.debug("Received media from '{}' in '{}'", user0Name, user1Name);
|
|
||||||
waitForStream(1, user1Name, 1);
|
|
||||||
log.debug("Received media from '{}' in '{}'", user1Name, user1Name);
|
|
||||||
|
|
||||||
// Guard time to see application in action
|
|
||||||
sleep(PLAY_TIME);
|
|
||||||
|
|
||||||
// Stop application by caller
|
|
||||||
exitFromRoom(0, user0Name);
|
|
||||||
exitFromRoom(1, user1Name);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,120 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.browser;
|
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.kurento.test.browser.WebPage;
|
|
||||||
|
|
||||||
import io.openvidu.test.RoomFunctionalBrowserTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Room browser test. Designed for the demo app.
|
|
||||||
*
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 6.0.0
|
|
||||||
*/
|
|
||||||
public class UnpublishMedia extends RoomFunctionalBrowserTest<WebPage> {
|
|
||||||
|
|
||||||
public static final int NUM_USERS = 3;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() throws Exception {
|
|
||||||
ITERATIONS = 3;
|
|
||||||
|
|
||||||
final boolean[] activeUsers = new boolean[NUM_USERS];
|
|
||||||
|
|
||||||
final CountDownLatch[] joinCdl = createCdl(ITERATIONS, NUM_USERS);
|
|
||||||
final CountDownLatch[] publishCdl = createCdl(ITERATIONS, NUM_USERS * NUM_USERS);
|
|
||||||
final CountDownLatch[] unpublishCdl = createCdl(ITERATIONS, 1);
|
|
||||||
final CountDownLatch[] verifyCdl = createCdl(ITERATIONS, NUM_USERS);
|
|
||||||
final CountDownLatch[] leaveCdl = createCdl(ITERATIONS, NUM_USERS);
|
|
||||||
|
|
||||||
final int[] unpublisherIndex = new int[ITERATIONS];
|
|
||||||
for (int i = 0; i < unpublisherIndex.length; i++) {
|
|
||||||
unpublisherIndex[i] = random.nextInt(NUM_USERS);
|
|
||||||
}
|
|
||||||
|
|
||||||
iterParallelUsers(NUM_USERS, ITERATIONS, new UserLifecycle() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run(final int numUser, final int iteration) throws Exception {
|
|
||||||
final String userName = getBrowserKey(numUser);
|
|
||||||
|
|
||||||
log.info("User '{}' is joining room '{}'", userName, roomName);
|
|
||||||
synchronized (browsersLock) {
|
|
||||||
joinToRoom(numUser, userName, roomName);
|
|
||||||
activeUsers[numUser] = true;
|
|
||||||
verify(activeUsers);
|
|
||||||
joinCdl[iteration].countDown();
|
|
||||||
}
|
|
||||||
log.info("User '{}' joined room '{}'", userName, roomName);
|
|
||||||
joinCdl[iteration].await(PLAY_TIME * 5000L, TimeUnit.MILLISECONDS);
|
|
||||||
|
|
||||||
final long start = System.currentTimeMillis();
|
|
||||||
|
|
||||||
parallelTasks(NUM_USERS, USER_BROWSER_PREFIX, "parallelWaitForStream", new Task() {
|
|
||||||
@Override
|
|
||||||
public void exec(int numTask) throws Exception {
|
|
||||||
String videoUserName = getBrowserKey(numTask);
|
|
||||||
synchronized (browsersLock) {
|
|
||||||
waitForStream(numUser, userName, numTask);
|
|
||||||
}
|
|
||||||
long duration = System.currentTimeMillis() - start;
|
|
||||||
log.info("Video received in browser of user '{}' for user '{}' in {} millis", userName,
|
|
||||||
videoUserName, duration);
|
|
||||||
publishCdl[iteration].countDown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
publishCdl[iteration].await(PLAY_TIME * 5000L, TimeUnit.MILLISECONDS);
|
|
||||||
|
|
||||||
synchronized (browsersLock) {
|
|
||||||
if (numUser == unpublisherIndex[iteration]) {
|
|
||||||
log.info("User '{}' unpublishing media in room '{}'", userName, roomName);
|
|
||||||
unpublish(numUser);
|
|
||||||
log.info("User '{}' unpublished media in room '{}'", userName, roomName);
|
|
||||||
activeUsers[numUser] = false;
|
|
||||||
unpublishCdl[iteration].countDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unpublishCdl[iteration].await(PLAY_TIME * 5000L, TimeUnit.MILLISECONDS);
|
|
||||||
|
|
||||||
synchronized (browsersLock) {
|
|
||||||
verify(activeUsers);
|
|
||||||
verifyCdl[iteration].countDown();
|
|
||||||
}
|
|
||||||
log.info("{} - Verified that '{}' unpublished media in room '{}'", userName,
|
|
||||||
getBrowserKey(unpublisherIndex[iteration]), roomName);
|
|
||||||
verifyCdl[iteration].await(PLAY_TIME * 5000L, TimeUnit.MILLISECONDS);
|
|
||||||
|
|
||||||
sleep(PLAY_TIME);
|
|
||||||
|
|
||||||
log.info("User '{}' is exiting from room '{}'", userName, roomName);
|
|
||||||
synchronized (browsersLock) {
|
|
||||||
exitFromRoom(numUser, userName);
|
|
||||||
activeUsers[numUser] = false;
|
|
||||||
verify(activeUsers);
|
|
||||||
leaveCdl[iteration].countDown();
|
|
||||||
}
|
|
||||||
log.info("User '{}' exited from room '{}'", userName, roomName);
|
|
||||||
leaveCdl[iteration].await(PLAY_TIME * 5000L, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,129 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.browser;
|
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.kurento.test.browser.WebPage;
|
|
||||||
|
|
||||||
import io.openvidu.test.RoomFunctionalBrowserTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Room browser test. Designed for the demo app.
|
|
||||||
*
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 6.0.0
|
|
||||||
*/
|
|
||||||
public class UnsubscribeFromMedia extends RoomFunctionalBrowserTest<WebPage> {
|
|
||||||
|
|
||||||
public static final int NUM_USERS = 3;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() throws Exception {
|
|
||||||
final boolean[] activeUsers = new boolean[NUM_USERS];
|
|
||||||
|
|
||||||
final CountDownLatch[] joinCdl = createCdl(ITERATIONS, NUM_USERS);
|
|
||||||
final CountDownLatch[] publishCdl = createCdl(ITERATIONS, NUM_USERS * NUM_USERS);
|
|
||||||
final CountDownLatch[] unsubscribeCdl = createCdl(ITERATIONS, NUM_USERS);
|
|
||||||
final CountDownLatch[] verifyCdl = createCdl(ITERATIONS, NUM_USERS);
|
|
||||||
final CountDownLatch[] leaveCdl = createCdl(ITERATIONS, NUM_USERS);
|
|
||||||
|
|
||||||
final int[] unsubscribeFromIndex = new int[ITERATIONS];
|
|
||||||
for (int i = 0; i < unsubscribeFromIndex.length; i++) {
|
|
||||||
unsubscribeFromIndex[i] = random.nextInt(NUM_USERS);
|
|
||||||
}
|
|
||||||
|
|
||||||
iterParallelUsers(NUM_USERS, ITERATIONS, new UserLifecycle() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run(final int numUser, final int iteration) throws Exception {
|
|
||||||
final String userName = getBrowserKey(numUser);
|
|
||||||
|
|
||||||
log.info("User '{}' is joining room '{}'", userName, roomName);
|
|
||||||
synchronized (browsersLock) {
|
|
||||||
joinToRoom(numUser, userName, roomName);
|
|
||||||
activeUsers[numUser] = true;
|
|
||||||
verify(activeUsers);
|
|
||||||
joinCdl[iteration].countDown();
|
|
||||||
}
|
|
||||||
log.info("User '{}' joined room '{}'", userName, roomName);
|
|
||||||
|
|
||||||
joinCdl[iteration].await(PLAY_TIME * 5000L, TimeUnit.MILLISECONDS);
|
|
||||||
|
|
||||||
final long start = System.currentTimeMillis();
|
|
||||||
|
|
||||||
parallelTasks(NUM_USERS, USER_BROWSER_PREFIX, "parallelWaitForStream", new Task() {
|
|
||||||
@Override
|
|
||||||
public void exec(int numTask) throws Exception {
|
|
||||||
String videoUserName = getBrowserKey(numTask);
|
|
||||||
synchronized (browsersLock) {
|
|
||||||
waitForStream(numUser, userName, numTask);
|
|
||||||
}
|
|
||||||
long duration = System.currentTimeMillis() - start;
|
|
||||||
log.info("Video received in browser of user '{}' for user '{}' in {} millis", userName,
|
|
||||||
videoUserName, duration);
|
|
||||||
publishCdl[iteration].countDown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
publishCdl[iteration].await(PLAY_TIME * 5000L, TimeUnit.MILLISECONDS);
|
|
||||||
|
|
||||||
if (execExceptions != null && !execExceptions.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String userUnsubscribe = getBrowserKey(unsubscribeFromIndex[iteration]);
|
|
||||||
if (numUser != unsubscribeFromIndex[iteration]) {
|
|
||||||
log.info("User '{}' unsubscribing from '{}' (vTag={}) in room '{}'", userName,
|
|
||||||
userUnsubscribe, getBrowserNativeStreamName(unsubscribeFromIndex[iteration]),
|
|
||||||
roomName);
|
|
||||||
synchronized (browsersLock) {
|
|
||||||
unsubscribe(numUser, unsubscribeFromIndex[iteration]);
|
|
||||||
}
|
|
||||||
log.info("User '{}' unsubscribed from '{}' in room '{}'", userName, userUnsubscribe,
|
|
||||||
roomName);
|
|
||||||
} else {
|
|
||||||
activeUsers[numUser] = false;
|
|
||||||
}
|
|
||||||
unsubscribeCdl[iteration].countDown();
|
|
||||||
unsubscribeCdl[iteration].await(PLAY_TIME * 5000L, TimeUnit.MILLISECONDS);
|
|
||||||
|
|
||||||
if (numUser != unsubscribeFromIndex[iteration]) {
|
|
||||||
synchronized (browsersLock) {
|
|
||||||
verify(activeUsers);
|
|
||||||
}
|
|
||||||
log.info("{} - Verified that I've unsubscribed from '{}' media in room '{}'", userName,
|
|
||||||
userUnsubscribe, roomName);
|
|
||||||
}
|
|
||||||
verifyCdl[iteration].countDown();
|
|
||||||
verifyCdl[iteration].await(PLAY_TIME * 5000L, TimeUnit.MILLISECONDS);
|
|
||||||
|
|
||||||
log.info("User '{}' is exiting from room '{}'", userName, roomName);
|
|
||||||
synchronized (browsersLock) {
|
|
||||||
exitFromRoom(numUser, userName);
|
|
||||||
activeUsers[numUser] = false;
|
|
||||||
verify(activeUsers);
|
|
||||||
leaveCdl[iteration].countDown();
|
|
||||||
}
|
|
||||||
log.info("User '{}' exited from room '{}'", userName, roomName);
|
|
||||||
leaveCdl[iteration].await(PLAY_TIME * 5000L, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.browser;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.kurento.test.browser.WebPage;
|
|
||||||
|
|
||||||
import io.openvidu.test.RoomFunctionalBrowserTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Web app availability basic test.
|
|
||||||
*
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 6.2.1
|
|
||||||
*/
|
|
||||||
public class WebAppAvailability extends RoomFunctionalBrowserTest<WebPage> {
|
|
||||||
|
|
||||||
public static final int NUM_USERS = 1;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() throws Exception {
|
|
||||||
boolean[] activeUsers = new boolean[NUM_USERS];
|
|
||||||
|
|
||||||
int numUser = 0;
|
|
||||||
String userName = getBrowserKey(numUser);
|
|
||||||
log.info("User '{}' is joining room '{}'", userName, roomName);
|
|
||||||
joinToRoom(numUser, userName, roomName);
|
|
||||||
activeUsers[numUser] = true;
|
|
||||||
verify(activeUsers);
|
|
||||||
log.info("User '{}' joined room '{}'", userName, roomName);
|
|
||||||
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
waitForStream(numUser, userName, numUser);
|
|
||||||
long duration = System.currentTimeMillis() - start;
|
|
||||||
log.info("Video received in browser of user '{}' for user '{}' in {} millis", userName,
|
|
||||||
userName, duration);
|
|
||||||
|
|
||||||
log.info("User '{}' is exiting from room '{}'", userName, roomName);
|
|
||||||
exitFromRoom(numUser, userName);
|
|
||||||
activeUsers[numUser] = false;
|
|
||||||
verify(activeUsers);
|
|
||||||
log.info("User '{}' exited from room '{}'", userName, roomName);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.config;
|
|
||||||
|
|
||||||
import static org.kurento.test.config.TestConfiguration.KMS_WS_URI_DEFAULT;
|
|
||||||
import static org.kurento.test.config.TestConfiguration.KMS_WS_URI_PROP;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Kurento Room test properties.
|
|
||||||
*
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 6.2.1
|
|
||||||
*/
|
|
||||||
public class RoomTestConfiguration {
|
|
||||||
|
|
||||||
public static final String ROOM_APP_CLASSNAME_PROP = "room.app.classnames";
|
|
||||||
public static final String ROOM_APP_CLASSNAME_DEFAULT = "[org.kurento.room.basic.KurentoRoomBasicApp,"
|
|
||||||
+ "org.kurento.room.demo.KurentoRoomDemoApp]";
|
|
||||||
|
|
||||||
public static final String EXTRA_KMS_WS_URI_PROP = KMS_WS_URI_PROP + ".extra";
|
|
||||||
public static final String EXTRA_KMS_WS_URI_DEFAULT = KMS_WS_URI_DEFAULT;
|
|
||||||
|
|
||||||
public static final String ROOM_PREFIX = "room";
|
|
||||||
public static final String USER_BROWSER_PREFIX = "browser";
|
|
||||||
public static final String USER_FAKE_PREFIX = "user";
|
|
||||||
public static final String DEFAULT_ROOM = ROOM_PREFIX;
|
|
||||||
|
|
||||||
public final static int DEFAULT_ROOM_INOUT_AWAIT_TIME_IN_SECONDS = 60;
|
|
||||||
public final static int DEFAULT_ACTIVE_LIVE_TOTAL_TIMEOUT_IN_SECONDS = 60;
|
|
||||||
public final static int DEFAULT_PLAY_TIME_IN_SECONDS = 30;
|
|
||||||
public static final int TASKS_TIMEOUT_IN_MINUTES = 15;
|
|
||||||
}
|
|
|
@ -1,149 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.fake;
|
|
||||||
|
|
||||||
import static io.openvidu.test.config.RoomTestConfiguration.EXTRA_KMS_WS_URI_DEFAULT;
|
|
||||||
import static io.openvidu.test.config.RoomTestConfiguration.EXTRA_KMS_WS_URI_PROP;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.kurento.client.KurentoClient;
|
|
||||||
import org.kurento.client.KurentoConnectionListener;
|
|
||||||
import org.kurento.commons.PropertiesManager;
|
|
||||||
import org.kurento.test.browser.WebPage;
|
|
||||||
|
|
||||||
import io.openvidu.test.RoomFunctionalFakeTest;
|
|
||||||
import io.openvidu.test.config.RoomTestConfiguration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests multiple fake WebRTC users concurrently joining the same room. Some of them are built on a
|
|
||||||
* pipeline from an extra KMS instance. (the config key for the WS URI of this instance is
|
|
||||||
* {@link RoomTestConfiguration#EXTRA_KMS_WS_URI_PROP}, with the default value
|
|
||||||
* {@link RoomTestConfiguration#EXTRA_KMS_WS_URI_DEFAULT})
|
|
||||||
*
|
|
||||||
* @see RoomTestConfiguration#EXTRA_KMS_WS_URI_PROP
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 6.2.1
|
|
||||||
*/
|
|
||||||
public class ExtraKmsFakeUsers extends RoomFunctionalFakeTest<WebPage> {
|
|
||||||
|
|
||||||
public final static int NUM_USERS = 0;
|
|
||||||
|
|
||||||
public static String[] relativeUris = { "/video/filter/fiwarecut.webm",
|
|
||||||
"/video/filter/fiwarecut_30.webm", "/video/filter/street.webm" };
|
|
||||||
|
|
||||||
public static String[] extraRelativeUris = { "/video/filter/plates.webm" };
|
|
||||||
|
|
||||||
public String testExtraFakeKmsWsUri;
|
|
||||||
|
|
||||||
public KurentoClient testExtraFakeKurento;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setupBrowserTest() throws InterruptedException {
|
|
||||||
testExtraFakeKmsWsUri = PropertiesManager
|
|
||||||
.getProperty(EXTRA_KMS_WS_URI_PROP, fakeKms.getWsUri());
|
|
||||||
if (testExtraFakeKmsWsUri == null) {
|
|
||||||
testExtraFakeKmsWsUri = EXTRA_KMS_WS_URI_DEFAULT;
|
|
||||||
log.debug(
|
|
||||||
"Extra Fake KMS URI: {} (default value, as '{}' was not specified nor the Fake KMS had one)",
|
|
||||||
testExtraFakeKmsWsUri, EXTRA_KMS_WS_URI_PROP);
|
|
||||||
} else {
|
|
||||||
log.debug("Extra Fake KMS URI: {}", testExtraFakeKmsWsUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
super.setupBrowserTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void teardownBrowserTest() {
|
|
||||||
super.teardownBrowserTest();
|
|
||||||
if (testExtraFakeKurento != null) {
|
|
||||||
testExtraFakeKurento.destroy();
|
|
||||||
testExtraFakeKurento = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected synchronized KurentoClient getTestExtraFakeKurento() {
|
|
||||||
if (testExtraFakeKurento == null) {
|
|
||||||
testExtraFakeKurento = KurentoClient.create(testExtraFakeKmsWsUri,
|
|
||||||
new KurentoConnectionListener() {
|
|
||||||
@Override
|
|
||||||
public void connected() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void connectionFailed() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void disconnected() {
|
|
||||||
testExtraFakeKurento = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reconnected(boolean sameServer) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return testExtraFakeKurento;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() {
|
|
||||||
int fakeUsers = relativeUris.length;
|
|
||||||
|
|
||||||
CountDownLatch joinLatch = parallelJoinFakeUsers(Arrays.asList(relativeUris), roomName,
|
|
||||||
fakeKurentoClient);
|
|
||||||
|
|
||||||
await(joinLatch, JOIN_ROOM_TOTAL_TIMEOUT_IN_SECONDS, "joinRoom", fakeUsers);
|
|
||||||
|
|
||||||
log.info("\n-----------------\n" + "Join concluded in room '{}'" + "\n-----------------\n",
|
|
||||||
roomName);
|
|
||||||
|
|
||||||
String aux = USER_FAKE_PREFIX;
|
|
||||||
USER_FAKE_PREFIX = USER_FAKE_PREFIX + "extra";
|
|
||||||
|
|
||||||
int extraFakeUsers = extraRelativeUris.length;
|
|
||||||
|
|
||||||
joinLatch = parallelJoinFakeUsers(Arrays.asList(extraRelativeUris), roomName,
|
|
||||||
getTestExtraFakeKurento());
|
|
||||||
|
|
||||||
USER_FAKE_PREFIX = aux;
|
|
||||||
CountDownLatch waitForLatch = parallelWaitActiveLive(roomName, fakeUsers);
|
|
||||||
await(waitForLatch, ACTIVE_LIVE_TOTAL_TIMEOUT_IN_SECONDS, "waitForActiveLive", fakeUsers);
|
|
||||||
|
|
||||||
USER_FAKE_PREFIX = USER_FAKE_PREFIX + "extra";
|
|
||||||
waitForLatch = parallelWaitActiveLive(roomName, extraFakeUsers);
|
|
||||||
await(waitForLatch, ACTIVE_LIVE_TOTAL_TIMEOUT_IN_SECONDS, "waitForActiveLiveExtra",
|
|
||||||
extraFakeUsers);
|
|
||||||
|
|
||||||
idlePeriod();
|
|
||||||
|
|
||||||
USER_FAKE_PREFIX = aux;
|
|
||||||
CountDownLatch leaveLatch = parallelLeaveFakeUsers(roomName, fakeUsers);
|
|
||||||
await(leaveLatch, LEAVE_ROOM_TOTAL_TIMEOUT_IN_SECONDS, "leaveRoom", fakeUsers);
|
|
||||||
|
|
||||||
USER_FAKE_PREFIX = USER_FAKE_PREFIX + "extra";
|
|
||||||
leaveLatch = parallelLeaveFakeUsers(roomName, extraFakeUsers);
|
|
||||||
await(leaveLatch, LEAVE_ROOM_TOTAL_TIMEOUT_IN_SECONDS, "leaveRoomExtra", extraFakeUsers);
|
|
||||||
|
|
||||||
log.info("\n-----------------\n" + "Leave concluded in room '{}'" + "\n-----------------\n",
|
|
||||||
roomName);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,116 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.fake;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.kurento.test.browser.WebPage;
|
|
||||||
|
|
||||||
import io.openvidu.test.RoomFunctionalFakeTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests multiple fake WebRTC and Selenium (Chrome) users sequentially joining the same room.
|
|
||||||
*
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 6.2.1
|
|
||||||
*/
|
|
||||||
public class MixedUsers extends RoomFunctionalFakeTest<WebPage> {
|
|
||||||
|
|
||||||
public static String[] relativeUris = { "/video/filter/fiwarecut.webm",
|
|
||||||
"/video/filter/fiwarecut_30.webm" };
|
|
||||||
|
|
||||||
public final static int CHROME_SPINNER_USERS = 1;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() {
|
|
||||||
int fakeUsers = relativeUris.length;
|
|
||||||
|
|
||||||
CountDownLatch joinLatch = parallelJoinFakeUsers(Arrays.asList(relativeUris), roomName,
|
|
||||||
fakeKurentoClient);
|
|
||||||
|
|
||||||
// fail if necessary before continuing
|
|
||||||
failWithExceptions();
|
|
||||||
|
|
||||||
boolean[] activeBrowserUsers = new boolean[CHROME_SPINNER_USERS];
|
|
||||||
int numUser = 0;
|
|
||||||
String userName = getBrowserKey(numUser);
|
|
||||||
log.info("User '{}' is joining room '{}'", userName, roomName);
|
|
||||||
joinToRoom(numUser, userName, roomName);
|
|
||||||
activeBrowserUsers[numUser] = true;
|
|
||||||
verify(activeBrowserUsers); // only browser users
|
|
||||||
log.info("User '{}' joined room '{}'", userName, roomName);
|
|
||||||
|
|
||||||
await(joinLatch, JOIN_ROOM_TOTAL_TIMEOUT_IN_SECONDS, "joinRoom", fakeUsers);
|
|
||||||
log.info("\n-----------------\n" + "Join concluded in room '{}'" + "\n-----------------\n",
|
|
||||||
roomName);
|
|
||||||
|
|
||||||
CountDownLatch waitForLatch = parallelWaitActiveLive(roomName, fakeUsers);
|
|
||||||
await(waitForLatch, ACTIVE_LIVE_TOTAL_TIMEOUT_IN_SECONDS, "waitForActiveLive", fakeUsers);
|
|
||||||
|
|
||||||
// verify from the browser
|
|
||||||
Map<String, Boolean> activeFakeWrUsers = new HashMap<String, Boolean>();
|
|
||||||
for (int i = 0; i < fakeUsers; i++) {
|
|
||||||
activeFakeWrUsers.put(getFakeKey(i), true);
|
|
||||||
}
|
|
||||||
verify(activeBrowserUsers, activeFakeWrUsers);
|
|
||||||
|
|
||||||
// let's check that video streams are being received in the browser
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
waitForStream(numUser, userName, numUser);
|
|
||||||
long duration = System.currentTimeMillis() - start;
|
|
||||||
log.info("Video received in browser of user '{}' for user '{}' in {} millis", userName,
|
|
||||||
userName, duration);
|
|
||||||
for (int i = 0; i < fakeUsers; i++) {
|
|
||||||
start = System.currentTimeMillis();
|
|
||||||
waitForStream(numUser, userName, getFakeNativeStreamName(i));
|
|
||||||
duration = System.currentTimeMillis() - start;
|
|
||||||
log.info("Video received in browser of user '{}' for user '{}' in {} millis", userName,
|
|
||||||
getFakeKey(i), duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
long aux = ROOM_ACTIVITY_IN_SECONDS;
|
|
||||||
ROOM_ACTIVITY_IN_SECONDS = 20;
|
|
||||||
idlePeriod();
|
|
||||||
|
|
||||||
int targetIndex = random.nextInt(fakeUsers);
|
|
||||||
log.debug("Selecting video of user {}", getFakeKey(targetIndex));
|
|
||||||
selectVideoTag(numUser, getFakeVideoStreamName(targetIndex));
|
|
||||||
|
|
||||||
ROOM_ACTIVITY_IN_SECONDS = aux;
|
|
||||||
idlePeriod();
|
|
||||||
|
|
||||||
CountDownLatch leaveLatch = parallelLeaveFakeUsers(roomName, fakeUsers);
|
|
||||||
await(leaveLatch, LEAVE_ROOM_TOTAL_TIMEOUT_IN_SECONDS, "leaveRoom", fakeUsers);
|
|
||||||
|
|
||||||
for (int i = 0; i < fakeUsers; i++) {
|
|
||||||
activeFakeWrUsers.put(getFakeKey(i), false);
|
|
||||||
}
|
|
||||||
verify(activeBrowserUsers, activeFakeWrUsers);
|
|
||||||
|
|
||||||
log.info("User '{}' is exiting from room '{}'", userName, roomName);
|
|
||||||
exitFromRoom(numUser, userName);
|
|
||||||
activeBrowserUsers[numUser] = false;
|
|
||||||
verify(activeBrowserUsers);
|
|
||||||
log.info("User '{}' exited from room '{}'", userName, roomName);
|
|
||||||
|
|
||||||
log.info("\n-----------------\n" + "Leave concluded in room '{}'" + "\n-----------------\n",
|
|
||||||
roomName);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.fake;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.kurento.test.browser.WebPage;
|
|
||||||
|
|
||||||
import io.openvidu.test.RoomFunctionalFakeTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests several fake WebRTC users' concurrently joining the same room.
|
|
||||||
*
|
|
||||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
|
||||||
* @since 6.2.1
|
|
||||||
*/
|
|
||||||
public abstract class ParallelNFakeUsers extends RoomFunctionalFakeTest<WebPage> {
|
|
||||||
|
|
||||||
public final static int NUM_USERS = 0;
|
|
||||||
|
|
||||||
public static String[] relativeUris = { "/video/filter/fiwarecut.webm",
|
|
||||||
"/video/filter/fiwarecut_30.webm", "/video/filter/street.webm" };
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() {
|
|
||||||
int fakeUsers = relativeUris.length;
|
|
||||||
|
|
||||||
CountDownLatch joinLatch = parallelJoinFakeUsers(Arrays.asList(relativeUris), roomName,
|
|
||||||
fakeKurentoClient);
|
|
||||||
|
|
||||||
await(joinLatch, JOIN_ROOM_TOTAL_TIMEOUT_IN_SECONDS, "joinRoom", fakeUsers);
|
|
||||||
|
|
||||||
log.info("\n-----------------\n" + "Join concluded in room '{}'" + "\n-----------------\n",
|
|
||||||
roomName);
|
|
||||||
|
|
||||||
CountDownLatch waitForLatch = parallelWaitActiveLive(roomName, fakeUsers);
|
|
||||||
|
|
||||||
await(waitForLatch, ACTIVE_LIVE_TOTAL_TIMEOUT_IN_SECONDS, "waitForActiveLive", fakeUsers);
|
|
||||||
|
|
||||||
idlePeriod();
|
|
||||||
|
|
||||||
CountDownLatch leaveLatch = parallelLeaveFakeUsers(roomName, fakeUsers);
|
|
||||||
|
|
||||||
await(leaveLatch, LEAVE_ROOM_TOTAL_TIMEOUT_IN_SECONDS, "leaveRoom", fakeUsers);
|
|
||||||
|
|
||||||
log.info("\n-----------------\n" + "Leave concluded in room '{}'" + "\n-----------------\n",
|
|
||||||
roomName);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.fake.util;
|
|
||||||
|
|
||||||
public class AudioVideoFile {
|
|
||||||
private String audio;
|
|
||||||
private String video;
|
|
||||||
|
|
||||||
public AudioVideoFile(String audio, String video) {
|
|
||||||
super();
|
|
||||||
this.audio = audio;
|
|
||||||
this.video = video;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAudio() {
|
|
||||||
return audio;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAudio(String audio) {
|
|
||||||
this.audio = audio;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getVideo() {
|
|
||||||
return video;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setVideo(String video) {
|
|
||||||
this.video = video;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
builder.append("[");
|
|
||||||
if (audio != null) {
|
|
||||||
builder.append("audio=").append(audio).append(", ");
|
|
||||||
}
|
|
||||||
if (video != null) {
|
|
||||||
builder.append("video=").append(video);
|
|
||||||
}
|
|
||||||
builder.append("]");
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,498 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.fake.util;
|
|
||||||
|
|
||||||
import java.io.Closeable;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentSkipListMap;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.kurento.client.EndOfStreamEvent;
|
|
||||||
import org.kurento.client.ErrorEvent;
|
|
||||||
import org.kurento.client.EventListener;
|
|
||||||
import org.kurento.client.IceCandidate;
|
|
||||||
import org.kurento.client.MediaPipeline;
|
|
||||||
import org.kurento.client.MediaState;
|
|
||||||
import org.kurento.client.MediaStateChangedEvent;
|
|
||||||
import org.kurento.client.OnIceCandidateEvent;
|
|
||||||
import org.kurento.client.PlayerEndpoint;
|
|
||||||
import org.kurento.client.WebRtcEndpoint;
|
|
||||||
import io.openvidu.client.OpenViduClient;
|
|
||||||
import io.openvidu.client.internal.IceCandidateInfo;
|
|
||||||
import io.openvidu.client.internal.Notification;
|
|
||||||
import io.openvidu.client.internal.ParticipantLeftInfo;
|
|
||||||
import io.openvidu.client.internal.ParticipantPublishedInfo;
|
|
||||||
import io.openvidu.client.internal.ParticipantUnpublishedInfo;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class FakeParticipant implements Closeable {
|
|
||||||
private static final long WAIT_ACTIVE_LIVE_BY_PEER_TIMEOUT = 10; // seconds
|
|
||||||
|
|
||||||
private static Logger log = LoggerFactory.getLogger(FakeParticipant.class);
|
|
||||||
|
|
||||||
private OpenViduClient jsonRpcClient;
|
|
||||||
|
|
||||||
private MediaPipeline pipeline;
|
|
||||||
private WebRtcEndpoint webRtc;
|
|
||||||
private CountDownLatch ownLatch = new CountDownLatch(1);
|
|
||||||
private PlayerEndpoint player;
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
private String room;
|
|
||||||
private String playerUri;
|
|
||||||
|
|
||||||
private boolean autoMedia = false;
|
|
||||||
private boolean loopMedia = false;
|
|
||||||
|
|
||||||
private Map<String, String> peerStreams = new ConcurrentSkipListMap<String, String>();
|
|
||||||
private Map<String, WebRtcEndpoint> peerEndpoints = new ConcurrentSkipListMap<String, WebRtcEndpoint>();
|
|
||||||
private Map<String, CountDownLatch> peerLatches = new ConcurrentSkipListMap<String, CountDownLatch>();
|
|
||||||
|
|
||||||
private Thread notifThread;
|
|
||||||
|
|
||||||
public FakeParticipant(String serviceUrl, String name, String room, String playerUri,
|
|
||||||
MediaPipeline pipeline, boolean autoMedia, boolean loopMedia) {
|
|
||||||
this.name = name;
|
|
||||||
this.room = room;
|
|
||||||
this.playerUri = playerUri;
|
|
||||||
this.autoMedia = autoMedia;
|
|
||||||
this.loopMedia = loopMedia;
|
|
||||||
this.pipeline = pipeline;
|
|
||||||
this.jsonRpcClient = new OpenViduClient(serviceUrl);
|
|
||||||
this.notifThread = new Thread(name + "-notif") {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
internalGetNotification();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
log.debug("Interrupted while running notification polling");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.notifThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void internalGetNotification() throws InterruptedException {
|
|
||||||
log.info("Starting receiving notifications by polling blocking queue");
|
|
||||||
while (true) {
|
|
||||||
try {
|
|
||||||
Notification notif = jsonRpcClient.getServerNotification();
|
|
||||||
if (notif == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
log.debug("Polled notif {}", notif);
|
|
||||||
switch (notif.getMethod()) {
|
|
||||||
case ICECANDIDATE_METHOD:
|
|
||||||
onIceCandidate(notif);
|
|
||||||
break;
|
|
||||||
case MEDIAERROR_METHOD:
|
|
||||||
// TODO
|
|
||||||
break;
|
|
||||||
case PARTICIPANTEVICTED_METHOD:
|
|
||||||
// TODO
|
|
||||||
break;
|
|
||||||
case PARTICIPANTJOINED_METHOD:
|
|
||||||
// TODO
|
|
||||||
break;
|
|
||||||
case PARTICIPANTLEFT_METHOD:
|
|
||||||
onParticipantLeft(notif);
|
|
||||||
break;
|
|
||||||
case PARTICIPANTPUBLISHED_METHOD:
|
|
||||||
onParticipantPublished(notif);
|
|
||||||
break;
|
|
||||||
case PARTICIPANTSENDMESSAGE_METHOD:
|
|
||||||
break;
|
|
||||||
case PARTICIPANTUNPUBLISHED_METHOD:
|
|
||||||
onParticipantUnpublish(notif);
|
|
||||||
break;
|
|
||||||
case ROOMCLOSED_METHOD:
|
|
||||||
// TODO
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("Encountered a problem when reading " + "the notifications queue", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onParticipantUnpublish(Notification notif) {
|
|
||||||
ParticipantUnpublishedInfo info = (ParticipantUnpublishedInfo) notif;
|
|
||||||
log.debug("Notif details {}: {}", info.getClass().getSimpleName(), info);
|
|
||||||
releaseRemote(info.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onParticipantLeft(Notification notif) {
|
|
||||||
ParticipantLeftInfo info = (ParticipantLeftInfo) notif;
|
|
||||||
log.debug("Notif details {}: {}", info.getClass().getSimpleName(), info);
|
|
||||||
releaseRemote(info.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void releaseRemote(String remote) {
|
|
||||||
WebRtcEndpoint peer = peerEndpoints.get(remote);
|
|
||||||
if (peer != null) {
|
|
||||||
peer.release();
|
|
||||||
}
|
|
||||||
peerEndpoints.remove(remote);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onParticipantPublished(Notification notif) {
|
|
||||||
ParticipantPublishedInfo info = (ParticipantPublishedInfo) notif;
|
|
||||||
log.debug("Notif details {}: {}", info.getClass().getSimpleName(), info);
|
|
||||||
String remote = info.getId();
|
|
||||||
addPeerStream(remote, info.getStreams());
|
|
||||||
if (autoMedia) {
|
|
||||||
if (peerEndpoints.containsKey(remote)) {
|
|
||||||
log.info("(autosubscribe on) Already subscribed to {}. No actions required.", remote);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
subscribe(remote);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onIceCandidate(Notification notif) {
|
|
||||||
IceCandidateInfo info = (IceCandidateInfo) notif;
|
|
||||||
log.debug("Notif details {}: {}", info.getClass().getSimpleName(), info);
|
|
||||||
String epname = info.getEndpointName();
|
|
||||||
if (name.equals(epname)) {
|
|
||||||
if (webRtc != null) {
|
|
||||||
webRtc.addIceCandidate(toKurentoIceCandidate(info.getIceCandidate()));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
WebRtcEndpoint peer = peerEndpoints.get(epname);
|
|
||||||
if (peer != null) {
|
|
||||||
peer.addIceCandidate(toKurentoIceCandidate(info.getIceCandidate()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IceCandidate toKurentoIceCandidate(
|
|
||||||
io.openvidu.client.internal.IceCandidate iceCandidate) {
|
|
||||||
return new IceCandidate(iceCandidate.getCandidate(), iceCandidate.getSdpMid(),
|
|
||||||
iceCandidate.getSdpMLineIndex());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void joinRoom() {
|
|
||||||
try {
|
|
||||||
addPeers(jsonRpcClient.joinRoom(room, name));
|
|
||||||
log.info("Joined room {}: {} peers", room, peerStreams);
|
|
||||||
if (autoMedia) {
|
|
||||||
log.debug("Automedia on, publishing and subscribing to as many as {} publishers",
|
|
||||||
peerStreams.size());
|
|
||||||
publish();
|
|
||||||
if (!peerStreams.isEmpty()) {
|
|
||||||
for (Entry<String, String> e : peerStreams.entrySet()) {
|
|
||||||
String stream = e.getValue();
|
|
||||||
String remote = e.getKey();
|
|
||||||
if (stream != null) {
|
|
||||||
subscribe(remote);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.debug("Finished subscribing to existing publishers");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.warn("Unable to join room '{}'", room, e);
|
|
||||||
Assert.fail("Unable to join: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void leaveRoom() {
|
|
||||||
try {
|
|
||||||
jsonRpcClient.leaveRoom();
|
|
||||||
log.info("Left room '{}'", room);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.warn("Unable to leave room '{}'", room, e);
|
|
||||||
Assert.fail("Unable to leave room: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void publish() {
|
|
||||||
try {
|
|
||||||
String sdpOffer = createWebRtcForParticipant();
|
|
||||||
String sdpAnswer = jsonRpcClient.publishVideo(sdpOffer, false);
|
|
||||||
this.webRtc.processAnswer(sdpAnswer);
|
|
||||||
this.webRtc.gatherCandidates();
|
|
||||||
player.play();
|
|
||||||
log.debug("Published media in room '{}'", room);
|
|
||||||
log.trace("Published media in room '{}'- SDP OFFER:\n{}\nSDP ANSWER:\n{}", room, sdpOffer,
|
|
||||||
sdpAnswer);
|
|
||||||
} catch (IOException | URISyntaxException e) {
|
|
||||||
log.warn("Unable to publish in room '{}'", room, e);
|
|
||||||
Assert.fail("Unable to publish: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unpublish() {
|
|
||||||
try {
|
|
||||||
jsonRpcClient.unpublishVideo();
|
|
||||||
log.debug("Unpublished media");
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.warn("Unable to unpublish in room '{}'", room, e);
|
|
||||||
Assert.fail("Unable to unpublish: " + e.getMessage());
|
|
||||||
} finally {
|
|
||||||
if (player != null) {
|
|
||||||
player.stop();
|
|
||||||
player.release();
|
|
||||||
}
|
|
||||||
if (webRtc != null) {
|
|
||||||
webRtc.release();
|
|
||||||
}
|
|
||||||
ownLatch = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void subscribe(String remoteName) {
|
|
||||||
try {
|
|
||||||
if (peerEndpoints.containsKey(remoteName)) {
|
|
||||||
log.warn("Already subscribed to {}", remoteName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String sdpOffer = createWebRtcForPeer(remoteName);
|
|
||||||
String sdpAnswer = jsonRpcClient.receiveVideoFrom(peerStreams.get(remoteName), sdpOffer);
|
|
||||||
WebRtcEndpoint peer = peerEndpoints.get(remoteName);
|
|
||||||
if (peer == null) {
|
|
||||||
throw new Exception("Receiving endpoint not found for peer " + remoteName);
|
|
||||||
}
|
|
||||||
peer.processAnswer(sdpAnswer);
|
|
||||||
peer.gatherCandidates();
|
|
||||||
log.debug("Subscribed to '{}' in room '{}'", peerStreams.get(remoteName), room);
|
|
||||||
log.trace("Subscribed to '{}' in room '{}' - SDP OFFER:\n{}\nSDP ANSWER:\n{}",
|
|
||||||
peerStreams.get(remoteName), room, sdpOffer, sdpAnswer);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("Unable to subscribe in room '{}' to '{}'", room, remoteName, e);
|
|
||||||
Assert.fail("Unable to subscribe: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void unsubscribe(String remoteName) {
|
|
||||||
WebRtcEndpoint peer = null;
|
|
||||||
try {
|
|
||||||
peer = peerEndpoints.get(remoteName);
|
|
||||||
if (peer == null) {
|
|
||||||
log.warn("No local peer found for remote {}", remoteName);
|
|
||||||
}
|
|
||||||
jsonRpcClient.unsubscribeFromVideo(peerStreams.get(remoteName));
|
|
||||||
log.debug("Unsubscribed from {}", peerStreams.get(remoteName));
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.warn("Unable to unsubscribe in room '{}' from '{}'", room, remoteName, e);
|
|
||||||
Assert.fail("Unable to unsubscribe: " + e.getMessage());
|
|
||||||
} finally {
|
|
||||||
if (peer != null) {
|
|
||||||
peer.release();
|
|
||||||
}
|
|
||||||
peerEndpoints.remove(remoteName);
|
|
||||||
peerLatches.remove(remoteName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<String> getPeers() {
|
|
||||||
return peerStreams.keySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String createWebRtcForParticipant() throws URISyntaxException {
|
|
||||||
|
|
||||||
webRtc = new WebRtcEndpoint.Builder(pipeline).build();
|
|
||||||
ownLatch = new CountDownLatch(1);
|
|
||||||
|
|
||||||
webRtc.addOnIceCandidateListener(new EventListener<OnIceCandidateEvent>() {
|
|
||||||
@Override
|
|
||||||
public void onEvent(OnIceCandidateEvent event) {
|
|
||||||
try {
|
|
||||||
log.debug("New ICE candidate: {}, {}, {}", event.getCandidate().getCandidate(),
|
|
||||||
event.getCandidate().getSdpMid(), event.getCandidate().getSdpMLineIndex());
|
|
||||||
jsonRpcClient.onIceCandidate(name, event.getCandidate().getCandidate(),
|
|
||||||
event.getCandidate().getSdpMid(), event.getCandidate().getSdpMLineIndex());
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("Exception sending iceCanditate. Exception {}:{}", e.getClass().getName(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
webRtc.addMediaStateChangedListener(new EventListener<MediaStateChangedEvent>() {
|
|
||||||
@Override
|
|
||||||
public void onEvent(MediaStateChangedEvent event) {
|
|
||||||
log.info("Media state changed: {}", event.getNewState());
|
|
||||||
if (event.getNewState() == MediaState.CONNECTED) {
|
|
||||||
ownLatch.countDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
player = new PlayerEndpoint.Builder(pipeline, playerUri).build();
|
|
||||||
player.addErrorListener(new EventListener<ErrorEvent>() {
|
|
||||||
@Override
|
|
||||||
public void onEvent(ErrorEvent event) {
|
|
||||||
log.warn("ErrorEvent for player of '{}': {}", name, event.getDescription());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
player.addEndOfStreamListener(new EventListener<EndOfStreamEvent>() {
|
|
||||||
@Override
|
|
||||||
public void onEvent(EndOfStreamEvent event) {
|
|
||||||
if (loopMedia) {
|
|
||||||
log.debug("Replaying {}", playerUri);
|
|
||||||
player.play();
|
|
||||||
} else {
|
|
||||||
log.debug("Finished playing from {}", playerUri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
player.connect(webRtc);
|
|
||||||
log.debug("Playing media from {}", playerUri);
|
|
||||||
return webRtc.generateOffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String createWebRtcForPeer(final String remoteName) throws Exception {
|
|
||||||
if (peerEndpoints.containsKey(remoteName)) {
|
|
||||||
throw new Exception("Already subscribed to " + remoteName);
|
|
||||||
}
|
|
||||||
|
|
||||||
WebRtcEndpoint peer = new WebRtcEndpoint.Builder(pipeline).build();
|
|
||||||
final CountDownLatch peerLatch = new CountDownLatch(1);
|
|
||||||
|
|
||||||
peer.addOnIceCandidateListener(new EventListener<OnIceCandidateEvent>() {
|
|
||||||
@Override
|
|
||||||
public void onEvent(OnIceCandidateEvent event) {
|
|
||||||
try {
|
|
||||||
jsonRpcClient.onIceCandidate(remoteName, event.getCandidate().getCandidate(),
|
|
||||||
event.getCandidate().getSdpMid(), event.getCandidate().getSdpMLineIndex());
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("Exception sending iceCanditate. Exception {}:{}", e.getClass().getName(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
peer.addMediaStateChangedListener(new EventListener<MediaStateChangedEvent>() {
|
|
||||||
@Override
|
|
||||||
public void onEvent(MediaStateChangedEvent event) {
|
|
||||||
log.info("{}: Media state changed for remote {}: {}", name, remoteName,
|
|
||||||
event.getNewState());
|
|
||||||
if (event.getNewState() == MediaState.CONNECTED) {
|
|
||||||
peerLatch.countDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
peerEndpoints.put(remoteName, peer);
|
|
||||||
peerLatches.put(remoteName, peerLatch);
|
|
||||||
|
|
||||||
return peer.generateOffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
log.debug("Closing {}", name);
|
|
||||||
try {
|
|
||||||
if (jsonRpcClient != null) {
|
|
||||||
jsonRpcClient.close();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Exception closing jsonRpcClient", e);
|
|
||||||
}
|
|
||||||
notifThread.interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void waitForActiveLive(CountDownLatch waitForLatch) {
|
|
||||||
try {
|
|
||||||
boolean allPeersConnected = true;
|
|
||||||
for (WebRtcEndpoint peer : peerEndpoints.values()) {
|
|
||||||
if (peer.getMediaState() != MediaState.CONNECTED) {
|
|
||||||
allPeersConnected = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean ownConnected = webRtc.getMediaState() == MediaState.CONNECTED;
|
|
||||||
|
|
||||||
if (ownConnected && allPeersConnected) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
long remaining = WAIT_ACTIVE_LIVE_BY_PEER_TIMEOUT * (peerEndpoints.size() + 1);
|
|
||||||
log.debug("{}: Start waiting for ACTIVE_LIVE in session '{}' - max {}s", name, room,
|
|
||||||
remaining);
|
|
||||||
remaining = remaining * 1000L;
|
|
||||||
|
|
||||||
if (!ownConnected) {
|
|
||||||
remaining = waitForLatch(remaining, ownLatch, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!allPeersConnected) {
|
|
||||||
for (Entry<String, WebRtcEndpoint> e : peerEndpoints.entrySet()) {
|
|
||||||
String remoteName = e.getKey();
|
|
||||||
if (e.getValue().getMediaState() != MediaState.CONNECTED) {
|
|
||||||
remaining = waitForLatch(remaining, peerLatches.get(remoteName), remoteName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("{}: WaitForActiveLive error", name, e);
|
|
||||||
throw e;
|
|
||||||
} finally {
|
|
||||||
waitForLatch.countDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private long waitForLatch(long remaining, CountDownLatch latch, String epname) {
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
try {
|
|
||||||
if (!latch.await(remaining, TimeUnit.MILLISECONDS)) {
|
|
||||||
throw new RuntimeException("Timeout waiting for ACTIVE_LIVE in participant '" + name
|
|
||||||
+ "' of session '" + room + "' for endpoint '" + epname + "'");
|
|
||||||
}
|
|
||||||
remaining -= System.currentTimeMillis() - start;
|
|
||||||
log.trace("ACTIVE_LIVE - remaining {} ms", remaining);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
log.warn("InterruptedException when waiting for ACTIVE_LIVE in participant '{}' "
|
|
||||||
+ "of session '{}' for endpoint '{}'", name, room, epname);
|
|
||||||
}
|
|
||||||
return remaining;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addPeers(Map<String, List<String>> newPeers) {
|
|
||||||
for (String name : newPeers.keySet()) {
|
|
||||||
addPeerStream(name, newPeers.get(name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void addPeerStream(String name, List<String> streams) {
|
|
||||||
if (streams == null || streams.isEmpty()) {
|
|
||||||
log.warn("Wrong streams info for {}: {}", name, streams);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.peerStreams.containsKey(name)) {
|
|
||||||
log.warn("Overriding peer {}: {} - new: {}", name, this.peerStreams.get(name), streams);
|
|
||||||
}
|
|
||||||
this.peerStreams.put(name, name + "_" + streams.get(0));
|
|
||||||
log.debug("Added first remote stream for {}: {}", name, this.peerStreams.get(name));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,102 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.fake.util;
|
|
||||||
|
|
||||||
import java.io.Closeable;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
|
|
||||||
import org.kurento.client.KurentoClient;
|
|
||||||
import org.kurento.client.MediaPipeline;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores the fake WebRTC participants for a session (room). Each participant will have assigned a
|
|
||||||
* shared {@link MediaPipeline} which it can use to create media elements and interact with the
|
|
||||||
* session. More than one pipelines are allowed for each session.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
|
||||||
*/
|
|
||||||
public class FakeSession implements Closeable {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(FakeSession.class);
|
|
||||||
|
|
||||||
private String serviceUrl;
|
|
||||||
private String room;
|
|
||||||
private KurentoClient defaultKurento;
|
|
||||||
|
|
||||||
private Map<KurentoClient, TestPipeline> pipelines = new ConcurrentHashMap<KurentoClient, TestPipeline>();
|
|
||||||
|
|
||||||
private Map<String, FakeParticipant> participants = new HashMap<String, FakeParticipant>();
|
|
||||||
|
|
||||||
public FakeSession(String serviceUrl, String room, KurentoClient kurento) {
|
|
||||||
this.serviceUrl = serviceUrl;
|
|
||||||
this.room = room;
|
|
||||||
this.defaultKurento = kurento;
|
|
||||||
this.pipelines.put(kurento, new TestPipeline(kurento, room));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
log.debug("Closing Session '{}'", room);
|
|
||||||
for (FakeParticipant p : participants.values()) {
|
|
||||||
p.close();
|
|
||||||
}
|
|
||||||
for (TestPipeline pipeline : this.pipelines.values()) {
|
|
||||||
pipeline.closePipeline();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void newParticipant(String name, String playerUri, boolean autoMedia, boolean loopMedia) {
|
|
||||||
newParticipant(name, playerUri, autoMedia, loopMedia, defaultKurento);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void newParticipant(String name, String playerUri, boolean autoMedia, boolean loopMedia,
|
|
||||||
KurentoClient kurento) {
|
|
||||||
TestPipeline pipeline = getOrCreatePipeline(kurento);
|
|
||||||
pipeline.createPipeline();
|
|
||||||
FakeParticipant participant = new FakeParticipant(serviceUrl, name, room, playerUri,
|
|
||||||
pipeline.getPipeline(), autoMedia, loopMedia);
|
|
||||||
participants.put(name, participant);
|
|
||||||
participant.joinRoom();
|
|
||||||
}
|
|
||||||
|
|
||||||
public FakeParticipant getParticipant(String name) {
|
|
||||||
return participants.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void waitForActiveLive(CountDownLatch waitForLatch) {
|
|
||||||
for (FakeParticipant p : participants.values()) {
|
|
||||||
p.waitForActiveLive(waitForLatch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private TestPipeline getOrCreatePipeline(KurentoClient kurento) {
|
|
||||||
TestPipeline pipeline = this.pipelines.get(kurento);
|
|
||||||
if (pipeline == null) {
|
|
||||||
String desc = kurento.getServerManager().getId();
|
|
||||||
pipeline = this.pipelines.putIfAbsent(kurento, new TestPipeline(kurento, room, desc));
|
|
||||||
if (pipeline != null) {
|
|
||||||
log.debug("Pipeline already created for room '{}' and kurento '{}'", room, desc);
|
|
||||||
}
|
|
||||||
pipeline = this.pipelines.get(kurento);
|
|
||||||
}
|
|
||||||
return pipeline;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,107 +0,0 @@
|
||||||
/*
|
|
||||||
* (C) Copyright 2017-2020 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.fake.util;
|
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.kurento.client.ErrorEvent;
|
|
||||||
import org.kurento.client.EventListener;
|
|
||||||
import org.kurento.client.KurentoClient;
|
|
||||||
import org.kurento.client.MediaPipeline;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps a pipeline used to execute fake participants in a test session (room).
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
|
||||||
*/
|
|
||||||
public class TestPipeline {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(TestPipeline.class);
|
|
||||||
|
|
||||||
private KurentoClient kurento;
|
|
||||||
private MediaPipeline pipeline;
|
|
||||||
private CountDownLatch pipelineLatch = new CountDownLatch(1);
|
|
||||||
private Object pipelineCreateLock = new Object();
|
|
||||||
private Object pipelineReleaseLock = new Object();
|
|
||||||
private volatile boolean pipelineReleased = false;
|
|
||||||
private String description = "default";
|
|
||||||
private String room = "room";
|
|
||||||
|
|
||||||
public TestPipeline(KurentoClient kurento, String room, String pipeDescription) {
|
|
||||||
this.kurento = kurento;
|
|
||||||
if (room != null) {
|
|
||||||
this.room = room;
|
|
||||||
}
|
|
||||||
if (pipeDescription != null) {
|
|
||||||
this.description = pipeDescription;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public TestPipeline(KurentoClient kurento, String room) {
|
|
||||||
this(kurento, room, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MediaPipeline getPipeline() {
|
|
||||||
try {
|
|
||||||
pipelineLatch.await(60, TimeUnit.SECONDS);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return this.pipeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void createPipeline() {
|
|
||||||
synchronized (pipelineCreateLock) {
|
|
||||||
if (pipeline != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
log.info("Session '{}': Creating MediaPipeline-{}", room, description);
|
|
||||||
try {
|
|
||||||
pipeline = kurento.createMediaPipeline();
|
|
||||||
pipelineLatch.countDown();
|
|
||||||
log.debug("Session '{}': Created MediaPipeline-{}", room, description);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Unable to create MediaPipeline-{} for Session '{}'", description, room, e);
|
|
||||||
pipelineLatch.countDown();
|
|
||||||
}
|
|
||||||
if (getPipeline() == null) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"Unable to create MediaPipeline-" + description + " for session '" + room + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
pipeline.addErrorListener(new EventListener<ErrorEvent>() {
|
|
||||||
@Override
|
|
||||||
public void onEvent(ErrorEvent event) {
|
|
||||||
String desc = event.getType() + ": " + event.getDescription() + "(errCode="
|
|
||||||
+ event.getErrorCode() + ")";
|
|
||||||
log.warn("Session '{}': Pipeline error encountered for MediaPipeline-{}: {}", room,
|
|
||||||
description, desc);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void closePipeline() {
|
|
||||||
synchronized (pipelineReleaseLock) {
|
|
||||||
if (pipeline == null || pipelineReleased) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
getPipeline().release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
6
pom.xml
6
pom.xml
|
@ -63,7 +63,6 @@
|
||||||
|
|
||||||
<version.openvidu.java.client>2.12.1</version.openvidu.java.client>
|
<version.openvidu.java.client>2.12.1</version.openvidu.java.client>
|
||||||
<version.openvidu.client>1.1.0</version.openvidu.client>
|
<version.openvidu.client>1.1.0</version.openvidu.client>
|
||||||
<version.openvidu.test>1.1.0</version.openvidu.test>
|
|
||||||
<version.openvidu.test.browsers>1.1.0</version.openvidu.test.browsers>
|
<version.openvidu.test.browsers>1.1.0</version.openvidu.test.browsers>
|
||||||
|
|
||||||
<version.enforcer.plugin>3.0.0-M3</version.enforcer.plugin>
|
<version.enforcer.plugin>3.0.0-M3</version.enforcer.plugin>
|
||||||
|
@ -219,7 +218,6 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module>openvidu-server</module>
|
<module>openvidu-server</module>
|
||||||
<module>openvidu-client</module>
|
<module>openvidu-client</module>
|
||||||
<module>openvidu-test</module>
|
|
||||||
<module>openvidu-test-e2e</module>
|
<module>openvidu-test-e2e</module>
|
||||||
<module>openvidu-test-browsers</module>
|
<module>openvidu-test-browsers</module>
|
||||||
<module>openvidu-java-client</module>
|
<module>openvidu-java-client</module>
|
||||||
|
@ -288,10 +286,6 @@
|
||||||
<groupId>io.openvidu</groupId>
|
<groupId>io.openvidu</groupId>
|
||||||
<artifactId>openvidu-client</artifactId>
|
<artifactId>openvidu-client</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>io.openvidu</groupId>
|
|
||||||
<artifactId>openvidu-test</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.openvidu</groupId>
|
<groupId>io.openvidu</groupId>
|
||||||
<artifactId>openvidu-test-e2e</artifactId>
|
<artifactId>openvidu-test-e2e</artifactId>
|
||||||
|
|
Loading…
Reference in New Issue