From 0b86079855b2bc120a6c7790c53c927d95485b62 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Fri, 19 Oct 2018 08:20:30 -0700 Subject: WifiConfigStore Refactor (1/2) New WifiConfigStore Architecture: a) WifiConfigStore can now manage multiple user store files (StoreFile). It now manages a total of 3 files: 1 shared & 1 user (both existing) & 1 new one specifically for network suggestions. b) Clients(StoreData) should now register themselves to write/read from any one of the store files. c) |StoreFile|'s are only written if any one of the |StoreData|'s registered for that file indicates that it has new data to write. PS: Please refer to the bug for a summary of problems with the previous architecture. Bug: 117599800 Test: Unit tests Test: Verified upgrading device with some store data to the new architecture and ensured that we don't lose any data. Test: Will send for integration tests. Change-Id: Iebe54b6bef4d203540e7da490eae9851131d8827 --- .../android/server/wifi/WifiConfigStoreTest.java | 387 ++++++++++++++------- 1 file changed, 254 insertions(+), 133 deletions(-) (limited to 'tests') diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java index 1741acc4b..0240a67ab 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java @@ -27,6 +27,8 @@ import android.net.wifi.WifiConfiguration; import android.os.test.TestLooper; import android.support.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.XmlUtil; @@ -53,13 +55,6 @@ import java.util.Set; */ @SmallTest public class WifiConfigStoreTest { - // Store file content without any data. - private static final String EMPTY_FILE_CONTENT = - "\n" - + "\n" - + "\n" - + "\n"; - private static final String TEST_USER_DATA = "UserData"; private static final String TEST_SHARE_DATA = "ShareData"; private static final String TEST_CREATOR_NAME = "CreatorName"; @@ -150,7 +145,10 @@ public class WifiConfigStoreTest { @Mock private Clock mClock; private MockStoreFile mSharedStore; private MockStoreFile mUserStore; - private MockStoreData mStoreData; + private MockStoreFile mUserNetworkSuggestionsStore; + private List mUserStores = new ArrayList(); + private MockStoreData mSharedStoreData; + private MockStoreData mUserStoreData; /** * Test instance of WifiConfigStore. @@ -168,9 +166,15 @@ public class WifiConfigStoreTest { .thenReturn(mAlarmManager.getAlarmManager()); when(mContext.getPackageManager()).thenReturn(mPackageManager); when(mPackageManager.getNameForUid(anyInt())).thenReturn(TEST_CREATOR_NAME); - mUserStore = new MockStoreFile(); - mSharedStore = new MockStoreFile(); - mStoreData = new MockStoreData(); + 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); } /** @@ -194,24 +198,20 @@ 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}. + * Verify that no write occurs if there is {@link StoreData} registered for any + * {@link StoreFile}. * * @throws Exception */ @Test - public void testWriteWithEmptyData() throws Exception { + public void testWriteWithNoStoreData() throws Exception { // Perform force write to both share and user store file. - mWifiConfigStore.switchUserStoreAndRead(mUserStore); + mWifiConfigStore.setUserStores(mUserStores); 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())); + assertFalse(mSharedStore.isStoreWritten()); + assertFalse(mUserStore.isStoreWritten()); + assertFalse(mUserNetworkSuggestionsStore.isStoreWritten()); } /** @@ -221,12 +221,17 @@ public class WifiConfigStoreTest { */ @Test public void testForceWrite() throws Exception { - mWifiConfigStore.switchUserStoreAndRead(mUserStore); + // 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()); } /** @@ -235,18 +240,24 @@ public class WifiConfigStoreTest { */ @Test public void testBufferedWrite() throws Exception { - mWifiConfigStore.switchUserStoreAndRead(mUserStore); + // 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()); } /** @@ -257,12 +268,14 @@ public class WifiConfigStoreTest { @Test public void testForceWriteAfterBufferedWrite() throws Exception { // Register a test data container with bogus data. - mWifiConfigStore.registerStoreData(mStoreData); - mStoreData.setShareData("abcds"); - mStoreData.setUserData("asdfa"); + mWifiConfigStore.registerStoreData(mSharedStoreData); + mWifiConfigStore.registerStoreData(mUserStoreData); + + mSharedStoreData.setData("abcds"); + mUserStoreData.setData("asdfa"); // Perform buffered write for both user and share store file. - mWifiConfigStore.switchUserStoreAndRead(mUserStore); + mWifiConfigStore.switchUserStoresAndRead(mUserStores); mWifiConfigStore.write(false); assertTrue(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG)); @@ -271,8 +284,8 @@ public class WifiConfigStoreTest { // 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); + mUserStoreData.setData(TEST_USER_DATA); + mSharedStoreData.setData(TEST_SHARE_DATA); mWifiConfigStore.write(true); assertFalse(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG)); @@ -281,10 +294,48 @@ public class WifiConfigStoreTest { // 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()); + 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. @@ -292,24 +343,25 @@ public class WifiConfigStoreTest { @Test public void testReadAfterWrite() throws Exception { // Register data container. - mWifiConfigStore.registerStoreData(mStoreData); + mWifiConfigStore.registerStoreData(mSharedStoreData); + mWifiConfigStore.registerStoreData(mUserStoreData); // Read both share and user config store. - mWifiConfigStore.switchUserStoreAndRead(mUserStore); + mWifiConfigStore.switchUserStoresAndRead(mUserStores); // Verify no data is read. - assertNull(mStoreData.getUserData()); - assertNull(mStoreData.getShareData()); + assertNull(mUserStoreData.getData()); + assertNull(mSharedStoreData.getData()); // Write share and user data. - mStoreData.setUserData(TEST_USER_DATA); - mStoreData.setShareData(TEST_SHARE_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, mStoreData.getUserData()); - assertEquals(TEST_SHARE_DATA, mStoreData.getShareData()); + assertEquals(TEST_USER_DATA, mUserStoreData.getData()); + assertEquals(TEST_SHARE_DATA, mSharedStoreData.getData()); } /** @@ -320,19 +372,25 @@ public class WifiConfigStoreTest { */ @Test public void testReadWithNoSharedStoreFileAndUserStoreNotVisible() throws Exception { - WifiConfigStore.StoreData storeData = mock(WifiConfigStore.StoreData.class); + 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(storeData); + 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(storeData).resetData(eq(true)); - verify(storeData).deserializeData(eq(null), anyInt(), eq(true)); - verify(storeData, never()).resetData(eq(false)); - verify(storeData, never()).deserializeData(eq(null), anyInt(), eq(false)); + verify(sharedStoreData).resetData(); + verify(sharedStoreData).deserializeData(eq(null), anyInt()); + verify(userStoreData, never()).resetData(); + verify(userStoreData, never()).deserializeData(any(), anyInt()); } /** @@ -342,21 +400,27 @@ public class WifiConfigStoreTest { */ @Test public void testReadWithNoStoreFiles() throws Exception { - WifiConfigStore.StoreData storeData = mock(WifiConfigStore.StoreData.class); + 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(storeData); + mWifiConfigStore.registerStoreData(sharedStoreData); + mWifiConfigStore.registerStoreData(userStoreData); // Read both share and user config store. - mWifiConfigStore.switchUserStoreAndRead(mUserStore); + mWifiConfigStore.setUserStores(mUserStores); assertFalse(mWifiConfigStore.areStoresPresent()); mWifiConfigStore.read(); // Ensure that we got the call to deserialize empty shared & user data. - verify(storeData).resetData(eq(true)); - verify(storeData).deserializeData(eq(null), anyInt(), eq(true)); - verify(storeData, times(2)).resetData(eq(false)); - verify(storeData, times(2)).deserializeData(eq(null), anyInt(), eq(false)); + verify(userStoreData).resetData(); + verify(userStoreData).deserializeData(eq(null), anyInt()); + verify(sharedStoreData).resetData(); + verify(sharedStoreData).deserializeData(eq(null), anyInt()); } /** @@ -367,14 +431,14 @@ public class WifiConfigStoreTest { @Test public void testReadAfterWriteWithNoUserStore() throws Exception { // Setup data container. - mWifiConfigStore.registerStoreData(mStoreData); - mStoreData.setShareData(TEST_SHARE_DATA); + 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, mStoreData.getShareData()); + assertEquals(TEST_SHARE_DATA, mSharedStoreData.getData()); } /** @@ -386,21 +450,22 @@ public class WifiConfigStoreTest { @Test public void testReadWillResetStoreData() throws Exception { // Register and setup store data. - mWifiConfigStore.registerStoreData(mStoreData); + mWifiConfigStore.registerStoreData(mSharedStoreData); + mWifiConfigStore.registerStoreData(mUserStoreData); // Perform force write with empty data content to both user and share store file. - mWifiConfigStore.switchUserStoreAndRead(mUserStore); + mWifiConfigStore.switchUserStoresAndRead(mUserStores); mWifiConfigStore.write(true); // Setup data container with some value. - mStoreData.setUserData(TEST_USER_DATA); - mStoreData.setShareData(TEST_SHARE_DATA); + 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(mStoreData.getShareData()); - assertNull(mStoreData.getUserData()); + assertNull(mSharedStoreData.getData()); + assertNull(mUserStoreData.getData()); } /** @@ -413,7 +478,7 @@ public class WifiConfigStoreTest { @Test public void testReadWifiConfigStoreData() throws Exception { // Setup network list. - NetworkListStoreData networkList = new NetworkListStoreData(mContext); + NetworkListStoreData networkList = new NetworkListUserStoreData(mContext); mWifiConfigStore.registerStoreData(networkList); WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); openNetwork.creatorName = TEST_CREATOR_NAME; @@ -440,9 +505,9 @@ public class WifiConfigStoreTest { byte[] xmlBytes = xmlString.getBytes(StandardCharsets.UTF_8); mUserStore.storeRawDataToWrite(xmlBytes); - mWifiConfigStore.switchUserStoreAndRead(mUserStore); + mWifiConfigStore.switchUserStoresAndRead(mUserStores); WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore( - userConfigs, networkList.getUserConfigurations()); + userConfigs, networkList.getConfigurations()); assertEquals(ssidList, deletedEphemeralSsids.getSsidList()); } @@ -455,10 +520,10 @@ public class WifiConfigStoreTest { @Test public void testWriteWifiConfigStoreData() throws Exception { // Setup user store. - mWifiConfigStore.switchUserStoreAndRead(mUserStore); + mWifiConfigStore.switchUserStoresAndRead(mUserStores); // Setup network list store data. - NetworkListStoreData networkList = new NetworkListStoreData(mContext); + NetworkListStoreData networkList = new NetworkListUserStoreData(mContext); mWifiConfigStore.registerStoreData(networkList); WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); openNetwork.creatorName = TEST_CREATOR_NAME; @@ -467,7 +532,7 @@ public class WifiConfigStoreTest { openNetwork.setRandomizedMacAddress(TEST_RANDOMIZED_MAC); List userConfigs = new ArrayList<>(); userConfigs.add(openNetwork); - networkList.setUserConfigurations(userConfigs); + networkList.setConfigurations(userConfigs); // Setup deleted ephemeral SSID list store data. DeletedEphemeralSsidsStoreData deletedEphemeralSsids = @@ -503,14 +568,12 @@ public class WifiConfigStoreTest { public void testReadWifiConfigStoreDataIndicateClientsThatThereIsNoDataForThem() throws Exception { // Set both the user store & shared store files. - mWifiConfigStore.switchUserStoreAndRead(mUserStore); + mWifiConfigStore.switchUserStoresAndRead(mUserStores); String storeData1Name = "test1"; String storeData2Name = "test2"; - WifiConfigStore.StoreData storeData1 = mock(WifiConfigStore.StoreData.class); - WifiConfigStore.StoreData storeData2 = mock(WifiConfigStore.StoreData.class); - when(storeData1.getName()).thenReturn(storeData1Name); - when(storeData2.getName()).thenReturn(storeData2Name); + StoreData storeData1 = mock(StoreData.class); + StoreData storeData2 = mock(StoreData.class); assertTrue(mWifiConfigStore.registerStoreData(storeData1)); assertTrue(mWifiConfigStore.registerStoreData(storeData2)); @@ -524,57 +587,121 @@ public class WifiConfigStoreTest { 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(), eq(true)); - verify(storeData1, never()).deserializeData(eq(null), anyInt(), eq(true)); - verify(storeData1).deserializeData(eq(null), anyInt(), eq(false)); - verify(storeData2).deserializeData(eq(null), anyInt(), eq(true)); - verify(storeData2).deserializeData(eq(null), anyInt(), eq(false)); + 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(), eq(true)); - verify(storeData1).deserializeData(eq(null), anyInt(), eq(false)); - verify(storeData2).deserializeData(eq(null), anyInt(), eq(true)); - verify(storeData2).deserializeData(notNull(), anyInt(), eq(false)); - verify(storeData2, never()).deserializeData(eq(null), anyInt(), eq(false)); + 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(), eq(true)); - verify(storeData1, never()).deserializeData(eq(null), anyInt(), eq(true)); - verify(storeData1).deserializeData(eq(null), anyInt(), eq(false)); - verify(storeData2).deserializeData(eq(null), anyInt(), eq(true)); - verify(storeData2).deserializeData(notNull(), anyInt(), eq(false)); - verify(storeData2, never()).deserializeData(eq(null), anyInt(), eq(false)); + 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(), eq(true)); - verify(storeData1, never()).deserializeData(eq(null), anyInt(), eq(true)); - verify(storeData1).deserializeData(eq(null), anyInt(), eq(false)); - verify(storeData2).deserializeData(notNull(), anyInt(), eq(true)); - verify(storeData2, never()).deserializeData(eq(null), anyInt(), eq(true)); - verify(storeData2).deserializeData(eq(null), anyInt(), eq(false)); + 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. @@ -591,7 +718,7 @@ public class WifiConfigStoreTest { + "\n" + "\n"; mUserStore.storeRawDataToWrite(storeFileData.getBytes(StandardCharsets.UTF_8)); - mWifiConfigStore.switchUserStoreAndRead(mUserStore); + mWifiConfigStore.switchUserStoresAndRead(mUserStores); } /** @@ -621,8 +748,8 @@ public class WifiConfigStoreTest { private byte[] mStoreBytes; private boolean mStoreWritten; - public MockStoreFile() { - super(new File("MockStoreFile")); + MockStoreFile(@WifiConfigStore.StoreFileId int fileId) { + super(new File("MockStoreFile"), fileId); } @Override @@ -643,7 +770,9 @@ public class WifiConfigStoreTest { @Override public void writeBufferedRawData() { - mStoreWritten = true; + if (!ArrayUtils.isEmpty(mStoreBytes)) { + mStoreWritten = true; + } } public byte[] getStoreBytes() { @@ -658,71 +787,63 @@ public class WifiConfigStoreTest { /** * Mock data container for providing test data for the store file. */ - private class MockStoreData implements WifiConfigStore.StoreData { + private class MockStoreData implements 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; + private @WifiConfigStore.StoreFileId int mFileId; + private String mData; + private boolean mHasAnyNewData = true; - MockStoreData() {} + MockStoreData(@WifiConfigStore.StoreFileId int fileId) { + mFileId = fileId; + } @Override - public void serializeData(XmlSerializer out, boolean shared) + public void serializeData(XmlSerializer out) throws XmlPullParserException, IOException { - if (shared) { - XmlUtil.writeNextValue(out, XML_TAG_TEST_DATA, mShareData); - } else { - XmlUtil.writeNextValue(out, XML_TAG_TEST_DATA, mUserData); - } + XmlUtil.writeNextValue(out, XML_TAG_TEST_DATA, mData); } @Override - public void deserializeData(XmlPullParser in, int outerTagDepth, boolean shared) + public void deserializeData(XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { if (in == null) { return; } - if (shared) { - mShareData = (String) XmlUtil.readNextValueWithName(in, XML_TAG_TEST_DATA); - } else { - mUserData = (String) XmlUtil.readNextValueWithName(in, XML_TAG_TEST_DATA); - } + mData = (String) XmlUtil.readNextValueWithName(in, XML_TAG_TEST_DATA); } @Override - public void resetData(boolean shared) { - if (shared) { - mShareData = null; - } else { - mUserData = null; - } + public void resetData() { + mData = null; } @Override - public String getName() { - return XML_TAG_TEST_HEADER; + public boolean hasNewDataToSerialize() { + return mHasAnyNewData; } @Override - public boolean supportShareData() { - return true; + public String getName() { + return XML_TAG_TEST_HEADER; } - public String getShareData() { - return mShareData; + @Override + public @WifiConfigStore.StoreFileId int getStoreFileId() { + return mFileId; } - public void setShareData(String shareData) { - mShareData = shareData; + public String getData() { + return mData; } - public String getUserData() { - return mUserData; + public void setData(String data) { + mData = data; } - public void setUserData(String userData) { - mUserData = userData; + public void setHasAnyNewData(boolean hasAnyNewData) { + mHasAnyNewData = hasAnyNewData; } } } -- cgit v1.2.3