1bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay/*
2bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay * Copyright (C) 2016 The Android Open Source Project
3bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay *
4bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay * Licensed under the Apache License, Version 2.0 (the "License");
5bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay * you may not use this file except in compliance with the License.
6bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay * You may obtain a copy of the License at
7bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay *
8bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay *      http://www.apache.org/licenses/LICENSE-2.0
9bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay *
10bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay * Unless required by applicable law or agreed to in writing, software
11bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay * distributed under the License is distributed on an "AS IS" BASIS,
12bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay * See the License for the specific language governing permissions and
14bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay * limitations under the License.
15bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay */
16bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
17edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tanpackage com.android.documentsui.testing;
18bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
19bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKayimport static junit.framework.Assert.assertFalse;
20894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tanimport static junit.framework.Assert.assertTrue;
21894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan
22894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tanimport android.os.Handler;
23894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tanimport android.os.Looper;
24894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tanimport android.os.SystemClock;
25bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
26bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKayimport java.util.ArrayList;
27bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKayimport java.util.Collection;
28894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tanimport java.util.Collections;
29bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKayimport java.util.List;
30bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKayimport java.util.concurrent.Callable;
31894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tanimport java.util.concurrent.CountDownLatch;
32bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKayimport java.util.concurrent.Delayed;
33bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKayimport java.util.concurrent.ExecutionException;
34bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKayimport java.util.concurrent.Future;
35bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKayimport java.util.concurrent.ScheduledExecutorService;
36bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKayimport java.util.concurrent.ScheduledFuture;
37bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKayimport java.util.concurrent.TimeUnit;
38bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKayimport java.util.concurrent.TimeoutException;
39bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
40bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKaypublic class TestScheduledExecutorService implements ScheduledExecutorService {
41bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
42bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    private List<TestFuture> scheduled = new ArrayList<>();
43bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    private boolean shutdown;
44bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
45bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    @Override
46bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    public void shutdown() {
47bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        this.shutdown = true;
48bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
49bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
50bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    @Override
51bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    public List<Runnable> shutdownNow() {
52bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        this.shutdown = true;
53894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan        return Collections.emptyList();
54bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
55bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
56edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan    public void assertShutdown() {
57894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan        assertTrue("Executor wasn't shut down.", shutdown);
58bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
59bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
60bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    @Override
61bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    public boolean isShutdown() {
62bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        return shutdown;
63bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
64bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
65bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    @Override
66bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    public boolean isTerminated() {
67bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        throw new UnsupportedOperationException();
68bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
69bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
70bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    @Override
71bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
72bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        throw new UnsupportedOperationException();
73bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
74bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
75bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    @Override
76bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    public <T> Future<T> submit(Callable<T> task) {
77bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        throw new UnsupportedOperationException();
78bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
79bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
80bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    @Override
81bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    public <T> Future<T> submit(Runnable task, T result) {
82bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        throw new UnsupportedOperationException();
83bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
84bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
85bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    @Override
86bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    public Future<?> submit(Runnable task) {
87810fb82f4461544ce34a5702668cf0e3123582c2Garfield, Tan        return schedule(task, 0, TimeUnit.MILLISECONDS);
88bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
89bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
90bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    @Override
91bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
92bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay            throws InterruptedException {
93bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        throw new UnsupportedOperationException();
94bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
95bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
96bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    @Override
97bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout,
98bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay            TimeUnit unit) throws InterruptedException {
99bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        throw new UnsupportedOperationException();
100bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
101bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
102bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    @Override
103bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
104bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay            throws InterruptedException, ExecutionException {
105bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        throw new UnsupportedOperationException();
106bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
107bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
108bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    @Override
109bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
110bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay            throws InterruptedException, ExecutionException, TimeoutException {
111bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        throw new UnsupportedOperationException();
112bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
113bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
114bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    @Override
115bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    public void execute(Runnable command) {
116edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan        schedule(command, 0, TimeUnit.MILLISECONDS);
117bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
118bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
119bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    @Override
120bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
121bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        TestFuture future = new TestFuture(command, delay, unit);
122bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        scheduled.add(future);
123bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        return future;
124bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
125bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
126bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    @Override
127bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
128bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        throw new UnsupportedOperationException();
129bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
130bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
131bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    @Override
132bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period,
133bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay            TimeUnit unit) {
134bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        throw new UnsupportedOperationException();
135bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
136bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
137bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    @Override
138bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay,
139bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay            long delay, TimeUnit unit) {
140bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        throw new UnsupportedOperationException();
141bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
142bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
143edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan    public void runAll() {
144894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan        while (!scheduled.isEmpty()) {
145894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan            TestFuture future = scheduled.remove(scheduled.size() - 1);
146bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay            future.runnable.run();
147bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        }
148bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
149bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
150edce554c3eaff20a9bf349c1bc18c0b49e812c74Garfield, Tan    public void run(int taskIndex) {
151bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        scheduled.get(taskIndex).runnable.run();
152d79ef7f8da3f13cdd219901252bfb7cfd62456a5Garfield Tan
153d79ef7f8da3f13cdd219901252bfb7cfd62456a5Garfield Tan        scheduled.remove(taskIndex);
154bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
155bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
15697b4be4638f1697895e5d1f3fdf8bf28a3bb9c13Steve McKay    public void assertAlive() {
157bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        assertFalse(isShutdown());
158bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
159bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
160894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan    public void waitForTasks(long millisTimeout) throws Exception {
161894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan        millisTimeout = (millisTimeout > 0) ? millisTimeout : Long.MAX_VALUE;
162894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan
163894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan        final long startTime = SystemClock.uptimeMillis();
164894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan
165894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan        // We need to wait on all AsyncTasks to finish AND to post results back.
166894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan        // *** Results are posted on main thread ***, but tests run in their own
167894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan        // thread. So even with our test executor we still have races.
168894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan        //
169894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan        // To work around this issue post our own runnable to the main thread
170894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan        // which we presume will be the *last* runnable (after any from AsyncTasks)
171894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan        // and then wait for our runnable to be called.
172894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan        while (!scheduled.isEmpty() && millisTimeout > 0) {
173894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan            CountDownLatch latch = new CountDownLatch(1);
174894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan            runAll();
175894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan            new Handler(Looper.getMainLooper()).post(latch::countDown);
176894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan            latch.await(millisTimeout, TimeUnit.MILLISECONDS);
177894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan
178894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan            millisTimeout -= (SystemClock.uptimeMillis() - startTime);
179894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan        }
180894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan    }
181894d487698ff5c7052f499602fb74ad89f1d2d15Garfield Tan
182bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    static class TestFuture implements ScheduledFuture<Void> {
183bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
184bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        final Runnable runnable;
185bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        final long delay;
186bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        final TimeUnit unit;
187bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
188bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        public TestFuture(Runnable runnable, long delay, TimeUnit unit) {
189bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay            this.runnable = runnable;
190bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay            this.delay = delay;
191bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay            this.unit = unit;
192bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        }
193bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
194bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        @Override
195bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        public long getDelay(TimeUnit unit) {
196bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay            return 0;
197bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        }
198bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
199bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        @Override
200bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        public int compareTo(Delayed arg0) {
201bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay            return 0;
202bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        }
203bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
204bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        @Override
205bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        public boolean cancel(boolean mayInterruptIfRunning) {
206bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay            return false;
207bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        }
208bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
209bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        @Override
210bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        public boolean isCancelled() {
211bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay            return false;
212bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        }
213bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
214bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        @Override
215bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        public boolean isDone() {
216bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay            return false;
217bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        }
218bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
219bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        @Override
220bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        public Void get() throws InterruptedException, ExecutionException {
221bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay            return null;
222bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        }
223bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay
224bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        @Override
225bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        public Void get(long timeout, TimeUnit unit)
226bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay                throws InterruptedException, ExecutionException, TimeoutException {
227bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay            return null;
228bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay        }
229bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay    }
230bbeba5265c5baa42c6db93fc8030c6055747da4dSteve McKay}
231