1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package android.testing; 16 17 import static org.junit.Assert.assertEquals; 18 import static org.junit.Assert.assertNotEquals; 19 import static org.junit.Assert.assertTrue; 20 import static org.mockito.Matchers.any; 21 import static org.mockito.Matchers.eq; 22 import static org.mockito.Mockito.inOrder; 23 import static org.mockito.Mockito.mock; 24 import static org.mockito.Mockito.never; 25 import static org.mockito.Mockito.spy; 26 import static org.mockito.Mockito.times; 27 import static org.mockito.Mockito.verify; 28 import static org.mockito.Mockito.when; 29 30 import android.os.Handler; 31 import android.os.Looper; 32 import android.os.Message; 33 import android.test.suitebuilder.annotation.SmallTest; 34 import android.testing.TestableLooper.MessageHandler; 35 import android.testing.TestableLooper.RunWithLooper; 36 37 import org.junit.Before; 38 import org.junit.Test; 39 import org.junit.runner.RunWith; 40 import org.mockito.InOrder; 41 42 @SmallTest 43 @RunWith(AndroidTestingRunner.class) 44 @RunWithLooper 45 public class TestableLooperTest { 46 47 private TestableLooper mTestableLooper; 48 49 @Before setup()50 public void setup() throws Exception { 51 mTestableLooper = TestableLooper.get(this); 52 } 53 54 @Test testMessageExecuted()55 public void testMessageExecuted() throws Exception { 56 Handler h = new Handler(); 57 Runnable r = mock(Runnable.class); 58 h.post(r); 59 verify(r, never()).run(); 60 mTestableLooper.processAllMessages(); 61 verify(r).run(); 62 } 63 64 @Test testMessageCallback()65 public void testMessageCallback() throws Exception { 66 Handler h = new Handler(); 67 Message m = h.obtainMessage(3); 68 Runnable r = mock(Runnable.class); 69 MessageHandler messageHandler = mock(MessageHandler.class); 70 when(messageHandler.onMessageHandled(any())).thenReturn(false); 71 mTestableLooper.setMessageHandler(messageHandler); 72 73 m.sendToTarget(); 74 h.post(r); 75 76 mTestableLooper.processAllMessages(); 77 78 verify(messageHandler).onMessageHandled(eq(m)); 79 // This should never be run becaus the mock returns false on the first message, and 80 // the second will get skipped. 81 verify(r, never()).run(); 82 } 83 84 @Test testProcessNumberOfMessages()85 public void testProcessNumberOfMessages() throws Exception { 86 Handler h = new Handler(); 87 Runnable r = mock(Runnable.class); 88 h.post(r); 89 h.post(r); 90 h.post(r); 91 92 mTestableLooper.processMessages(2); 93 94 verify(r, times(2)).run(); 95 } 96 97 @Test testProcessAllMessages()98 public void testProcessAllMessages() throws Exception { 99 Handler h = new Handler(); 100 Runnable r = mock(Runnable.class); 101 Runnable poster = () -> h.post(r); 102 h.post(poster); 103 104 mTestableLooper.processAllMessages(); 105 verify(r).run(); 106 } 107 108 @Test test3Chain()109 public void test3Chain() throws Exception { 110 Handler h = new Handler(); 111 Runnable r = mock(Runnable.class); 112 Runnable poster = () -> h.post(r); 113 Runnable poster2 = () -> h.post(poster); 114 h.post(poster2); 115 116 mTestableLooper.processAllMessages(); 117 verify(r).run(); 118 } 119 120 @Test testProcessAllMessages_2Messages()121 public void testProcessAllMessages_2Messages() throws Exception { 122 Handler h = new Handler(); 123 Runnable r = mock(Runnable.class); 124 Runnable r2 = mock(Runnable.class); 125 h.post(r); 126 h.post(r2); 127 128 mTestableLooper.processAllMessages(); 129 verify(r).run(); 130 verify(r2).run(); 131 } 132 133 @Test testMainLooper()134 public void testMainLooper() throws Exception { 135 assertNotEquals(Looper.myLooper(), Looper.getMainLooper()); 136 Runnable r = mock(Runnable.class); 137 Runnable r2 = mock(Runnable.class); 138 TestableLooper testableLooper = new TestableLooper(Looper.getMainLooper()); 139 140 try { 141 testableLooper.setMessageHandler(m -> { 142 if (m.getCallback() == r) return true; 143 return false; 144 }); 145 new Handler(Looper.getMainLooper()).post(r); 146 testableLooper.processAllMessages(); 147 148 verify(r).run(); 149 verify(r2, never()).run(); 150 } finally { 151 testableLooper.destroy(); 152 } 153 } 154 155 @Test testNonMainLooperAnnotation()156 public void testNonMainLooperAnnotation() { 157 assertNotEquals(Looper.myLooper(), Looper.getMainLooper()); 158 } 159 160 @Test 161 @RunWithLooper(setAsMainLooper = true) testMainLooperAnnotation()162 public void testMainLooperAnnotation() { 163 assertEquals(Looper.myLooper(), Looper.getMainLooper()); 164 } 165 166 @Test testCorrectLooperExecution()167 public void testCorrectLooperExecution() throws Exception { 168 boolean[] hasRun = new boolean[]{false}; 169 Runnable r = () -> { 170 assertEquals("Should run on main looper", Looper.getMainLooper(), Looper.myLooper()); 171 hasRun[0] = true; 172 }; 173 TestableLooper testableLooper = new TestableLooper(Looper.getMainLooper()); 174 try { 175 new Handler(Looper.getMainLooper()).post(r); 176 testableLooper.processAllMessages(); 177 178 assertTrue(hasRun[0]); 179 } finally { 180 testableLooper.destroy(); 181 } 182 } 183 184 @Test testDelayedDispatchNoTimeMove()185 public void testDelayedDispatchNoTimeMove() { 186 Handler handler = spy(new Handler(mTestableLooper.getLooper())); 187 InOrder inOrder = inOrder(handler); 188 189 final Message messageA = handler.obtainMessage(1); 190 final Message messageB = handler.obtainMessage(2); 191 192 handler.sendMessageDelayed(messageA, 0); 193 handler.sendMessageDelayed(messageB, 0); 194 195 mTestableLooper.processAllMessages(); 196 197 inOrder.verify(handler).dispatchMessage(messageA); 198 inOrder.verify(handler).dispatchMessage(messageB); 199 } 200 201 @Test testDelayedMessageDoesntSend()202 public void testDelayedMessageDoesntSend() { 203 Handler handler = spy(new Handler(mTestableLooper.getLooper())); 204 InOrder inOrder = inOrder(handler); 205 206 final Message messageA = handler.obtainMessage(1); 207 final Message messageB = handler.obtainMessage(2); 208 final Message messageC = handler.obtainMessage(3); 209 210 handler.sendMessageDelayed(messageA, 0); 211 handler.sendMessageDelayed(messageB, 0); 212 handler.sendMessageDelayed(messageC, 500); 213 214 mTestableLooper.processAllMessages(); 215 216 inOrder.verify(handler).dispatchMessage(messageA); 217 inOrder.verify(handler).dispatchMessage(messageB); 218 verify(handler, never()).dispatchMessage(messageC); 219 } 220 221 @Test testMessageSendsAfterDelay()222 public void testMessageSendsAfterDelay() { 223 Handler handler = spy(new Handler(mTestableLooper.getLooper())); 224 InOrder inOrder = inOrder(handler); 225 226 final Message messageA = handler.obtainMessage(1); 227 final Message messageB = handler.obtainMessage(2); 228 final Message messageC = handler.obtainMessage(3); 229 230 handler.sendMessageDelayed(messageA, 0); 231 handler.sendMessageDelayed(messageB, 0); 232 handler.sendMessageDelayed(messageC, 500); 233 234 mTestableLooper.moveTimeForward(500); 235 mTestableLooper.processAllMessages(); 236 237 inOrder.verify(handler).dispatchMessage(messageA); 238 inOrder.verify(handler).dispatchMessage(messageB); 239 inOrder.verify(handler).dispatchMessage(messageC); 240 } 241 242 @Test testProcessMessagesNonBlocking_onlyArgNumber()243 public void testProcessMessagesNonBlocking_onlyArgNumber() { 244 Handler h = new Handler(mTestableLooper.getLooper()); 245 Runnable r = mock(Runnable.class); 246 247 h.post(r); 248 h.post(r); 249 h.post(r); 250 251 int processed = mTestableLooper.processMessagesNonBlocking(2); 252 253 verify(r, times(2)).run(); 254 assertEquals(2, processed); 255 } 256 257 @Test testProcessMessagesNonBlocking_lessMessagesThanArg()258 public void testProcessMessagesNonBlocking_lessMessagesThanArg() { 259 Handler h = new Handler(mTestableLooper.getLooper()); 260 Runnable r = mock(Runnable.class); 261 262 h.post(r); 263 h.post(r); 264 h.post(r); 265 266 int processed = mTestableLooper.processMessagesNonBlocking(5); 267 268 verify(r, times(3)).run(); 269 assertEquals(3, processed); 270 } 271 } 272