/*
 * 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.app.test.TestAlarmManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.MacAddress;
import android.net.wifi.WifiConfiguration;
import android.os.test.TestLooper;

import androidx.test.filters.SmallTest;

import com.android.internal.util.ArrayUtils;
import com.android.server.wifi.WifiConfigStore.StoreData;
import com.android.server.wifi.WifiConfigStore.StoreFile;
import com.android.server.wifi.util.DataIntegrityChecker;
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.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Unit tests for {@link com.android.server.wifi.WifiConfigStore}.
 */
@SmallTest
public class WifiConfigStoreTest {
    private static final String TEST_USER_DATA = "UserData";
    private static final String TEST_SHARE_DATA = "ShareData";
    private static final String TEST_CREATOR_NAME = "CreatorName";
    private static final MacAddress TEST_RANDOMIZED_MAC =
            MacAddress.fromString("da:a1:19:c4:26:fa");

    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"
                    + "<byte-array name=\"AllowedGroupMgmtCiphers\" num=\"0\"></byte-array>\n"
                    + "<byte-array name=\"AllowedSuiteBCiphers\" num=\"0\"></byte-array>\n"
                    + "<boolean name=\"Shared\" value=\"%s\" />\n"
                    + "<int name=\"Status\" value=\"2\" />\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"
                    + "<int name=\"MeteredOverride\" value=\"0\" />\n"
                    + "<boolean name=\"UseExternalScores\" value=\"false\" />\n"
                    + "<int name=\"NumAssociation\" value=\"0\" />\n"
                    + "<int name=\"CreatorUid\" value=\"%d\" />\n"
                    + "<string name=\"CreatorName\">%s</string>\n"
                    + "<null name=\"CreationTime\" />\n"
                    + "<int name=\"LastUpdateUid\" value=\"-1\" />\n"
                    + "<null name=\"LastUpdateName\" />\n"
                    + "<int name=\"LastConnectUid\" value=\"0\" />\n"
                    + "<boolean name=\"IsLegacyPasspointConfig\" value=\"false\" />\n"
                    + "<long-array name=\"RoamingConsortiumOIs\" num=\"0\" />\n"
                    + "<string name=\"RandomizedMacAddress\">%s</string>\n"
                    + "<int name=\"MacRandomizationSetting\" value=\"1\" />\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"
                    + "<map name=\"SSIDList\">\n"
                    + "<long name=\"%s\" value=\"0\" />\n"
                    + "</map>\n"
                    + "</DeletedEphemeralSSIDList>\n"
                    + "</WifiConfigStoreData>\n";

    private static final String TEST_DATA_XML_STRING_FORMAT_WITH_ONE_DATA_SOURCE =
            "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
                    + "<WifiConfigStoreData>\n"
                    + "<int name=\"Version\" value=\"1\" />\n"
                    + "<%s/>n"
                    + "</WifiConfigStoreData>\n";
    private static final String TEST_DATA_XML_STRING_FORMAT_WITH_TWO_DATA_SOURCE =
            "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
                    + "<WifiConfigStoreData>\n"
                    + "<int name=\"Version\" value=\"1\" />\n"
                    + "<%s/>n"
                    + "<%s/>n"
                    + "</WifiConfigStoreData>\n";
    // Test mocks
    @Mock private Context mContext;
    @Mock private PackageManager mPackageManager;
    private TestAlarmManager mAlarmManager;
    private TestLooper mLooper;
    @Mock private Clock mClock;
    @Mock private WifiMetrics mWifiMetrics;
    @Mock private DataIntegrityChecker mDataIntegrityChecker;
    private MockStoreFile mSharedStore;
    private MockStoreFile mUserStore;
    private MockStoreFile mUserNetworkSuggestionsStore;
    private List<StoreFile> mUserStores = new ArrayList<StoreFile>();
    private MockStoreData mSharedStoreData;
    private MockStoreData mUserStoreData;

    /**
     * Test instance of WifiConfigStore.
     */
    private WifiConfigStore mWifiConfigStore;

    /**
     * Setup mocks before the test starts.
     */
    private void setupMocks() throws Exception {
        MockitoAnnotations.initMocks(this);
        mAlarmManager = new TestAlarmManager();
        mLooper = new TestLooper();
        when(mContext.getSystemService(Context.ALARM_SERVICE))
                .thenReturn(mAlarmManager.getAlarmManager());
        when(mContext.getPackageManager()).thenReturn(mPackageManager);
        when(mPackageManager.getNameForUid(anyInt())).thenReturn(TEST_CREATOR_NAME);
        mSharedStore = new MockStoreFile(WifiConfigStore.STORE_FILE_SHARED_GENERAL);
        mUserStore = new MockStoreFile(WifiConfigStore.STORE_FILE_USER_GENERAL);
        mUserNetworkSuggestionsStore =
                new MockStoreFile(WifiConfigStore.STORE_FILE_USER_NETWORK_SUGGESTIONS);
        mUserStores.add(mUserStore);
        mUserStores.add(mUserNetworkSuggestionsStore);

        mSharedStoreData = new MockStoreData(WifiConfigStore.STORE_FILE_SHARED_GENERAL);
        mUserStoreData = new MockStoreData(WifiConfigStore.STORE_FILE_USER_GENERAL);
    }

    /**
     * Setup the test environment.
     */
    @Before
    public void setUp() throws Exception {
        setupMocks();

        mWifiConfigStore = new WifiConfigStore(mContext, mLooper.getLooper(), mClock, mWifiMetrics,
                mSharedStore);
        // Enable verbose logging before tests.
        mWifiConfigStore.enableVerboseLogging(true);
    }

    /**
     * Called after each test
     */
    @After
    public void cleanup() {
        validateMockitoUsage();
    }

    /**
     * Verify that no write occurs if there is {@link StoreData} registered for any
     * {@link StoreFile}.
     *
     * @throws Exception
     */
    @Test
    public void testWriteWithNoStoreData() throws Exception {
        // Perform force write to both share and user store file.
        mWifiConfigStore.setUserStores(mUserStores);
        mWifiConfigStore.write(true);

        assertFalse(mSharedStore.isStoreWritten());
        assertFalse(mUserStore.isStoreWritten());
        assertFalse(mUserNetworkSuggestionsStore.isStoreWritten());

        verify(mWifiMetrics, never()).noteWifiConfigStoreWriteDuration(anyInt());
    }

    /**
     * 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.
     */
    @Test
    public void testForceWrite() throws Exception {
        // Register data container.
        mWifiConfigStore.registerStoreData(mSharedStoreData);
        mWifiConfigStore.registerStoreData(mUserStoreData);

        mWifiConfigStore.switchUserStoresAndRead(mUserStores);
        mWifiConfigStore.write(true);

        assertFalse(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG));
        assertTrue(mSharedStore.isStoreWritten());
        assertTrue(mUserStore.isStoreWritten());
        assertFalse(mUserNetworkSuggestionsStore.isStoreWritten());

        verify(mWifiMetrics).noteWifiConfigStoreWriteDuration(anyInt());
    }

    /**
     * Tests the write API with the force flag set to false.
     * Expected behavior: This should set an alarm to write to the store files.
     */
    @Test
    public void testBufferedWrite() throws Exception {
        // Register data container.
        mWifiConfigStore.registerStoreData(mSharedStoreData);
        mWifiConfigStore.registerStoreData(mUserStoreData);

        mWifiConfigStore.switchUserStoresAndRead(mUserStores);
        mWifiConfigStore.write(false);

        assertTrue(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG));
        assertFalse(mSharedStore.isStoreWritten());
        assertFalse(mUserStore.isStoreWritten());
        assertFalse(mUserNetworkSuggestionsStore.isStoreWritten());

        // Now send the alarm and ensure that the writes happen.
        mAlarmManager.dispatch(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG);
        mLooper.dispatchAll();
        assertTrue(mSharedStore.isStoreWritten());
        assertTrue(mUserStore.isStoreWritten());
        assertFalse(mUserNetworkSuggestionsStore.isStoreWritten());

        verify(mWifiMetrics).noteWifiConfigStoreWriteDuration(anyInt());
    }

    /**
     * Tests the force write after a buffered write.
     * Expected behaviour: The force write should override the previous buffered write and stop the
     * buffer write alarms.
     */
    @Test
    public void testForceWriteAfterBufferedWrite() throws Exception {
        // Register a test data container with bogus data.
        mWifiConfigStore.registerStoreData(mSharedStoreData);
        mWifiConfigStore.registerStoreData(mUserStoreData);

        mSharedStoreData.setData("abcds");
        mUserStoreData.setData("asdfa");

        // Perform buffered write for both user and share store file.
        mWifiConfigStore.switchUserStoresAndRead(mUserStores);
        mWifiConfigStore.write(false);

        assertTrue(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG));
        assertFalse(mSharedStore.isStoreWritten());
        assertFalse(mUserStore.isStoreWritten());

        // 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.
        mUserStoreData.setData(TEST_USER_DATA);
        mSharedStoreData.setData(TEST_SHARE_DATA);
        mWifiConfigStore.write(true);

        assertFalse(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG));
        assertTrue(mSharedStore.isStoreWritten());
        assertTrue(mUserStore.isStoreWritten());

        // Verify correct data are loaded to the data container after a read.
        mWifiConfigStore.read();
        assertEquals(TEST_USER_DATA, mUserStoreData.getData());
        assertEquals(TEST_SHARE_DATA, mSharedStoreData.getData());
    }

    /**
     * Tests the force write with no new data after a buffered write.
     * Expected behaviour: The force write should flush the previous buffered write and stop the
     * buffer write alarms.
     */
    @Test
    public void testForceWriteWithNoNewDataAfterBufferedWrite() throws Exception {
        // Register a test data container with bogus data.
        mWifiConfigStore.registerStoreData(mSharedStoreData);
        mWifiConfigStore.registerStoreData(mUserStoreData);

        mSharedStoreData.setData("abcds");
        mUserStoreData.setData("asdfa");

        // Perform buffered write for both user and share store file.
        mWifiConfigStore.switchUserStoresAndRead(mUserStores);
        mWifiConfigStore.write(false);

        assertTrue(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG));
        assertFalse(mSharedStore.isStoreWritten());
        assertFalse(mUserStore.isStoreWritten());

        // Containers have no new data.
        mUserStoreData.setHasAnyNewData(false);
        mSharedStoreData.setHasAnyNewData(false);
        mWifiConfigStore.write(true);

        assertFalse(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG));
        assertTrue(mSharedStore.isStoreWritten());
        assertTrue(mUserStore.isStoreWritten());

        // Verify correct data are loaded to the data container after a read.
        mWifiConfigStore.read();
        assertEquals("abcds", mSharedStoreData.getData());
        assertEquals("asdfa", mUserStoreData.getData());
    }


    /**
     * Tests the read API behaviour after a write to the store files.
     * Expected behaviour: The read should return the same data that was last written.
     */
    @Test
    public void testReadAfterWrite() throws Exception {
        // Register data container.
        mWifiConfigStore.registerStoreData(mSharedStoreData);
        mWifiConfigStore.registerStoreData(mUserStoreData);

        // Read both share and user config store.
        mWifiConfigStore.switchUserStoresAndRead(mUserStores);

        // Verify no data is read.
        assertNull(mUserStoreData.getData());
        assertNull(mSharedStoreData.getData());

        // Write share and user data.
        mUserStoreData.setData(TEST_USER_DATA);
        mSharedStoreData.setData(TEST_SHARE_DATA);
        mWifiConfigStore.write(true);

        // Read and verify the data content in the data container.
        mWifiConfigStore.read();
        assertEquals(TEST_USER_DATA, mUserStoreData.getData());
        assertEquals(TEST_SHARE_DATA, mSharedStoreData.getData());

        verify(mWifiMetrics, times(2)).noteWifiConfigStoreReadDuration(anyInt());
        verify(mWifiMetrics).noteWifiConfigStoreWriteDuration(anyInt());
    }

    /**
     * Tests the read API behaviour after a write to the store files (with no integrity checks).
     * Expected behaviour: The read should return the same data that was last written.
     */
    @Test
    public void testReadAfterWriteWithNoIntegrityCheck() throws Exception {
        // Recreate the mock store files with no data integrity checking.
        mUserStores.clear();
        mSharedStore = new MockStoreFile(WifiConfigStore.STORE_FILE_SHARED_GENERAL, null);
        mUserStore = new MockStoreFile(WifiConfigStore.STORE_FILE_USER_GENERAL, null);
        mUserNetworkSuggestionsStore =
                new MockStoreFile(WifiConfigStore.STORE_FILE_USER_NETWORK_SUGGESTIONS, null);
        mUserStores.add(mUserStore);
        mUserStores.add(mUserNetworkSuggestionsStore);
        mWifiConfigStore = new WifiConfigStore(mContext, mLooper.getLooper(), mClock, mWifiMetrics,
                mSharedStore);

        // Register data container.
        mWifiConfigStore.registerStoreData(mSharedStoreData);
        mWifiConfigStore.registerStoreData(mUserStoreData);

        // Read both share and user config store.
        mWifiConfigStore.switchUserStoresAndRead(mUserStores);

        // Verify no data is read.
        assertNull(mUserStoreData.getData());
        assertNull(mSharedStoreData.getData());

        // Write share and user data.
        mUserStoreData.setData(TEST_USER_DATA);
        mSharedStoreData.setData(TEST_SHARE_DATA);
        mWifiConfigStore.write(true);

        // Read and verify the data content in the data container.
        mWifiConfigStore.read();
        assertEquals(TEST_USER_DATA, mUserStoreData.getData());
        assertEquals(TEST_SHARE_DATA, mSharedStoreData.getData());

        verify(mWifiMetrics, times(2)).noteWifiConfigStoreReadDuration(anyInt());
        verify(mWifiMetrics).noteWifiConfigStoreWriteDuration(anyInt());
    }

    /**
     * Tests the read API behaviour when the shared store file is empty and the user store
     * is not yet visible (user not yet unlocked).
     * Expected behaviour: The read should return an empty store data instance when the file not
     * found exception is raised.
     */
    @Test
    public void testReadWithNoSharedStoreFileAndUserStoreNotVisible() throws Exception {
        StoreData sharedStoreData = mock(StoreData.class);
        when(sharedStoreData.getStoreFileId())
                .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL);
        StoreData userStoreData = mock(StoreData.class);
        when(userStoreData.getStoreFileId())
                .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL);

        // Reading the mock store without a write should simulate the file not found case because
        // |readRawData| would return null.
        mWifiConfigStore.registerStoreData(sharedStoreData);
        mWifiConfigStore.registerStoreData(userStoreData);
        assertFalse(mWifiConfigStore.areStoresPresent());
        mWifiConfigStore.read();

        // Ensure that we got the call to deserialize empty shared data, but no user data.
        verify(sharedStoreData).resetData();
        verify(sharedStoreData).deserializeData(eq(null), anyInt());
        verify(userStoreData, never()).resetData();
        verify(userStoreData, never()).deserializeData(any(), anyInt());
    }

    /**
     * Tests the read API behaviour when there are no user/shared store files on the device.
     * Expected behaviour: The read should return an empty store data instance when the file not
     * found exception is raised.
     */
    @Test
    public void testReadWithNoStoreFiles() throws Exception {
        StoreData sharedStoreData = mock(StoreData.class);
        when(sharedStoreData.getStoreFileId())
                .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL);
        StoreData userStoreData = mock(StoreData.class);
        when(userStoreData.getStoreFileId())
                .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL);

        // Reading the mock store without a write should simulate the file not found case because
        // |readRawData| would return null.
        mWifiConfigStore.registerStoreData(sharedStoreData);
        mWifiConfigStore.registerStoreData(userStoreData);
        // Read both share and user config store.
        mWifiConfigStore.setUserStores(mUserStores);
        assertFalse(mWifiConfigStore.areStoresPresent());
        mWifiConfigStore.read();

        // Ensure that we got the call to deserialize empty shared & user data.
        verify(userStoreData).resetData();
        verify(userStoreData).deserializeData(eq(null), anyInt());
        verify(sharedStoreData).resetData();
        verify(sharedStoreData).deserializeData(eq(null), anyInt());
    }

    /**
     * Tests the read API behaviour after a write to the shared store file when the user
     * store file is null.
     * Expected behaviour: The read should return the same data that was last written.
     */
    @Test
    public void testReadAfterWriteWithNoUserStore() throws Exception {
        // Setup data container.
        mWifiConfigStore.registerStoreData(mSharedStoreData);
        mSharedStoreData.setData(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, mSharedStoreData.getData());
    }

    /**
     * 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(mSharedStoreData);
        mWifiConfigStore.registerStoreData(mUserStoreData);

        // Perform force write with empty data content to both user and share store file.
        mWifiConfigStore.switchUserStoresAndRead(mUserStores);
        mWifiConfigStore.write(true);

        // Setup data container with some value.
        mUserStoreData.setData(TEST_USER_DATA);
        mSharedStoreData.setData(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(mSharedStoreData.getData());
        assertNull(mUserStoreData.getData());
    }

    /**
     * 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 NetworkListUserStoreData(mContext);
        mWifiConfigStore.registerStoreData(networkList);
        WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
        openNetwork.creatorName = TEST_CREATOR_NAME;
        openNetwork.setIpConfiguration(
                WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy());
        openNetwork.setRandomizedMacAddress(TEST_RANDOMIZED_MAC);
        List<WifiConfiguration> userConfigs = new ArrayList<>();
        userConfigs.add(openNetwork);

        // Setup deleted ephemeral SSID list.
        DeletedEphemeralSsidsStoreData deletedEphemeralSsids =
                new DeletedEphemeralSsidsStoreData(mClock);
        mWifiConfigStore.registerStoreData(deletedEphemeralSsids);
        String testSsid = "\"Test SSID\"";
        Map<String, Long> ssidMap = new HashMap<>();
        ssidMap.put(testSsid, 0L);

        // Setup user store XML bytes.
        String xmlString = String.format(TEST_DATA_XML_STRING_FORMAT,
                openNetwork.configKey().replaceAll("\"", "&quot;"),
                openNetwork.SSID.replaceAll("\"", "&quot;"),
                openNetwork.shared, openNetwork.creatorUid, openNetwork.creatorName,
                openNetwork.getRandomizedMacAddress(), testSsid.replaceAll("\"", "&quot;"));
        byte[] xmlBytes = xmlString.getBytes(StandardCharsets.UTF_8);
        mUserStore.storeRawDataToWrite(xmlBytes);

        mWifiConfigStore.switchUserStoresAndRead(mUserStores);
        WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore(
                userConfigs, networkList.getConfigurations());
        assertEquals(ssidMap, deletedEphemeralSsids.getSsidToTimeMap());
    }

    /**
     * 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
     */
    @Test
    public void testWriteWifiConfigStoreData() throws Exception {
        // Setup user store.
        mWifiConfigStore.switchUserStoresAndRead(mUserStores);

        // Setup network list store data.
        NetworkListStoreData networkList = new NetworkListUserStoreData(mContext);
        mWifiConfigStore.registerStoreData(networkList);
        WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
        openNetwork.creatorName = TEST_CREATOR_NAME;
        openNetwork.setIpConfiguration(
                WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy());
        openNetwork.setRandomizedMacAddress(TEST_RANDOMIZED_MAC);
        List<WifiConfiguration> userConfigs = new ArrayList<>();
        userConfigs.add(openNetwork);
        networkList.setConfigurations(userConfigs);

        // Setup deleted ephemeral SSID list store data.
        DeletedEphemeralSsidsStoreData deletedEphemeralSsids =
                new DeletedEphemeralSsidsStoreData(mClock);
        mWifiConfigStore.registerStoreData(deletedEphemeralSsids);
        String testSsid = "Test SSID";
        Map<String, Long> ssidMap = new HashMap<>();
        ssidMap.put(testSsid, 0L);
        deletedEphemeralSsids.setSsidToTimeMap(ssidMap);

        // Setup expected XML bytes.
        String xmlString = String.format(TEST_DATA_XML_STRING_FORMAT,
                openNetwork.configKey().replaceAll("\"", "&quot;"),
                openNetwork.SSID.replaceAll("\"", "&quot;"),
                openNetwork.shared, openNetwork.creatorUid, openNetwork.creatorName,
                openNetwork.getRandomizedMacAddress(), testSsid.replaceAll("\"", "&quot;"));

        mWifiConfigStore.write(true);
        // Verify the user store content.
        assertEquals(xmlString, new String(mUserStore.getStoreBytes()));
    }

    /**
     * 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 testReadWifiConfigStoreDataIndicateClientsThatThereIsNoDataForThem()
            throws Exception {
        // Set both the user store & shared store files.
        mWifiConfigStore.switchUserStoresAndRead(mUserStores);

        String storeData1Name = "test1";
        String storeData2Name = "test2";
        StoreData storeData1 = mock(StoreData.class);
        StoreData storeData2 = mock(StoreData.class);

        assertTrue(mWifiConfigStore.registerStoreData(storeData1));
        assertTrue(mWifiConfigStore.registerStoreData(storeData2));

        String fileContentsXmlStringWithOnlyStoreData1 =
                String.format(TEST_DATA_XML_STRING_FORMAT_WITH_ONE_DATA_SOURCE, storeData1Name);
        String fileContentsXmlStringWithOnlyStoreData2 =
                String.format(TEST_DATA_XML_STRING_FORMAT_WITH_ONE_DATA_SOURCE, storeData2Name);
        String fileContentsXmlStringWithStoreData1AndStoreData2 =
                String.format(TEST_DATA_XML_STRING_FORMAT_WITH_TWO_DATA_SOURCE,
                        storeData1Name, storeData2Name);

        // Scenario 1: StoreData1 in shared store file.
        when(storeData1.getName()).thenReturn(storeData1Name);
        when(storeData2.getName()).thenReturn(storeData2Name);
        when(storeData1.getStoreFileId())
                .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL);
        when(storeData2.getStoreFileId())
                .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL);
        mSharedStore.storeRawDataToWrite(fileContentsXmlStringWithOnlyStoreData1.getBytes());
        mUserStore.storeRawDataToWrite(null);

        mWifiConfigStore.read();
        verify(storeData1).deserializeData(notNull(), anyInt());
        verify(storeData1, never()).deserializeData(eq(null), anyInt());
        verify(storeData2).deserializeData(eq(null), anyInt());
        reset(storeData1, storeData2);

        // Scenario 2: StoreData2 in user store file.
        when(storeData1.getName()).thenReturn(storeData1Name);
        when(storeData2.getName()).thenReturn(storeData2Name);
        when(storeData1.getStoreFileId())
                .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL);
        when(storeData2.getStoreFileId())
                .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL);
        mSharedStore.storeRawDataToWrite(null);
        mUserStore.storeRawDataToWrite(fileContentsXmlStringWithOnlyStoreData2.getBytes());

        mWifiConfigStore.read();
        verify(storeData1).deserializeData(eq(null), anyInt());
        verify(storeData2).deserializeData(notNull(), anyInt());
        verify(storeData2, never()).deserializeData(eq(null), anyInt());
        reset(storeData1, storeData2);

        // Scenario 3: StoreData1 in shared store file & StoreData2 in user store file.
        when(storeData1.getName()).thenReturn(storeData1Name);
        when(storeData2.getName()).thenReturn(storeData2Name);
        when(storeData1.getStoreFileId())
                .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL);
        when(storeData2.getStoreFileId())
                .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL);
        mSharedStore.storeRawDataToWrite(fileContentsXmlStringWithOnlyStoreData1.getBytes());
        mUserStore.storeRawDataToWrite(fileContentsXmlStringWithOnlyStoreData2.getBytes());

        mWifiConfigStore.read();
        verify(storeData1).deserializeData(notNull(), anyInt());
        verify(storeData1, never()).deserializeData(eq(null), anyInt());
        verify(storeData2).deserializeData(notNull(), anyInt());
        verify(storeData2, never()).deserializeData(eq(null), anyInt());
        reset(storeData1, storeData2);

        // Scenario 4: StoreData1 & StoreData2 in shared store file.
        when(storeData1.getName()).thenReturn(storeData1Name);
        when(storeData2.getName()).thenReturn(storeData2Name);
        when(storeData1.getStoreFileId())
                .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL);
        when(storeData2.getStoreFileId())
                .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL);
        mSharedStore.storeRawDataToWrite(
                fileContentsXmlStringWithStoreData1AndStoreData2.getBytes());
        mUserStore.storeRawDataToWrite(null);

        mWifiConfigStore.read();
        verify(storeData1).deserializeData(notNull(), anyInt());
        verify(storeData1, never()).deserializeData(eq(null), anyInt());
        verify(storeData2).deserializeData(notNull(), anyInt());
        verify(storeData2, never()).deserializeData(eq(null), anyInt());
        reset(storeData1, storeData2);
    }

    /**
     * Tests the write API behavior when all the store data's registered for a given store file
     * has no new data to write.
     * Expected behaviour: The write should not trigger a new file write for that specific store
     * file.
     */
    @Test
    public void testWriteWithNoNewData() throws Exception {
        StoreData sharedStoreData = mock(StoreData.class);
        when(sharedStoreData.getStoreFileId())
                .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL);
        when(sharedStoreData.hasNewDataToSerialize()).thenReturn(true);
        when(sharedStoreData.getName()).thenReturn("sharedStoreData");

        StoreData userStoreData = mock(StoreData.class);
        when(userStoreData.getStoreFileId())
                .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL);
        when(userStoreData.hasNewDataToSerialize()).thenReturn(true);
        when(userStoreData.getName()).thenReturn("userStoreData");

        StoreData userStoreNetworkSuggestionsData =
                mock(StoreData.class);
        when(userStoreNetworkSuggestionsData.getStoreFileId())
                .thenReturn(WifiConfigStore.STORE_FILE_USER_NETWORK_SUGGESTIONS);
        when(userStoreNetworkSuggestionsData.hasNewDataToSerialize()).thenReturn(false);
        when(userStoreNetworkSuggestionsData.getName())
                .thenReturn("userStoreNetworkSuggestionsData");

        assertTrue(mWifiConfigStore.registerStoreData(sharedStoreData));
        assertTrue(mWifiConfigStore.registerStoreData(userStoreData));
        assertTrue(mWifiConfigStore.registerStoreData(userStoreNetworkSuggestionsData));

        // Write both share and user config store.
        mWifiConfigStore.setUserStores(mUserStores);

        // Now trigger a write.
        mWifiConfigStore.write(true);

        verify(sharedStoreData).hasNewDataToSerialize();
        verify(userStoreData).hasNewDataToSerialize();
        verify(userStoreNetworkSuggestionsData).hasNewDataToSerialize();

        // Verify that we serialized data from the first 2 data source, but not from the last one.
        verify(sharedStoreData).serializeData(any());
        verify(userStoreData).serializeData(any());
        verify(userStoreNetworkSuggestionsData, never()).serializeData(any());
    }

    /**
     * Verify that a XmlPullParserException will be thrown when reading an user store file
     * containing unknown data.
     *
     * @throws Exception
     */
    @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.switchUserStoresAndRead(mUserStores);
    }

    /**
     * Verify that a XmlPullParserException will be thrown when reading the share store file
     * containing unknown data.
     *
     * @throws Exception
     */
    @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();
    }

    /**
     * Mock Store File to redirect all file writes from WifiConfigStore to local buffers.
     * This can be used to examine the data output by WifiConfigStore.
     */
    private class MockStoreFile extends StoreFile {
        private byte[] mStoreBytes;
        private boolean mStoreWritten;

        MockStoreFile(@WifiConfigStore.StoreFileId int fileId) {
            super(new File("MockStoreFile"), fileId, mDataIntegrityChecker);
        }

        MockStoreFile(@WifiConfigStore.StoreFileId int fileId,
                      DataIntegrityChecker dataIntegrityChecker) {
            super(new File("MockStoreFile"), fileId, dataIntegrityChecker);
        }

        @Override
        public byte[] readRawData() {
            return mStoreBytes;
        }

        @Override
        public void storeRawDataToWrite(byte[] data) {
            mStoreBytes = data;
            mStoreWritten = false;
        }

        @Override
        public boolean exists() {
            return (mStoreBytes != null);
        }

        @Override
        public void writeBufferedRawData() {
            if (!ArrayUtils.isEmpty(mStoreBytes)) {
                mStoreWritten = true;
            }
        }

        public byte[] getStoreBytes() {
            return mStoreBytes;
        }

        public boolean isStoreWritten() {
            return mStoreWritten;
        }
    }

    /**
     * Mock data container for providing test data for the store file.
     */
    private class MockStoreData implements StoreData {
        private static final String XML_TAG_TEST_HEADER = "TestHeader";
        private static final String XML_TAG_TEST_DATA = "TestData";

        private @WifiConfigStore.StoreFileId int mFileId;
        private String mData;
        private boolean mHasAnyNewData = true;

        MockStoreData(@WifiConfigStore.StoreFileId int fileId) {
            mFileId = fileId;
        }

        @Override
        public void serializeData(XmlSerializer out)
                throws XmlPullParserException, IOException {
            XmlUtil.writeNextValue(out, XML_TAG_TEST_DATA, mData);
        }

        @Override
        public void deserializeData(XmlPullParser in, int outerTagDepth)
                throws XmlPullParserException, IOException {
            if (in == null) {
                return;
            }
            mData = (String) XmlUtil.readNextValueWithName(in, XML_TAG_TEST_DATA);
        }

        @Override
        public void resetData() {
            mData = null;
        }

        @Override
        public boolean hasNewDataToSerialize() {
            return mHasAnyNewData;
        }

        @Override
        public String getName() {
            return XML_TAG_TEST_HEADER;
        }

        @Override
        public @WifiConfigStore.StoreFileId int getStoreFileId() {
            return mFileId;
        }

        public String getData() {
            return mData;
        }

        public void setData(String data) {
            mData = data;
        }

        public void setHasAnyNewData(boolean hasAnyNewData) {
            mHasAnyNewData = hasAnyNewData;
        }
    }
}
