NetworkListStoreDataTest.java revision 0a0b5035ce8013ed327a0802357a1b7df3061912
1/*
2 * Copyright (C) 2017 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.*;
20import static org.mockito.Mockito.*;
21
22import android.net.wifi.WifiConfiguration;
23import android.test.suitebuilder.annotation.SmallTest;
24import android.util.Xml;
25
26import com.android.internal.util.FastXmlSerializer;
27
28import org.junit.Before;
29import org.junit.Test;
30import org.xmlpull.v1.XmlPullParser;
31import org.xmlpull.v1.XmlPullParserException;
32import org.xmlpull.v1.XmlSerializer;
33
34import java.io.ByteArrayInputStream;
35import java.io.ByteArrayOutputStream;
36import java.nio.charset.StandardCharsets;
37import java.util.ArrayList;
38import java.util.Arrays;
39import java.util.List;
40
41/**
42 * Unit tests for {@link com.android.server.wifi.NetworksListStoreData}.
43 */
44@SmallTest
45public class NetworkListStoreDataTest {
46
47    private static final String TEST_SSID = "WifiConfigStoreDataSSID_";
48    private static final String TEST_CONNECT_CHOICE = "XmlUtilConnectChoice";
49    private static final long TEST_CONNECT_CHOICE_TIMESTAMP = 0x4566;
50    private static final String SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT =
51            "<Network>\n"
52                    + "<WifiConfiguration>\n"
53                    + "<string name=\"ConfigKey\">%s</string>\n"
54                    + "<string name=\"SSID\">%s</string>\n"
55                    + "<null name=\"BSSID\" />\n"
56                    + "<null name=\"PreSharedKey\" />\n"
57                    + "<null name=\"WEPKeys\" />\n"
58                    + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n"
59                    + "<boolean name=\"HiddenSSID\" value=\"false\" />\n"
60                    + "<boolean name=\"RequirePMF\" value=\"false\" />\n"
61                    + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n"
62                    + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n"
63                    + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n"
64                    + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n"
65                    + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n"
66                    + "<boolean name=\"Shared\" value=\"%s\" />\n"
67                    + "<null name=\"FQDN\" />\n"
68                    + "<null name=\"ProviderFriendlyName\" />\n"
69                    + "<null name=\"LinkedNetworksList\" />\n"
70                    + "<null name=\"DefaultGwMacAddress\" />\n"
71                    + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n"
72                    + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n"
73                    + "<int name=\"UserApproved\" value=\"0\" />\n"
74                    + "<boolean name=\"MeteredHint\" value=\"false\" />\n"
75                    + "<boolean name=\"UseExternalScores\" value=\"false\" />\n"
76                    + "<int name=\"NumAssociation\" value=\"0\" />\n"
77                    + "<int name=\"CreatorUid\" value=\"%d\" />\n"
78                    + "<null name=\"CreatorName\" />\n"
79                    + "<null name=\"CreationTime\" />\n"
80                    + "<int name=\"LastUpdateUid\" value=\"-1\" />\n"
81                    + "<null name=\"LastUpdateName\" />\n"
82                    + "<int name=\"LastConnectUid\" value=\"0\" />\n"
83                    + "</WifiConfiguration>\n"
84                    + "<NetworkStatus>\n"
85                    + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n"
86                    + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n"
87                    + "<null name=\"ConnectChoice\" />\n"
88                    + "<long name=\"ConnectChoiceTimeStamp\" value=\"-1\" />\n"
89                    + "<boolean name=\"HasEverConnected\" value=\"false\" />\n"
90                    + "</NetworkStatus>\n"
91                    + "<IpConfiguration>\n"
92                    + "<string name=\"IpAssignment\">DHCP</string>\n"
93                    + "<string name=\"ProxySettings\">NONE</string>\n"
94                    + "</IpConfiguration>\n"
95                    + "</Network>\n";
96
97    private static final String SINGLE_EAP_NETWORK_DATA_XML_STRING_FORMAT =
98            "<Network>\n"
99                    + "<WifiConfiguration>\n"
100                    + "<string name=\"ConfigKey\">%s</string>\n"
101                    + "<string name=\"SSID\">%s</string>\n"
102                    + "<null name=\"BSSID\" />\n"
103                    + "<null name=\"PreSharedKey\" />\n"
104                    + "<null name=\"WEPKeys\" />\n"
105                    + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n"
106                    + "<boolean name=\"HiddenSSID\" value=\"false\" />\n"
107                    + "<boolean name=\"RequirePMF\" value=\"false\" />\n"
108                    + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">0c</byte-array>\n"
109                    + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n"
110                    + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n"
111                    + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n"
112                    + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n"
113                    + "<boolean name=\"Shared\" value=\"%s\" />\n"
114                    + "<null name=\"FQDN\" />\n"
115                    + "<null name=\"ProviderFriendlyName\" />\n"
116                    + "<null name=\"LinkedNetworksList\" />\n"
117                    + "<null name=\"DefaultGwMacAddress\" />\n"
118                    + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n"
119                    + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n"
120                    + "<int name=\"UserApproved\" value=\"0\" />\n"
121                    + "<boolean name=\"MeteredHint\" value=\"false\" />\n"
122                    + "<boolean name=\"UseExternalScores\" value=\"false\" />\n"
123                    + "<int name=\"NumAssociation\" value=\"0\" />\n"
124                    + "<int name=\"CreatorUid\" value=\"%d\" />\n"
125                    + "<null name=\"CreatorName\" />\n"
126                    + "<null name=\"CreationTime\" />\n"
127                    + "<int name=\"LastUpdateUid\" value=\"-1\" />\n"
128                    + "<null name=\"LastUpdateName\" />\n"
129                    + "<int name=\"LastConnectUid\" value=\"0\" />\n"
130                    + "</WifiConfiguration>\n"
131                    + "<NetworkStatus>\n"
132                    + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n"
133                    + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n"
134                    + "<null name=\"ConnectChoice\" />\n"
135                    + "<long name=\"ConnectChoiceTimeStamp\" value=\"-1\" />\n"
136                    + "<boolean name=\"HasEverConnected\" value=\"false\" />\n"
137                    + "</NetworkStatus>\n"
138                    + "<IpConfiguration>\n"
139                    + "<string name=\"IpAssignment\">DHCP</string>\n"
140                    + "<string name=\"ProxySettings\">NONE</string>\n"
141                    + "</IpConfiguration>\n"
142                    + "<WifiEnterpriseConfiguration>\n"
143                    + "<string name=\"Identity\"></string>\n"
144                    + "<string name=\"AnonIdentity\"></string>\n"
145                    + "<string name=\"Password\"></string>\n"
146                    + "<string name=\"ClientCert\"></string>\n"
147                    + "<string name=\"CaCert\"></string>\n"
148                    + "<string name=\"SubjectMatch\"></string>\n"
149                    + "<string name=\"Engine\"></string>\n"
150                    + "<string name=\"EngineId\"></string>\n"
151                    + "<string name=\"PrivateKeyId\"></string>\n"
152                    + "<string name=\"AltSubjectMatch\"></string>\n"
153                    + "<string name=\"DomSuffixMatch\"></string>\n"
154                    + "<string name=\"CaPath\"></string>\n"
155                    + "<int name=\"EapMethod\" value=\"2\" />\n"
156                    + "<int name=\"Phase2Method\" value=\"0\" />\n"
157                    + "</WifiEnterpriseConfiguration>\n"
158                    + "</Network>\n";
159
160    private NetworkListStoreData mNetworkListStoreData;
161
162    @Before
163    public void setUp() throws Exception {
164        mNetworkListStoreData = new NetworkListStoreData();
165    }
166
167    /**
168     * Helper function for serializing configuration data to a XML block.
169     *
170     * @param shared Flag indicating serializing shared or user configurations
171     * @return byte[] of the XML data
172     * @throws Exception
173     */
174    private byte[] serializeData(boolean shared) throws Exception {
175        final XmlSerializer out = new FastXmlSerializer();
176        final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
177        out.setOutput(outputStream, StandardCharsets.UTF_8.name());
178        mNetworkListStoreData.serializeData(out, shared);
179        out.flush();
180        return outputStream.toByteArray();
181    }
182
183    /**
184     * Helper function for parsing configuration data from a XML block.
185     *
186     * @param data XML data to parse from
187     * @param shared Flag indicating parsing of shared or user configurations
188     * @return List of WifiConfiguration parsed
189     * @throws Exception
190     */
191    private List<WifiConfiguration> deserializeData(byte[] data, boolean shared) throws Exception {
192        final XmlPullParser in = Xml.newPullParser();
193        final ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
194        in.setInput(inputStream, StandardCharsets.UTF_8.name());
195        mNetworkListStoreData.deserializeData(in, in.getDepth(), shared);
196        if (shared) {
197            return mNetworkListStoreData.getSharedConfigurations();
198        } else {
199            return mNetworkListStoreData.getUserConfigurations();
200        }
201    }
202
203    /**
204     * Helper function for generating a network list for testing purpose.  The network list
205     * will contained an open and an EAP network.
206     *
207     * @param shared Flag indicating shared network
208     * @return List of WifiConfiguration
209     */
210    private List<WifiConfiguration> getTestNetworksConfig(boolean shared) {
211        WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
212        openNetwork.shared = shared;
213        openNetwork.setIpConfiguration(
214                WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy());
215        WifiConfiguration eapNetwork = WifiConfigurationTestUtil.createEapNetwork();
216        eapNetwork.shared = shared;
217        eapNetwork.setIpConfiguration(
218                WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy());
219        List<WifiConfiguration> networkList = new ArrayList<>();
220        networkList.add(openNetwork);
221        networkList.add(eapNetwork);
222        return networkList;
223    }
224
225    /**
226     * Helper function for generating XML block containing two networks, an open and an EAP
227     * network.
228     *
229     * @param openNetwork The WifiConfiguration for an open network
230     * @param eapNetwork The WifiConfiguration for an EAP network
231     * @return byte[] of the XML data
232     */
233    private byte[] getTestNetworksXmlBytes(WifiConfiguration openNetwork,
234            WifiConfiguration eapNetwork) {
235        String openNetworkXml = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT,
236                openNetwork.configKey().replaceAll("\"", "&quot;"),
237                openNetwork.SSID.replaceAll("\"", "&quot;"),
238                openNetwork.shared, openNetwork.creatorUid);
239        String eapNetworkXml = String.format(SINGLE_EAP_NETWORK_DATA_XML_STRING_FORMAT,
240                eapNetwork.configKey().replaceAll("\"", "&quot;"),
241                eapNetwork.SSID.replaceAll("\"", "&quot;"),
242                eapNetwork.shared, eapNetwork.creatorUid);
243        return (openNetworkXml + eapNetworkXml).getBytes(StandardCharsets.UTF_8);
244    }
245
246    /**
247     * Verify that serializing the store data without any configuration doesn't cause any crash
248     * and no data should be serialized.
249     *
250     * @throws Exception
251     */
252    @Test
253    public void serializeEmptyConfigs() throws Exception {
254        assertEquals(0, serializeData(true /* shared */).length);
255        assertEquals(0, serializeData(false /* shared */).length);
256    }
257
258    /**
259     * Verify that parsing an empty data doesn't cause any crash and no configuration should
260     * be parsed.
261     *
262     * @throws Exception
263     */
264    @Test
265    public void deserializeEmptyData() throws Exception {
266        assertTrue(deserializeData(new byte[0], true /* shared */).isEmpty());
267        assertTrue(deserializeData(new byte[0], false /* shared */).isEmpty());
268    }
269
270    /**
271     * Verify that NetworkListStoreData does support share data.
272     *
273     * @throws Exception
274     */
275    @Test
276    public void supportShareData() throws Exception {
277        assertTrue(mNetworkListStoreData.supportShareData());
278    }
279
280    /**
281     * Verify that the shared configurations (containing an open and an EAP network) are serialized
282     * correctly, matching the expected XML string.
283     *
284     * @throws Exception
285     */
286    @Test
287    public void serializeSharedConfigurations() throws Exception {
288        List<WifiConfiguration> networkList = getTestNetworksConfig(true /* shared */);
289        mNetworkListStoreData.setSharedConfigurations(networkList);
290        byte[] expectedData = getTestNetworksXmlBytes(networkList.get(0), networkList.get(1));
291        assertTrue(Arrays.equals(expectedData, serializeData(true /* shared */)));
292    }
293
294    /**
295     * Verify that the shared configurations are parsed correctly from a XML string containing
296     * test networks (an open and an EAP network).
297     * @throws Exception
298     */
299    @Test
300    public void deserializeSharedConfigurations() throws Exception {
301        List<WifiConfiguration> networkList = getTestNetworksConfig(true /* shared */);
302        byte[] xmlData = getTestNetworksXmlBytes(networkList.get(0), networkList.get(1));
303        WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore(
304                networkList, deserializeData(xmlData, true /* shared */));
305    }
306
307    /**
308     * Verify that the user configurations (containing an open and an EAP network) are serialized
309     * correctly, matching the expected XML string.
310     *
311     * @throws Exception
312     */
313    @Test
314    public void serializeUserConfigurations() throws Exception {
315        List<WifiConfiguration> networkList = getTestNetworksConfig(false /* shared */);
316        mNetworkListStoreData.setUserConfigurations(networkList);
317        byte[] expectedData = getTestNetworksXmlBytes(networkList.get(0), networkList.get(1));
318        assertTrue(Arrays.equals(expectedData, serializeData(false /* shared */)));
319    }
320
321    /**
322     * Verify that the user configurations are parsed correctly from a XML string containing
323     * test networks (an open and an EAP network).
324     * @throws Exception
325     */
326    @Test
327    public void deserializeUserConfigurations() throws Exception {
328        List<WifiConfiguration> networkList = getTestNetworksConfig(false /* shared */);
329        byte[] xmlData = getTestNetworksXmlBytes(networkList.get(0), networkList.get(1));
330        WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore(
331                networkList, deserializeData(xmlData, false /* shared */));
332    }
333
334    /**
335     * Verify that a XmlPullParserException will be thrown when parsing a <Network> block
336     * containing an unknown tag.
337     *
338     * @throws Exception
339     */
340    @Test(expected = XmlPullParserException.class)
341    public void parseNetworkWithUnknownTag() throws Exception {
342        String configFormat =
343                "<Network>\n"
344                        + "<WifiConfiguration>\n"
345                        + "<string name=\"ConfigKey\">%s</string>\n"
346                        + "<string name=\"SSID\">%s</string>\n"
347                        + "<null name=\"BSSID\" />\n"
348                        + "<null name=\"PreSharedKey\" />\n"
349                        + "<null name=\"WEPKeys\" />\n"
350                        + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n"
351                        + "<boolean name=\"HiddenSSID\" value=\"false\" />\n"
352                        + "<boolean name=\"RequirePMF\" value=\"false\" />\n"
353                        + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n"
354                        + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n"
355                        + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n"
356                        + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n"
357                        + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n"
358                        + "<boolean name=\"Shared\" value=\"%s\" />\n"
359                        + "<null name=\"FQDN\" />\n"
360                        + "<null name=\"ProviderFriendlyName\" />\n"
361                        + "<null name=\"LinkedNetworksList\" />\n"
362                        + "<null name=\"DefaultGwMacAddress\" />\n"
363                        + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n"
364                        + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n"
365                        + "<int name=\"UserApproved\" value=\"0\" />\n"
366                        + "<boolean name=\"MeteredHint\" value=\"false\" />\n"
367                        + "<boolean name=\"UseExternalScores\" value=\"false\" />\n"
368                        + "<int name=\"NumAssociation\" value=\"0\" />\n"
369                        + "<int name=\"CreatorUid\" value=\"%d\" />\n"
370                        + "<null name=\"CreatorName\" />\n"
371                        + "<null name=\"CreationTime\" />\n"
372                        + "<int name=\"LastUpdateUid\" value=\"-1\" />\n"
373                        + "<null name=\"LastUpdateName\" />\n"
374                        + "<int name=\"LastConnectUid\" value=\"0\" />\n"
375                        + "</WifiConfiguration>\n"
376                        + "<NetworkStatus>\n"
377                        + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n"
378                        + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n"
379                        + "<null name=\"ConnectChoice\" />\n"
380                        + "<long name=\"ConnectChoiceTimeStamp\" value=\"-1\" />\n"
381                        + "<boolean name=\"HasEverConnected\" value=\"false\" />\n"
382                        + "</NetworkStatus>\n"
383                        + "<IpConfiguration>\n"
384                        + "<string name=\"IpAssignment\">DHCP</string>\n"
385                        + "<string name=\"ProxySettings\">NONE</string>\n"
386                        + "</IpConfiguration>\n"
387                        + "<Unknown>"       // Unknown tag.
388                        + "<int name=\"test\" value=\"0\" />\n"
389                        + "</Unknown>"
390                        + "</Network>\n";
391        WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
392        byte[] xmlData = String.format(configFormat,
393                openNetwork.configKey().replaceAll("\"", "&quot;"),
394                openNetwork.SSID.replaceAll("\"", "&quot;"),
395                openNetwork.shared, openNetwork.creatorUid).getBytes(StandardCharsets.UTF_8);
396        deserializeData(xmlData, true);
397    }
398
399    /**
400     * Verify that a XmlPullParseException will be thrown when parsing a network configuration
401     * containing a mismatched config key.
402     *
403     * @throws Exception
404     */
405    @Test(expected = XmlPullParserException.class)
406    public void parseNetworkWithMismatchConfigKey() throws Exception {
407        WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
408        byte[] xmlData = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT,
409                "InvalidConfigKey",
410                openNetwork.SSID.replaceAll("\"", "&quot;"),
411                openNetwork.shared, openNetwork.creatorUid).getBytes(StandardCharsets.UTF_8);
412        deserializeData(xmlData, true);
413    }
414}
415