1 // Copyright 2022 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 package org.chromium.base.task.test; 5 6 import android.os.Looper; 7 8 import org.junit.rules.ExternalResource; 9 import org.robolectric.Shadows; 10 import org.robolectric.android.util.concurrent.PausedExecutorService; 11 12 import org.chromium.base.task.PostTask; 13 14 import java.util.concurrent.TimeUnit; 15 16 /** Allows tests to manually schedule background tasks posted via PostTask APIs. */ 17 public class PausedExecutorTestRule extends ExternalResource { 18 private final PausedExecutorService mPausedExecutor = new PausedExecutorService(); 19 20 @Override before()21 protected void before() { 22 PostTask.setPrenativeThreadPoolExecutorForTesting(mPausedExecutor); 23 } 24 25 @Override after()26 protected void after() { 27 mPausedExecutor.shutdownNow(); 28 try { 29 mPausedExecutor.awaitTermination(1, TimeUnit.SECONDS); 30 } catch (InterruptedException e) { 31 throw new RuntimeException(e); 32 } 33 } 34 35 /** 36 * Runs all currently background tasks and waits for them to finish. 37 * Warning: This will deadlock if a background tasks blocks on the UI thread. 38 * @return Whether any background tasks were run. 39 */ runAllBackgroundAndUi()40 public boolean runAllBackgroundAndUi() { 41 int taskCount = 0; 42 for (int i = 0; i < 100; ++i) { 43 Shadows.shadowOf(Looper.getMainLooper()).idle(); 44 if (!mPausedExecutor.hasQueuedTasks()) { 45 return taskCount > 0; 46 } 47 taskCount += mPausedExecutor.runAll(); 48 } 49 throw new AssertionError("Infinite loop of background->foreground->background jobs"); 50 } 51 } 52