1 package android.app; 2 3 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 4 import static com.google.common.truth.Truth.assertThat; 5 import static org.junit.Assert.assertThrows; 6 import static org.robolectric.annotation.LooperMode.Mode.PAUSED; 7 8 import android.os.Handler; 9 import android.os.Looper; 10 import androidx.test.ext.junit.runners.AndroidJUnit4; 11 import java.util.ArrayList; 12 import java.util.List; 13 import org.junit.Test; 14 import org.junit.runner.RunWith; 15 import org.robolectric.annotation.LooperMode; 16 import org.robolectric.annotation.internal.DoNotInstrument; 17 18 /** 19 * Tests to verify android.app.Instrumentation APIs behave consistently between Robolectric and 20 * device. 21 */ 22 @DoNotInstrument 23 @RunWith(AndroidJUnit4.class) 24 @LooperMode(PAUSED) 25 public final class InstrumentationTest { 26 27 /** 28 * Verify that runOnMainSync main looper synchronization is consistent between on device and 29 * robolectric. 30 */ 31 @Test runOnMainSync()32 public void runOnMainSync() { 33 final List<String> events = new ArrayList<>(); 34 Handler mainHandler = new Handler(Looper.getMainLooper()); 35 36 mainHandler.post(() -> events.add("before runOnMainSync")); 37 getInstrumentation() 38 .runOnMainSync( 39 new Runnable() { 40 @Override 41 public void run() { 42 events.add("in runOnMainSync"); 43 // as expected, on device tests become flaky and fail deterministically on 44 // Robolectric with this line, as runOnMainSync does not drain the main looper 45 // after runnable executes 46 // mainHandler.post(() -> events.add("post from runOnMainSync")); 47 } 48 }); 49 50 assertThat(events).containsExactly("before runOnMainSync", "in runOnMainSync").inOrder(); 51 } 52 53 @Test runOnMainSync_propagatesException()54 public void runOnMainSync_propagatesException() { 55 assertThrows( 56 IllegalStateException.class, 57 () -> 58 getInstrumentation() 59 .runOnMainSync( 60 () -> { 61 throw new IllegalStateException("test"); 62 })); 63 } 64 } 65