diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2017-02-10 19:37:37 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-02-10 19:37:38 +0000 |
commit | 2f74844643d30a69e77436e93ad904c7701bac5e (patch) | |
tree | 391cbc5fbfb3b59a549215c03c4ce68a36df0f73 /tests | |
parent | 1b1bafd2b0278e2079f6ece9081ddb25cdf2c254 (diff) | |
parent | 0a0b5035ce8013ed327a0802357a1b7df3061912 (diff) |
Merge "Wifi configuration store data refactor"
Diffstat (limited to 'tests')
5 files changed, 1051 insertions, 606 deletions
diff --git a/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java new file mode 100644 index 000000000..0db93f598 --- /dev/null +++ b/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wifi; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import android.test.suitebuilder.annotation.SmallTest; +import android.util.Xml; + +import com.android.internal.util.FastXmlSerializer; + +import org.junit.Before; +import org.junit.Test; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * Unit tests for {@link com.android.server.wifi.DeletedEphemeralSsidsStoreData}. + */ +@SmallTest +public class DeletedEphemeralSsidsStoreDataTest { + private static final String TEST_SSID1 = "SSID 1"; + private static final String TEST_SSID2 = "SSID 2"; + private static final String TEST_SSID_LIST_XML_STRING = + "<set name=\"SSIDList\">\n" + + "<string>" + TEST_SSID1 + "</string>\n" + + "<string>" + TEST_SSID2 + "</string>\n" + + "</set>\n"; + private static final byte[] TEST_SSID_LIST_XML_BYTES = + TEST_SSID_LIST_XML_STRING.getBytes(StandardCharsets.UTF_8); + private DeletedEphemeralSsidsStoreData mDeletedEphemeralSsidsStoreData; + + @Before + public void setUp() throws Exception { + mDeletedEphemeralSsidsStoreData = new DeletedEphemeralSsidsStoreData(); + } + + /** + * Helper function for serializing configuration data to a XML block. + * + * @param shared Flag indicating serializing shared or user configurations + * @return byte[] of the XML data + * @throws Exception + */ + private byte[] serializeData(boolean shared) throws Exception { + final XmlSerializer out = new FastXmlSerializer(); + final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + out.setOutput(outputStream, StandardCharsets.UTF_8.name()); + mDeletedEphemeralSsidsStoreData.serializeData(out, shared); + out.flush(); + return outputStream.toByteArray(); + } + + /** + * Helper function for parsing configuration data from a XML block. + * + * @param data XML data to parse from + * @param shared Flag indicating parsing of shared or user configurations + * @return SSID list + * @throws Exception + */ + private Set<String> deserializeData(byte[] data, boolean shared) throws Exception { + final XmlPullParser in = Xml.newPullParser(); + final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); + in.setInput(inputStream, StandardCharsets.UTF_8.name()); + mDeletedEphemeralSsidsStoreData.deserializeData(in, in.getDepth(), shared); + return mDeletedEphemeralSsidsStoreData.getSsidList(); + } + + /** + * Verify that a XmlPullParserException will be thrown when attempting to serialize SSID list + * to the share store, since the deleted ephemeral SSID list should never be persist + * to the share store. + * + * @throws Exception + */ + @Test(expected = XmlPullParserException.class) + public void serializeShareData() throws Exception { + serializeData(true /* shared */); + } + + /** + * Verify that a XmlPullParserException will be thrown when attempting to parse SSID list + * from the share store, since the deleted ephemeral SSID list should never be persist + * to the share store. + * + * @throws Exception + */ + @Test(expected = XmlPullParserException.class) + public void deserializeShareData() throws Exception { + deserializeData(new byte[0], true /* shared */); + } + + /** + * Verify that serializing the user store data without any configuration doesn't cause any + * crash and no data should be serialized. + * + * @throws Exception + */ + @Test + public void serializeEmptyConfigs() throws Exception { + assertEquals(0, serializeData(false /* shared */).length); + } + + /** + * Verify that parsing an empty data doesn't cause any crash and no configuration should + * be deserialized. + * + * @throws Exception + */ + @Test + public void deserializeEmptyData() throws Exception { + assertTrue(deserializeData(new byte[0], false /* shared */).isEmpty()); + } + + /** + * Verify that DeletedEphemeralSsidsStoreData does not support share data. + * + * @throws Exception + */ + @Test + public void supportShareData() throws Exception { + assertFalse(mDeletedEphemeralSsidsStoreData.supportShareData()); + } + + /** + * Verify that user store SSID list is serialized correctly, matches the predefined test + * XML data. + * + * @throws Exception + */ + @Test + public void serializeSsidList() throws Exception { + Set<String> ssidList = new HashSet<>(); + ssidList.add(TEST_SSID1); + ssidList.add(TEST_SSID2); + mDeletedEphemeralSsidsStoreData.setSsidList(ssidList); + byte[] actualData = serializeData(false /* shared */); + assertTrue(Arrays.equals(TEST_SSID_LIST_XML_BYTES, actualData)); + } + + /** + * Verify that user store SSID list is deserialized correctly using the predefined test XML + * data. + * + * @throws Exception + */ + @Test + public void deserializeSsidList() throws Exception { + Set<String> ssidList = new HashSet<>(); + ssidList.add(TEST_SSID1); + ssidList.add(TEST_SSID2); + assertEquals(ssidList, deserializeData(TEST_SSID_LIST_XML_BYTES, false /* shared */)); + } +} diff --git a/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java new file mode 100644 index 000000000..a1f0057e2 --- /dev/null +++ b/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java @@ -0,0 +1,414 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wifi; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import android.net.wifi.WifiConfiguration; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.Xml; + +import com.android.internal.util.FastXmlSerializer; + +import org.junit.Before; +import org.junit.Test; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Unit tests for {@link com.android.server.wifi.NetworksListStoreData}. + */ +@SmallTest +public class NetworkListStoreDataTest { + + private static final String TEST_SSID = "WifiConfigStoreDataSSID_"; + private static final String TEST_CONNECT_CHOICE = "XmlUtilConnectChoice"; + private static final long TEST_CONNECT_CHOICE_TIMESTAMP = 0x4566; + private static final String SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT = + "<Network>\n" + + "<WifiConfiguration>\n" + + "<string name=\"ConfigKey\">%s</string>\n" + + "<string name=\"SSID\">%s</string>\n" + + "<null name=\"BSSID\" />\n" + + "<null name=\"PreSharedKey\" />\n" + + "<null name=\"WEPKeys\" />\n" + + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" + + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" + + "<boolean name=\"RequirePMF\" value=\"false\" />\n" + + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n" + + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n" + + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n" + + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n" + + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n" + + "<boolean name=\"Shared\" value=\"%s\" />\n" + + "<null name=\"FQDN\" />\n" + + "<null name=\"ProviderFriendlyName\" />\n" + + "<null name=\"LinkedNetworksList\" />\n" + + "<null name=\"DefaultGwMacAddress\" />\n" + + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n" + + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n" + + "<int name=\"UserApproved\" value=\"0\" />\n" + + "<boolean name=\"MeteredHint\" value=\"false\" />\n" + + "<boolean name=\"UseExternalScores\" value=\"false\" />\n" + + "<int name=\"NumAssociation\" value=\"0\" />\n" + + "<int name=\"CreatorUid\" value=\"%d\" />\n" + + "<null name=\"CreatorName\" />\n" + + "<null name=\"CreationTime\" />\n" + + "<int name=\"LastUpdateUid\" value=\"-1\" />\n" + + "<null name=\"LastUpdateName\" />\n" + + "<int name=\"LastConnectUid\" value=\"0\" />\n" + + "</WifiConfiguration>\n" + + "<NetworkStatus>\n" + + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n" + + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n" + + "<null name=\"ConnectChoice\" />\n" + + "<long name=\"ConnectChoiceTimeStamp\" value=\"-1\" />\n" + + "<boolean name=\"HasEverConnected\" value=\"false\" />\n" + + "</NetworkStatus>\n" + + "<IpConfiguration>\n" + + "<string name=\"IpAssignment\">DHCP</string>\n" + + "<string name=\"ProxySettings\">NONE</string>\n" + + "</IpConfiguration>\n" + + "</Network>\n"; + + private static final String SINGLE_EAP_NETWORK_DATA_XML_STRING_FORMAT = + "<Network>\n" + + "<WifiConfiguration>\n" + + "<string name=\"ConfigKey\">%s</string>\n" + + "<string name=\"SSID\">%s</string>\n" + + "<null name=\"BSSID\" />\n" + + "<null name=\"PreSharedKey\" />\n" + + "<null name=\"WEPKeys\" />\n" + + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" + + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" + + "<boolean name=\"RequirePMF\" value=\"false\" />\n" + + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">0c</byte-array>\n" + + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n" + + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n" + + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n" + + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n" + + "<boolean name=\"Shared\" value=\"%s\" />\n" + + "<null name=\"FQDN\" />\n" + + "<null name=\"ProviderFriendlyName\" />\n" + + "<null name=\"LinkedNetworksList\" />\n" + + "<null name=\"DefaultGwMacAddress\" />\n" + + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n" + + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n" + + "<int name=\"UserApproved\" value=\"0\" />\n" + + "<boolean name=\"MeteredHint\" value=\"false\" />\n" + + "<boolean name=\"UseExternalScores\" value=\"false\" />\n" + + "<int name=\"NumAssociation\" value=\"0\" />\n" + + "<int name=\"CreatorUid\" value=\"%d\" />\n" + + "<null name=\"CreatorName\" />\n" + + "<null name=\"CreationTime\" />\n" + + "<int name=\"LastUpdateUid\" value=\"-1\" />\n" + + "<null name=\"LastUpdateName\" />\n" + + "<int name=\"LastConnectUid\" value=\"0\" />\n" + + "</WifiConfiguration>\n" + + "<NetworkStatus>\n" + + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n" + + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n" + + "<null name=\"ConnectChoice\" />\n" + + "<long name=\"ConnectChoiceTimeStamp\" value=\"-1\" />\n" + + "<boolean name=\"HasEverConnected\" value=\"false\" />\n" + + "</NetworkStatus>\n" + + "<IpConfiguration>\n" + + "<string name=\"IpAssignment\">DHCP</string>\n" + + "<string name=\"ProxySettings\">NONE</string>\n" + + "</IpConfiguration>\n" + + "<WifiEnterpriseConfiguration>\n" + + "<string name=\"Identity\"></string>\n" + + "<string name=\"AnonIdentity\"></string>\n" + + "<string name=\"Password\"></string>\n" + + "<string name=\"ClientCert\"></string>\n" + + "<string name=\"CaCert\"></string>\n" + + "<string name=\"SubjectMatch\"></string>\n" + + "<string name=\"Engine\"></string>\n" + + "<string name=\"EngineId\"></string>\n" + + "<string name=\"PrivateKeyId\"></string>\n" + + "<string name=\"AltSubjectMatch\"></string>\n" + + "<string name=\"DomSuffixMatch\"></string>\n" + + "<string name=\"CaPath\"></string>\n" + + "<int name=\"EapMethod\" value=\"2\" />\n" + + "<int name=\"Phase2Method\" value=\"0\" />\n" + + "</WifiEnterpriseConfiguration>\n" + + "</Network>\n"; + + private NetworkListStoreData mNetworkListStoreData; + + @Before + public void setUp() throws Exception { + mNetworkListStoreData = new NetworkListStoreData(); + } + + /** + * Helper function for serializing configuration data to a XML block. + * + * @param shared Flag indicating serializing shared or user configurations + * @return byte[] of the XML data + * @throws Exception + */ + private byte[] serializeData(boolean shared) throws Exception { + final XmlSerializer out = new FastXmlSerializer(); + final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + out.setOutput(outputStream, StandardCharsets.UTF_8.name()); + mNetworkListStoreData.serializeData(out, shared); + out.flush(); + return outputStream.toByteArray(); + } + + /** + * Helper function for parsing configuration data from a XML block. + * + * @param data XML data to parse from + * @param shared Flag indicating parsing of shared or user configurations + * @return List of WifiConfiguration parsed + * @throws Exception + */ + private List<WifiConfiguration> deserializeData(byte[] data, boolean shared) throws Exception { + final XmlPullParser in = Xml.newPullParser(); + final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); + in.setInput(inputStream, StandardCharsets.UTF_8.name()); + mNetworkListStoreData.deserializeData(in, in.getDepth(), shared); + if (shared) { + return mNetworkListStoreData.getSharedConfigurations(); + } else { + return mNetworkListStoreData.getUserConfigurations(); + } + } + + /** + * Helper function for generating a network list for testing purpose. The network list + * will contained an open and an EAP network. + * + * @param shared Flag indicating shared network + * @return List of WifiConfiguration + */ + private List<WifiConfiguration> getTestNetworksConfig(boolean shared) { + WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); + openNetwork.shared = shared; + openNetwork.setIpConfiguration( + WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy()); + WifiConfiguration eapNetwork = WifiConfigurationTestUtil.createEapNetwork(); + eapNetwork.shared = shared; + eapNetwork.setIpConfiguration( + WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy()); + List<WifiConfiguration> networkList = new ArrayList<>(); + networkList.add(openNetwork); + networkList.add(eapNetwork); + return networkList; + } + + /** + * Helper function for generating XML block containing two networks, an open and an EAP + * network. + * + * @param openNetwork The WifiConfiguration for an open network + * @param eapNetwork The WifiConfiguration for an EAP network + * @return byte[] of the XML data + */ + private byte[] getTestNetworksXmlBytes(WifiConfiguration openNetwork, + WifiConfiguration eapNetwork) { + String openNetworkXml = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT, + openNetwork.configKey().replaceAll("\"", """), + openNetwork.SSID.replaceAll("\"", """), + openNetwork.shared, openNetwork.creatorUid); + String eapNetworkXml = String.format(SINGLE_EAP_NETWORK_DATA_XML_STRING_FORMAT, + eapNetwork.configKey().replaceAll("\"", """), + eapNetwork.SSID.replaceAll("\"", """), + eapNetwork.shared, eapNetwork.creatorUid); + return (openNetworkXml + eapNetworkXml).getBytes(StandardCharsets.UTF_8); + } + + /** + * Verify that serializing the store data without any configuration doesn't cause any crash + * and no data should be serialized. + * + * @throws Exception + */ + @Test + public void serializeEmptyConfigs() throws Exception { + assertEquals(0, serializeData(true /* shared */).length); + assertEquals(0, serializeData(false /* shared */).length); + } + + /** + * Verify that parsing an empty data doesn't cause any crash and no configuration should + * be parsed. + * + * @throws Exception + */ + @Test + public void deserializeEmptyData() throws Exception { + assertTrue(deserializeData(new byte[0], true /* shared */).isEmpty()); + assertTrue(deserializeData(new byte[0], false /* shared */).isEmpty()); + } + + /** + * Verify that NetworkListStoreData does support share data. + * + * @throws Exception + */ + @Test + public void supportShareData() throws Exception { + assertTrue(mNetworkListStoreData.supportShareData()); + } + + /** + * Verify that the shared configurations (containing an open and an EAP network) are serialized + * correctly, matching the expected XML string. + * + * @throws Exception + */ + @Test + public void serializeSharedConfigurations() throws Exception { + List<WifiConfiguration> networkList = getTestNetworksConfig(true /* shared */); + mNetworkListStoreData.setSharedConfigurations(networkList); + byte[] expectedData = getTestNetworksXmlBytes(networkList.get(0), networkList.get(1)); + assertTrue(Arrays.equals(expectedData, serializeData(true /* shared */))); + } + + /** + * Verify that the shared configurations are parsed correctly from a XML string containing + * test networks (an open and an EAP network). + * @throws Exception + */ + @Test + public void deserializeSharedConfigurations() throws Exception { + List<WifiConfiguration> networkList = getTestNetworksConfig(true /* shared */); + byte[] xmlData = getTestNetworksXmlBytes(networkList.get(0), networkList.get(1)); + WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore( + networkList, deserializeData(xmlData, true /* shared */)); + } + + /** + * Verify that the user configurations (containing an open and an EAP network) are serialized + * correctly, matching the expected XML string. + * + * @throws Exception + */ + @Test + public void serializeUserConfigurations() throws Exception { + List<WifiConfiguration> networkList = getTestNetworksConfig(false /* shared */); + mNetworkListStoreData.setUserConfigurations(networkList); + byte[] expectedData = getTestNetworksXmlBytes(networkList.get(0), networkList.get(1)); + assertTrue(Arrays.equals(expectedData, serializeData(false /* shared */))); + } + + /** + * Verify that the user configurations are parsed correctly from a XML string containing + * test networks (an open and an EAP network). + * @throws Exception + */ + @Test + public void deserializeUserConfigurations() throws Exception { + List<WifiConfiguration> networkList = getTestNetworksConfig(false /* shared */); + byte[] xmlData = getTestNetworksXmlBytes(networkList.get(0), networkList.get(1)); + WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore( + networkList, deserializeData(xmlData, false /* shared */)); + } + + /** + * Verify that a XmlPullParserException will be thrown when parsing a <Network> block + * containing an unknown tag. + * + * @throws Exception + */ + @Test(expected = XmlPullParserException.class) + public void parseNetworkWithUnknownTag() throws Exception { + String configFormat = + "<Network>\n" + + "<WifiConfiguration>\n" + + "<string name=\"ConfigKey\">%s</string>\n" + + "<string name=\"SSID\">%s</string>\n" + + "<null name=\"BSSID\" />\n" + + "<null name=\"PreSharedKey\" />\n" + + "<null name=\"WEPKeys\" />\n" + + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" + + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" + + "<boolean name=\"RequirePMF\" value=\"false\" />\n" + + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n" + + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n" + + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n" + + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n" + + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n" + + "<boolean name=\"Shared\" value=\"%s\" />\n" + + "<null name=\"FQDN\" />\n" + + "<null name=\"ProviderFriendlyName\" />\n" + + "<null name=\"LinkedNetworksList\" />\n" + + "<null name=\"DefaultGwMacAddress\" />\n" + + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n" + + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n" + + "<int name=\"UserApproved\" value=\"0\" />\n" + + "<boolean name=\"MeteredHint\" value=\"false\" />\n" + + "<boolean name=\"UseExternalScores\" value=\"false\" />\n" + + "<int name=\"NumAssociation\" value=\"0\" />\n" + + "<int name=\"CreatorUid\" value=\"%d\" />\n" + + "<null name=\"CreatorName\" />\n" + + "<null name=\"CreationTime\" />\n" + + "<int name=\"LastUpdateUid\" value=\"-1\" />\n" + + "<null name=\"LastUpdateName\" />\n" + + "<int name=\"LastConnectUid\" value=\"0\" />\n" + + "</WifiConfiguration>\n" + + "<NetworkStatus>\n" + + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n" + + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n" + + "<null name=\"ConnectChoice\" />\n" + + "<long name=\"ConnectChoiceTimeStamp\" value=\"-1\" />\n" + + "<boolean name=\"HasEverConnected\" value=\"false\" />\n" + + "</NetworkStatus>\n" + + "<IpConfiguration>\n" + + "<string name=\"IpAssignment\">DHCP</string>\n" + + "<string name=\"ProxySettings\">NONE</string>\n" + + "</IpConfiguration>\n" + + "<Unknown>" // Unknown tag. + + "<int name=\"test\" value=\"0\" />\n" + + "</Unknown>" + + "</Network>\n"; + WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); + byte[] xmlData = String.format(configFormat, + openNetwork.configKey().replaceAll("\"", """), + openNetwork.SSID.replaceAll("\"", """), + openNetwork.shared, openNetwork.creatorUid).getBytes(StandardCharsets.UTF_8); + deserializeData(xmlData, true); + } + + /** + * Verify that a XmlPullParseException will be thrown when parsing a network configuration + * containing a mismatched config key. + * + * @throws Exception + */ + @Test(expected = XmlPullParserException.class) + public void parseNetworkWithMismatchConfigKey() throws Exception { + WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); + byte[] xmlData = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT, + "InvalidConfigKey", + openNetwork.SSID.replaceAll("\"", """), + openNetwork.shared, openNetwork.creatorUid).getBytes(StandardCharsets.UTF_8); + deserializeData(xmlData, true); + } +} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java index 8c0163dda..892081423 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java @@ -40,6 +40,7 @@ import android.os.UserManager; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; import android.text.TextUtils; +import android.util.Pair; import com.android.internal.R; import com.android.server.wifi.WifiConfigStoreLegacy.WifiConfigStoreDataLegacy; @@ -103,9 +104,12 @@ public class WifiConfigManagerTest { @Mock private PackageManager mPackageManager; @Mock private DevicePolicyManagerInternal mDevicePolicyManagerInternal; @Mock private WifiPermissionsWrapper mWifiPermissionsWrapper; + @Mock private NetworkListStoreData mNetworkListStoreData; + @Mock private DeletedEphemeralSsidsStoreData mDeletedEphemeralSsidsStoreData; private MockResources mResources; private InOrder mContextConfigStoreMockOrder; + private InOrder mNetworkListStoreDataMockOrder; private WifiConfigManager mWifiConfigManager; /** @@ -118,6 +122,7 @@ public class WifiConfigManagerTest { // Set up the inorder for verifications. This is needed to verify that the broadcasts, // store writes for network updates followed by network additions are in the expected order. mContextConfigStoreMockOrder = inOrder(mContext, mWifiConfigStore); + mNetworkListStoreDataMockOrder = inOrder(mNetworkListStoreData); // Set up the package name stuff & permission override. when(mContext.getPackageManager()).thenReturn(mPackageManager); @@ -173,9 +178,6 @@ public class WifiConfigManagerTest { .thenReturn(true); when(mWifiConfigStore.areStoresPresent()).thenReturn(true); - when(mWifiConfigStore.read()) - .thenReturn(new WifiConfigStoreData(new ArrayList<WifiConfiguration>(), - new ArrayList<WifiConfiguration>(), new HashSet<String>())); when(mDevicePolicyManagerInternal.isActiveAdminWithPolicy(anyInt(), anyInt())) .thenReturn(false); @@ -285,9 +287,13 @@ public class WifiConfigManagerTest { assertTrue(addNetworkToWifiConfigManager(openNetwork).isSuccess()); // The open network addition should trigger a store write. - WifiConfigStoreData storeData = captureWriteStoreData(); - assertFalse(isNetworkInConfigStoreData(ephemeralNetwork, storeData)); - assertTrue(isNetworkInConfigStoreData(openNetwork, storeData)); + Pair<List<WifiConfiguration>, List<WifiConfiguration>> networkListStoreData = + captureWriteNetworksListStoreData(); + List<WifiConfiguration> networkList = new ArrayList<>(); + networkList.addAll(networkListStoreData.first); + networkList.addAll(networkListStoreData.second); + assertFalse(isNetworkInConfigStoreData(ephemeralNetwork, networkList)); + assertTrue(isNetworkInConfigStoreData(openNetwork, networkList)); } /** @@ -1822,10 +1828,9 @@ public class WifiConfigManagerTest { add(user1Network); } }; - WifiConfigStoreData loadStoreData = - new WifiConfigStoreData(sharedNetworks, user1Networks, new HashSet<String>()); - when(mWifiConfigStore.read()).thenReturn(loadStoreData); + setupStoreDataForRead(sharedNetworks, user1Networks, new HashSet<String>()); assertTrue(mWifiConfigManager.loadFromStore()); + verify(mWifiConfigStore).read(); // Fetch the network ID's assigned to the shared networks initially. int sharedNetwork1Id = WifiConfiguration.INVALID_NETWORK_ID; @@ -1848,14 +1853,11 @@ public class WifiConfigManagerTest { add(user2Network); } }; - WifiConfigStoreData newUserStoreData = - new WifiConfigStoreData(new ArrayList<WifiConfiguration>(), user2Networks, - new HashSet<String>()); - when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class))) - .thenReturn(newUserStoreData); + setupStoreDataForUserRead(user2Networks, new HashSet<String>()); // Now switch the user to user 2 and ensure that shared network's IDs have not changed. when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true); mWifiConfigManager.handleUserSwitch(user2); + verify(mWifiConfigStore).switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)); // Again fetch the network ID's assigned to the shared networks and ensure they have not // changed. @@ -1908,10 +1910,9 @@ public class WifiConfigManagerTest { add(user1Network); } }; - WifiConfigStoreData loadStoreData = - new WifiConfigStoreData(sharedNetworks, user1Networks, new HashSet<String>()); - when(mWifiConfigStore.read()).thenReturn(loadStoreData); + setupStoreDataForRead(sharedNetworks, user1Networks, new HashSet<String>()); assertTrue(mWifiConfigManager.loadFromStore()); + verify(mWifiConfigStore).read(); // Fetch the network ID assigned to the user 1 network initially. int user1NetworkId = WifiConfiguration.INVALID_NETWORK_ID; @@ -1929,14 +1930,11 @@ public class WifiConfigManagerTest { add(user2Network); } }; - WifiConfigStoreData newUserStoreData = - new WifiConfigStoreData(new ArrayList<WifiConfiguration>(), user2Networks, - new HashSet<String>()); - when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class))) - .thenReturn(newUserStoreData); + setupStoreDataForUserRead(user2Networks, new HashSet<String>()); // Now switch the user to user 2 and ensure that user 1's private network has been removed. when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true); Set<Integer> removedNetworks = mWifiConfigManager.handleUserSwitch(user2); + verify(mWifiConfigStore).switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)); assertTrue((removedNetworks.size() == 1) && (removedNetworks.contains(user1NetworkId))); // Set the expected networks to be |sharedNetwork| and |user2Network|. @@ -1983,11 +1981,10 @@ public class WifiConfigManagerTest { add(sharedNetwork); } }; - WifiConfigStoreData loadStoreData = - new WifiConfigStoreData(sharedNetworks, new ArrayList<WifiConfiguration>(), - new HashSet<String>()); - when(mWifiConfigStore.read()).thenReturn(loadStoreData); + setupStoreDataForRead(sharedNetworks, new ArrayList<WifiConfiguration>(), + new HashSet<String>()); assertTrue(mWifiConfigManager.loadFromStore()); + verify(mWifiConfigStore).read(); // Set up the user 2 store data that is loaded at user switch. List<WifiConfiguration> user2Networks = new ArrayList<WifiConfiguration>() { @@ -1995,14 +1992,11 @@ public class WifiConfigManagerTest { add(user2Network); } }; - WifiConfigStoreData newUserStoreData = - new WifiConfigStoreData(new ArrayList<WifiConfiguration>(), user2Networks, - new HashSet<String>()); - when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class))) - .thenReturn(newUserStoreData); + setupStoreDataForUserRead(user2Networks, new HashSet<String>()); // Now switch the user to user 2 and ensure that no private network has been removed. when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true); Set<Integer> removedNetworks = mWifiConfigManager.handleUserSwitch(user2); + verify(mWifiConfigStore).switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)); assertTrue(removedNetworks.isEmpty()); } @@ -2040,11 +2034,10 @@ public class WifiConfigManagerTest { add(user2Network); } }; - WifiConfigStoreData loadStoreData = - new WifiConfigStoreData(sharedNetworks, new ArrayList<WifiConfiguration>(), - new HashSet<String>()); - when(mWifiConfigStore.read()).thenReturn(loadStoreData); + setupStoreDataForRead(sharedNetworks, new ArrayList<WifiConfiguration>(), + new HashSet<String>()); assertTrue(mWifiConfigManager.loadFromStore()); + verify(mWifiConfigStore).read(); // Set up the user store data that is loaded at user unlock. List<WifiConfiguration> userNetworks = new ArrayList<WifiConfiguration>() { @@ -2052,19 +2045,17 @@ public class WifiConfigManagerTest { add(user1Network); } }; - WifiConfigStoreData unlockLoadStoreData = - new WifiConfigStoreData(new ArrayList<WifiConfiguration>(), userNetworks, - new HashSet<String>()); - when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class))) - .thenReturn(unlockLoadStoreData); + setupStoreDataForUserRead(userNetworks, new HashSet<String>()); mWifiConfigManager.handleUserUnlock(user1); + verify(mWifiConfigStore).switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)); // Capture the written data for the user 1 and ensure that it corresponds to what was // setup. - WifiConfigStoreData writtenStoreData = captureWriteStoreData(); + Pair<List<WifiConfiguration>, List<WifiConfiguration>> writtenNetworkList = + captureWriteNetworksListStoreData(); WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - sharedNetworks, writtenStoreData.getSharedConfigurations()); + sharedNetworks, writtenNetworkList.first); WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - userNetworks, writtenStoreData.getUserConfigurations()); + userNetworks, writtenNetworkList.second); // Now switch the user to user2 and ensure that user 2's private network has been moved to // the user store. @@ -2087,19 +2078,19 @@ public class WifiConfigManagerTest { }; // Capture the first written data triggered for saving the old user's network // configurations. - writtenStoreData = captureWriteStoreData(); + writtenNetworkList = captureWriteNetworksListStoreData(); WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - sharedNetworks, writtenStoreData.getSharedConfigurations()); + sharedNetworks, writtenNetworkList.first); WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - userNetworks, writtenStoreData.getUserConfigurations()); + userNetworks, writtenNetworkList.second); // Now capture the next written data triggered after the switch and ensure that user 2's // network is now in user store data. - writtenStoreData = captureWriteStoreData(); + writtenNetworkList = captureWriteNetworksListStoreData(); WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - expectedSharedNetworks, writtenStoreData.getSharedConfigurations()); + expectedSharedNetworks, writtenNetworkList.first); WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate( - expectedUserNetworks, writtenStoreData.getUserConfigurations()); + expectedUserNetworks, writtenNetworkList.second); } /** @@ -2116,11 +2107,7 @@ public class WifiConfigManagerTest { // Set up the internal data first. assertTrue(mWifiConfigManager.loadFromStore()); - when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class))) - .thenReturn(new WifiConfigStoreData( - new ArrayList<WifiConfiguration>(), new ArrayList<WifiConfiguration>(), - new HashSet<String>())); - + setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>()); // user2 is unlocked and switched to foreground. when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true); mWifiConfigManager.handleUserSwitch(user2); @@ -2155,11 +2142,7 @@ public class WifiConfigManagerTest { mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) .switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)); - when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class))) - .thenReturn(new WifiConfigStoreData( - new ArrayList<WifiConfiguration>(), new ArrayList<WifiConfiguration>(), - new HashSet<String>())); - + setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>()); // Unlock the user2 and ensure that we read the data now. mWifiConfigManager.handleUserUnlock(user2); mContextConfigStoreMockOrder.verify(mWifiConfigStore) @@ -2186,8 +2169,7 @@ public class WifiConfigManagerTest { mWifiConfigManager.handleUserStop(user1); mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) .switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)); - mContextConfigStoreMockOrder.verify(mWifiConfigStore).write( - anyBoolean(), any(WifiConfigStoreData.class)); + mContextConfigStoreMockOrder.verify(mWifiConfigStore).write(anyBoolean()); } /** @@ -2201,23 +2183,17 @@ public class WifiConfigManagerTest { // Set up the internal data first. assertTrue(mWifiConfigManager.loadFromStore()); mContextConfigStoreMockOrder.verify(mWifiConfigStore).read(); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .write(anyBoolean(), any(WifiConfigStoreData.class)); + mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) .switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)); - when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class))) - .thenReturn(new WifiConfigStoreData( - new ArrayList<WifiConfiguration>(), new ArrayList<WifiConfiguration>(), - new HashSet<String>())); - + setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>()); // Unlock the user1 (default user) for the first time and ensure that we read the data. mWifiConfigManager.handleUserUnlock(user1); mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).read(); mContextConfigStoreMockOrder.verify(mWifiConfigStore) .switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)); - mContextConfigStoreMockOrder.verify(mWifiConfigStore) - .write(anyBoolean(), any(WifiConfigStoreData.class)); + mContextConfigStoreMockOrder.verify(mWifiConfigStore).write(anyBoolean()); } /** @@ -2233,23 +2209,17 @@ public class WifiConfigManagerTest { // data. mWifiConfigManager.handleUserUnlock(user1); mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).read(); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .write(anyBoolean(), any(WifiConfigStoreData.class)); + mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) .switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)); - when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class))) - .thenReturn(new WifiConfigStoreData( - new ArrayList<WifiConfiguration>(), new ArrayList<WifiConfiguration>(), - new HashSet<String>())); - + setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>()); // Read from store now. assertTrue(mWifiConfigManager.loadFromStore()); mContextConfigStoreMockOrder.verify(mWifiConfigStore).read(); mContextConfigStoreMockOrder.verify(mWifiConfigStore) .switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)); - mContextConfigStoreMockOrder.verify(mWifiConfigStore) - .write(anyBoolean(), any(WifiConfigStoreData.class)); + mContextConfigStoreMockOrder.verify(mWifiConfigStore).write(anyBoolean()); } /** @@ -2265,11 +2235,7 @@ public class WifiConfigManagerTest { // Set up the internal data first. assertTrue(mWifiConfigManager.loadFromStore()); - when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class))) - .thenReturn(new WifiConfigStoreData( - new ArrayList<WifiConfiguration>(), new ArrayList<WifiConfiguration>(), - new HashSet<String>())); - + setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>()); // user2 is unlocked and switched to foreground. when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true); mWifiConfigManager.handleUserSwitch(user2); @@ -2297,8 +2263,7 @@ public class WifiConfigManagerTest { mWifiConfigManager.handleUserSwitch(user2); mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) .switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .write(anyBoolean(), any(WifiConfigStoreData.class)); + mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); } /** @@ -2314,8 +2279,7 @@ public class WifiConfigManagerTest { mWifiConfigManager.handleUserUnlock(user1); mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) .switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)); - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .write(anyBoolean(), any(WifiConfigStoreData.class)); + mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); } /** @@ -2439,10 +2403,7 @@ public class WifiConfigManagerTest { verify(mWifiConfigStore, never()).read(); verify(mWifiConfigStoreLegacy, never()).read(); - when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class))) - .thenReturn(new WifiConfigStoreData( - new ArrayList<WifiConfiguration>(), new ArrayList<WifiConfiguration>(), - new HashSet<String>())); + setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>()); // Now switch the user to user 2. when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true); mWifiConfigManager.handleUserSwitch(user2); @@ -2563,8 +2524,7 @@ public class WifiConfigManagerTest { // This should have triggered 2 buffered writes. 1 for setting the connect choice, 1 for // clearing it after network removal. - mContextConfigStoreMockOrder.verify(mWifiConfigStore, times(2)) - .write(eq(false), any(WifiConfigStoreData.class)); + mContextConfigStoreMockOrder.verify(mWifiConfigStore, times(2)).write(eq(false)); } /** @@ -3147,7 +3107,8 @@ public class WifiConfigManagerTest { new WifiConfigManager( mContext, mFrameworkFacade, mClock, mUserManager, mTelephonyManager, mWifiKeyStore, mWifiConfigStore, mWifiConfigStoreLegacy, - mWifiPermissionsWrapper); + mWifiPermissionsWrapper, mNetworkListStoreData, + mDeletedEphemeralSsidsStoreData); mWifiConfigManager.enableVerboseLogging(1); } @@ -3270,15 +3231,22 @@ public class WifiConfigManagerTest { } /** - * Helper method to capture the store data written in WifiConfigStore.write() method. + * Helper method to capture the networks list store data that will be written by + * WifiConfigStore.write() method. */ - private WifiConfigStoreData captureWriteStoreData() { + private Pair<List<WifiConfiguration>, List<WifiConfiguration>> + captureWriteNetworksListStoreData() { try { - ArgumentCaptor<WifiConfigStoreData> storeDataCaptor = - ArgumentCaptor.forClass(WifiConfigStoreData.class); - mContextConfigStoreMockOrder.verify(mWifiConfigStore) - .write(anyBoolean(), storeDataCaptor.capture()); - return storeDataCaptor.getValue(); + ArgumentCaptor<ArrayList> sharedConfigsCaptor = + ArgumentCaptor.forClass(ArrayList.class); + ArgumentCaptor<ArrayList> userConfigsCaptor = + ArgumentCaptor.forClass(ArrayList.class); + mNetworkListStoreDataMockOrder.verify(mNetworkListStoreData) + .setSharedConfigurations(sharedConfigsCaptor.capture()); + mNetworkListStoreDataMockOrder.verify(mNetworkListStoreData) + .setUserConfigurations(userConfigsCaptor.capture()); + mContextConfigStoreMockOrder.verify(mWifiConfigStore).write(anyBoolean()); + return Pair.create(sharedConfigsCaptor.getValue(), userConfigsCaptor.getValue()); } catch (Exception e) { fail("Exception encountered during write " + e); } @@ -3289,20 +3257,24 @@ public class WifiConfigManagerTest { * Returns whether the provided network was in the store data or not. */ private boolean isNetworkInConfigStoreData(WifiConfiguration configuration) { - WifiConfigStoreData storeData = captureWriteStoreData(); - if (storeData == null) { + Pair<List<WifiConfiguration>, List<WifiConfiguration>> networkListStoreData = + captureWriteNetworksListStoreData(); + if (networkListStoreData == null) { return false; } - return isNetworkInConfigStoreData(configuration, storeData); + List<WifiConfiguration> networkList = new ArrayList<>(); + networkList.addAll(networkListStoreData.first); + networkList.addAll(networkListStoreData.second); + return isNetworkInConfigStoreData(configuration, networkList); } /** * Returns whether the provided network was in the store data or not. */ private boolean isNetworkInConfigStoreData( - WifiConfiguration configuration, WifiConfigStoreData storeData) { + WifiConfiguration configuration, List<WifiConfiguration> networkList) { boolean foundNetworkInStoreData = false; - for (WifiConfiguration retrievedConfig : storeData.getConfigurations()) { + for (WifiConfiguration retrievedConfig : networkList) { if (retrievedConfig.configKey().equals(configuration.configKey())) { foundNetworkInStoreData = true; break; @@ -3312,6 +3284,28 @@ public class WifiConfigManagerTest { } /** + * Setup expectations for WifiNetworksListStoreData and DeletedEphemeralSsidsStoreData + * after WifiConfigStore#read. + */ + private void setupStoreDataForRead(List<WifiConfiguration> sharedConfigurations, + List<WifiConfiguration> userConfigurations, Set<String> deletedEphemeralSsids) { + when(mNetworkListStoreData.getSharedConfigurations()) + .thenReturn(sharedConfigurations); + when(mNetworkListStoreData.getUserConfigurations()).thenReturn(userConfigurations); + when(mDeletedEphemeralSsidsStoreData.getSsidList()).thenReturn(deletedEphemeralSsids); + } + + /** + * Setup expectations for WifiNetworksListStoreData and DeletedEphemeralSsidsStoreData + * after WifiConfigStore#switchUserStoreAndRead. + */ + private void setupStoreDataForUserRead(List<WifiConfiguration> userConfigurations, + Set<String> deletedEphemeralSsids) { + when(mNetworkListStoreData.getUserConfigurations()).thenReturn(userConfigurations); + when(mDeletedEphemeralSsidsStoreData.getSsidList()).thenReturn(deletedEphemeralSsids); + } + + /** * Verifies that the provided network was not present in the last config store write. */ private void verifyNetworkNotInConfigStoreData(WifiConfiguration configuration) { @@ -3441,8 +3435,7 @@ public class WifiConfigManagerTest { verifyNetworkAddBroadcast(configuration); // Ensure that the write was not invoked for ephemeral network addition. - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .write(anyBoolean(), any(WifiConfigStoreData.class)); + mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); return result; } @@ -3462,8 +3455,7 @@ public class WifiConfigManagerTest { any(WifiConfiguration.class)); verifyNetworkAddBroadcast(configuration); // Ensure that the write was not invoked for Passpoint network addition. - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .write(anyBoolean(), any(WifiConfigStoreData.class)); + mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); return result; } @@ -3541,8 +3533,7 @@ public class WifiConfigManagerTest { verifyNetworkRemoveBroadcast(configuration); // Ensure that the write was not invoked for ephemeral network remove. - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .write(anyBoolean(), any(WifiConfigStoreData.class)); + mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); } /** @@ -3556,8 +3547,7 @@ public class WifiConfigManagerTest { verify(mWifiKeyStore, never()).removeKeys(any(WifiEnterpriseConfig.class)); verifyNetworkRemoveBroadcast(configuration); // Ensure that the write was not invoked for Passpoint network remove. - mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()) - .write(anyBoolean(), any(WifiConfigStoreData.class)); + mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean()); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreDataTest.java deleted file mode 100644 index 3fa5d3dab..000000000 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreDataTest.java +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wifi; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiConfiguration.NetworkSelectionStatus; -import android.test.suitebuilder.annotation.SmallTest; - -import org.junit.Test; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Random; -import java.util.Set; - -/** - * Unit tests for {@link com.android.server.wifi.WifiConfigStoreData}. - */ -@SmallTest -public class WifiConfigStoreDataTest { - - private static final String TEST_SSID = "WifiConfigStoreDataSSID_"; - private static final String TEST_CONNECT_CHOICE = "XmlUtilConnectChoice"; - private static final long TEST_CONNECT_CHOICE_TIMESTAMP = 0x4566; - private static final Set<String> TEST_DELETED_EPHEMERAL_LIST = new HashSet<String>() { - { - add("\"" + TEST_SSID + "1\""); - add("\"" + TEST_SSID + "2\""); - } - }; - private static final String SINGLE_OPEN_NETWORK_LIST_XML_STRING_FORMAT = - "<NetworkList>\n" - + "<Network>\n" - + "<WifiConfiguration>\n" - + "<string name=\"ConfigKey\">%s</string>\n" - + "<string name=\"SSID\">%s</string>\n" - + "<null name=\"BSSID\" />\n" - + "<null name=\"PreSharedKey\" />\n" - + "<null name=\"WEPKeys\" />\n" - + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" - + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" - + "<boolean name=\"RequirePMF\" value=\"false\" />\n" - + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n" - + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n" - + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n" - + "<boolean name=\"Shared\" value=\"%s\" />\n" - + "<null name=\"FQDN\" />\n" - + "<null name=\"ProviderFriendlyName\" />\n" - + "<null name=\"LinkedNetworksList\" />\n" - + "<null name=\"DefaultGwMacAddress\" />\n" - + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n" - + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n" - + "<int name=\"UserApproved\" value=\"0\" />\n" - + "<boolean name=\"MeteredHint\" value=\"false\" />\n" - + "<boolean name=\"UseExternalScores\" value=\"false\" />\n" - + "<int name=\"NumAssociation\" value=\"0\" />\n" - + "<int name=\"CreatorUid\" value=\"%d\" />\n" - + "<null name=\"CreatorName\" />\n" - + "<null name=\"CreationTime\" />\n" - + "<int name=\"LastUpdateUid\" value=\"-1\" />\n" - + "<null name=\"LastUpdateName\" />\n" - + "<int name=\"LastConnectUid\" value=\"0\" />\n" - + "</WifiConfiguration>\n" - + "<NetworkStatus>\n" - + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n" - + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n" - + "<null name=\"ConnectChoice\" />\n" - + "<long name=\"ConnectChoiceTimeStamp\" value=\"-1\" />\n" - + "<boolean name=\"HasEverConnected\" value=\"false\" />\n" - + "</NetworkStatus>\n" - + "<IpConfiguration>\n" - + "<string name=\"IpAssignment\">DHCP</string>\n" - + "<string name=\"ProxySettings\">NONE</string>\n" - + "</IpConfiguration>\n" - + "</Network>\n" - + "</NetworkList>\n"; - private static final String SINGLE_OPEN_NETWORK_SHARED_DATA_XML_STRING_FORMAT = - "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" - + "<WifiConfigStoreData>\n" - + "<int name=\"Version\" value=\"1\" />\n" - + SINGLE_OPEN_NETWORK_LIST_XML_STRING_FORMAT - + "</WifiConfigStoreData>\n"; - private static final String SINGLE_OPEN_NETWORK_USER_DATA_XML_STRING_FORMAT = - "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" - + "<WifiConfigStoreData>\n" - + "<int name=\"Version\" value=\"1\" />\n" - + SINGLE_OPEN_NETWORK_LIST_XML_STRING_FORMAT - + "<DeletedEphemeralSSIDList>\n" - + "<set name=\"SSIDList\" />\n" - + "</DeletedEphemeralSSIDList>\n" - + "</WifiConfigStoreData>\n"; - - /** - * Asserts that the 2 config store data are equal. - */ - public static void assertConfigStoreDataEqual( - WifiConfigStoreData expected, WifiConfigStoreData actual) { - WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore( - expected.getConfigurations(), actual.getConfigurations()); - assertEquals(expected.getDeletedEphemeralSSIDs(), actual.getDeletedEphemeralSSIDs()); - } - - /** - * Verify that multiple shared networks with different credential types and IpConfiguration - * types are serialized and deserialized correctly. - */ - @Test - public void testMultipleNetworkAllShared() - throws XmlPullParserException, IOException { - List<WifiConfiguration> configurations = createNetworks(true); - serializeDeserializeConfigStoreData(configurations, new ArrayList<WifiConfiguration>()); - } - - /** - * Verify that multiple user networks with different credential types and IpConfiguration - * types are serialized and deserialized correctly. - */ - @Test - public void testMultipleNetworksAllUser() - throws XmlPullParserException, IOException { - List<WifiConfiguration> configurations = createNetworks(false); - serializeDeserializeConfigStoreData(new ArrayList<WifiConfiguration>(), configurations); - } - - /** - * Verify that multiple networks with different credential types and IpConfiguration - * types are serialized and deserialized correctly when both user & shared networks are present. - */ - @Test - public void testMultipleNetworksSharedAndUserNetworks() - throws XmlPullParserException, IOException { - List<WifiConfiguration> configurations = createNetworks(); - // Let's split the list of networks into 2 and make all the networks in the first list - // shared and the second list all user networks. - int listSize = configurations.size(); - List<WifiConfiguration> sharedConfigurations = configurations.subList(0, listSize / 2); - List<WifiConfiguration> userConfigurations = configurations.subList(listSize / 2, listSize); - for (WifiConfiguration config : sharedConfigurations) { - config.shared = true; - } - for (WifiConfiguration config : userConfigurations) { - config.shared = false; - } - serializeDeserializeConfigStoreData(sharedConfigurations, userConfigurations); - } - - /** - * Verify that multiple shared networks with different credential types and IpConfiguration - * types are serialized and deserialized correctly when the shared data bytes are null in - * |parseRawData| method. - */ - @Test - public void testMultipleNetworksSharedDataNullInParseRawData() - throws XmlPullParserException, IOException { - List<WifiConfiguration> configurations = createNetworks(false); - serializeDeserializeConfigStoreData( - new ArrayList<WifiConfiguration>(), configurations, true, false); - } - - /** - * Verify that multiple shared networks with different credential types and IpConfiguration - * types are serialized and deserialized correctly when the user data bytes are null in - * |parseRawData| method. - */ - @Test - public void testMultipleNetworksUserDataNullInParseRawData() - throws XmlPullParserException, IOException { - List<WifiConfiguration> configurations = createNetworks(true); - serializeDeserializeConfigStoreData( - configurations, new ArrayList<WifiConfiguration>(), false, true); - } - - /** - * Verify that a network with invalid entepriseConfig data is serialized/deserialized - * correctly. - */ - @Test - public void testInvalidEnterpriseConfig() - throws XmlPullParserException, IOException { - WifiConfiguration eapNetwork = WifiConfigurationTestUtil.createEapNetwork(); - eapNetwork.enterpriseConfig = new WifiEnterpriseConfig(); - List<WifiConfiguration> configurations = Arrays.asList(eapNetwork); - serializeDeserializeConfigStoreData( - new ArrayList<WifiConfiguration>(), configurations, false, false); - } - - /** - * Verify that the manually populated xml string for is deserialized/serialized correctly. - * This generates a store data corresponding to the XML string and verifies that the string - * is indeed parsed correctly to the store data. - */ - @Test - public void testManualConfigStoreDataParse() { - WifiConfiguration sharedNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - sharedNetwork.shared = true; - sharedNetwork.setIpConfiguration(WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy()); - WifiConfiguration userNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - userNetwork.setIpConfiguration(WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy()); - userNetwork.shared = false; - - // Create the store data for comparison. - List<WifiConfiguration> sharedNetworks = new ArrayList<>(); - List<WifiConfiguration> userNetworks = new ArrayList<>(); - sharedNetworks.add(sharedNetwork); - userNetworks.add(userNetwork); - WifiConfigStoreData storeData = - new WifiConfigStoreData(sharedNetworks, userNetworks, new HashSet<String>()); - - String sharedStoreXmlString = - String.format(SINGLE_OPEN_NETWORK_SHARED_DATA_XML_STRING_FORMAT, - sharedNetwork.configKey().replaceAll("\"", """), - sharedNetwork.SSID.replaceAll("\"", """), - sharedNetwork.shared, sharedNetwork.creatorUid); - String userStoreXmlString = - String.format(SINGLE_OPEN_NETWORK_USER_DATA_XML_STRING_FORMAT, - userNetwork.configKey().replaceAll("\"", """), - userNetwork.SSID.replaceAll("\"", """), - userNetwork.shared, userNetwork.creatorUid); - byte[] rawSharedData = sharedStoreXmlString.getBytes(); - byte[] rawUserData = userStoreXmlString.getBytes(); - WifiConfigStoreData retrievedStoreData = null; - try { - retrievedStoreData = WifiConfigStoreData.parseRawData(rawSharedData, rawUserData); - } catch (Exception e) { - // Assert if an exception was raised. - fail("Error in parsing the xml data: " + e - + ". Shared data: " + sharedStoreXmlString - + ", User data: " + userStoreXmlString); - } - // Compare the retrieved config store data with the original. - assertConfigStoreDataEqual(storeData, retrievedStoreData); - - // Now convert the store data to XML bytes and compare the output with the expected string. - byte[] retrievedSharedStoreXmlBytes = null; - byte[] retrievedUserStoreXmlBytes = null; - try { - retrievedSharedStoreXmlBytes = retrievedStoreData.createSharedRawData(); - retrievedUserStoreXmlBytes = retrievedStoreData.createUserRawData(); - } catch (Exception e) { - // Assert if an exception was raised. - fail("Error in writing the xml data: " + e); - } - String retrievedSharedStoreXmlString = - new String(retrievedSharedStoreXmlBytes, StandardCharsets.UTF_8); - String retrievedUserStoreXmlString = - new String(retrievedUserStoreXmlBytes, StandardCharsets.UTF_8); - assertEquals("Retrieved: " + retrievedSharedStoreXmlString - + ", Expected: " + sharedStoreXmlString, - sharedStoreXmlString, retrievedSharedStoreXmlString); - assertEquals("Retrieved: " + retrievedUserStoreXmlString - + ", Expected: " + userStoreXmlString, - userStoreXmlString, retrievedUserStoreXmlString); - } - - /** - * Verify that XML with corrupted version provided to WifiConfigStoreData is ignored correctly. - */ - @Test - public void testCorruptVersionConfigStoreData() { - String storeDataAsString = - "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" - + "<WifiConfigStoreData>\n" - + "<int name=\"Version\" value=\"200\" />\n" - + "</WifiConfigStoreData>\n"; - byte[] rawData = storeDataAsString.getBytes(); - try { - WifiConfigStoreData storeData = WifiConfigStoreData.parseRawData(rawData, rawData); - } catch (Exception e) { - return; - } - // Assert if there was no exception was raised. - fail(); - } - - /** - * Verify that XML with no network list provided to WifiConfigStoreData is ignored correctly. - */ - @Test - public void testCorruptNetworkListConfigStoreData() { - String storeDataAsString = - "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" - + "<WifiConfigStoreData>\n" - + "<int name=\"Version\" value=\"1\" />\n" - + "</WifiConfigStoreData>\n"; - byte[] rawData = storeDataAsString.getBytes(); - try { - WifiConfigStoreData storeData = WifiConfigStoreData.parseRawData(rawData, rawData); - } catch (Exception e) { - return; - } - // Assert if there was no exception was raised. - fail(); - } - - /** - * Verify that any corrupted data provided to WifiConfigStoreData is ignored correctly. - */ - @Test - public void testRandomCorruptConfigStoreData() { - Random random = new Random(); - byte[] rawData = new byte[100]; - random.nextBytes(rawData); - try { - WifiConfigStoreData storeData = WifiConfigStoreData.parseRawData(rawData, rawData); - } catch (Exception e) { - return; - } - // Assert if there was no exception was raised. - fail(); - } - - /** - * Helper method to add 4 networks with different credential types, IpConfiguration - * types for all tests in the class. - * - * @return - */ - private List<WifiConfiguration> createNetworks() { - List<WifiConfiguration> configurations = new ArrayList<>(); - - WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork(); - wepNetwork.setIpConfiguration(WifiConfigurationTestUtil.createDHCPIpConfigurationWithPacProxy()); - wepNetwork.getNetworkSelectionStatus().setNetworkSelectionStatus( - NetworkSelectionStatus.NETWORK_SELECTION_ENABLED); - configurations.add(wepNetwork); - - WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); - pskNetwork.setIpConfiguration(WifiConfigurationTestUtil.createStaticIpConfigurationWithPacProxy()); - pskNetwork.getNetworkSelectionStatus().setNetworkSelectionStatus( - NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED); - pskNetwork.getNetworkSelectionStatus().setNetworkSelectionDisableReason( - NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION); - configurations.add(pskNetwork); - - WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); - openNetwork.setIpConfiguration(WifiConfigurationTestUtil.createStaticIpConfigurationWithStaticProxy()); - openNetwork.getNetworkSelectionStatus().setNetworkSelectionStatus( - NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED); - openNetwork.getNetworkSelectionStatus().setNetworkSelectionDisableReason( - NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER); - configurations.add(openNetwork); - - WifiConfiguration eapNetwork = WifiConfigurationTestUtil.createEapNetwork(); - eapNetwork.setIpConfiguration(WifiConfigurationTestUtil.createPartialStaticIpConfigurationWithPacProxy()); - eapNetwork.getNetworkSelectionStatus().setConnectChoice(TEST_CONNECT_CHOICE); - eapNetwork.getNetworkSelectionStatus().setConnectChoiceTimestamp( - TEST_CONNECT_CHOICE_TIMESTAMP); - eapNetwork.getNetworkSelectionStatus().setHasEverConnected(true); - configurations.add(eapNetwork); - - return configurations; - } - - private List<WifiConfiguration> createNetworks(boolean shared) { - List<WifiConfiguration> configurations = createNetworks(); - for (WifiConfiguration config : configurations) { - config.shared = shared; - } - return configurations; - } - - /** - * Helper method to serialize/deserialize store data. - */ - private void serializeDeserializeConfigStoreData( - List<WifiConfiguration> sharedConfigurations, - List<WifiConfiguration> userConfigurations) - throws XmlPullParserException, IOException { - serializeDeserializeConfigStoreData(sharedConfigurations, userConfigurations, false, false); - } - - /** - * Helper method to ensure the the provided config store data is serialized/deserialized - * correctly. - * This method serialize the provided config store data instance to raw bytes in XML format - * and then deserialzes the raw bytes back to a config store data instance. It then - * compares that the original config store data matches with the deserialzed instance. - * - * @param sharedConfigurations list of configurations to be added in the shared store data instance. - * @param userConfigurations list of configurations to be added in the user store data instance. - * @param setSharedDataNull whether to set the shared data to null to simulate the non-existence - * of the shared store file. - * @param setUserDataNull whether to set the user data to null to simulate the non-existence - * of the user store file. - */ - private void serializeDeserializeConfigStoreData( - List<WifiConfiguration> sharedConfigurations, - List<WifiConfiguration> userConfigurations, - boolean setSharedDataNull, boolean setUserDataNull) - throws XmlPullParserException, IOException { - // Will not work if both the flags are set because then we need to ignore the configuration - // list as well. - assertFalse(setSharedDataNull & setUserDataNull); - - Set<String> deletedEphemeralList; - if (setUserDataNull) { - deletedEphemeralList = new HashSet<>(); - } else { - deletedEphemeralList = TEST_DELETED_EPHEMERAL_LIST; - } - - // Serialize the data. - WifiConfigStoreData storeData = - new WifiConfigStoreData( - sharedConfigurations, userConfigurations, deletedEphemeralList); - - byte[] sharedDataBytes = null; - byte[] userDataBytes = null; - if (!setSharedDataNull) { - sharedDataBytes = storeData.createSharedRawData(); - } - if (!setUserDataNull) { - userDataBytes = storeData.createUserRawData(); - } - - // Deserialize the data. - WifiConfigStoreData retrievedStoreData = - WifiConfigStoreData.parseRawData(sharedDataBytes, userDataBytes); - assertConfigStoreDataEqual(storeData, retrievedStoreData); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java index f567ef6d5..b7e642c91 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java @@ -16,8 +16,6 @@ package com.android.server.wifi; -import static com.android.server.wifi.WifiConfigStoreDataTest.assertConfigStoreDataEqual; - import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -28,23 +26,99 @@ import android.os.test.TestLooper; import android.test.suitebuilder.annotation.SmallTest; import com.android.server.wifi.WifiConfigStore.StoreFile; +import com.android.server.wifi.util.XmlUtil; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Set; /** * Unit tests for {@link com.android.server.wifi.WifiConfigStore}. */ @SmallTest public class WifiConfigStoreTest { + // Store file content without any data. + private static final String EMPTY_FILE_CONTENT = + "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + + "<WifiConfigStoreData>\n" + + "<int name=\"Version\" value=\"1\" />\n" + + "</WifiConfigStoreData>\n"; + + private static final String TEST_USER_DATA = "UserData"; + private static final String TEST_SHARE_DATA = "ShareData"; + + private static final String TEST_DATA_XML_STRING_FORMAT = + "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + + "<WifiConfigStoreData>\n" + + "<int name=\"Version\" value=\"1\" />\n" + + "<NetworkList>\n" + + "<Network>\n" + + "<WifiConfiguration>\n" + + "<string name=\"ConfigKey\">%s</string>\n" + + "<string name=\"SSID\">%s</string>\n" + + "<null name=\"BSSID\" />\n" + + "<null name=\"PreSharedKey\" />\n" + + "<null name=\"WEPKeys\" />\n" + + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n" + + "<boolean name=\"HiddenSSID\" value=\"false\" />\n" + + "<boolean name=\"RequirePMF\" value=\"false\" />\n" + + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n" + + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n" + + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n" + + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n" + + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n" + + "<boolean name=\"Shared\" value=\"%s\" />\n" + + "<null name=\"FQDN\" />\n" + + "<null name=\"ProviderFriendlyName\" />\n" + + "<null name=\"LinkedNetworksList\" />\n" + + "<null name=\"DefaultGwMacAddress\" />\n" + + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n" + + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n" + + "<int name=\"UserApproved\" value=\"0\" />\n" + + "<boolean name=\"MeteredHint\" value=\"false\" />\n" + + "<boolean name=\"UseExternalScores\" value=\"false\" />\n" + + "<int name=\"NumAssociation\" value=\"0\" />\n" + + "<int name=\"CreatorUid\" value=\"%d\" />\n" + + "<null name=\"CreatorName\" />\n" + + "<null name=\"CreationTime\" />\n" + + "<int name=\"LastUpdateUid\" value=\"-1\" />\n" + + "<null name=\"LastUpdateName\" />\n" + + "<int name=\"LastConnectUid\" value=\"0\" />\n" + + "</WifiConfiguration>\n" + + "<NetworkStatus>\n" + + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n" + + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n" + + "<null name=\"ConnectChoice\" />\n" + + "<long name=\"ConnectChoiceTimeStamp\" value=\"-1\" />\n" + + "<boolean name=\"HasEverConnected\" value=\"false\" />\n" + + "</NetworkStatus>\n" + + "<IpConfiguration>\n" + + "<string name=\"IpAssignment\">DHCP</string>\n" + + "<string name=\"ProxySettings\">NONE</string>\n" + + "</IpConfiguration>\n" + + "</Network>\n" + + "</NetworkList>\n" + + "<DeletedEphemeralSSIDList>\n" + + "<set name=\"SSIDList\">\n" + + "<string>%s</string>\n" + + "</set>\n" + + "</DeletedEphemeralSSIDList>\n" + + "</WifiConfigStoreData>\n"; + // Test mocks @Mock private Context mContext; private TestAlarmManager mAlarmManager; @@ -52,6 +126,7 @@ public class WifiConfigStoreTest { @Mock private Clock mClock; private MockStoreFile mSharedStore; private MockStoreFile mUserStore; + private MockStoreData mStoreData; /** * Test instance of WifiConfigStore. @@ -69,6 +144,7 @@ public class WifiConfigStoreTest { .thenReturn(mAlarmManager.getAlarmManager()); mUserStore = new MockStoreFile(); mSharedStore = new MockStoreFile(); + mStoreData = new MockStoreData(); } /** @@ -79,7 +155,6 @@ public class WifiConfigStoreTest { setupMocks(); mWifiConfigStore = new WifiConfigStore(mContext, mLooper.getLooper(), mClock, mSharedStore); - // Enable verbose logging before tests. mWifiConfigStore.enableVerboseLogging(true); } @@ -93,6 +168,27 @@ public class WifiConfigStoreTest { } /** + * Verify the contents of the config file with empty data. The data content should be the + * same as {@link #EMPTY_FILE_CONTENT}. + * + * @throws Exception + */ + @Test + public void testWriteWithEmptyData() throws Exception { + // Perform force write to both share and user store file. + mWifiConfigStore.switchUserStoreAndRead(mUserStore); + mWifiConfigStore.write(true); + + assertFalse(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG)); + assertTrue(mSharedStore.isStoreWritten()); + assertTrue(mUserStore.isStoreWritten()); + assertTrue(Arrays.equals(EMPTY_FILE_CONTENT.getBytes(StandardCharsets.UTF_8), + mSharedStore.getStoreBytes())); + assertTrue(Arrays.equals(EMPTY_FILE_CONTENT.getBytes(StandardCharsets.UTF_8), + mUserStore.getStoreBytes())); + } + + /** * Tests the write API with the force flag set to true. * Expected behavior: This should trigger an immediate write to the store files and no alarms * should be started. @@ -100,7 +196,7 @@ public class WifiConfigStoreTest { @Test public void testForceWrite() throws Exception { mWifiConfigStore.switchUserStoreAndRead(mUserStore); - mWifiConfigStore.write(true, getEmptyStoreData()); + mWifiConfigStore.write(true); assertFalse(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG)); assertTrue(mSharedStore.isStoreWritten()); @@ -114,7 +210,7 @@ public class WifiConfigStoreTest { @Test public void testBufferedWrite() throws Exception { mWifiConfigStore.switchUserStoreAndRead(mUserStore); - mWifiConfigStore.write(false, getEmptyStoreData()); + mWifiConfigStore.write(false); assertTrue(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG)); assertFalse(mSharedStore.isStoreWritten()); @@ -134,30 +230,33 @@ public class WifiConfigStoreTest { */ @Test public void testForceWriteAfterBufferedWrite() throws Exception { - WifiConfigStoreData bufferedStoreData = createSingleOpenNetworkStoreData(); + // Register a test data container with bogus data. + mWifiConfigStore.registerStoreData(mStoreData); + mStoreData.setShareData("abcds"); + mStoreData.setUserData("asdfa"); + + // Perform buffered write for both user and share store file. mWifiConfigStore.switchUserStoreAndRead(mUserStore); - mWifiConfigStore.write(false, bufferedStoreData); + mWifiConfigStore.write(false); assertTrue(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG)); assertFalse(mSharedStore.isStoreWritten()); assertFalse(mUserStore.isStoreWritten()); - // Now send a force write and ensure that the writes have been performed and alarms have - // been stopped. - WifiConfigStoreData forcedStoreData = createSinglePskNetworkStoreData(); - mWifiConfigStore.write(true, forcedStoreData); + // Update the container with new set of data. The send a force write and ensure that the + // writes have been performed and alarms have been stopped and updated data are written. + mStoreData.setUserData(TEST_USER_DATA); + mStoreData.setShareData(TEST_SHARE_DATA); + mWifiConfigStore.write(true); assertFalse(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG)); assertTrue(mSharedStore.isStoreWritten()); assertTrue(mUserStore.isStoreWritten()); - // Now deserialize the data and ensure that the configuration retrieved matches the force - // write data. - WifiConfigStoreData retrievedStoreData = - WifiConfigStoreData.parseRawData( - mSharedStore.getStoreBytes(), mUserStore.getStoreBytes()); - - assertConfigStoreDataEqual(forcedStoreData, retrievedStoreData); + // Verify correct data are loaded to the data container after a read. + mWifiConfigStore.read(); + assertEquals(TEST_USER_DATA, mStoreData.getUserData()); + assertEquals(TEST_SHARE_DATA, mStoreData.getShareData()); } /** @@ -166,12 +265,25 @@ public class WifiConfigStoreTest { */ @Test public void testReadAfterWrite() throws Exception { - WifiConfigStoreData writeData = createSingleOpenNetworkStoreData(); + // Register data container. + mWifiConfigStore.registerStoreData(mStoreData); + + // Read both share and user config store. mWifiConfigStore.switchUserStoreAndRead(mUserStore); - mWifiConfigStore.write(true, writeData); - WifiConfigStoreData readData = mWifiConfigStore.read(); - assertConfigStoreDataEqual(writeData, readData); + // Verify no data is read. + assertNull(mStoreData.getUserData()); + assertNull(mStoreData.getShareData()); + + // Write share and user data. + mStoreData.setUserData(TEST_USER_DATA); + mStoreData.setShareData(TEST_SHARE_DATA); + mWifiConfigStore.write(true); + + // Read and verify the data content in the data container. + mWifiConfigStore.read(); + assertEquals(TEST_USER_DATA, mStoreData.getUserData()); + assertEquals(TEST_SHARE_DATA, mStoreData.getShareData()); } /** @@ -183,9 +295,13 @@ public class WifiConfigStoreTest { public void testReadWithNoStoreFile() throws Exception { // Reading the mock store without a write should simulate the file not found case because // |readRawData| would return null. + mWifiConfigStore.registerStoreData(mStoreData); assertFalse(mWifiConfigStore.areStoresPresent()); - WifiConfigStoreData readData = mWifiConfigStore.read(); - assertConfigStoreDataEqual(getEmptyStoreData(), readData); + mWifiConfigStore.read(); + + // Empty data. + assertNull(mStoreData.getUserData()); + assertNull(mStoreData.getShareData()); } /** @@ -195,40 +311,164 @@ public class WifiConfigStoreTest { */ @Test public void testReadAfterWriteWithNoUserStore() throws Exception { - WifiConfigStoreData writeData = createSingleOpenNetworkStoreData(); - mWifiConfigStore.write(true, writeData); - WifiConfigStoreData readData = mWifiConfigStore.read(); + // Setup data container. + mWifiConfigStore.registerStoreData(mStoreData); + mStoreData.setUserData(TEST_USER_DATA); + mStoreData.setShareData(TEST_SHARE_DATA); + + // Perform write for the share store file. + mWifiConfigStore.write(true); + mWifiConfigStore.read(); + // Verify data content for both user and share data. + assertEquals(TEST_SHARE_DATA, mStoreData.getShareData()); + assertNull(mStoreData.getUserData()); + } + + /** + * Verifies that a read operation will reset the data in the data container, to avoid + * any stale data from previous read. + * + * @throws Exception + */ + @Test + public void testReadWillResetStoreData() throws Exception { + // Register and setup store data. + mWifiConfigStore.registerStoreData(mStoreData); + + // Perform force write with empty data content to both user and share store file. + mWifiConfigStore.switchUserStoreAndRead(mUserStore); + mWifiConfigStore.write(true); - assertConfigStoreDataEqual(writeData, readData); + // Setup data container with some value. + mStoreData.setUserData(TEST_USER_DATA); + mStoreData.setShareData(TEST_SHARE_DATA); + + // Perform read of both user and share store file and verify data in the data container + // is in sync (empty) with what is in the file. + mWifiConfigStore.read(); + assertNull(mStoreData.getShareData()); + assertNull(mStoreData.getUserData()); + } + + /** + * Verify that a store file contained WiFi configuration store data (network list and + * deleted ephemeral SSID list) using the predefined test XML data is read and parsed + * correctly. + * + * @throws Exception + */ + @Test + public void testReadWifiConfigStoreData() throws Exception { + // Setup network list. + NetworkListStoreData networkList = new NetworkListStoreData(); + mWifiConfigStore.registerStoreData(networkList); + WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); + openNetwork.setIpConfiguration( + WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy()); + List<WifiConfiguration> userConfigs = new ArrayList<>(); + userConfigs.add(openNetwork); + + // Setup deleted ephemeral SSID list. + DeletedEphemeralSsidsStoreData deletedEphemeralSsids = + new DeletedEphemeralSsidsStoreData(); + mWifiConfigStore.registerStoreData(deletedEphemeralSsids); + String testSsid = "Test SSID"; + Set<String> ssidList = new HashSet<>(); + ssidList.add(testSsid); + + // Setup user store XML bytes. + String xmlString = String.format(TEST_DATA_XML_STRING_FORMAT, + openNetwork.configKey().replaceAll("\"", """), + openNetwork.SSID.replaceAll("\"", """), + openNetwork.shared, openNetwork.creatorUid, testSsid); + byte[] xmlBytes = xmlString.getBytes(StandardCharsets.UTF_8); + mUserStore.storeRawDataToWrite(xmlBytes); + + mWifiConfigStore.switchUserStoreAndRead(mUserStore); + WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore( + userConfigs, networkList.getUserConfigurations()); + assertEquals(ssidList, deletedEphemeralSsids.getSsidList()); } /** - * Returns an empty store data object. + * Verify that the WiFi configuration store data containing network list and deleted + * ephemeral SSID list are serialized correctly, matches the predefined test XML data. + * + * @throws Exception */ - private WifiConfigStoreData getEmptyStoreData() { - return new WifiConfigStoreData( - new ArrayList<WifiConfiguration>(), new ArrayList<WifiConfiguration>(), - new HashSet<String>()); + @Test + public void testWriteWifiConfigStoreData() throws Exception { + // Setup user store. + mWifiConfigStore.switchUserStoreAndRead(mUserStore); + + // Setup network list store data. + NetworkListStoreData networkList = new NetworkListStoreData(); + mWifiConfigStore.registerStoreData(networkList); + WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); + openNetwork.setIpConfiguration( + WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy()); + List<WifiConfiguration> userConfigs = new ArrayList<>(); + userConfigs.add(openNetwork); + networkList.setUserConfigurations(userConfigs); + + // Setup deleted ephemeral SSID list store data. + DeletedEphemeralSsidsStoreData deletedEphemeralSsids = + new DeletedEphemeralSsidsStoreData(); + mWifiConfigStore.registerStoreData(deletedEphemeralSsids); + String testSsid = "Test SSID"; + Set<String> ssidList = new HashSet<>(); + ssidList.add(testSsid); + deletedEphemeralSsids.setSsidList(ssidList); + + // Setup expected XML bytes. + String xmlString = String.format(TEST_DATA_XML_STRING_FORMAT, + openNetwork.configKey().replaceAll("\"", """), + openNetwork.SSID.replaceAll("\"", """), + openNetwork.shared, openNetwork.creatorUid, testSsid); + byte[] xmlBytes = xmlString.getBytes(StandardCharsets.UTF_8); + + mWifiConfigStore.write(true); + assertEquals(xmlBytes.length, mUserStore.getStoreBytes().length); + // Verify the user store content. + assertTrue(Arrays.equals(xmlBytes, mUserStore.getStoreBytes())); } /** - * Returns an store data object with a single open network. + * Verify that a XmlPullParserException will be thrown when reading an user store file + * containing unknown data. + * + * @throws Exception */ - private WifiConfigStoreData createSingleOpenNetworkStoreData() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createOpenNetwork()); - return new WifiConfigStoreData( - configurations, new ArrayList<WifiConfiguration>(), new HashSet<String>()); + @Test(expected = XmlPullParserException.class) + public void testReadUserStoreContainedUnknownData() throws Exception { + String storeFileData = + "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + + "<WifiConfigStoreData>\n" + + "<int name=\"Version\" value=\"1\" />\n" + + "<UnknownTag>\n" // No StoreData registered to handle this tag. + + "</UnknownTag>\n" + + "</WifiConfigStoreData>\n"; + mUserStore.storeRawDataToWrite(storeFileData.getBytes(StandardCharsets.UTF_8)); + mWifiConfigStore.switchUserStoreAndRead(mUserStore); } /** - * Returns an store data object with a single psk network. + * Verify that a XmlPullParserException will be thrown when reading the share store file + * containing unknown data. + * + * @throws Exception */ - private WifiConfigStoreData createSinglePskNetworkStoreData() { - List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(WifiConfigurationTestUtil.createPskNetwork()); - return new WifiConfigStoreData( - configurations, new ArrayList<WifiConfiguration>(), new HashSet<String>()); + @Test(expected = XmlPullParserException.class) + public void testReadShareStoreContainedUnknownData() throws Exception { + String storeFileData = + "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + + "<WifiConfigStoreData>\n" + + "<int name=\"Version\" value=\"1\" />\n" + + "<UnknownTag>\n" // No StoreData registered to handle this tag. + + "</UnknownTag>\n" + + "</WifiConfigStoreData>\n"; + mSharedStore.storeRawDataToWrite(storeFileData.getBytes(StandardCharsets.UTF_8)); + mWifiConfigStore.read(); } /** @@ -259,6 +499,7 @@ public class WifiConfigStoreTest { return (mStoreBytes != null); } + @Override public void writeBufferedRawData() { mStoreWritten = true; } @@ -271,4 +512,72 @@ public class WifiConfigStoreTest { return mStoreWritten; } } + + /** + * Mock data container for providing test data for the store file. + */ + private class MockStoreData implements WifiConfigStore.StoreData { + private static final String XML_TAG_TEST_HEADER = "TestHeader"; + private static final String XML_TAG_TEST_DATA = "TestData"; + + private String mShareData; + private String mUserData; + + MockStoreData() {} + + @Override + public void serializeData(XmlSerializer out, boolean shared) + throws XmlPullParserException, IOException { + if (shared) { + XmlUtil.writeNextValue(out, XML_TAG_TEST_DATA, mShareData); + } else { + XmlUtil.writeNextValue(out, XML_TAG_TEST_DATA, mUserData); + } + } + + @Override + public void deserializeData(XmlPullParser in, int outerTagDepth, boolean shared) + throws XmlPullParserException, IOException { + if (shared) { + mShareData = (String) XmlUtil.readNextValueWithName(in, XML_TAG_TEST_DATA); + } else { + mUserData = (String) XmlUtil.readNextValueWithName(in, XML_TAG_TEST_DATA); + } + } + + @Override + public void resetData(boolean shared) { + if (shared) { + mShareData = null; + } else { + mUserData = null; + } + } + + @Override + public String getName() { + return XML_TAG_TEST_HEADER; + } + + @Override + public boolean supportShareData() { + return true; + } + + public String getShareData() { + return mShareData; + } + + public void setShareData(String shareData) { + mShareData = shareData; + } + + public String getUserData() { + return mUserData; + } + + public void setUserData(String userData) { + mUserData = userData; + } + } } |