Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(625)

Unified Diff: webrtc/examples/androidjunit/src/org/appspot/apprtc/TCPChannelClientTest.java

Issue 1963053002: Direct IP connect functionality for AppRTC Android demo. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Reorder field modifiers Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/examples/androidapp/src/org/appspot/apprtc/TCPChannelClient.java ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/examples/androidjunit/src/org/appspot/apprtc/TCPChannelClientTest.java
diff --git a/webrtc/examples/androidjunit/src/org/appspot/apprtc/TCPChannelClientTest.java b/webrtc/examples/androidjunit/src/org/appspot/apprtc/TCPChannelClientTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a734a071d17e47efa934e91eb47e706e95ef04ce
--- /dev/null
+++ b/webrtc/examples/androidjunit/src/org/appspot/apprtc/TCPChannelClientTest.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2016 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+package org.appspot.apprtc;
+
+import org.appspot.apprtc.util.LooperExecutor;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowLog;
+
+import java.util.ArrayDeque;
+import java.util.Queue;
+
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class TCPChannelClientTest {
+ private static final int PORT = 8888;
+ /**
+ * How long we wait before trying to connect to the server. Chosen quite arbitrarily and
+ * could be made smaller if need be.
+ */
+ private static final int SERVER_WAIT = 10;
+ private static final int CONNECT_TIMEOUT = 100;
+ private static final int SEND_TIMEOUT = 100;
+ private static final int DISCONNECT_TIMEOUT = 100;
+ private static final String TEST_MESSAGE_SERVER = "Hello, Server!";
+ private static final String TEST_MESSAGE_CLIENT = "Hello, Client!";
+
+ @Mock TCPChannelClient.TCPChannelEvents serverEvents;
+ @Mock TCPChannelClient.TCPChannelEvents clientEvents;
+
+ private final ExecutorThread executorThread = new ExecutorThread();
+ private final Queue<Runnable> executorQueue = new ArrayDeque<Runnable>();
magjed_webrtc 2016/05/17 12:54:37 If you make |executorQueue| a BlockingQueue instea
sakal 2016/05/17 13:46:26 Done.
+ @Mock LooperExecutor executor;
magjed_webrtc 2016/05/17 12:54:38 I don't really understand why you need to mock Loo
sakal 2016/05/17 13:46:26 Mocking LooperExecutor was a selection of multiple
+
+ private TCPChannelClient server;
+ private TCPChannelClient client;
+
+ /**
+ * Runs commands on executor queue until stopped with requestStop.
+ */
+ private class ExecutorThread extends Thread {
+ private volatile boolean shouldStop = false;
+
+ @Override
+ public void run() {
+ while (true) {
magjed_webrtc 2016/05/17 12:54:38 while (!shouldStop) ?
sakal 2016/05/17 13:46:26 Done.
+ Runnable runnable;
magjed_webrtc 2016/05/17 12:54:37 nit: Make |runnable| final.
sakal 2016/05/17 13:46:26 Done.
+
+ synchronized (executorQueue) {
+ while (executorQueue.isEmpty()) {
+ try {
+ executorQueue.wait();
+ } catch (InterruptedException e) {
+ if (!shouldStop) {
+ fail(e.getMessage());
+ }
+ }
+
+ if (shouldStop) {
+ return;
+ }
+ }
+
+ runnable = executorQueue.remove();
+ }
+
+ runnable.run();
+ }
+ }
+
+ public void requestStop() {
+ shouldStop = true;
+ interrupt();
+ }
+ }
+
+
+ /**
+ * Executes the runnable passed to the constructor and sets isDone flag afterwards.
+ */
+ private static class ExecuteAndWaitRunnable implements Runnable {
+ public boolean isDone = false;
+ private Runnable runnable;
magjed_webrtc 2016/05/17 12:54:38 nit: Make |runnable| final.
sakal 2016/05/17 13:46:26 Done.
+
+ ExecuteAndWaitRunnable(Runnable runnable) {
+ this.runnable = runnable;
+ }
+
+ @Override
+ public void run() {
+ runnable.run();
+
+ synchronized (this) {
+ isDone = true;
+ notifyAll();
+ }
+ }
+ }
+
+ @Before
+ public void setUp() {
+ ShadowLog.stream = System.out;
+
+ MockitoAnnotations.initMocks(this);
+
+ Answer queueRunnableAnswer = new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ Runnable runnable = invocation.getArgumentAt(0, Runnable.class);
+
+ synchronized (executorQueue) {
+ executorQueue.add(runnable);
+ executorQueue.notify();
+ }
+
+ return null;
+ }
+ };
+ doAnswer(queueRunnableAnswer).when(executor).execute(any(Runnable.class));
+ when(executor.checkOnLooperThread()).thenAnswer(new Answer<Boolean>() {
+ @Override
+ public Boolean answer(InvocationOnMock invocation) throws Throwable {
+ return Thread.currentThread() == executorThread;
+ }
+ });
+
+ executorThread.start();
+ }
+
+ @After
+ public void tearDown() {
+ verifyNoMoreEvents();
+
+ executeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ client.disconnect();
+ server.disconnect();
+ }
+ });
+
+ // Stop the executor thread
+ executorThread.requestStop();
+ executor.requestStop();
+ try {
+ executorThread.join();
+ executor.join();
+ } catch (InterruptedException e) {
+ fail(e.getMessage());
+ }
+ executorQueue.clear();
+ }
+
+ @Test
+ public void testConnectIPv4() {
+ setUpIPv4Server();
+ try {
+ Thread.sleep(SERVER_WAIT);
+ } catch (InterruptedException e) {
+ fail(e.getMessage());
+ }
+ setUpIPv4Client();
+
+ verify(serverEvents, timeout(CONNECT_TIMEOUT)).onTCPConnected(true);
+ verify(clientEvents, timeout(CONNECT_TIMEOUT)).onTCPConnected(false);
+ }
+
+ @Test
+ public void testConnectIPv6() {
+ setUpIPv6Server();
+ try {
+ Thread.sleep(SERVER_WAIT);
+ } catch (InterruptedException e) {
+ fail(e.getMessage());
+ }
+ setUpIPv6Client();
+
+ verify(serverEvents, timeout(CONNECT_TIMEOUT)).onTCPConnected(true);
+ verify(clientEvents, timeout(CONNECT_TIMEOUT)).onTCPConnected(false);
+ }
+
+ @Test
+ public void testSendData() {
+ testConnectIPv4();
+
+ executeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ client.send(TEST_MESSAGE_SERVER);
+ server.send(TEST_MESSAGE_CLIENT);
+ }
+ });
+
+ verify(serverEvents, timeout(SEND_TIMEOUT)).onTCPMessage(TEST_MESSAGE_SERVER);
+ verify(clientEvents, timeout(SEND_TIMEOUT)).onTCPMessage(TEST_MESSAGE_CLIENT);
+ }
+
+ @Test
+ public void testDisconnectServer() {
+ testConnectIPv4();
+ executeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ server.disconnect();
+ }
+ });
+
+ verify(serverEvents, timeout(DISCONNECT_TIMEOUT)).onTCPClose();
+ verify(clientEvents, timeout(DISCONNECT_TIMEOUT)).onTCPClose();
+ }
+
+ @Test
+ public void testDisconnectClient() {
+ testConnectIPv4();
+ executeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ client.disconnect();
+ }
+ });
+
+ verify(serverEvents, timeout(DISCONNECT_TIMEOUT)).onTCPClose();
+ verify(clientEvents, timeout(DISCONNECT_TIMEOUT)).onTCPClose();
+ }
+
+ private void setUpIPv4Server() {
+ setUpServer("0.0.0.0", PORT);
+ }
+
+ private void setUpIPv4Client() {
+ setUpClient("127.0.0.1", PORT);
+ }
+
+ private void setUpIPv6Server() {
+ setUpServer("::", PORT);
+ }
+
+ private void setUpIPv6Client() {
+ setUpClient("::1", PORT);
+ }
+
+ private void setUpServer(String ip, int port) {
+ server = new TCPChannelClient(executor, serverEvents, ip, port);
+ }
+
+ private void setUpClient(String ip, int port) {
+ client = new TCPChannelClient(executor, clientEvents, ip, port);
+ }
+
+ /**
+ * Queues runnable to be run and waits for it to be executed by the executor thread
+ */
+ private void executeAndWait(Runnable runnable) {
+ ExecuteAndWaitRunnable executeAndWaitRunnable = new ExecuteAndWaitRunnable(runnable);
+ executor.execute(executeAndWaitRunnable);
+ executor.requestStart();
+
+ synchronized (executeAndWaitRunnable) {
+ while (!executeAndWaitRunnable.isDone) {
+ try {
+ executeAndWaitRunnable.wait();
+ } catch (InterruptedException e) {
+ fail(e.getMessage());
+ }
+ }
+ }
+ }
+
+ /**
+ * Verifies no more server or client events have been issued
+ */
+ private void verifyNoMoreEvents() {
+ verifyNoMoreInteractions(serverEvents);
+ verifyNoMoreInteractions(clientEvents);
+ }
+}
« no previous file with comments | « webrtc/examples/androidapp/src/org/appspot/apprtc/TCPChannelClient.java ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698