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