| /* | |
| * 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 static org.junit.Assert.fail; | |
| import static org.mockito.Mockito.timeout; | |
| import static org.mockito.Mockito.verify; | |
| import static org.mockito.Mockito.verifyNoMoreInteractions; | |
| import android.os.Build; | |
| import org.junit.After; | |
| import org.junit.Before; | |
| import org.junit.Ignore; | |
| import org.junit.Test; | |
| import org.junit.runner.RunWith; | |
| import org.mockito.Mock; | |
| import org.mockito.MockitoAnnotations; | |
| import org.robolectric.annotation.Config; | |
| import org.robolectric.shadows.ShadowLog; | |
| import org.robolectric.RobolectricTestRunner; | |
| import java.util.concurrent.ExecutorService; | |
| import java.util.concurrent.Executors; | |
| import java.util.concurrent.TimeUnit; | |
| @RunWith(RobolectricTestRunner.class) | |
| @Config(manifest = Config.NONE) | |
| public class TCPChannelClientTest { | |
| private static final int PORT = 9000 + Build.VERSION.SDK_INT; | |
| /** | |
| * How long we wait before trying to connect to the server. Note: was | |
| * previously only 10, which was too short (tests were flaky). | |
| */ | |
| private static final int SERVER_WAIT = 300; | |
| private static final int CONNECT_TIMEOUT = 1000; | |
| private static final int SEND_TIMEOUT = 1000; | |
| private static final int DISCONNECT_TIMEOUT = 1000; | |
| private static final int TERMINATION_TIMEOUT = 1000; | |
| 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 ExecutorService executor; | |
| private TCPChannelClient server; | |
| private TCPChannelClient client; | |
| @Before | |
| public void setUp() { | |
| ShadowLog.stream = System.out; | |
| MockitoAnnotations.initMocks(this); | |
| executor = Executors.newSingleThreadExecutor(); | |
| } | |
| @After | |
| public void tearDown() { | |
| verifyNoMoreEvents(); | |
| executeAndWait(new Runnable() { | |
| @Override | |
| public void run() { | |
| client.disconnect(); | |
| server.disconnect(); | |
| } | |
| }); | |
| // Stop the executor thread | |
| executor.shutdown(); | |
| try { | |
| executor.awaitTermination(TERMINATION_TIMEOUT, TimeUnit.MILLISECONDS); | |
| } catch (InterruptedException e) { | |
| fail(e.getMessage()); | |
| } | |
| } | |
| private void connectIPv4Helper() { | |
| 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 testConnectIPv4() { | |
| connectIPv4Helper(); | |
| } | |
| // TODO:b/389829614 - Below test is failing. | |
| @Test | |
| @Ignore | |
| 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() { | |
| connectIPv4Helper(); | |
| 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() { | |
| connectIPv4Helper(); | |
| 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() { | |
| connectIPv4Helper(); | |
| 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); | |
| } | |
| /** | |
| * Verifies no more server or client events have been issued | |
| */ | |
| private void verifyNoMoreEvents() { | |
| verifyNoMoreInteractions(serverEvents); | |
| verifyNoMoreInteractions(clientEvents); | |
| } | |
| /** | |
| * Queues runnable to be run and waits for it to be executed by the executor thread | |
| */ | |
| public void executeAndWait(Runnable runnable) { | |
| try { | |
| executor.submit(runnable).get(); | |
| } catch (Exception e) { | |
| fail(e.getMessage()); | |
| } | |
| } | |
| } |