EventsTest.java revision 7dfacdb1c820f955cb3cd6032ff5fbc2dd7d9df5
1/* 2 * Copyright (C) 2011 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 */ 16package android.animation; 17 18import android.os.Handler; 19import android.test.ActivityInstrumentationTestCase2; 20import android.test.UiThreadTest; 21import android.test.suitebuilder.annotation.MediumTest; 22import android.test.suitebuilder.annotation.SmallTest; 23 24/** 25 * Tests for the various lifecycle events of Animators. This abstract class is subclassed by 26 * concrete implementations that provide the actual Animator objects being tested. All of the 27 * testing mechanisms are in this class; the subclasses are only responsible for providing 28 * the mAnimator object. 29 * 30 * This test is more complicated than a typical synchronous test because much of the functionality 31 * must happen on the UI thread. Some tests do this by using the UiThreadTest annotation to 32 * automatically run the whole test on that thread. Other tests must run on the UI thread and also 33 * wait for some later event to occur before ending. These tests use a combination of an 34 * AbstractFuture mechanism and a delayed action to release that Future later. 35 */ 36public abstract class EventsTest 37 extends ActivityInstrumentationTestCase2<BasicAnimatorActivity> { 38 39 private static final int ANIM_DURATION = 400; 40 private static final int ANIM_DELAY = 100; 41 private static final int ANIM_MID_DURATION = ANIM_DURATION / 2; 42 private static final int ANIM_MID_DELAY = ANIM_DELAY / 2; 43 44 private boolean mRunning; // tracks whether we've started the animator 45 private boolean mCanceled; // trackes whether we've canceled the animator 46 private Animator.AnimatorListener mFutureListener; // mechanism for delaying the end of the test 47 private FutureWaiter mFuture; // Mechanism for waiting for the UI test to complete 48 private Animator.AnimatorListener mListener; // Listener that handles/tests the events 49 50 protected Animator mAnimator; // The animator used in the tests. Must be set in subclass 51 // setup() method prior to calling the superclass setup() 52 53 /** 54 * Cancels the given animator. Used to delay cancelation until some later time (after the 55 * animator has started playing). 56 */ 57 static class Canceler implements Runnable { 58 Animator mAnim; 59 public Canceler(Animator anim) { 60 mAnim = anim; 61 } 62 @Override 63 public void run() { 64 mAnim.cancel(); 65 } 66 }; 67 68 /** 69 * Releases the given Future object when the listener's end() event is called. Specifically, 70 * it releases it after some further delay, to give the test time to do other things right 71 * after an animation ends. 72 */ 73 static class FutureReleaseListener extends AnimatorListenerAdapter { 74 FutureWaiter mFuture; 75 76 public FutureReleaseListener(FutureWaiter future) { 77 mFuture = future; 78 } 79 @Override 80 public void onAnimationEnd(Animator animation) { 81 Handler handler = new Handler(); 82 handler.postDelayed(new Runnable() { 83 @Override 84 public void run() { 85 mFuture.release(); 86 } 87 }, ANIM_MID_DURATION); 88 } 89 }; 90 91 public EventsTest() { 92 super(BasicAnimatorActivity.class); 93 } 94 95 96 /** 97 * Sets up the fields used by each test. Subclasses must override this method to create 98 * the protected mAnimator object used in all tests. Overrides must create that animator 99 * and then call super.setup(), where further properties are set on that animator. 100 * @throws Exception 101 */ 102 @Override 103 public void setUp() throws Exception { 104 super.setUp(); 105 106 // mListener is the main testing mechanism of this file. The asserts of each test 107 // are embedded in the listener callbacks that it implements. 108 mListener = new AnimatorListenerAdapter() { 109 @Override 110 public void onAnimationCancel(Animator animation) { 111 // This should only be called on an animation that has been started and not 112 // yet canceled or ended 113 assertFalse(mCanceled); 114 assertTrue(mRunning); 115 mCanceled = true; 116 } 117 118 @Override 119 public void onAnimationEnd(Animator animation) { 120 // This should only be called on an animation that has been started and not 121 // yet ended 122 assertTrue(mRunning); 123 mRunning = false; 124 super.onAnimationEnd(animation); 125 } 126 }; 127 128 mAnimator.addListener(mListener); 129 mAnimator.setDuration(ANIM_DURATION); 130 131 mFuture = new FutureWaiter(); 132 133 mRunning = false; 134 mCanceled = false; 135 } 136 137 /** 138 * Verify that calling cancel on an unstarted animator does nothing. 139 */ 140 @UiThreadTest 141 @SmallTest 142 public void testCancel() throws Exception { 143 mAnimator.cancel(); 144 } 145 146 /** 147 * Verify that calling cancel on a started animator does the right thing. 148 */ 149 @UiThreadTest 150 @SmallTest 151 public void testStartCancel() throws Exception { 152 mRunning = true; 153 mAnimator.start(); 154 mAnimator.cancel(); 155 } 156 157 /** 158 * Same as testStartCancel, but with a startDelayed animator 159 */ 160 @UiThreadTest 161 @SmallTest 162 public void testStartDelayedCancel() throws Exception { 163 mAnimator.setStartDelay(ANIM_DELAY); 164 mRunning = true; 165 mAnimator.start(); 166 mAnimator.cancel(); 167 } 168 169 /** 170 * Verify that canceling an animator that is playing does the right thing. 171 */ 172 @MediumTest 173 public void testPlayingCancel() throws Exception { 174 mFutureListener = new FutureReleaseListener(mFuture); 175 getActivity().runOnUiThread(new Runnable() { 176 @Override 177 public void run() { 178 try { 179 Handler handler = new Handler(); 180 mAnimator.addListener(mFutureListener); 181 mRunning = true; 182 mAnimator.start(); 183 handler.postDelayed(new Canceler(mAnimator), ANIM_MID_DURATION); 184 } catch (junit.framework.AssertionFailedError e) { 185 mFuture.setException(new RuntimeException(e)); 186 } 187 } 188 }); 189 mFuture.get(); 190 } 191 192 /** 193 * Same as testPlayingCancel, but with a startDelayed animator 194 */ 195 @MediumTest 196 public void testPlayingDelayedCancel() throws Exception { 197 mAnimator.setStartDelay(ANIM_DELAY); 198 mFutureListener = new FutureReleaseListener(mFuture); 199 getActivity().runOnUiThread(new Runnable() { 200 @Override 201 public void run() { 202 try { 203 Handler handler = new Handler(); 204 mAnimator.addListener(mFutureListener); 205 mRunning = true; 206 mAnimator.start(); 207 handler.postDelayed(new Canceler(mAnimator), ANIM_MID_DURATION); 208 } catch (junit.framework.AssertionFailedError e) { 209 mFuture.setException(new RuntimeException(e)); 210 } 211 } 212 }); 213 mFuture.get(); 214 } 215 216 /** 217 * Verifies that canceling a started animation after it has already been canceled 218 * does nothing. 219 */ 220 @MediumTest 221 public void testStartDoubleCancel() throws Exception { 222 mFutureListener = new FutureReleaseListener(mFuture); 223 getActivity().runOnUiThread(new Runnable() { 224 @Override 225 public void run() { 226 try { 227 mRunning = true; 228 mAnimator.start(); 229 mAnimator.cancel(); 230 mAnimator.cancel(); 231 mFuture.release(); 232 } catch (junit.framework.AssertionFailedError e) { 233 mFuture.setException(new RuntimeException(e)); 234 } 235 } 236 }); 237 mFuture.get(); 238 } 239 240 /** 241 * Same as testStartDoubleCancel, but with a startDelayed animator 242 */ 243 @MediumTest 244 public void testStartDelayedDoubleCancel() throws Exception { 245 mAnimator.setStartDelay(ANIM_DELAY); 246 mFutureListener = new FutureReleaseListener(mFuture); 247 getActivity().runOnUiThread(new Runnable() { 248 @Override 249 public void run() { 250 try { 251 mRunning = true; 252 mAnimator.start(); 253 mAnimator.cancel(); 254 mAnimator.cancel(); 255 mFuture.release(); 256 } catch (junit.framework.AssertionFailedError e) { 257 mFuture.setException(new RuntimeException(e)); 258 } 259 } 260 }); 261 mFuture.get(); 262 } 263 264 265} 266