blob: 40d83b5b91717240c702e831843af9b4b55a0467 [file] [log] [blame]
Christopher Wiley1c811fa2016-05-18 17:09:56 -07001/*
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
17package android.os.test;
18
19import static org.hamcrest.core.IsEqual.equalTo;
20import static org.junit.Assert.assertEquals;
21import static org.junit.Assert.assertTrue;
22import static org.mockito.Matchers.any;
23import static org.mockito.Mockito.inOrder;
24import static org.mockito.Mockito.never;
25import static org.mockito.Mockito.spy;
26
27import android.os.Handler;
28import android.os.Looper;
29import android.os.Message;
30import android.test.suitebuilder.annotation.SmallTest;
31
32import org.junit.Before;
33import org.junit.Rule;
34import org.junit.Test;
35import org.junit.rules.ErrorCollector;
36import org.mockito.ArgumentCaptor;
37import org.mockito.InOrder;
38import org.mockito.MockitoAnnotations;
39
40/**
41 * Test TestLooperAbstractTime which provides control over "time". Note that
42 * real-time is being used as well. Therefore small time increments are NOT
43 * reliable. All tests are in "K" units (i.e. *1000).
44 */
45
46@SmallTest
47public class TestLooperTest {
48 private TestLooper mTestLooper;
49 private Handler mHandler;
50 private Handler mHandlerSpy;
51
52 @Rule
53 public ErrorCollector collector = new ErrorCollector();
54
55 @Before
56 public void setUp() throws Exception {
57 MockitoAnnotations.initMocks(this);
58
59 mTestLooper = new TestLooper();
60 mHandler = new Handler(mTestLooper.getLooper());
61 mHandlerSpy = spy(mHandler);
62 }
63
64 /**
65 * Basic test with no time stamps: dispatch 4 messages, check that all 4
66 * delivered (in correct order).
67 */
68 @Test
69 public void testNoTimeMovement() {
70 final int messageA = 1;
71 final int messageB = 2;
72 final int messageC = 3;
73
74 InOrder inOrder = inOrder(mHandlerSpy);
75 ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
76
77 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageA));
78 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageA));
79 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageB));
80 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageC));
81 mTestLooper.dispatchAll();
82
83 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
84 collector.checkThat("1: messageA", messageA, equalTo(messageCaptor.getValue().what));
85 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
86 collector.checkThat("2: messageA", messageA, equalTo(messageCaptor.getValue().what));
87 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
88 collector.checkThat("3: messageB", messageB, equalTo(messageCaptor.getValue().what));
89 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
90 collector.checkThat("4: messageC", messageC, equalTo(messageCaptor.getValue().what));
91
92 inOrder.verify(mHandlerSpy, never()).handleMessage(any(Message.class));
93 }
94
95 /**
96 * Test message sequence: A, B, C@5K, A@10K. Don't move time.
97 * <p>
98 * Expected: only get A, B
99 */
100 @Test
101 public void testDelayedDispatchNoTimeMove() {
102 final int messageA = 1;
103 final int messageB = 2;
104 final int messageC = 3;
105
106 InOrder inOrder = inOrder(mHandlerSpy);
107 ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
108
109 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageA));
110 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageB));
111 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageC), 5000);
112 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageA), 10000);
113 mTestLooper.dispatchAll();
114
115 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
116 collector.checkThat("1: messageA", messageA, equalTo(messageCaptor.getValue().what));
117 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
118 collector.checkThat("2: messageB", messageB, equalTo(messageCaptor.getValue().what));
119
120 inOrder.verify(mHandlerSpy, never()).handleMessage(any(Message.class));
121 }
122
123 /**
124 * Test message sequence: A, B, C@5K, A@10K, Advance time by 5K.
125 * <p>
126 * Expected: only get A, B, C
127 */
128 @Test
129 public void testDelayedDispatchAdvanceTimeOnce() {
130 final int messageA = 1;
131 final int messageB = 2;
132 final int messageC = 3;
133
134 InOrder inOrder = inOrder(mHandlerSpy);
135 ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
136
137 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageA));
138 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageB));
139 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageC), 5000);
140 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageA), 10000);
141 mTestLooper.moveTimeForward(5000);
142 mTestLooper.dispatchAll();
143
144 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
145 collector.checkThat("1: messageA", messageA, equalTo(messageCaptor.getValue().what));
146 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
147 collector.checkThat("2: messageB", messageB, equalTo(messageCaptor.getValue().what));
148 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
149 collector.checkThat("3: messageC", messageC, equalTo(messageCaptor.getValue().what));
150
151 inOrder.verify(mHandlerSpy, never()).handleMessage(any(Message.class));
152 }
153
154 /**
155 * Test message sequence: A, B, C@5K, Advance time by 4K, A@1K, B@2K Advance
156 * time by 1K.
157 * <p>
158 * Expected: get A, B, C, A
159 */
160 @Test
161 public void testDelayedDispatchAdvanceTimeTwice() {
162 final int messageA = 1;
163 final int messageB = 2;
164 final int messageC = 3;
165
166 InOrder inOrder = inOrder(mHandlerSpy);
167 ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
168
169 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageA));
170 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageB));
171 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageC), 5000);
172 mTestLooper.moveTimeForward(4000);
173 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageA), 1000);
174 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageB), 2000);
175 mTestLooper.moveTimeForward(1000);
176 mTestLooper.dispatchAll();
177
178 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
179 collector.checkThat("1: messageA", messageA, equalTo(messageCaptor.getValue().what));
180 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
181 collector.checkThat("2: messageB", messageB, equalTo(messageCaptor.getValue().what));
182 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
183 collector.checkThat("3: messageC", messageC, equalTo(messageCaptor.getValue().what));
184 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
185 collector.checkThat("4: messageA", messageA, equalTo(messageCaptor.getValue().what));
186
187 inOrder.verify(mHandlerSpy, never()).handleMessage(any(Message.class));
188 }
189
190 /**
191 * Test message sequence: A, B, C@5K, Advance time by 4K, A@5K, B@2K Advance
192 * time by 3K.
193 * <p>
194 * Expected: get A, B, C, B
195 */
196 @Test
197 public void testDelayedDispatchReverseOrder() {
198 final int messageA = 1;
199 final int messageB = 2;
200 final int messageC = 3;
201
202 InOrder inOrder = inOrder(mHandlerSpy);
203 ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
204
205 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageA));
206 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageB));
207 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageC), 5000);
208 mTestLooper.moveTimeForward(4000);
209 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageA), 5000);
210 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageB), 2000);
211 mTestLooper.moveTimeForward(3000);
212 mTestLooper.dispatchAll();
213
214 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
215 collector.checkThat("1: messageA", messageA, equalTo(messageCaptor.getValue().what));
216 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
217 collector.checkThat("2: messageB", messageB, equalTo(messageCaptor.getValue().what));
218 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
219 collector.checkThat("3: messageC", messageC, equalTo(messageCaptor.getValue().what));
220 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
221 collector.checkThat("4: messageB", messageB, equalTo(messageCaptor.getValue().what));
222
223 inOrder.verify(mHandlerSpy, never()).handleMessage(any(Message.class));
224 }
225
226 /**
227 * Test message sequence: A, B, C@5K, Advance time by 4K, dispatch all,
228 * A@5K, B@2K Advance time by 3K, dispatch all.
229 * <p>
230 * Expected: get A, B after first dispatch; then C, B after second dispatch
231 */
232 @Test
233 public void testDelayedDispatchAllMultipleTimes() {
234 final int messageA = 1;
235 final int messageB = 2;
236 final int messageC = 3;
237
238 InOrder inOrder = inOrder(mHandlerSpy);
239 ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
240
241 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageA));
242 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageB));
243 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageC), 5000);
244 mTestLooper.moveTimeForward(4000);
245 mTestLooper.dispatchAll();
246
247 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
248 collector.checkThat("1: messageA", messageA, equalTo(messageCaptor.getValue().what));
249 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
250 collector.checkThat("2: messageB", messageB, equalTo(messageCaptor.getValue().what));
251
252 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageA), 5000);
253 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageB), 2000);
254 mTestLooper.moveTimeForward(3000);
255 mTestLooper.dispatchAll();
256
257 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
258 collector.checkThat("3: messageC", messageC, equalTo(messageCaptor.getValue().what));
259 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture());
260 collector.checkThat("4: messageB", messageB, equalTo(messageCaptor.getValue().what));
261
262 inOrder.verify(mHandlerSpy, never()).handleMessage(any(Message.class));
263 }
264
265 /**
266 * Test AutoDispatch for a single message.
267 * This test would ideally use the Channel sendMessageSynchronously. At this time, the setup to
268 * get a working test channel is cumbersome. Until this is fixed, we substitute with a
269 * sendMessage followed by a blocking call. The main test thread blocks until the test handler
270 * receives the test message (messageA) and sets a boolean true. Once the boolean is true, the
271 * main thread will exit the busy wait loop, stop autoDispatch and check the assert.
272 *
273 * Enable AutoDispatch, add message, block on message being handled and stop AutoDispatch.
274 * <p>
275 * Expected: handleMessage is called for messageA and stopAutoDispatch is called.
276 */
277 @Test
278 public void testAutoDispatchWithSingleMessage() {
279 final int mLoopSleepTimeMs = 5;
280
281 final int messageA = 1;
282
283 TestLooper mockLooper = new TestLooper();
284 class TestHandler extends Handler {
285 public volatile boolean handledMessage = false;
286 TestHandler(Looper looper) {
287 super(looper);
288 }
289
290 @Override
291 public void handleMessage(Message msg) {
292 if (msg.what == messageA) {
293 handledMessage = true;
294 }
295 }
296 }
297
298 TestHandler testHandler = new TestHandler(mockLooper.getLooper());
299 mockLooper.startAutoDispatch();
300 testHandler.sendMessage(testHandler.obtainMessage(messageA));
301 while (!testHandler.handledMessage) {
302 // Block until message is handled
303 try {
304 Thread.sleep(mLoopSleepTimeMs);
305 } catch (InterruptedException e) {
306 // Interrupted while sleeping.
307 }
308 }
309 mockLooper.stopAutoDispatch();
310 assertTrue("TestHandler should have received messageA", testHandler.handledMessage);
311 }
312
313 /**
314 * Test starting AutoDispatch while already running throws IllegalStateException
315 * Enable AutoDispatch two times in a row.
316 * <p>
317 * Expected: catch IllegalStateException on second call.
318 */
319 @Test(expected = IllegalStateException.class)
320 public void testRepeatedStartAutoDispatchThrowsException() {
321 mTestLooper.startAutoDispatch();
322 mTestLooper.startAutoDispatch();
323 }
324
325 /**
326 * Test stopping AutoDispatch without previously starting throws IllegalStateException
327 * Stop AutoDispatch
328 * <p>
329 * Expected: catch IllegalStateException on second call.
330 */
331 @Test(expected = IllegalStateException.class)
332 public void testStopAutoDispatchWithoutStartThrowsException() {
333 mTestLooper.stopAutoDispatch();
334 }
335
336 /**
337 * Test AutoDispatch exits and does not dispatch a later message.
338 * Start and stop AutoDispatch then add a message.
339 * <p>
340 * Expected: After AutoDispatch is stopped, dispatchAll will return 1.
341 */
342 @Test
343 public void testAutoDispatchStopsCleanlyWithoutDispatchingAMessage() {
344 final int messageA = 1;
345
346 InOrder inOrder = inOrder(mHandlerSpy);
347 ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
348
349 mTestLooper.startAutoDispatch();
350 try {
351 mTestLooper.stopAutoDispatch();
352 } catch (IllegalStateException e) {
353 // Stopping without a dispatch will throw an exception.
354 }
355
356 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageA));
357 assertEquals("One message should be dispatched", 1, mTestLooper.dispatchAll());
358 }
359
360 /**
361 * Test AutoDispatch throws an exception when no messages are dispatched.
362 * Start and stop AutoDispatch
363 * <p>
364 * Expected: Exception is thrown with the stopAutoDispatch call.
365 */
366 @Test(expected = IllegalStateException.class)
367 public void testAutoDispatchThrowsExceptionWhenNoMessagesDispatched() {
368 mTestLooper.startAutoDispatch();
369 mTestLooper.stopAutoDispatch();
370 }
371}