WifiStateMachinePrimeTest.java revision bfc30bd4c2ff0c62d6cfff22088a935878966a46
1/*
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 com.android.server.wifi;
18
19import static org.junit.Assert.assertEquals;
20import static org.mockito.Mockito.*;
21
22import android.net.wifi.IApInterface;
23import android.net.wifi.IWificond;
24import android.net.wifi.WifiConfiguration;
25import android.net.wifi.WifiManager;
26import android.os.INetworkManagementService;
27import android.os.test.TestLooper;
28import android.test.suitebuilder.annotation.SmallTest;
29import android.util.Log;
30
31import org.junit.After;
32import org.junit.Before;
33import org.junit.Test;
34import org.mockito.Mock;
35import org.mockito.MockitoAnnotations;
36import org.mockito.invocation.InvocationOnMock;
37import org.mockito.stubbing.Answer;
38
39/**
40 * Unit tests for {@link com.android.server.wifi.WifiStateMachinePrime}.
41 */
42@SmallTest
43public class WifiStateMachinePrimeTest {
44    public static final String TAG = "WifiStateMachinePrimeTest";
45
46    private static final String CLIENT_MODE_STATE_STRING = "ClientModeState";
47    private static final String SCAN_ONLY_MODE_STATE_STRING = "ScanOnlyModeState";
48    private static final String SOFT_AP_MODE_STATE_STRING = "SoftAPModeState";
49    private static final String WIFI_DISABLED_STATE_STRING = "WifiDisabledState";
50    private static final String CLIENT_MODE_ACTIVE_STATE_STRING = "ClientModeActiveState";
51    private static final String SCAN_ONLY_MODE_ACTIVE_STATE_STRING = "ScanOnlyModeActiveState";
52    private static final String SOFT_AP_MODE_ACTIVE_STATE_STRING = "SoftAPModeActiveState";
53
54    @Mock WifiInjector mWifiInjector;
55    TestLooper mLooper;
56    @Mock IWificond mWificond;
57    @Mock IApInterface mApInterface;
58    @Mock INetworkManagementService mNMService;
59    @Mock SoftApManager mSoftApManager;
60    SoftApManager.Listener mSoftApListener;
61    @Mock WifiConfiguration mApConfig;
62    WifiStateMachinePrime mWifiStateMachinePrime;
63
64    /**
65     * Set up the test environment.
66     */
67    @Before
68    public void setUp() throws Exception {
69        Log.d(TAG, "Setting up ...");
70
71        MockitoAnnotations.initMocks(this);
72        mLooper = new TestLooper();
73
74        mWifiInjector = mock(WifiInjector.class);
75        mWifiStateMachinePrime = createWifiStateMachinePrime();
76    }
77
78    private WifiStateMachinePrime createWifiStateMachinePrime() {
79        when(mWifiInjector.makeWificond()).thenReturn(null);
80        return new WifiStateMachinePrime(mWifiInjector, mLooper.getLooper(), mNMService);
81    }
82
83    /**
84     * Clean up after tests - explicitly set tested object to null.
85     */
86    @After
87    public void cleanUp() throws Exception {
88        mWifiStateMachinePrime = null;
89    }
90
91    /**
92     * Helper method to enter the SoftApActiveMode for WifiStateMachinePrime.
93     *
94     * This method puts the test object into the correct state and verifies steps along the way.
95     */
96    private void enterSoftApActiveMode() throws Exception {
97        String fromState = mWifiStateMachinePrime.getCurrentMode();
98        when(mWifiInjector.makeWificond()).thenReturn(mWificond);
99        when(mWificond.createApInterface()).thenReturn(mApInterface);
100        doAnswer(
101                new Answer<Object>() {
102                    public SoftApManager answer(InvocationOnMock invocation) {
103                        mSoftApListener = (SoftApManager.Listener) invocation.getArguments()[1];
104                        return mSoftApManager;
105                    }
106                }).when(mWifiInjector).makeSoftApManager(any(INetworkManagementService.class),
107                                                         any(SoftApManager.Listener.class),
108                                                         any(IApInterface.class),
109                                                         any(WifiConfiguration.class));
110        mWifiStateMachinePrime.enterSoftAPMode();
111        mLooper.dispatchNext();
112        assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
113        Log.e("WifiStateMachinePrimeTest", "check fromState: " + fromState);
114        if (!fromState.equals(WIFI_DISABLED_STATE_STRING)) {
115            verify(mWificond).tearDownInterfaces();
116        }
117        mLooper.dispatchNext();
118        assertEquals(SOFT_AP_MODE_ACTIVE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
119        verify(mSoftApManager).start();
120    }
121
122    /**
123     * Test that when a new instance of WifiStateMachinePrime is created, any existing interfaces in
124     * the retrieved Wificond instance are cleaned up.
125     * Expectations:  When the new WifiStateMachinePrime instance is created a call to
126     * Wificond.tearDownInterfaces() is made.
127     */
128    @Test
129    public void testWificondExistsOnStartup() throws Exception {
130        when(mWifiInjector.makeWificond()).thenReturn(mWificond);
131        WifiStateMachinePrime testWifiStateMachinePrime =
132                new WifiStateMachinePrime(mWifiInjector, mLooper.getLooper(), mNMService);
133        verify(mWificond).tearDownInterfaces();
134    }
135
136    /**
137     * Test that WifiStateMachinePrime properly enters the SoftApModeActiveState from the
138     * WifiDisabled state.
139     */
140    @Test
141    public void testEnterSoftApModeFromDisabled() throws Exception {
142        enterSoftApActiveMode();
143    }
144
145    /**
146     * Test that WifiStateMachinePrime properly enters the SoftApModeActiveState from another state.
147     * Expectations: When going from one state to another, any interfaces that are still up are torn
148     * down.
149     */
150    @Test
151    public void testEnterSoftApModeFromDifferentState() throws Exception {
152        when(mWifiInjector.makeWificond()).thenReturn(mWificond);
153        mWifiStateMachinePrime.enterClientMode();
154        mLooper.dispatchNext();
155        assertEquals(CLIENT_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
156        enterSoftApActiveMode();
157    }
158
159    /**
160     * Test that we can disable wifi fully from the SoftApModeActiveState.
161     */
162    @Test
163    public void testDisableWifiFromSoftApModeActiveState() throws Exception {
164        enterSoftApActiveMode();
165
166        mWifiStateMachinePrime.disableWifi();
167        mLooper.dispatchNext();
168        verify(mSoftApManager).stop();
169        verify(mWificond).tearDownInterfaces();
170        assertEquals(WIFI_DISABLED_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
171    }
172
173    /**
174     * Test that we can disable wifi fully from the SoftApModeState.
175     */
176    @Test
177    public void testDisableWifiFromSoftApModeState() throws Exception {
178        // Use a failure getting wificond to stay in the SoftAPModeState
179        when(mWifiInjector.makeWificond()).thenReturn(null);
180        mWifiStateMachinePrime.enterSoftAPMode();
181        mLooper.dispatchNext();
182        assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
183        mLooper.dispatchNext();
184        assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
185
186        mWifiStateMachinePrime.disableWifi();
187        mLooper.dispatchNext();
188        // mWificond will be null due to this test, no call to tearDownInterfaces here.
189        assertEquals(WIFI_DISABLED_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
190    }
191
192    /**
193     * Test that we can switch from SoftApActiveMode to another mode.
194     * Expectation: When switching out of SoftApModeActiveState we stop the SoftApManager and tear
195     * down existing interfaces.
196     */
197    @Test
198    public void testSwitchModeWhenSoftApActiveMode() throws Exception {
199        enterSoftApActiveMode();
200
201        mWifiStateMachinePrime.enterClientMode();
202        mLooper.dispatchNext();
203        verify(mSoftApManager).stop();
204        verify(mWificond).tearDownInterfaces();
205        assertEquals(CLIENT_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
206    }
207
208    /**
209     * Test that we do not attempt to enter SoftApModeActiveState when we cannot get a reference to
210     * wificond.
211     * Expectations: After a failed attempt to get wificond from WifiInjector, we should remain in
212     * the SoftApModeState.
213     */
214    @Test
215    public void testWificondNullWhenSwitchingToApMode() throws Exception {
216        when(mWifiInjector.makeWificond()).thenReturn(null);
217        mWifiStateMachinePrime.enterSoftAPMode();
218        mLooper.dispatchNext();
219        assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
220        mLooper.dispatchNext();
221        assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
222    }
223
224    /**
225     * Test that we do not attempt to enter SoftApModeActiveState when we cannot get an ApInterface
226     * from wificond.
227     * Expectations: After a failed attempt to get an ApInterface from WifiInjector, we should
228     * remain in the SoftApModeState.
229     */
230    @Test
231    public void testAPInterfaceFailedWhenSwitchingToApMode() throws Exception {
232        when(mWifiInjector.makeWificond()).thenReturn(mWificond);
233        when(mWificond.createApInterface()).thenReturn(null);
234        mWifiStateMachinePrime.enterSoftAPMode();
235        mLooper.dispatchNext();
236        assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
237        mLooper.dispatchNext();
238        assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
239    }
240
241    /**
242     * Test that we do can enter the SoftApModeActiveState if we are already in the SoftApModeState.
243     * Expectations: We should exit the current SoftApModeState and re-enter before successfully
244     * entering the SoftApModeActiveState.
245     */
246    @Test
247    public void testEnterSoftApModeActiveWhenAlreadyInSoftApMode() throws Exception {
248        when(mWifiInjector.makeWificond()).thenReturn(mWificond);
249        when(mWificond.createApInterface()).thenReturn(null);
250        mWifiStateMachinePrime.enterSoftAPMode();
251        mLooper.dispatchNext();
252        assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
253        mLooper.dispatchNext();
254        assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
255
256        enterSoftApActiveMode();
257        verify(mWificond).tearDownInterfaces();
258    }
259
260    /**
261     * Test that we return to the SoftApModeState after a failure is reported when in the
262     * SoftApModeActiveState.
263     * Expectations: We should exit the SoftApModeActiveState and stop the SoftApManager.
264     */
265    @Test
266    public void testSoftApFailureWhenActive() throws Exception {
267        enterSoftApActiveMode();
268        // now inject failure through the SoftApManager.Listener
269        mSoftApListener.onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, 0);
270        mLooper.dispatchNext();
271        assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
272        verify(mSoftApManager).stop();
273    }
274
275    /**
276     * Test that we return to the SoftApModeState after the SoftApManager is stopped in the
277     * SoftApModeActiveState.
278     * Expectations: We should exit the SoftApModeActiveState and stop the SoftApManager.
279     */
280    @Test
281    public void testSoftApDisabledWhenActive() throws Exception {
282        enterSoftApActiveMode();
283        // now inject failure through the SoftApManager.Listener
284        mSoftApListener.onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, 0);
285        mLooper.dispatchNext();
286        assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
287        verify(mSoftApManager).stop();
288    }
289
290    /**
291     * Test that we safely disable wifi if it is already disabled.
292     * Expectations: We should not interact with wificond since we should have already cleaned up
293     * everything.
294     */
295    @Test
296    public void disableWifiWhenAlreadyOff() throws Exception {
297        verifyNoMoreInteractions(mWificond);
298        mWifiStateMachinePrime.disableWifi();
299    }
300}
301