1 // Copyright 2018 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 5 package org.chromium.base.test.task; 6 7 import android.os.Handler; 8 import android.os.HandlerThread; 9 import android.os.Looper; 10 11 import org.chromium.base.task.TaskRunner; 12 13 import java.util.List; 14 import java.util.concurrent.atomic.AtomicBoolean; 15 16 /** Collection of helpers for testing the java PostTask. */ 17 public class SchedulerTestHelpers { postRecordOrderTask( TaskRunner taskQueue, List<Integer> orderList, int order)18 public static void postRecordOrderTask( 19 TaskRunner taskQueue, List<Integer> orderList, int order) { 20 postRecordOrderDelayedTask(taskQueue, orderList, order, 0); 21 } 22 postRecordOrderDelayedTask( TaskRunner taskQueue, List<Integer> orderList, int order, long delay)23 public static void postRecordOrderDelayedTask( 24 TaskRunner taskQueue, List<Integer> orderList, int order, long delay) { 25 taskQueue.postDelayedTask(() -> orderList.add(order), delay); 26 } 27 postTaskAndBlockUntilRun(TaskRunner taskQueue)28 public static void postTaskAndBlockUntilRun(TaskRunner taskQueue) { 29 postDelayedTaskAndBlockUntilRun(taskQueue, 0); 30 } 31 postDelayedTaskAndBlockUntilRun(TaskRunner taskQueue, long delay)32 public static void postDelayedTaskAndBlockUntilRun(TaskRunner taskQueue, long delay) { 33 final Object lock = new Object(); 34 final AtomicBoolean taskExecuted = new AtomicBoolean(); 35 taskQueue.postDelayedTask( 36 () -> { 37 synchronized (lock) { 38 taskExecuted.set(true); 39 lock.notify(); 40 } 41 }, 42 delay); 43 synchronized (lock) { 44 try { 45 while (!taskExecuted.get()) { 46 lock.wait(); 47 } 48 } catch (InterruptedException ie) { 49 ie.printStackTrace(); 50 } 51 } 52 } 53 postThreeTasksInOrder(TaskRunner taskQueue, List<Integer> orderList)54 public static void postThreeTasksInOrder(TaskRunner taskQueue, List<Integer> orderList) { 55 postRecordOrderTask(taskQueue, orderList, 1); 56 postRecordOrderTask(taskQueue, orderList, 2); 57 postRecordOrderTask(taskQueue, orderList, 3); 58 } 59 postThreeDelayedTasksInOrder(TaskRunner taskQueue, List<Integer> orderList)60 public static void postThreeDelayedTasksInOrder(TaskRunner taskQueue, List<Integer> orderList) { 61 postRecordOrderDelayedTask(taskQueue, orderList, 1, 1); 62 postRecordOrderDelayedTask(taskQueue, orderList, 2, 1); 63 postRecordOrderDelayedTask(taskQueue, orderList, 3, 1); 64 } 65 66 /** 67 * A helper which posts a task on the handler which when run blocks until unblock() is called. 68 */ 69 public static class HandlerBlocker { 70 final Handler mHandler; 71 final Object mLock = new Object(); 72 final AtomicBoolean mTaskExecuted = new AtomicBoolean(); 73 HandlerBlocker(Handler handler)74 public HandlerBlocker(Handler handler) { 75 mHandler = handler; 76 } 77 78 /** Posts a task that blocks until unblock() is called. */ postBlockingTask()79 public void postBlockingTask() { 80 mHandler.post( 81 () -> { 82 synchronized (mLock) { 83 try { 84 while (!mTaskExecuted.get()) { 85 mLock.wait(); 86 } 87 } catch (InterruptedException ie) { 88 ie.printStackTrace(); 89 } 90 } 91 }); 92 } 93 unblock()94 public void unblock() { 95 synchronized (mLock) { 96 mTaskExecuted.set(true); 97 mLock.notify(); 98 } 99 } 100 } 101 ; 102 103 /** Waits until the looper's MessageQueue becomes idle. */ preNativeRunUntilIdle(HandlerThread handlerThread)104 public static void preNativeRunUntilIdle(HandlerThread handlerThread) { 105 final Object lock = new Object(); 106 final AtomicBoolean taskExecuted = new AtomicBoolean(); 107 108 new Handler(handlerThread.getLooper()) 109 .post( 110 () -> { 111 Looper.myQueue() 112 .addIdleHandler( 113 () -> { 114 synchronized (lock) { 115 taskExecuted.set(true); 116 lock.notify(); 117 } 118 return false; 119 }); 120 }); 121 122 synchronized (lock) { 123 try { 124 while (!taskExecuted.get()) { 125 lock.wait(); 126 } 127 } catch (InterruptedException ie) { 128 ie.printStackTrace(); 129 } 130 } 131 } 132 } 133