1 /* 2 * Copyright (C) 2016 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.documentsui.testing; 18 19 import java.util.Date; 20 import java.util.Iterator; 21 import java.util.LinkedList; 22 import java.util.ListIterator; 23 import java.util.Timer; 24 import java.util.TimerTask; 25 26 /** 27 * A {@link Timer} for testing that can dial its clock hands to any future time. 28 */ 29 public class TestTimer extends Timer { 30 31 private long mNow = 0; 32 33 private final LinkedList<Task> mTaskList = new LinkedList<>(); 34 35 public long getNow() { 36 return mNow; 37 } 38 39 public void fastForwardTo(long time) { 40 if (time < mNow) { 41 throw new IllegalArgumentException("Can't fast forward to past."); 42 } 43 44 mNow = time; 45 while (!mTaskList.isEmpty() && mTaskList.getFirst().mExecuteTime <= mNow) { 46 Task task = mTaskList.getFirst(); 47 if (!task.isCancelled()) { 48 task.run(); 49 } 50 mTaskList.removeFirst(); 51 } 52 } 53 54 public boolean hasScheduledTask() { 55 return !mTaskList.isEmpty(); 56 } 57 58 public void fastForwardToNextTask() { 59 if (!hasScheduledTask()) { 60 throw new IllegalStateException("There is no scheduled task!"); 61 } 62 fastForwardTo(mTaskList.getFirst().mExecuteTime); 63 } 64 65 @Override 66 public void cancel() { 67 mTaskList.clear(); 68 } 69 70 @Override 71 public int purge() { 72 int count = 0; 73 Iterator<Task> iter = mTaskList.iterator(); 74 while (iter.hasNext()) { 75 Task task = iter.next(); 76 if (task.isCancelled()) { 77 iter.remove(); 78 ++count; 79 } 80 } 81 return count; 82 } 83 84 @Override 85 public void schedule(TimerTask task, Date time) { 86 long executeTime = time.getTime(); 87 scheduleAtTime(task, executeTime); 88 } 89 90 @Override 91 public void schedule(TimerTask task, Date firstTime, long period) { 92 throw new UnsupportedOperationException(); 93 } 94 95 @Override 96 public void schedule(TimerTask task, long delay) { 97 long executeTime = mNow + delay; 98 scheduleAtTime(task, executeTime); 99 } 100 101 @Override 102 public void schedule(TimerTask task, long delay, long period) { 103 throw new UnsupportedOperationException(); 104 } 105 106 @Override 107 public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) { 108 throw new UnsupportedOperationException(); 109 } 110 111 @Override 112 public void scheduleAtFixedRate(TimerTask task, long delay, long period) { 113 throw new UnsupportedOperationException(); 114 } 115 116 public void scheduleAtTime(TimerTask task, long executeTime) { 117 Task testTimerTask = (Task) task; 118 testTimerTask.mExecuteTime = executeTime; 119 120 ListIterator<Task> iter = mTaskList.listIterator(0); 121 while (iter.hasNext()) { 122 if (iter.next().mExecuteTime >= executeTime) { 123 break; 124 } 125 } 126 iter.add(testTimerTask); 127 } 128 129 public static class Task extends TimerTask { 130 private boolean mIsCancelled; 131 private long mExecuteTime; 132 133 private TimerTask mDelegate; 134 135 public Task(TimerTask delegate) { 136 mDelegate = delegate; 137 } 138 139 @Override 140 public boolean cancel() { 141 mIsCancelled = true; 142 return mDelegate.cancel(); 143 } 144 145 @Override 146 public void run() { 147 mDelegate.run(); 148 } 149 150 boolean isCancelled() { 151 return mIsCancelled; 152 } 153 } 154 } 155