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.junit.Assert.fail;
21
22import android.test.suitebuilder.annotation.SmallTest;
23
24import org.junit.Before;
25import org.junit.Test;
26import org.mockito.Mock;
27import org.mockito.MockitoAnnotations;
28
29import java.io.BufferedReader;
30import java.io.IOException;
31import java.io.StringReader;
32import java.util.ArrayList;
33import java.util.HashMap;
34import java.util.Map;
35
36/**
37 * Unit tests for {@link com.android.server.wifi.WifiConfigStore}.
38 */
39@SmallTest
40public class WifiConfigStoreTest {
41    private static final String KEY_SSID = "ssid";
42    private static final String KEY_PSK = "psk";
43    private static final String KEY_KEY_MGMT = "key_mgmt";
44    private static final String KEY_PRIORITY = "priority";
45    private static final String KEY_DISABLED = "disabled";
46    private static final String KEY_ID_STR = "id_str";
47    // This is not actually present as a key in the wpa_supplicant.conf file, but
48    // is used in tests to conveniently access the configKey for a test network.
49    private static final String CONFIG_KEY = "configKey";
50
51    private static final HashMap<String, String> NETWORK_0_VARS = new HashMap<>();
52    static {
53        NETWORK_0_VARS.put(KEY_SSID, "\"TestNetwork0\"");
54        NETWORK_0_VARS.put(KEY_KEY_MGMT, "NONE");
55        NETWORK_0_VARS.put(KEY_PRIORITY, "2");
56        NETWORK_0_VARS.put(KEY_ID_STR, ""
57                + "\"%7B%22creatorUid%22%3A%221000%22%2C%22configKey%22%3A%22%5C%22"
58                + "TestNetwork0%5C%22NONE%22%7D\"");
59        NETWORK_0_VARS.put(CONFIG_KEY, "\"TestNetwork0\"NONE");
60    }
61
62    private static final HashMap<String, String> NETWORK_1_VARS = new HashMap<>();
63    static {
64        NETWORK_1_VARS.put(KEY_SSID, "\"Test Network 1\"");
65        NETWORK_1_VARS.put(KEY_KEY_MGMT, "NONE");
66        NETWORK_1_VARS.put(KEY_PRIORITY, "3");
67        NETWORK_1_VARS.put(KEY_DISABLED, "1");
68        NETWORK_1_VARS.put(KEY_ID_STR, ""
69                + "\"%7B%22creatorUid%22%3A%221000%22%2C%22configKey%22%3A%22%5C%22"
70                + "Test+Network+1%5C%22NONE%22%7D\"");
71        NETWORK_1_VARS.put(CONFIG_KEY, "\"Test Network 1\"NONE");
72    }
73
74    private static final HashMap<String, String> NETWORK_2_VARS = new HashMap<>();
75    static {
76        NETWORK_2_VARS.put(KEY_SSID, "\"testNetwork2\"");
77        NETWORK_2_VARS.put(KEY_KEY_MGMT, "NONE");
78        NETWORK_2_VARS.put(KEY_PRIORITY, "4");
79        NETWORK_2_VARS.put(KEY_DISABLED, "1");
80        NETWORK_2_VARS.put(KEY_ID_STR, ""
81                + "\"%7B%22creatorUid%22%3A%221000%22%2C%22configKey%22%3A%22%5C%22"
82                + "testNetwork2%5C%22NONE%22%7D\"");
83        NETWORK_2_VARS.put(CONFIG_KEY, "\"testNetwork2\"NONE");
84    }
85
86    private static final HashMap<String, String> NETWORK_3_VARS = new HashMap<>();
87    static {
88        NETWORK_3_VARS.put(KEY_SSID, "\"testwpa2psk\"");
89        NETWORK_3_VARS.put(KEY_PSK, "blahblah");
90        NETWORK_3_VARS.put(KEY_KEY_MGMT, "WPA-PSK");
91        NETWORK_3_VARS.put(KEY_PRIORITY, "6");
92        NETWORK_3_VARS.put(KEY_DISABLED, "1");
93        NETWORK_3_VARS.put(KEY_ID_STR, ""
94                + "\"%7B%22creatorUid%22%3A%221000%22%2C%22configKey%22%3A%22%5C%22"
95                + "testwpa2psk%5C%22WPA_PSK%22%7D\"");
96        NETWORK_3_VARS.put(CONFIG_KEY, "\"testwpa2psk\"WPA_PSK");
97    }
98
99    private static final ArrayList<HashMap<String, String>> NETWORK_VARS = new ArrayList<HashMap<String, String>>();
100    static {
101        NETWORK_VARS.add(NETWORK_0_VARS);
102        NETWORK_VARS.add(NETWORK_1_VARS);
103        NETWORK_VARS.add(NETWORK_2_VARS);
104        NETWORK_VARS.add(NETWORK_3_VARS);
105    }
106
107    // Taken from wpa_supplicant.conf actual test device Some fields modified for privacy.
108    private static final String TEST_WPA_SUPPLICANT_CONF = ""
109            + "ctrl_interface=/data/misc/wifi/sockets\n"
110            + "disable_scan_offload=1\n"
111            + "driver_param=use_p2p_group_interface=1p2p_device=1\n"
112            + "update_config=1\n"
113            + "device_name=testdevice\n"
114            + "manufacturer=TestManufacturer\n"
115            + "model_name=Testxus\n"
116            + "model_number=Testxus\n"
117            + "serial_number=1ABCD12345678912\n"
118            + "device_type=12-3456A456-7\n"
119            + "config_methods=physical_display virtual_push_button\n"
120            + "p2p_no_go_freq=5170-5740\n"
121            + "pmf=1\n"
122            + "external_sim=1\n"
123            + "wowlan_triggers=any\n"
124            + "p2p_search_delay=0\n"
125            + "network={\n"
126            + "        " + KEY_SSID + "=" + NETWORK_0_VARS.get(KEY_SSID) + "\n"
127            + "        " + KEY_KEY_MGMT + "=" + NETWORK_0_VARS.get(KEY_KEY_MGMT) + "\n"
128            + "        " + KEY_PRIORITY + "=" + NETWORK_0_VARS.get(KEY_PRIORITY) + "\n"
129            + "        " + KEY_ID_STR + "=" + NETWORK_0_VARS.get(KEY_ID_STR) + "\n"
130            + "}\n"
131            + "\n"
132            + "network={\n"
133            + "        " + KEY_SSID + "=" + NETWORK_1_VARS.get(KEY_SSID) + "\n"
134            + "        " + KEY_KEY_MGMT + "=" + NETWORK_1_VARS.get(KEY_KEY_MGMT) + "\n"
135            + "        " + KEY_PRIORITY + "=" + NETWORK_1_VARS.get(KEY_PRIORITY) + "\n"
136            + "        " + KEY_DISABLED + "=" + NETWORK_1_VARS.get(KEY_DISABLED) + "\n"
137            + "        " + KEY_ID_STR + "=" + NETWORK_1_VARS.get(KEY_ID_STR) + "\n"
138            + "}\n"
139            + "\n"
140            + "network={\n"
141            + "        " + KEY_SSID + "=" + NETWORK_2_VARS.get(KEY_SSID) + "\n"
142            + "        " + KEY_KEY_MGMT + "=" + NETWORK_2_VARS.get(KEY_KEY_MGMT) + "\n"
143            + "        " + KEY_PRIORITY + "=" + NETWORK_2_VARS.get(KEY_PRIORITY) + "\n"
144            + "        " + KEY_DISABLED + "=" + NETWORK_2_VARS.get(KEY_DISABLED) + "\n"
145            + "        " + KEY_ID_STR + "=" + NETWORK_2_VARS.get(KEY_ID_STR) + "\n"
146            + "}\n"
147            + "\n"
148            + "network={\n"
149            + "        " + KEY_SSID + "=" + NETWORK_3_VARS.get(KEY_SSID) + "\n"
150            + "        " + KEY_PSK + "=" + NETWORK_3_VARS.get(KEY_PSK) + "\n"
151            + "        " + KEY_KEY_MGMT + "=" + NETWORK_3_VARS.get(KEY_KEY_MGMT) + "\n"
152            + "        " + KEY_PRIORITY + "=" + NETWORK_3_VARS.get(KEY_PRIORITY) + "\n"
153            + "        " + KEY_DISABLED + "=" + NETWORK_3_VARS.get(KEY_DISABLED) + "\n"
154            + "        " + KEY_ID_STR + "=" + NETWORK_3_VARS.get(KEY_ID_STR) + "\n"
155            + "}\n";
156
157    @Mock private WifiNative mWifiNative;
158    private MockKeyStore mMockKeyStore;
159    private WifiConfigStore mWifiConfigStore;
160
161    @Before
162    public void setUp() throws Exception {
163        MockitoAnnotations.initMocks(this);
164
165        mMockKeyStore = new MockKeyStore();
166        mWifiConfigStore = new WifiConfigStore(mWifiNative, mMockKeyStore.createMock(), null,
167                false, true);
168    }
169
170    /**
171     * Verifies that readNetworkVariableFromSupplicantFile() properly reads network variables from a
172     * wpa_supplicant.conf file.
173     */
174    @Test
175    public void readNetworkVariableFromSupplicantFile() throws Exception {
176        Map<String, String> ssidResults = readNetworkVariableFromSupplicantFile(KEY_SSID);
177        assertEquals(NETWORK_VARS.size(), ssidResults.size());
178        for (HashMap<String, String> single_network_vars : NETWORK_VARS) {
179            assertEquals(ssidResults.get(single_network_vars.get(CONFIG_KEY)),
180                    single_network_vars.get(KEY_SSID));
181        }
182
183        Map<String, String> pskResults = readNetworkVariableFromSupplicantFile(KEY_PSK);
184        // Only network 3 is secured with a password.
185        assertEquals(1, pskResults.size());
186        assertEquals(pskResults.get(NETWORK_3_VARS.get(CONFIG_KEY)),
187                    NETWORK_3_VARS.get(KEY_PSK));
188
189        Map<String, String> keyMgmtResults = readNetworkVariableFromSupplicantFile(KEY_KEY_MGMT);
190        assertEquals(NETWORK_VARS.size(), keyMgmtResults.size());
191        for (HashMap<String, String> single_network_vars : NETWORK_VARS) {
192            assertEquals(keyMgmtResults.get(single_network_vars.get(CONFIG_KEY)),
193                    single_network_vars.get(KEY_KEY_MGMT));
194        }
195
196        Map<String, String> priorityResults = readNetworkVariableFromSupplicantFile(KEY_PRIORITY);
197        assertEquals(NETWORK_VARS.size(), priorityResults.size());
198        for (HashMap<String, String> single_network_vars : NETWORK_VARS) {
199            assertEquals(priorityResults.get(single_network_vars.get(CONFIG_KEY)),
200                    single_network_vars.get(KEY_PRIORITY));
201        }
202
203        Map<String, String> disabledResults = readNetworkVariableFromSupplicantFile(KEY_DISABLED);
204        // All but network 0 are disabled.
205        assertEquals(NETWORK_VARS.size() - 1, disabledResults.size());
206        for (int i = 1; i < NETWORK_VARS.size(); ++i) {
207            assertEquals(disabledResults.get(NETWORK_VARS.get(i).get(CONFIG_KEY)),
208                    NETWORK_VARS.get(i).get(KEY_DISABLED));
209        }
210
211        Map<String, String> idStrResults = readNetworkVariableFromSupplicantFile(KEY_ID_STR);
212        assertEquals(NETWORK_VARS.size(), idStrResults.size());
213        for (HashMap<String, String> single_network_vars : NETWORK_VARS) {
214            assertEquals(idStrResults.get(single_network_vars.get(CONFIG_KEY)),
215                    single_network_vars.get(KEY_ID_STR));
216        }
217    }
218
219    /**
220     * Inject |TEST_WPA_SUPPLICANT_CONF| via the helper method readNetworkVariablesFromReader().
221     */
222    public Map<String, String> readNetworkVariableFromSupplicantFile(String key) throws Exception {
223        Map<String, String> result = new HashMap<>();
224        BufferedReader reader = null;
225        try {
226            reader = new BufferedReader(new StringReader(TEST_WPA_SUPPLICANT_CONF));
227            result = mWifiConfigStore.readNetworkVariablesFromReader(reader, key);
228        } catch (IOException e) {
229            fail("Error reading test supplicant conf string");
230        } finally {
231            try {
232                if (reader != null) {
233                    reader.close();
234                }
235            } catch (IOException e) {
236                // Just ignore if we can't close the reader.
237            }
238        }
239        return result;
240    }
241}
242