/* * 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 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.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 = 8888; /** * 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()); } } @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); } /** * 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()); } } }