PasspointManagerTest.java revision 4781e9e2904824ef1fbf8a0cf75e89fa957d6a92
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.hotspot2;
18
19import static android.net.wifi.WifiManager.EXTRA_PASSPOINT_ICON_BSSID;
20import static android.net.wifi.WifiManager.EXTRA_PASSPOINT_ICON_DATA;
21import static android.net.wifi.WifiManager.EXTRA_PASSPOINT_ICON_FILE;
22import static android.net.wifi.WifiManager.PASSPOINT_ICON_RECEIVED_ACTION;
23
24import static org.junit.Assert.assertEquals;
25import static org.junit.Assert.assertFalse;
26import static org.junit.Assert.assertTrue;
27import static org.mockito.Mockito.eq;
28import static org.mockito.Mockito.verify;
29import static org.mockito.Mockito.when;
30import static org.mockito.MockitoAnnotations.initMocks;
31
32import android.content.Context;
33import android.content.Intent;
34import android.net.wifi.EAPConstants;
35import android.net.wifi.hotspot2.PasspointConfiguration;
36import android.net.wifi.hotspot2.pps.Credential;
37import android.net.wifi.hotspot2.pps.HomeSP;
38import android.os.UserHandle;
39import android.test.suitebuilder.annotation.SmallTest;
40
41import com.android.server.wifi.FakeKeys;
42import com.android.server.wifi.IMSIParameter;
43import com.android.server.wifi.SIMAccessor;
44import com.android.server.wifi.WifiInjector;
45
46import org.junit.Before;
47import org.junit.Test;
48import org.mockito.ArgumentCaptor;
49import org.mockito.Mock;
50
51import java.util.ArrayList;
52import java.util.List;
53
54/**
55 * Unit tests for {@link com.android.server.wifi.hotspot2.PasspointManager}.
56 */
57@SmallTest
58public class PasspointManagerTest {
59    private static final long BSSID = 0x112233445566L;
60    private static final String ICON_FILENAME = "test";
61    private static final String TEST_FQDN = "test1.test.com";
62    private static final String TEST_FQDN1 = "test.com";
63    private static final String TEST_FRIENDLY_NAME = "friendly name";
64    private static final String TEST_REALM = "realm.test.com";
65    private static final String TEST_IMSI = "1234*";
66
67    @Mock Context mContext;
68    @Mock WifiInjector mWifiInjector;
69    @Mock PasspointEventHandler.Callbacks mCallbacks;
70    @Mock SIMAccessor mSimAccessor;
71    PasspointManager mManager;
72
73    /** Sets up test. */
74    @Before
75    public void setUp() throws Exception {
76        initMocks(this);
77        mManager = new PasspointManager(mContext, mWifiInjector, mSimAccessor);
78        ArgumentCaptor<PasspointEventHandler.Callbacks> callbacks =
79                ArgumentCaptor.forClass(PasspointEventHandler.Callbacks.class);
80        verify(mWifiInjector).makePasspointEventHandler(callbacks.capture());
81        mCallbacks = callbacks.getValue();
82    }
83
84    /**
85     * Verify PASSPOINT_ICON_RECEIVED_ACTION broadcast intent.
86     * @param bssid BSSID of the AP
87     * @param fileName Name of the icon file
88     * @param data icon data byte array
89     */
90    private void verifyIconIntent(long bssid, String fileName, byte[] data) {
91        ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
92        verify(mContext).sendBroadcastAsUser(intent.capture(), eq(UserHandle.ALL));
93        assertEquals(PASSPOINT_ICON_RECEIVED_ACTION, intent.getValue().getAction());
94        assertTrue(intent.getValue().getExtras().containsKey(EXTRA_PASSPOINT_ICON_BSSID));
95        assertEquals(bssid, intent.getValue().getExtras().getLong(EXTRA_PASSPOINT_ICON_BSSID));
96        assertTrue(intent.getValue().getExtras().containsKey(EXTRA_PASSPOINT_ICON_FILE));
97        assertEquals(fileName, intent.getValue().getExtras().getString(EXTRA_PASSPOINT_ICON_FILE));
98        if (data != null) {
99            assertTrue(intent.getValue().getExtras().containsKey(EXTRA_PASSPOINT_ICON_DATA));
100            assertEquals(data,
101                         intent.getValue().getExtras().getByteArray(EXTRA_PASSPOINT_ICON_DATA));
102        }
103    }
104
105    /**
106     * Verify that the given Passpoint configuration matches the one that's added to
107     * the PasspointManager.
108     *
109     * @param expectedConfig The expected installed Passpoint configuration
110     */
111    private void verifyInstalledConfig(PasspointConfiguration expectedConfig) {
112        List<PasspointConfiguration> installedConfigs = mManager.getProviderConfigs();
113        assertEquals(1, installedConfigs.size());
114        assertEquals(expectedConfig, installedConfigs.get(0));
115    }
116
117    /**
118     * Validate the broadcast intent when icon file retrieval succeeded.
119     *
120     * @throws Exception
121     */
122    @Test
123    public void iconResponseSuccess() throws Exception {
124        byte[] iconData = new byte[] {0x00, 0x11};
125        mCallbacks.onIconResponse(BSSID, ICON_FILENAME, iconData);
126        verifyIconIntent(BSSID, ICON_FILENAME, iconData);
127    }
128
129    /**
130     * Validate the broadcast intent when icon file retrieval failed.
131     *
132     * @throws Exception
133     */
134    @Test
135    public void iconResponseFailure() throws Exception {
136        mCallbacks.onIconResponse(BSSID, ICON_FILENAME, null);
137        verifyIconIntent(BSSID, ICON_FILENAME, null);
138    }
139
140    /**
141     * Verify that adding a provider with a null configuration will fail.
142     *
143     * @throws Exception
144     */
145    @Test
146    public void addProviderWithNullConfig() throws Exception {
147        assertFalse(mManager.addProvider(null));
148    }
149
150    /**
151     * Verify that adding a provider with a empty configuration will fail.
152     *
153     * @throws Exception
154     */
155    @Test
156    public void addProviderWithEmptyConfig() throws Exception {
157        assertFalse(mManager.addProvider(new PasspointConfiguration()));
158    }
159
160    /**
161     * Verify taht adding a provider with an invalid credential will fail (using EAP-TLS
162     * for user credential).
163     *
164     * @throws Exception
165     */
166    @Test
167    public void addProviderWithInvalidCredential() throws Exception {
168        PasspointConfiguration config = new PasspointConfiguration();
169        config.homeSp = new HomeSP();
170        config.homeSp.fqdn = TEST_FQDN;
171        config.homeSp.friendlyName = TEST_FRIENDLY_NAME;
172        config.credential = new Credential();
173        config.credential.realm = TEST_REALM;
174        config.credential.caCertificate = FakeKeys.CA_CERT0;
175        config.credential.userCredential = new Credential.UserCredential();
176        config.credential.userCredential.username = "username";
177        config.credential.userCredential.password = "password";
178        // EAP-TLS not allowed for user credential.
179        config.credential.userCredential.eapType = EAPConstants.EAP_TLS;
180        config.credential.userCredential.nonEapInnerMethod = "MS-CHAP";
181        assertFalse(mManager.addProvider(config));
182    }
183
184    /**
185     * Verify that adding a provider with a valid configuration and user credential will succeed.
186     *
187     * @throws Exception
188     */
189    @Test
190    public void addRemoveProviderWithValidUserCredential() throws Exception {
191        PasspointConfiguration config = new PasspointConfiguration();
192        config.homeSp = new HomeSP();
193        config.homeSp.fqdn = TEST_FQDN;
194        config.homeSp.friendlyName = TEST_FRIENDLY_NAME;
195        config.credential = new Credential();
196        config.credential.realm = TEST_REALM;
197        config.credential.caCertificate = FakeKeys.CA_CERT0;
198        config.credential.userCredential = new Credential.UserCredential();
199        config.credential.userCredential.username = "username";
200        config.credential.userCredential.password = "password";
201        config.credential.userCredential.eapType = EAPConstants.EAP_TTLS;
202        config.credential.userCredential.nonEapInnerMethod = "MS-CHAP";
203        assertTrue(mManager.addProvider(config));
204        verifyInstalledConfig(config);
205
206        // Remove the provider.
207        assertTrue(mManager.removeProvider(TEST_FQDN));
208        assertEquals(null, mManager.getProviderConfigs());
209    }
210
211    /**
212     * Verify that adding a provider with a valid configuration and SIM credential will succeed.
213     *
214     * @throws Exception
215     */
216    @Test
217    public void addRemoveProviderWithValidSimCredential() throws Exception {
218        PasspointConfiguration config = new PasspointConfiguration();
219        config.homeSp = new HomeSP();
220        config.homeSp.fqdn = TEST_FQDN;
221        config.homeSp.friendlyName = TEST_FRIENDLY_NAME;
222        config.credential = new Credential();
223        config.credential.realm = TEST_REALM;
224        config.credential.simCredential = new Credential.SimCredential();
225        config.credential.simCredential.imsi = TEST_IMSI;
226        config.credential.simCredential.eapType = EAPConstants.EAP_SIM;
227        when(mSimAccessor.getMatchingImsis(new IMSIParameter(TEST_IMSI)))
228                .thenReturn(new ArrayList<String>());
229        assertTrue(mManager.addProvider(config));
230        verifyInstalledConfig(config);
231
232        // Remove the provider.
233        assertTrue(mManager.removeProvider(TEST_FQDN));
234        assertEquals(null, mManager.getProviderConfigs());
235    }
236
237    /**
238     * Verify that adding a provider with an invalid SIM credential (configured IMSI doesn't
239     * match the IMSI of the installed SIM cards) will fail.
240     *
241     * @throws Exception
242     */
243    @Test
244    public void addProviderWithValidSimCredentialWithInvalidIMSI() throws Exception {
245        PasspointConfiguration config = new PasspointConfiguration();
246        config.homeSp = new HomeSP();
247        config.homeSp.fqdn = TEST_FQDN;
248        config.homeSp.friendlyName = TEST_FRIENDLY_NAME;
249        config.credential = new Credential();
250        config.credential.realm = TEST_REALM;
251        config.credential.simCredential = new Credential.SimCredential();
252        config.credential.simCredential.imsi = TEST_IMSI;
253        config.credential.simCredential.eapType = EAPConstants.EAP_SIM;
254        when(mSimAccessor.getMatchingImsis(new IMSIParameter(TEST_IMSI))).thenReturn(null);
255        assertFalse(mManager.addProvider(config));
256    }
257
258    /**
259     * Verify that adding a provider with the same base domain as the existing provider will
260     * succeed, and verify that the existing provider is replaced by the new provider with
261     * the new configuration.
262     *
263     * @throws Exception
264     */
265    @Test
266    public void addProviderWithExistingConfig() throws Exception {
267        // Add a provider with the original configuration.
268        PasspointConfiguration origConfig = new PasspointConfiguration();
269        origConfig.homeSp = new HomeSP();
270        origConfig.homeSp.fqdn = TEST_FQDN;
271        origConfig.homeSp.friendlyName = TEST_FRIENDLY_NAME;
272        origConfig.credential = new Credential();
273        origConfig.credential.realm = TEST_REALM;
274        origConfig.credential.simCredential = new Credential.SimCredential();
275        origConfig.credential.simCredential.imsi = TEST_IMSI;
276        origConfig.credential.simCredential.eapType = EAPConstants.EAP_SIM;
277        when(mSimAccessor.getMatchingImsis(new IMSIParameter(TEST_IMSI)))
278                .thenReturn(new ArrayList<String>());
279        assertTrue(mManager.addProvider(origConfig));
280        verifyInstalledConfig(origConfig);
281
282        // Add another provider with the same base domain as the existing provider.
283        // This should replace the existing provider with the new configuration.
284        PasspointConfiguration newConfig = new PasspointConfiguration();
285        newConfig.homeSp = new HomeSP();
286        newConfig.homeSp.fqdn = TEST_FQDN1;
287        newConfig.homeSp.friendlyName = TEST_FRIENDLY_NAME;
288        newConfig.credential = new Credential();
289        newConfig.credential.realm = TEST_REALM;
290        newConfig.credential.caCertificate = FakeKeys.CA_CERT0;
291        newConfig.credential.userCredential = new Credential.UserCredential();
292        newConfig.credential.userCredential.username = "username";
293        newConfig.credential.userCredential.password = "password";
294        newConfig.credential.userCredential.eapType = EAPConstants.EAP_TTLS;
295        newConfig.credential.userCredential.nonEapInnerMethod = "MS-CHAP";
296        assertTrue(mManager.addProvider(newConfig));
297        verifyInstalledConfig(newConfig);
298    }
299}
300