summaryrefslogtreecommitdiff
path: root/ravenwood/junit-src
diff options
context:
space:
mode:
author Makoto Onuki <omakoto@google.com> 2025-02-21 14:13:40 -0800
committer Makoto Onuki <omakoto@google.com> 2025-02-24 12:54:47 -0800
commitc8dac37e3e93fc73df332e1723888344655fe413 (patch)
tree06185ec61e481981f9921a4ad3710246f0929e5a /ravenwood/junit-src
parentca8ecbebc7e95f3dfec071fc68f43f0d388f7b7c (diff)
Multiple improvements
- Sysprops allowlist now fully moved to the text file. - Always enable the test timeout w/ improved stack traces - Add a method to "run on main thread" - Always enable the uncaught exception handler. - Tolerate assertion failures on the main looper. (rather than letting it crash the thread) - Also some other minor changes needed in my main work. Flag: EXEMPT host test change only Bug: 292141694 Test: $ANDROID_BUILD_TOP/frameworks/base/ravenwood/scripts/run-ravenwood-tests.sh Change-Id: I47b060021ce46b6e9fbe4aca63835745311a4b06
Diffstat (limited to 'ravenwood/junit-src')
-rw-r--r--ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodUtils.java138
1 files changed, 138 insertions, 0 deletions
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodUtils.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodUtils.java
index 19c1bffaebcd..3e2c4051b792 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodUtils.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodUtils.java
@@ -15,7 +15,20 @@
*/
package android.platform.test.ravenwood;
+import static com.android.ravenwood.common.RavenwoodCommonUtils.ReflectedMethod.reflectMethod;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Handler;
+import android.os.Looper;
+
import com.android.ravenwood.common.RavenwoodCommonUtils;
+import com.android.ravenwood.common.SneakyThrow;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
/**
* Utilities for writing (bivalent) ravenwood tests.
@@ -47,4 +60,129 @@ public class RavenwoodUtils {
public static void loadJniLibrary(String libname) {
RavenwoodCommonUtils.loadJniLibrary(libname);
}
+
+ private class MainHandlerHolder {
+ static Handler sMainHandler = new Handler(Looper.getMainLooper());
+ }
+
+ /**
+ * Returns the main thread handler.
+ */
+ public static Handler getMainHandler() {
+ return MainHandlerHolder.sMainHandler;
+ }
+
+ /**
+ * Run a Callable on Handler and wait for it to complete.
+ */
+ @Nullable
+ public static <T> T runOnHandlerSync(@NonNull Handler h, @NonNull Callable<T> c) {
+ var result = new AtomicReference<T>();
+ var thrown = new AtomicReference<Throwable>();
+ var latch = new CountDownLatch(1);
+ h.post(() -> {
+ try {
+ result.set(c.call());
+ } catch (Throwable th) {
+ thrown.set(th);
+ }
+ latch.countDown();
+ });
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while waiting on the Runnable", e);
+ }
+ var th = thrown.get();
+ if (th != null) {
+ SneakyThrow.sneakyThrow(th);
+ }
+ return result.get();
+ }
+
+
+ /**
+ * Run a Runnable on Handler and wait for it to complete.
+ */
+ @Nullable
+ public static void runOnHandlerSync(@NonNull Handler h, @NonNull Runnable r) {
+ runOnHandlerSync(h, () -> {
+ r.run();
+ return null;
+ });
+ }
+
+ /**
+ * Run a Callable on main thread and wait for it to complete.
+ */
+ @Nullable
+ public static <T> T runOnMainThreadSync(@NonNull Callable<T> c) {
+ return runOnHandlerSync(getMainHandler(), c);
+ }
+
+ /**
+ * Run a Runnable on main thread and wait for it to complete.
+ */
+ @Nullable
+ public static void runOnMainThreadSync(@NonNull Runnable r) {
+ runOnHandlerSync(getMainHandler(), r);
+ }
+
+ public static class MockitoHelper {
+ private MockitoHelper() {
+ }
+
+ /**
+ * Allow verifyZeroInteractions to work on ravenwood. It was replaced with a different
+ * method on. (Maybe we should do it in Ravenizer.)
+ */
+ public static void verifyZeroInteractions(Object... mocks) {
+ if (RavenwoodRule.isOnRavenwood()) {
+ // Mockito 4 or later
+ reflectMethod("org.mockito.Mockito", "verifyNoInteractions", Object[].class)
+ .callStatic(new Object[]{mocks});
+ } else {
+ // Mockito 2
+ reflectMethod("org.mockito.Mockito", "verifyZeroInteractions", Object[].class)
+ .callStatic(new Object[]{mocks});
+ }
+ }
+ }
+
+
+ /**
+ * Wrap the given {@link Supplier} to become memoized.
+ *
+ * The underlying {@link Supplier} will only be invoked once, and that result will be cached
+ * and returned for any future requests.
+ */
+ static <T> Supplier<T> memoize(ThrowingSupplier<T> supplier) {
+ return new Supplier<>() {
+ private T mInstance;
+
+ @Override
+ public T get() {
+ synchronized (this) {
+ if (mInstance == null) {
+ mInstance = create();
+ }
+ return mInstance;
+ }
+ }
+
+ private T create() {
+ try {
+ return supplier.get();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+
+ /** Used by {@link #memoize(ThrowingSupplier)} */
+ public interface ThrowingSupplier<T> {
+ /** */
+ T get() throws Exception;
+ }
}