@@ -16,6 +16,7 @@ import java.io.FileOutputStream;
1616import java.io.FileWriter;
1717import java.io.IOException;
1818import java.io.PrintWriter;
19+ import java.util.concurrent.atomic.AtomicInteger;
1920import org.junit.Test;
2021import org.junit.runner.RunWith;
2122import org.robolectric.Robolectric;
@@ -24,6 +25,7 @@ import org.robolectric.android.controller.ActivityController;
2425import org.robolectric.annotation.Config;
2526import org.robolectric.annotation.LooperMode;
2627import org.robolectric.shadows.ShadowLooper;
28+ import org.robolectric.util.Scheduler;
2729
2830@RunWith(RobolectricTestRunner.class)
2931@Config(sdk = 30)
@@ -187,11 +189,58 @@ public class @MAIN_NAME@UiTest {
187189 appendLogLine(formatted);
188190 }
189191
192+ private static final AtomicInteger PUMP_INVOCATION_COUNTER = new AtomicInteger();
193+
190194 private static void pumpSchedulers() {
191- ShadowLooper.idleMainLooper();
192- ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
193- Robolectric.flushForegroundThreadScheduler();
194- Robolectric.flushBackgroundThreadScheduler();
195+ int invocation = PUMP_INVOCATION_COUNTER.incrementAndGet();
196+ long start = System.currentTimeMillis();
197+ boolean verbose = invocation <= 5 || invocation % 10 == 0;
198+ if (verbose) {
199+ log("pumpSchedulers[" + invocation + "] begin");
200+ }
201+ try {
202+ ShadowLooper.idleMainLooper();
203+ if (verbose) {
204+ log("pumpSchedulers[" + invocation + "] after idleMainLooper");
205+ }
206+ ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
207+ if (verbose) {
208+ log("pumpSchedulers[" + invocation + "] after runUiThreadTasksIncludingDelayedTasks");
209+ }
210+ flushScheduler(Robolectric.getForegroundThreadScheduler(), "foreground", invocation, verbose);
211+ flushScheduler(Robolectric.getBackgroundThreadScheduler(), "background", invocation, verbose);
212+ } catch (Throwable t) {
213+ log("pumpSchedulers[" + invocation + "] threw " + t);
214+ throw t;
215+ } finally {
216+ if (verbose) {
217+ long elapsed = System.currentTimeMillis() - start;
218+ log("pumpSchedulers[" + invocation + "] finished after " + elapsed + "ms");
219+ }
220+ }
221+ }
222+
223+ private static void flushScheduler(Scheduler scheduler, String label, int invocation, boolean verbose) {
224+ if (scheduler == null) {
225+ if (verbose) {
226+ log("pumpSchedulers[" + invocation + "] no " + label + " scheduler available");
227+ }
228+ return;
229+ }
230+ int iterations = 0;
231+ while (scheduler.advanceToLastPostedRunnable()) {
232+ iterations++;
233+ if (iterations <= 5 || iterations % 50 == 0) {
234+ log("pumpSchedulers[" + invocation + "] ran " + label + " runnable #" + iterations);
235+ }
236+ if (iterations >= 5000) {
237+ log("pumpSchedulers[" + invocation + "] aborting " + label + " flush after " + iterations + " iterations");
238+ break;
239+ }
240+ }
241+ if (verbose) {
242+ log("pumpSchedulers[" + invocation + "] flushed " + label + " scheduler in " + iterations + " iterations");
243+ }
195244 }
196245
197246 private static synchronized void appendLogLine(String message) {
0 commit comments