Merge "New helpers: AndroidMockitoHelper.[run|call]On[Main|Ui]Thread()" into sc-dev
diff --git a/car-test-lib/src/android/car/test/mocks/AndroidMockitoHelper.java b/car-test-lib/src/android/car/test/mocks/AndroidMockitoHelper.java
index 150ab73..deb3946 100644
--- a/car-test-lib/src/android/car/test/mocks/AndroidMockitoHelper.java
+++ b/car-test-lib/src/android/car/test/mocks/AndroidMockitoHelper.java
@@ -17,12 +17,15 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.google.common.truth.Truth.assertWithMessage;
+
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.Activity;
import android.app.ActivityManager;
import android.car.test.util.UserTestingHelper;
import android.car.test.util.UserTestingHelper.UserInfoBuilder;
@@ -32,8 +35,10 @@
import android.content.pm.UserInfo;
import android.content.pm.UserInfo.UserInfoFlag;
import android.os.Binder;
+import android.os.Handler;
import android.os.IBinder;
import android.os.IInterface;
+import android.os.Looper;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
@@ -42,6 +47,9 @@
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicReference;
/**
* Provides common Mockito calls for core Android classes.
@@ -247,6 +255,81 @@
}
}
+ // TODO(b/192307581): add unit tests
+ /**
+ * Returns the result of the giving {@code callable} in the main thread, preparing the
+ * {@link Looper} if needed and using a default timeout.
+ */
+ public static <T> T syncCallOnMainThread(Callable<T> c) throws Exception {
+ return syncCallOnMainThread(JavaMockitoHelper.ASYNC_TIMEOUT_MS, c);
+ }
+
+ // TODO(b/192307581): add unit tests
+ /**
+ * Returns the result of the giving {@code callable} in the main thread, preparing the
+ * {@link Looper} if needed.
+ */
+ public static <T> T syncCallOnMainThread(long timeoutMs, Callable<T> callable)
+ throws Exception {
+ boolean quitLooper = false;
+ Looper looper = Looper.getMainLooper();
+ if (looper == null) {
+ Log.i(TAG, "preparing main looper");
+ Looper.prepareMainLooper();
+ looper = Looper.getMainLooper();
+ assertWithMessage("Looper.getMainLooper()").that(looper).isNotNull();
+ quitLooper = true;
+ }
+ Log.i(TAG, "looper: " + looper);
+ AtomicReference<Exception> exception = new AtomicReference<>();
+ AtomicReference<T> ref = new AtomicReference<>();
+ try {
+ Handler handler = new Handler(looper);
+ CountDownLatch latch = new CountDownLatch(1);
+ handler.post(() -> {
+ T result = null;
+ try {
+ result = callable.call();
+ } catch (Exception e) {
+ exception.set(e);
+ }
+ ref.set(result);
+ latch.countDown();
+ });
+ JavaMockitoHelper.await(latch, timeoutMs);
+ Exception e = exception.get();
+ if (e != null) throw e;
+ return ref.get();
+ } finally {
+ if (quitLooper) {
+ Log.i(TAG, "quitting looper: " + looper);
+ looper.quitSafely();
+ }
+ }
+ }
+
+ // TODO(b/192307581): add unit tests
+ /**
+ * Runs the giving {@code runnable} in the activity's UI thread, using a default timeout.
+ */
+ public static void syncRunOnUiThread(Activity activity, Runnable runnable) throws Exception {
+ syncRunOnUiThread(JavaMockitoHelper.ASYNC_TIMEOUT_MS, activity, runnable);
+ }
+
+ // TODO(b/192307581): add unit tests
+ /**
+ * Runs the giving {@code runnable} in the activity's UI thread.
+ */
+ public static void syncRunOnUiThread(long timeoutMs, Activity activity, Runnable runnable)
+ throws Exception {
+ CountDownLatch latch = new CountDownLatch(1);
+ activity.runOnUiThread(() -> {
+ runnable.run();
+ latch.countDown();
+ });
+ JavaMockitoHelper.await(latch, timeoutMs);
+ }
+
private AndroidMockitoHelper() {
throw new UnsupportedOperationException("contains only static methods");
}
diff --git a/car-test-lib/src/android/car/test/mocks/JavaMockitoHelper.java b/car-test-lib/src/android/car/test/mocks/JavaMockitoHelper.java
index 9430723..57d39a5 100644
--- a/car-test-lib/src/android/car/test/mocks/JavaMockitoHelper.java
+++ b/car-test-lib/src/android/car/test/mocks/JavaMockitoHelper.java
@@ -30,7 +30,7 @@
*/
public final class JavaMockitoHelper {
- private static final long ASYNC_TIMEOUT_MS = 500;
+ static final long ASYNC_TIMEOUT_MS = 500;
private static final String TAG = JavaMockitoHelper.class.getSimpleName();
diff --git a/tests/carservice_unit_test/src/com/android/car/admin/NewUserDisclaimerActivityTest.java b/tests/carservice_unit_test/src/com/android/car/admin/NewUserDisclaimerActivityTest.java
index b1e8b72..626b5c0 100644
--- a/tests/carservice_unit_test/src/com/android/car/admin/NewUserDisclaimerActivityTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/admin/NewUserDisclaimerActivityTest.java
@@ -36,6 +36,7 @@
import android.app.PendingIntent;
import android.app.UiAutomation;
import android.car.test.mocks.AbstractExtendedMockitoTestCase;
+import android.car.test.mocks.AndroidMockitoHelper;
import android.car.test.mocks.JavaMockitoHelper;
import android.content.Context;
import android.content.Intent;
@@ -111,15 +112,12 @@
@Test
public void testAccept() throws Exception {
- CountDownLatch latch = new CountDownLatch(1);
- mActivity.runOnUiThread(() -> {
+ AndroidMockitoHelper.syncRunOnUiThread(mActivity, () -> {
mActivity.onCreate(/* savedInstanceState= */ null);
Button button = mActivity.getAcceptButton();
Log.d(TAG, "Clicking accept button: " + button);
button.performClick();
- latch.countDown();
});
- JavaMockitoHelper.await(latch, TIMEOUT_MS);
verify(mService).setAcknowledged();
assertWithMessage("activity is finishing").that(mActivity.isFinishing()).isTrue();