Add two unit tests for Android AppRTCDemo.
First unit test will create peer connection client, run for a few second, close it and verify that there were no any errors and local video was rendered. Second unit test will run peer connection in a loopback mode. To run the test from command line install AppRTCDemoTest.apk and execute the command: adb shell am instrument -w org.appspot.apprtc.test/android.test.InstrumentationTestRunner R=jiayl@webrtc.org Review URL: https://webrtc-codereview.appspot.com/33609004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7991 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2014, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.appspot.apprtc.test;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.appspot.apprtc.AppRTCClient.SignalingParameters;
|
||||
import org.appspot.apprtc.PeerConnectionClient;
|
||||
import org.appspot.apprtc.PeerConnectionClient.PeerConnectionEvents;
|
||||
import org.webrtc.IceCandidate;
|
||||
import org.webrtc.MediaConstraints;
|
||||
import org.webrtc.PeerConnection;
|
||||
import org.webrtc.PeerConnectionFactory;
|
||||
import org.webrtc.SessionDescription;
|
||||
import org.webrtc.VideoRenderer;
|
||||
|
||||
import android.test.InstrumentationTestCase;
|
||||
import android.util.Log;
|
||||
|
||||
public class PeerConnectionClientTest extends InstrumentationTestCase
|
||||
implements PeerConnectionEvents {
|
||||
private static final String TAG = "RTCClientTest";
|
||||
private static final String STUN_SERVER = "stun:stun.l.google.com:19302";
|
||||
private static final int WAIT_TIMEOUT = 3000;
|
||||
private static final int EXPECTED_VIDEO_FRAMES = 15;
|
||||
|
||||
private volatile PeerConnectionClient pcClient;
|
||||
private volatile boolean loopback;
|
||||
private boolean isClosed;
|
||||
private boolean isIceConnected;
|
||||
private SessionDescription localSdp;
|
||||
private List<IceCandidate> iceCandidates = new LinkedList<IceCandidate>();
|
||||
private final Object localSdpEvent = new Object();
|
||||
private final Object iceCandidateEvent = new Object();
|
||||
private final Object iceConnectedEvent = new Object();
|
||||
private final Object closeEvent = new Object();
|
||||
|
||||
// Mock renderer implementation.
|
||||
private static class MockRenderer implements VideoRenderer.Callbacks {
|
||||
private final CountDownLatch doneRendering;
|
||||
private int width = -1;
|
||||
private int height = -1;
|
||||
private int numFramesDelivered = 0;
|
||||
|
||||
public MockRenderer(int expectedFrames) {
|
||||
doneRendering = new CountDownLatch(expectedFrames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setSize(int width, int height) {
|
||||
Log.d(TAG, "Set size: " + width + " x " + height);
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void renderFrame(VideoRenderer.I420Frame frame) {
|
||||
// Check that video dimensions have been set.
|
||||
if (numFramesDelivered == 0) {
|
||||
assertTrue("Video dimensions were not set.", width > 0 && height > 0);
|
||||
}
|
||||
numFramesDelivered++;
|
||||
doneRendering.countDown();
|
||||
}
|
||||
|
||||
public boolean waitForFramesRendered(int timeoutMs)
|
||||
throws InterruptedException {
|
||||
doneRendering.await(timeoutMs, TimeUnit.MILLISECONDS);
|
||||
return (doneRendering.getCount() <= 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Peer connection events implementation.
|
||||
@Override
|
||||
public void onLocalDescription(SessionDescription sdp) {
|
||||
Log.d(TAG, "LocalSDP type: " + sdp.type);
|
||||
synchronized (localSdpEvent) {
|
||||
localSdp = sdp;
|
||||
localSdpEvent.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIceCandidate(IceCandidate candidate) {
|
||||
Log.d(TAG, "IceCandidate: " + candidate.sdp);
|
||||
synchronized(iceCandidateEvent) {
|
||||
if (loopback) {
|
||||
pcClient.addRemoteIceCandidate(candidate);
|
||||
}
|
||||
iceCandidates.add(candidate);
|
||||
iceCandidateEvent.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIceConnected() {
|
||||
Log.d(TAG, "ICE Connected");
|
||||
synchronized(iceConnectedEvent) {
|
||||
isIceConnected = true;
|
||||
iceConnectedEvent.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIceDisconnected() {
|
||||
Log.d(TAG, "ICE Disconnected");
|
||||
synchronized(iceConnectedEvent) {
|
||||
isIceConnected = false;
|
||||
iceConnectedEvent.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPeerConnectionClosed() {
|
||||
Log.d(TAG, "PeerConnection closed");
|
||||
synchronized(closeEvent) {
|
||||
isClosed = true;
|
||||
closeEvent.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPeerConnectionError(String description) {
|
||||
fail("PC Error: " + description);
|
||||
}
|
||||
|
||||
// Helper wait functions.
|
||||
private boolean waitForLocalSDP(int timeoutMs)
|
||||
throws InterruptedException {
|
||||
synchronized(localSdpEvent) {
|
||||
if (localSdp == null) {
|
||||
localSdpEvent.wait(timeoutMs);
|
||||
}
|
||||
return (localSdp != null);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean waitForIceCandidates(int timeoutMs)
|
||||
throws InterruptedException {
|
||||
synchronized(iceCandidateEvent) {
|
||||
if (iceCandidates.size() == 0) {
|
||||
iceCandidateEvent.wait(timeoutMs);
|
||||
}
|
||||
return (iceCandidates.size() > 0);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean waitForIceConnected(int timeoutMs)
|
||||
throws InterruptedException {
|
||||
synchronized(iceConnectedEvent) {
|
||||
if (!isIceConnected) {
|
||||
iceConnectedEvent.wait(timeoutMs);
|
||||
}
|
||||
return isIceConnected;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean waitForPeerConnectionClosed(int timeoutMs)
|
||||
throws InterruptedException {
|
||||
synchronized(closeEvent) {
|
||||
if (!isClosed) {
|
||||
closeEvent.wait(timeoutMs);
|
||||
}
|
||||
return isClosed;
|
||||
}
|
||||
}
|
||||
|
||||
private SignalingParameters getTestSignalingParameters() {
|
||||
List<PeerConnection.IceServer> iceServers =
|
||||
new LinkedList<PeerConnection.IceServer>();
|
||||
PeerConnection.IceServer iceServer = new
|
||||
PeerConnection.IceServer(STUN_SERVER, "", "");
|
||||
iceServers.add(iceServer);
|
||||
MediaConstraints pcConstraints = new MediaConstraints();
|
||||
MediaConstraints videoConstraints = new MediaConstraints();
|
||||
MediaConstraints audioConstraints = new MediaConstraints();
|
||||
SignalingParameters signalingParameters = new SignalingParameters(
|
||||
iceServers, true,
|
||||
pcConstraints, videoConstraints, audioConstraints,
|
||||
null, null, null,
|
||||
null, null,
|
||||
null, null);
|
||||
return signalingParameters;
|
||||
}
|
||||
|
||||
// Unit tests.
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
Log.d(TAG, "setUp");
|
||||
super.setUp();
|
||||
pcClient = null;
|
||||
localSdp = null;
|
||||
iceCandidates.clear();
|
||||
isClosed = false;
|
||||
isIceConnected = false;
|
||||
loopback = false;
|
||||
Log.d(TAG, "initializeAndroidGlobals");
|
||||
assertTrue(PeerConnectionFactory.initializeAndroidGlobals(
|
||||
getInstrumentation().getContext(), true, true, true, null));
|
||||
}
|
||||
|
||||
public void testInitiatorCreation() throws InterruptedException {
|
||||
Log.d(TAG, "testInitiatorCreation");
|
||||
MockRenderer localRender = new MockRenderer(EXPECTED_VIDEO_FRAMES);
|
||||
MockRenderer remoteRender = new MockRenderer(EXPECTED_VIDEO_FRAMES);
|
||||
SignalingParameters signalingParameters = getTestSignalingParameters();
|
||||
|
||||
pcClient = new PeerConnectionClient(
|
||||
localRender, remoteRender, signalingParameters, this, 1000);
|
||||
pcClient.createOffer();
|
||||
|
||||
// Wait for local SDP and ice candidates set events.
|
||||
assertTrue("Local SDP was not set.", waitForLocalSDP(WAIT_TIMEOUT));
|
||||
assertTrue("ICE candidates were not generated.",
|
||||
waitForIceCandidates(WAIT_TIMEOUT));
|
||||
|
||||
// Check that local video frames were rendered.
|
||||
assertTrue("Local video frames were not rendered.",
|
||||
localRender.waitForFramesRendered(WAIT_TIMEOUT));
|
||||
|
||||
pcClient.close();
|
||||
assertTrue("PeerConnection close event was not received.",
|
||||
waitForPeerConnectionClosed(WAIT_TIMEOUT));
|
||||
Log.d(TAG, "testInitiatorCreation Done.");
|
||||
}
|
||||
|
||||
public void testLoopback() throws InterruptedException {
|
||||
Log.d(TAG, "testLoopback");
|
||||
MockRenderer localRender = new MockRenderer(EXPECTED_VIDEO_FRAMES);
|
||||
MockRenderer remoteRender = new MockRenderer(EXPECTED_VIDEO_FRAMES);
|
||||
SignalingParameters signalingParameters = getTestSignalingParameters();
|
||||
loopback = true;
|
||||
pcClient = new PeerConnectionClient(
|
||||
localRender, remoteRender, signalingParameters, this, 1000);
|
||||
pcClient.createOffer();
|
||||
|
||||
// Wait for local SDP, rename it to answer and set as remote SDP.
|
||||
assertTrue("Local SDP was not set.", waitForLocalSDP(WAIT_TIMEOUT));
|
||||
SessionDescription remoteSdp = new SessionDescription(
|
||||
SessionDescription.Type.fromCanonicalForm("answer"),
|
||||
localSdp.description);
|
||||
pcClient.setRemoteDescription(remoteSdp);
|
||||
|
||||
// Wait for ICE connection.
|
||||
assertTrue("ICE connection failure.", waitForIceConnected(WAIT_TIMEOUT));
|
||||
|
||||
// Check that local video frames were rendered.
|
||||
assertTrue("Local video frames were not rendered.",
|
||||
localRender.waitForFramesRendered(WAIT_TIMEOUT));
|
||||
|
||||
// Check that remote video frames were rendered.
|
||||
assertTrue("Remote video frames were not rendered.",
|
||||
remoteRender.waitForFramesRendered(WAIT_TIMEOUT));
|
||||
|
||||
pcClient.close();
|
||||
assertTrue(waitForPeerConnectionClosed(WAIT_TIMEOUT));
|
||||
Log.d(TAG, "testLoopback Done.");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user