1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.compatibility.common.util; 18 19 import static org.junit.Assert.fail; 20 21 import java.util.concurrent.Callable; 22 23 /** Test utility to check for or wait for a condition by polling. */ 24 public abstract class PollingCheck { 25 public static final PollingCheckClock DEFAULT_CLOCK = new SystemClock(); 26 private static final long TIME_SLICE = 50; 27 28 /** Clock for polling. */ 29 public interface PollingCheckClock { currentTimeMillis()30 long currentTimeMillis(); 31 sleep(long millis)32 default void sleep(long millis) throws InterruptedException { 33 Thread.sleep(millis); 34 } 35 } 36 37 private static class SystemClock implements PollingCheckClock { 38 @Override currentTimeMillis()39 public long currentTimeMillis() { 40 return System.currentTimeMillis(); 41 } 42 } 43 44 /** 45 * Repeatedly check a condition. 46 * 47 * @param clock Clock used for checking time and sleeping between checks 48 * @param pollInterval Time interval to wait between checks 49 * @param timeout Timeout after which to stop checking 50 * @param condition Condition to check 51 * @return {@code true} if the condition became true within the timeout, {@code false} otherwise 52 * @throws Exception 53 */ check( PollingCheckClock clock, long pollInterval, long timeout, Callable<Boolean> condition)54 public static boolean check( 55 PollingCheckClock clock, long pollInterval, long timeout, Callable<Boolean> condition) 56 throws Exception { 57 long start = clock.currentTimeMillis(); 58 59 if (condition.call()) { 60 return true; 61 } 62 63 while ((clock.currentTimeMillis() - start) < timeout) { 64 clock.sleep(pollInterval); 65 66 if (condition.call()) { 67 return true; 68 } 69 } 70 71 return false; 72 } 73 74 /** 75 * Repeatedly check a condition. Uses the default clock and polling interval. 76 * 77 * @param timeout Timeout after which to stop checking 78 * @param condition Condition to check 79 * @return {@code true} if the condition became true within the timeout, {@code false} otherwise 80 * @throws Exception 81 */ check(long timeout, Callable<Boolean> condition)82 public static boolean check(long timeout, Callable<Boolean> condition) throws Exception { 83 return check(DEFAULT_CLOCK, TIME_SLICE, timeout, condition); 84 } 85 86 /** 87 * Repeatedly check a condition. Throws an {@link AssertionError} if the condition does not 88 * become {@code true} within the timeout. 89 * 90 * @param clock Clock used for checking time and sleeping between checks 91 * @param pollInterval Time interval to wait between checks 92 * @param timeout Timeout after which to stop checking 93 * @param condition Condition to check 94 * @throws Exception 95 */ check( PollingCheckClock clock, String message, long pollInterval, long timeout, Callable<Boolean> condition)96 public static void check( 97 PollingCheckClock clock, 98 String message, 99 long pollInterval, 100 long timeout, 101 Callable<Boolean> condition) 102 throws Exception { 103 if (!check(clock, pollInterval, timeout, condition)) { 104 fail(message); 105 } 106 } 107 108 /** 109 * Repeatedly check a condition. Uses the default clock and polling interval. Throws an {@link 110 * AssertionError} if the condition does not become {@code true} within the timeout. 111 * 112 * @param timeout Timeout after which to stop checking 113 * @param condition Condition to check 114 * @throws Exception 115 */ check(String message, long timeout, Callable<Boolean> condition)116 public static void check(String message, long timeout, Callable<Boolean> condition) 117 throws Exception { 118 check(DEFAULT_CLOCK, message, TIME_SLICE, timeout, condition); 119 } 120 121 /** 122 * Waits for a condition to become {@code true}. Throws an {@link AssertionError} if the 123 * condition does not become {@code true} within the timeout. 124 * 125 * @param clock Clock used for checking time and sleeping between checks 126 * @param pollInterval Time interval to wait between checks 127 * @param timeout Timeout after which to stop checking 128 * @param condition Condition to check 129 * @throws Exception 130 */ waitFor( PollingCheckClock clock, long pollInterval, long timeout, final Callable<Boolean> condition)131 public static void waitFor( 132 PollingCheckClock clock, 133 long pollInterval, 134 long timeout, 135 final Callable<Boolean> condition) 136 throws Exception { 137 check(clock, "Unexpected timeout waiting for condition", pollInterval, timeout, condition); 138 } 139 140 /** 141 * Waits for a condition to become {@code true}. Uses the default clock and polling interval. 142 * Throws an {@link AssertionError} if the condition does not become {@code true} within the 143 * timeout. 144 * 145 * @param timeout Timeout after which to stop checking 146 * @param condition Condition to check 147 * @throws Exception 148 */ waitFor(long timeout, final Callable<Boolean> condition)149 public static void waitFor(long timeout, final Callable<Boolean> condition) throws Exception { 150 waitFor(DEFAULT_CLOCK, TIME_SLICE, timeout, condition); 151 } 152 } 153