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.mock; 23 import static org.mockito.Mockito.never; 24 import static org.mockito.Mockito.times; 25 import static org.mockito.Mockito.verify; 26 import static org.mockito.Mockito.when; 27 28 import org.junit.Before; 29 import org.junit.Test; 30 import org.junit.runner.RunWith; 31 32 import android.os.Handler; 33 import android.os.Looper; 34 import android.os.Message; 35 import android.test.suitebuilder.annotation.SmallTest; 36 import android.testing.TestableLooper.MessageHandler; 37 import android.testing.TestableLooper.RunWithLooper; 38 39 @SmallTest 40 @RunWith(AndroidTestingRunner.class) 41 @RunWithLooper 42 public class TestableLooperTest { 43 44 private TestableLooper mTestableLooper; 45 46 @Before setup()47 public void setup() throws Exception { 48 mTestableLooper = TestableLooper.get(this); 49 } 50 51 @Test testMessageExecuted()52 public void testMessageExecuted() throws Exception { 53 Handler h = new Handler(); 54 Runnable r = mock(Runnable.class); 55 h.post(r); 56 verify(r, never()).run(); 57 mTestableLooper.processAllMessages(); 58 verify(r).run(); 59 } 60 61 @Test testMessageCallback()62 public void testMessageCallback() throws Exception { 63 Handler h = new Handler(); 64 Message m = h.obtainMessage(3); 65 Runnable r = mock(Runnable.class); 66 MessageHandler messageHandler = mock(MessageHandler.class); 67 when(messageHandler.onMessageHandled(any())).thenReturn(false); 68 mTestableLooper.setMessageHandler(messageHandler); 69 70 m.sendToTarget(); 71 h.post(r); 72 73 mTestableLooper.processAllMessages(); 74 75 verify(messageHandler).onMessageHandled(eq(m)); 76 // This should never be run becaus the mock returns false on the first message, and 77 // the second will get skipped. 78 verify(r, never()).run(); 79 } 80 81 @Test testProcessNumberOfMessages()82 public void testProcessNumberOfMessages() throws Exception { 83 Handler h = new Handler(); 84 Runnable r = mock(Runnable.class); 85 h.post(r); 86 h.post(r); 87 h.post(r); 88 89 mTestableLooper.processMessages(2); 90 91 verify(r, times(2)).run(); 92 } 93 94 @Test testProcessAllMessages()95 public void testProcessAllMessages() throws Exception { 96 Handler h = new Handler(); 97 Runnable r = mock(Runnable.class); 98 Runnable poster = () -> h.post(r); 99 h.post(poster); 100 101 mTestableLooper.processAllMessages(); 102 verify(r).run(); 103 } 104 105 @Test test3Chain()106 public void test3Chain() throws Exception { 107 Handler h = new Handler(); 108 Runnable r = mock(Runnable.class); 109 Runnable poster = () -> h.post(r); 110 Runnable poster2 = () -> h.post(poster); 111 h.post(poster2); 112 113 mTestableLooper.processAllMessages(); 114 verify(r).run(); 115 } 116 117 @Test testProcessAllMessages_2Messages()118 public void testProcessAllMessages_2Messages() throws Exception { 119 Handler h = new Handler(); 120 Runnable r = mock(Runnable.class); 121 Runnable r2 = mock(Runnable.class); 122 h.post(r); 123 h.post(r2); 124 125 mTestableLooper.processAllMessages(); 126 verify(r).run(); 127 verify(r2).run(); 128 } 129 130 @Test testMainLooper()131 public void testMainLooper() throws Exception { 132 assertNotEquals(Looper.myLooper(), Looper.getMainLooper()); 133 Runnable r = mock(Runnable.class); 134 Runnable r2 = mock(Runnable.class); 135 TestableLooper testableLooper = new TestableLooper(Looper.getMainLooper()); 136 137 try { 138 testableLooper.setMessageHandler(m -> { 139 if (m.getCallback() == r) return true; 140 return false; 141 }); 142 new Handler(Looper.getMainLooper()).post(r); 143 testableLooper.processAllMessages(); 144 145 verify(r).run(); 146 verify(r2, never()).run(); 147 } finally { 148 testableLooper.destroy(); 149 } 150 } 151 152 @Test testNonMainLooperAnnotation()153 public void testNonMainLooperAnnotation() { 154 assertNotEquals(Looper.myLooper(), Looper.getMainLooper()); 155 } 156 157 @Test 158 @RunWithLooper(setAsMainLooper = true) testMainLooperAnnotation()159 public void testMainLooperAnnotation() { 160 assertEquals(Looper.myLooper(), Looper.getMainLooper()); 161 } 162 163 @Test testCorrectLooperExecution()164 public void testCorrectLooperExecution() throws Exception { 165 boolean[] hasRun = new boolean[] { false }; 166 Runnable r = () -> { 167 assertEquals("Should run on main looper", Looper.getMainLooper(), Looper.myLooper()); 168 hasRun[0] = true; 169 }; 170 TestableLooper testableLooper = new TestableLooper(Looper.getMainLooper()); 171 try { 172 new Handler(Looper.getMainLooper()).post(r); 173 testableLooper.processAllMessages(); 174 175 assertTrue(hasRun[0]); 176 } finally { 177 testableLooper.destroy(); 178 } 179 } 180 } 181