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