| // Copyright 2018 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package org.chromium.base.test.task; |
| |
| import android.os.Handler; |
| import android.os.HandlerThread; |
| import android.os.Looper; |
| |
| import org.chromium.base.task.TaskRunner; |
| |
| import java.util.List; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| |
| /** Collection of helpers for testing the java PostTask. */ |
| public class SchedulerTestHelpers { |
| public static void postRecordOrderTask( |
| TaskRunner taskQueue, List<Integer> orderList, int order) { |
| postRecordOrderDelayedTask(taskQueue, orderList, order, 0); |
| } |
| |
| public static void postRecordOrderDelayedTask( |
| TaskRunner taskQueue, List<Integer> orderList, int order, long delay) { |
| taskQueue.postDelayedTask(() -> orderList.add(order), delay); |
| } |
| |
| public static void postTaskAndBlockUntilRun(TaskRunner taskQueue) { |
| postDelayedTaskAndBlockUntilRun(taskQueue, 0); |
| } |
| |
| public static void postDelayedTaskAndBlockUntilRun(TaskRunner taskQueue, long delay) { |
| final Object lock = new Object(); |
| final AtomicBoolean taskExecuted = new AtomicBoolean(); |
| taskQueue.postDelayedTask( |
| () -> { |
| synchronized (lock) { |
| taskExecuted.set(true); |
| lock.notify(); |
| } |
| }, |
| delay); |
| synchronized (lock) { |
| try { |
| while (!taskExecuted.get()) { |
| lock.wait(); |
| } |
| } catch (InterruptedException ie) { |
| ie.printStackTrace(); |
| } |
| } |
| } |
| |
| public static void postThreeTasksInOrder(TaskRunner taskQueue, List<Integer> orderList) { |
| postRecordOrderTask(taskQueue, orderList, 1); |
| postRecordOrderTask(taskQueue, orderList, 2); |
| postRecordOrderTask(taskQueue, orderList, 3); |
| } |
| |
| public static void postThreeDelayedTasksInOrder(TaskRunner taskQueue, List<Integer> orderList) { |
| postRecordOrderDelayedTask(taskQueue, orderList, 1, 1); |
| postRecordOrderDelayedTask(taskQueue, orderList, 2, 1); |
| postRecordOrderDelayedTask(taskQueue, orderList, 3, 1); |
| } |
| |
| /** |
| * A helper which posts a task on the handler which when run blocks until unblock() is called. |
| */ |
| public static class HandlerBlocker { |
| final Handler mHandler; |
| final Object mLock = new Object(); |
| final AtomicBoolean mTaskExecuted = new AtomicBoolean(); |
| |
| public HandlerBlocker(Handler handler) { |
| mHandler = handler; |
| } |
| |
| /** Posts a task that blocks until unblock() is called. */ |
| public void postBlockingTask() { |
| mHandler.post( |
| () -> { |
| synchronized (mLock) { |
| try { |
| while (!mTaskExecuted.get()) { |
| mLock.wait(); |
| } |
| } catch (InterruptedException ie) { |
| ie.printStackTrace(); |
| } |
| } |
| }); |
| } |
| |
| public void unblock() { |
| synchronized (mLock) { |
| mTaskExecuted.set(true); |
| mLock.notify(); |
| } |
| } |
| } |
| ; |
| |
| /** Waits until the looper's MessageQueue becomes idle. */ |
| public static void preNativeRunUntilIdle(HandlerThread handlerThread) { |
| final Object lock = new Object(); |
| final AtomicBoolean taskExecuted = new AtomicBoolean(); |
| |
| new Handler(handlerThread.getLooper()) |
| .post( |
| () -> { |
| Looper.myQueue() |
| .addIdleHandler( |
| () -> { |
| synchronized (lock) { |
| taskExecuted.set(true); |
| lock.notify(); |
| } |
| return false; |
| }); |
| }); |
| |
| synchronized (lock) { |
| try { |
| while (!taskExecuted.get()) { |
| lock.wait(); |
| } |
| } catch (InterruptedException ie) { |
| ie.printStackTrace(); |
| } |
| } |
| } |
| } |