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:
@ -72,7 +72,7 @@ public class LooperExecutor extends Thread implements Executor {
|
|||||||
handler.post(new Runnable() {
|
handler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Looper.myLooper().quit();
|
handler.getLooper().quit();
|
||||||
Log.d(TAG, "Looper thread finished.");
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user