Convert LooperExecutorTest in AppRTC Demo into JUnit test

LooperExecutorTest now uses Robolectric instead of being instrumentation
test. This allows the test to be run faster and easier.

Review-Url: https://codereview.webrtc.org/1989813002
Cr-Commit-Position: refs/heads/master@{#12825}
This commit is contained in:
sakal
2016-05-20 03:56:49 -07:00
committed by Commit bot
parent 2d285ca150
commit f8312cb45a
3 changed files with 129 additions and 70 deletions

View File

@ -72,7 +72,7 @@ public class LooperExecutor extends Thread implements Executor {
handler.post(new Runnable() {
@Override
public void run() {
Looper.myLooper().quit();
handler.getLooper().quit();
Log.d(TAG, "Looper thread finished.");
}
});
@ -131,4 +131,10 @@ public class LooperExecutor extends Thread implements Executor {
}
}
/**
* Access to the handler for testing purposes.
*/
Handler getHandler() {
return handler;
}
}

View File

@ -0,0 +1,122 @@
/*
* 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.util;
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.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowLooper;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.robolectric.Robolectric.shadowOf;
@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class LooperExecutorTest {
private final static int RUN_TIMES = 10;
@Mock private Runnable mockRunnable;
private LooperExecutor executor;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
executor = new LooperExecutor();
}
@After
public void tearDown() {
executor.requestStop();
executePendingRunnables();
}
@Test
public void testExecute() {
executor.requestStart();
for (int i = 0; i < RUN_TIMES; i++) {
executor.execute(mockRunnable);
}
verifyNoMoreInteractions(mockRunnable);
executePendingRunnables();
verify(mockRunnable, times(RUN_TIMES)).run();
}
/**
* Test that runnables executed before requestStart are ignored.
*/
@Test
public void testExecuteBeforeStart() {
executor.execute(mockRunnable);
executor.requestStart();
executePendingRunnables();
verifyNoMoreInteractions(mockRunnable);
}
/**
* Test that runnables executed after requestStop are not executed.
*/
@Test
public void testExecuteAfterStop() {
executor.requestStart();
executor.requestStop();
executor.execute(mockRunnable);
executePendingRunnables();
verifyNoMoreInteractions(mockRunnable);
}
/**
* Test multiple requestStart calls are just ignored.
*/
@Test
public void testMultipleStarts() {
executor.requestStart();
testExecute();
}
/**
* Test multiple requestStop calls are just ignored.
*/
@Test
public void testMultipleStops() {
executor.requestStart();
executor.requestStop();
executor.requestStop();
executePendingRunnables();
}
/**
* Calls ShadowLooper's idle method in order to execute pending runnables.
*/
private void executePendingRunnables() {
ShadowLooper shadowLooper = getShadowLooper();
shadowLooper.idle();
}
/**
* Get ShadowLooper of the executor thread.
*/
private ShadowLooper getShadowLooper() {
return shadowOf(executor.getHandler().getLooper());
}
}

View File

@ -1,69 +0,0 @@
/*
* Copyright 2015 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.test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.appspot.apprtc.util.LooperExecutor;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
public class LooperExecutorTest extends InstrumentationTestCase {
private static final String TAG = "LooperTest";
private static final int WAIT_TIMEOUT = 5000;
@SmallTest
public void testLooperExecutor() throws InterruptedException {
Log.d(TAG, "testLooperExecutor");
final int counter[] = new int[1];
final int expectedCounter = 10;
final CountDownLatch looperDone = new CountDownLatch(1);
Runnable counterIncRunnable = new Runnable() {
@Override
public void run() {
counter[0]++;
Log.d(TAG, "Run " + counter[0]);
}
};
LooperExecutor executor = new LooperExecutor();
// Try to execute a counter increment task before starting an executor.
executor.execute(counterIncRunnable);
// Start the executor and run expected amount of counter increment task.
executor.requestStart();
for (int i = 0; i < expectedCounter; i++) {
executor.execute(counterIncRunnable);
}
executor.execute(new Runnable() {
@Override
public void run() {
looperDone.countDown();
}
});
executor.requestStop();
// Try to execute a task after stopping the executor.
executor.execute(counterIncRunnable);
// Wait for final looper task and make sure the counter increment task
// is executed expected amount of times.
looperDone.await(WAIT_TIMEOUT, TimeUnit.MILLISECONDS);
assertTrue (looperDone.getCount() == 0);
assertTrue (counter[0] == expectedCounter);
Log.d(TAG, "testLooperExecutor done");
}
}