1 /* 2 * Copyright (C) 2020 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.server.people.data; 18 19 import com.android.internal.util.Preconditions; 20 21 import com.google.common.collect.ImmutableList; 22 23 import java.util.ArrayList; 24 import java.util.Collection; 25 import java.util.List; 26 import java.util.concurrent.Callable; 27 import java.util.concurrent.Delayed; 28 import java.util.concurrent.ExecutionException; 29 import java.util.concurrent.Future; 30 import java.util.concurrent.ScheduledExecutorService; 31 import java.util.concurrent.ScheduledFuture; 32 import java.util.concurrent.TimeUnit; 33 import java.util.concurrent.TimeoutException; 34 35 /** 36 * Mock implementation of ScheduledExecutorService for testing. All commands will run 37 * synchronously. Commands passed to {@link #submit(Runnable)} and {@link #execute(Runnable)} will 38 * run immediately. Commands scheduled via {@link #schedule(Runnable, long, TimeUnit)} will run 39 * after calling {@link #fastForwardTime(long)}. 40 */ 41 class MockScheduledExecutorService implements ScheduledExecutorService { 42 43 private final List<Runnable> mExecutes = new ArrayList<>(); 44 private final List<MockScheduledFuture<?>> mFutures = new ArrayList<>(); 45 private long mTimeElapsedMillis = 0; 46 47 /** 48 * Advances fake time, runs all the commands for which the delay has expired. 49 */ fastForwardTime(long millis)50 long fastForwardTime(long millis) { 51 mTimeElapsedMillis += millis; 52 ImmutableList<MockScheduledFuture<?>> futuresCopy = ImmutableList.copyOf(mFutures); 53 mFutures.clear(); 54 long totalExecuted = 0; 55 for (MockScheduledFuture<?> future : futuresCopy) { 56 if (future.getDelay() < mTimeElapsedMillis) { 57 future.getRunnable().run(); 58 mExecutes.add(future.getRunnable()); 59 totalExecuted += 1; 60 } else { 61 mFutures.add(future); 62 } 63 } 64 return totalExecuted; 65 } 66 getExecutes()67 List<Runnable> getExecutes() { 68 return mExecutes; 69 } 70 getFutures()71 List<MockScheduledFuture<?>> getFutures() { 72 return mFutures; 73 } 74 resetTimeElapsedMillis()75 void resetTimeElapsedMillis() { 76 mTimeElapsedMillis = 0; 77 } 78 79 /** 80 * Fakes a schedule execution of {@link Runnable}. The command will be executed by an explicit 81 * call to {@link #fastForwardTime(long)}. 82 */ 83 @Override schedule(Runnable command, long delay, TimeUnit unit)84 public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) { 85 Preconditions.checkState(unit == TimeUnit.MILLISECONDS); 86 MockScheduledFuture<?> future = new MockScheduledFuture<>(command, delay, unit); 87 mFutures.add(future); 88 return future; 89 } 90 91 @Override schedule(Callable<V> callable, long delay, TimeUnit unit)92 public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) { 93 throw new UnsupportedOperationException(); 94 } 95 96 @Override scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)97 public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, 98 TimeUnit unit) { 99 return new MockScheduledFuture<>(command, period, unit); 100 } 101 102 @Override scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)103 public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, 104 long delay, TimeUnit unit) { 105 throw new UnsupportedOperationException(); 106 } 107 108 @Override shutdown()109 public void shutdown() { 110 throw new UnsupportedOperationException(); 111 } 112 113 @Override shutdownNow()114 public List<Runnable> shutdownNow() { 115 throw new UnsupportedOperationException(); 116 } 117 118 @Override isShutdown()119 public boolean isShutdown() { 120 return false; 121 } 122 123 @Override isTerminated()124 public boolean isTerminated() { 125 throw new UnsupportedOperationException(); 126 } 127 128 @Override awaitTermination(long timeout, TimeUnit unit)129 public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { 130 throw new UnsupportedOperationException(); 131 } 132 133 @Override submit(Callable<T> task)134 public <T> Future<T> submit(Callable<T> task) { 135 MockScheduledFuture<T> future = new MockScheduledFuture<>(task, 0, TimeUnit.MILLISECONDS); 136 try { 137 future.getCallable().call(); 138 } catch (Exception e) { 139 e.printStackTrace(); 140 } 141 return future; 142 } 143 144 @Override submit(Runnable task, T result)145 public <T> Future<T> submit(Runnable task, T result) { 146 throw new UnsupportedOperationException(); 147 } 148 149 @Override submit(Runnable runnable)150 public Future<?> submit(Runnable runnable) { 151 mExecutes.add(runnable); 152 MockScheduledFuture<?> future = new MockScheduledFuture<>(runnable, 0, 153 TimeUnit.MILLISECONDS); 154 future.getRunnable().run(); 155 return future; 156 } 157 158 @Override invokeAll(Collection<? extends Callable<T>> tasks)159 public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) 160 throws InterruptedException { 161 throw new UnsupportedOperationException(); 162 } 163 164 @Override invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)165 public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, 166 TimeUnit unit) throws InterruptedException { 167 throw new UnsupportedOperationException(); 168 } 169 170 @Override invokeAny(Collection<? extends Callable<T>> tasks)171 public <T> T invokeAny(Collection<? extends Callable<T>> tasks) 172 throws ExecutionException, InterruptedException { 173 throw new UnsupportedOperationException(); 174 } 175 176 @Override invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)177 public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) 178 throws ExecutionException, InterruptedException, TimeoutException { 179 throw new UnsupportedOperationException(); 180 } 181 182 @Override execute(Runnable command)183 public void execute(Runnable command) { 184 mExecutes.add(command); 185 command.run(); 186 } 187 188 class MockScheduledFuture<V> implements ScheduledFuture<V> { 189 190 private final Runnable mRunnable; 191 private final Callable<V> mCallable; 192 private final long mDelay; 193 private boolean mCancelled = false; 194 MockScheduledFuture(Runnable runnable, long delay, TimeUnit timeUnit)195 MockScheduledFuture(Runnable runnable, long delay, TimeUnit timeUnit) { 196 this(runnable, null, delay); 197 } 198 MockScheduledFuture(Callable<V> callable, long delay, TimeUnit timeUnit)199 MockScheduledFuture(Callable<V> callable, long delay, TimeUnit timeUnit) { 200 this(null, callable, delay); 201 } 202 MockScheduledFuture(Runnable runnable, Callable<V> callable, long delay)203 private MockScheduledFuture(Runnable runnable, Callable<V> callable, long delay) { 204 mCallable = callable; 205 mRunnable = runnable; 206 mDelay = delay; 207 } 208 getDelay()209 public long getDelay() { 210 return mDelay; 211 } 212 getRunnable()213 public Runnable getRunnable() { 214 return mRunnable; 215 } 216 getCallable()217 public Callable<V> getCallable() { 218 return mCallable; 219 } 220 221 @Override getDelay(TimeUnit unit)222 public long getDelay(TimeUnit unit) { 223 throw new UnsupportedOperationException(); 224 } 225 226 @Override compareTo(Delayed o)227 public int compareTo(Delayed o) { 228 throw new UnsupportedOperationException(); 229 } 230 231 @Override cancel(boolean mayInterruptIfRunning)232 public boolean cancel(boolean mayInterruptIfRunning) { 233 mCancelled = true; 234 return mFutures.remove(this); 235 } 236 237 @Override isCancelled()238 public boolean isCancelled() { 239 return mCancelled; 240 } 241 242 @Override isDone()243 public boolean isDone() { 244 return !mFutures.contains(this); 245 } 246 247 @Override get()248 public V get() throws ExecutionException, InterruptedException { 249 return null; 250 } 251 252 @Override get(long timeout, TimeUnit unit)253 public V get(long timeout, TimeUnit unit) 254 throws ExecutionException, InterruptedException, TimeoutException { 255 return null; 256 } 257 } 258 } 259