1 /*
2  * Copyright (C) 2017 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 androidx.testutils;
18 
19 import androidx.annotation.NonNull;
20 
21 import org.junit.Assert;
22 
23 /**
24  * Utility used for testing that allows to poll for a certain condition to happen within a timeout.
25  */
26 public abstract class PollingCheck {
27     private static final long DEFAULT_TIMEOUT = 3000;
28     private static final long TIME_SLICE = 50;
29     private final long mTimeout;
30 
31     /**
32      * The condition that the PollingCheck should use to proceed successfully.
33      */
34     public interface PollingCheckCondition {
35         /**
36          * @return Whether the polling condition has been met.
37          */
canProceed()38         boolean canProceed();
39     }
40 
PollingCheck(long timeout)41     public PollingCheck(long timeout) {
42         mTimeout = timeout;
43     }
44 
check()45     protected abstract boolean check();
46 
47     /**
48      * Start running the polling check.
49      */
run()50     public void run() {
51         if (check()) {
52             return;
53         }
54 
55         long timeout = mTimeout;
56         while (timeout > 0) {
57             try {
58                 Thread.sleep(TIME_SLICE);
59             } catch (InterruptedException e) {
60                 throw new AssertionError("unexpected InterruptedException");
61             }
62 
63             if (check()) {
64                 return;
65             }
66 
67             timeout -= TIME_SLICE;
68         }
69 
70         Assert.fail("unexpected timeout");
71     }
72 
73     /**
74      * Instantiate and start polling for a given condition with a default 3000ms timeout.
75      * @param condition The condition to check for success.
76      */
waitFor(final @NonNull PollingCheckCondition condition)77     public static void waitFor(final @NonNull PollingCheckCondition condition) {
78         new PollingCheck(DEFAULT_TIMEOUT) {
79             @Override
80             protected boolean check() {
81                 return condition.canProceed();
82             }
83         }.run();
84     }
85 
86     /**
87      * Instantiate and start polling for a given condition.
88      * @param timeout Time out in ms
89      * @param condition The condition to check for success.
90      */
waitFor(long timeout, final @NonNull PollingCheckCondition condition)91     public static void waitFor(long timeout, final @NonNull PollingCheckCondition condition) {
92         new PollingCheck(timeout) {
93             @Override
94             protected boolean check() {
95                 return condition.canProceed();
96             }
97         }.run();
98     }
99 }
100