diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 05:22:17 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 05:22:17 +0000 |
commit | 3466fd4eecbc152728a0f3ad3e2dacba45fd7a82 (patch) | |
tree | e03dc9d843034a476a34f3e1fb0d0a7accf4a17a /tests/unittests/src/com | |
parent | 65e30106a579db014c76b7d3a5cf0d2d3f349c63 (diff) | |
parent | 0a1ab1245ef3f64593d270f8cd5217a823e51c0c (diff) | |
download | Mms-3466fd4eecbc152728a0f3ad3e2dacba45fd7a82.tar.gz |
Snap for 10453563 from 0a1ab1245ef3f64593d270f8cd5217a823e51c0c to mainline-uwb-releaseaml_uwb_341710010aml_uwb_341513070aml_uwb_341511050aml_uwb_341310300aml_uwb_341310030aml_uwb_341111010aml_uwb_341011000android14-mainline-uwb-release
Change-Id: Idd342b326565dc5018697a07333e93b14c8b29dd
Diffstat (limited to 'tests/unittests/src/com')
4 files changed, 1178 insertions, 0 deletions
diff --git a/tests/unittests/src/com/android/mms/service/MmsHttpClientTest.java b/tests/unittests/src/com/android/mms/service/MmsHttpClientTest.java new file mode 100644 index 0000000..dd126e8 --- /dev/null +++ b/tests/unittests/src/com/android/mms/service/MmsHttpClientTest.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2023 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.mms.service; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.Network; +import android.os.Bundle; +import android.telephony.ServiceState; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import androidx.test.core.app.ApplicationProvider; + +import org.junit.After; +import org.junit.Before; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.junit.Test; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.reset; + +import android.util.Log; + +public class MmsHttpClientTest { + // Mocked classes + private Context mContext; + private TelephonyManager mTelephonyManager; + private SubscriptionManager mSubscriptionManager; + + // The raw phone number from TelephonyManager.getLine1Number + private static final String MACRO_LINE1 = "LINE1"; + // The phone number without country code + private static final String MACRO_LINE1NOCOUNTRYCODE = "LINE1NOCOUNTRYCODE"; + private String line1Number = "1234567890"; + private String subscriberPhoneNumber = "0987654321"; + private int subId = 1; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(ApplicationProvider.getApplicationContext()); + mTelephonyManager = mock(TelephonyManager.class); + mSubscriptionManager = mock(SubscriptionManager.class); + + when(mContext.getSystemService(Context.TELEPHONY_SERVICE)) + .thenReturn(mTelephonyManager); + when(mTelephonyManager.createForSubscriptionId(anyInt())) + .thenReturn(mTelephonyManager); + when(mContext.getSystemService(SubscriptionManager.class)) + .thenReturn(mSubscriptionManager); + } + + @After + public void tearDown() { + mContext = null; + mTelephonyManager = null; + mSubscriptionManager = null; + } + + @Test + public void getPhoneNumberForMacroLine1() { + String macro = MACRO_LINE1; + Bundle mmsConfig = new Bundle(); + String emptyStr = ""; + String phoneNo; + + /* when getLine1Number returns valid number */ + doReturn(line1Number).when(mTelephonyManager).getLine1Number(); + phoneNo = MmsHttpClient.getMacroValue(mContext, macro, mmsConfig, subId); + assertThat(phoneNo).isEqualTo(line1Number); + // getLine1NumberAPI should be called + verify(mTelephonyManager).getLine1Number(); + // getPhoneNumber should never be called + verify(mSubscriptionManager, never()).getPhoneNumber(subId); + + /* when getLine1Number returns empty string */ + doReturn(emptyStr).when(mTelephonyManager).getLine1Number(); + when(mSubscriptionManager.getPhoneNumber(subId)).thenReturn(subscriberPhoneNumber); + phoneNo = MmsHttpClient.getMacroValue(mContext, macro, mmsConfig, subId); + assertThat(phoneNo).isEqualTo(subscriberPhoneNumber); + verify(mSubscriptionManager).getPhoneNumber(subId); + + /* when getLine1Number returns null */ + reset(mSubscriptionManager); + when(mSubscriptionManager.getPhoneNumber(subId)).thenReturn(subscriberPhoneNumber); + doReturn(null).when(mTelephonyManager).getLine1Number(); + phoneNo = MmsHttpClient.getMacroValue(mContext, macro, mmsConfig, subId); + assertThat(phoneNo).isEqualTo(subscriberPhoneNumber); + verify(mSubscriptionManager).getPhoneNumber(subId); + } + + @Test + public void getPhoneNumberForMacroLine1CountryCode() throws Exception { + String macro = MACRO_LINE1NOCOUNTRYCODE; + String emptyStr = ""; + String phoneNo; + Bundle mmsConfig = new Bundle(); + + /* when getLine1Number returns valid number */ + doReturn(line1Number).when(mTelephonyManager).getLine1Number(); + phoneNo = MmsHttpClient.getMacroValue(mContext, macro, mmsConfig, subId); + assertThat(phoneNo).contains(line1Number); + // getLine1NumberAPI should be called + verify(mTelephonyManager).getLine1Number(); + // getPhoneNumber should never be called + verify(mSubscriptionManager, never()).getPhoneNumber(subId); + + /* when getLine1Number returns empty string */ + doReturn(emptyStr).when(mTelephonyManager).getLine1Number(); + when(mSubscriptionManager.getPhoneNumber(subId)).thenReturn(subscriberPhoneNumber); + phoneNo = MmsHttpClient.getMacroValue(mContext, macro, mmsConfig, subId); + assertThat(phoneNo).contains(subscriberPhoneNumber); + verify(mSubscriptionManager).getPhoneNumber(subId); + + /* when getLine1Number returns null */ + reset(mSubscriptionManager); + when(mSubscriptionManager.getPhoneNumber(subId)).thenReturn(subscriberPhoneNumber); + doReturn(null).when(mTelephonyManager).getLine1Number(); + phoneNo = MmsHttpClient.getMacroValue(mContext, macro, mmsConfig, subId); + assertThat(phoneNo).contains(subscriberPhoneNumber); + verify(mSubscriptionManager).getPhoneNumber(subId); + } +} diff --git a/tests/unittests/src/com/android/mms/service/metrics/MmsMetricsCollectorTest.java b/tests/unittests/src/com/android/mms/service/metrics/MmsMetricsCollectorTest.java new file mode 100644 index 0000000..8d93739 --- /dev/null +++ b/tests/unittests/src/com/android/mms/service/metrics/MmsMetricsCollectorTest.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2022 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.mms.service.metrics; + +import static com.android.mms.MmsStatsLog.INCOMING_MMS; +import static com.android.mms.MmsStatsLog.OUTGOING_MMS; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import android.app.StatsManager; +import android.content.Context; +import android.util.StatsEvent; + +import com.android.mms.IncomingMms; +import com.android.mms.OutgoingMms; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class MmsMetricsCollectorTest { + private static final long MIN_COOLDOWN_MILLIS = 23L * 3600L * 1000L; + Context mContext; + private PersistMmsAtomsStorage mPersistMmsAtomsStorage; + private MmsMetricsCollector mMmsMetricsCollector; + + @Before + public void setUp() { + mContext = mock(Context.class); + mPersistMmsAtomsStorage = mock(PersistMmsAtomsStorage.class); + mMmsMetricsCollector = new MmsMetricsCollector(mContext, mPersistMmsAtomsStorage); + } + + @After + public void tearDown() { + mContext = null; + mPersistMmsAtomsStorage = null; + mMmsMetricsCollector = null; + } + + @Test + public void onPullAtom_incomingMms_empty() { + doReturn(new ArrayList<>()).when(mPersistMmsAtomsStorage).getIncomingMms(anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMmsMetricsCollector.onPullAtom(INCOMING_MMS, actualAtoms); + + assertThat(actualAtoms).hasSize(0); + assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS); + } + + @Test + public void onPullAtom_incomingMms_tooFrequent() { + doReturn(null).when(mPersistMmsAtomsStorage).getIncomingMms(anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMmsMetricsCollector.onPullAtom(INCOMING_MMS, actualAtoms); + + assertThat(actualAtoms).hasSize(0); + assertThat(result).isEqualTo(StatsManager.PULL_SKIP); + verify(mPersistMmsAtomsStorage, times(1)) + .getIncomingMms(eq(MIN_COOLDOWN_MILLIS)); + verifyNoMoreInteractions(mPersistMmsAtomsStorage); + } + + @Test + public void onPullAtom_incomingMms_multipleMms() { + IncomingMms incomingMms = IncomingMms.newBuilder().build(); + doReturn(Arrays.asList(incomingMms, incomingMms, incomingMms, incomingMms)) + .when(mPersistMmsAtomsStorage).getIncomingMms(anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMmsMetricsCollector.onPullAtom(INCOMING_MMS, actualAtoms); + + assertThat(actualAtoms).hasSize(4); + assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS); + } + + @Test + public void onPullAtom_outgoingMms_empty() { + doReturn(new ArrayList<>()).when(mPersistMmsAtomsStorage).getOutgoingMms(anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMmsMetricsCollector.onPullAtom(OUTGOING_MMS, actualAtoms); + + assertThat(actualAtoms).hasSize(0); + assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS); + } + + @Test + public void onPullAtom_outgoingMms_tooFrequent() { + doReturn(null).when(mPersistMmsAtomsStorage).getOutgoingMms(anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMmsMetricsCollector.onPullAtom(OUTGOING_MMS, actualAtoms); + + assertThat(actualAtoms).hasSize(0); + assertThat(result).isEqualTo(StatsManager.PULL_SKIP); + verify(mPersistMmsAtomsStorage, times(1)) + .getOutgoingMms(eq(MIN_COOLDOWN_MILLIS)); + verifyNoMoreInteractions(mPersistMmsAtomsStorage); + } + + @Test + public void onPullAtom_outgoingMms_multipleMms() { + OutgoingMms outgoingMms = OutgoingMms.newBuilder().build(); + doReturn(Arrays.asList(outgoingMms, outgoingMms, outgoingMms, outgoingMms)) + .when(mPersistMmsAtomsStorage).getOutgoingMms(anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMmsMetricsCollector.onPullAtom(OUTGOING_MMS, actualAtoms); + + assertThat(actualAtoms).hasSize(4); + assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS); + } +}
\ No newline at end of file diff --git a/tests/unittests/src/com/android/mms/service/metrics/MmsStatsTest.java b/tests/unittests/src/com/android/mms/service/metrics/MmsStatsTest.java new file mode 100644 index 0000000..2b2cae5 --- /dev/null +++ b/tests/unittests/src/com/android/mms/service/metrics/MmsStatsTest.java @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2022 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.mms.service.metrics; + +import static com.android.mms.MmsStatsLog.INCOMING_MMS__RESULT__MMS_RESULT_SUCCESS; +import static com.android.mms.MmsStatsLog.OUTGOING_MMS__RESULT__MMS_RESULT_SUCCESS; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import android.app.Activity; +import android.content.Context; +import android.telephony.ServiceState; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import com.android.mms.IncomingMms; +import com.android.mms.OutgoingMms; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.mockito.ArgumentCaptor; + +public class MmsStatsTest { + // Mocked classes + private Context mContext; + private PersistMmsAtomsStorage mPersistMmsAtomsStorage; + private TelephonyManager mTelephonyManager; + private SubscriptionManager mSubscriptionManager; + + @Before + public void setUp() { + mContext = mock(Context.class); + mPersistMmsAtomsStorage = mock(PersistMmsAtomsStorage.class); + mTelephonyManager = mock(TelephonyManager.class); + mSubscriptionManager = mock(SubscriptionManager.class); + + doReturn(mSubscriptionManager).when(mContext).getSystemService( + Context.TELEPHONY_SUBSCRIPTION_SERVICE); + } + + @After + public void tearDown() { + mContext = null; + mPersistMmsAtomsStorage = null; + mTelephonyManager = null; + } + + @Test + public void addAtomToStorage_incomingMms_default() { + doReturn(null).when(mTelephonyManager).getServiceState(); + doReturn(TelephonyManager.UNKNOWN_CARRIER_ID).when(mTelephonyManager).getSimCarrierId(); + int inactiveSubId = 123; + MmsStats mmsStats = new MmsStats(mContext, mPersistMmsAtomsStorage, inactiveSubId, + mTelephonyManager, null, true); + mmsStats.addAtomToStorage(Activity.RESULT_OK); + + ArgumentCaptor<IncomingMms> incomingMmsCaptor = ArgumentCaptor.forClass(IncomingMms.class); + verify(mPersistMmsAtomsStorage).addIncomingMms(incomingMmsCaptor.capture()); + IncomingMms incomingMms = incomingMmsCaptor.getValue(); + assertThat(incomingMms.getRat()).isEqualTo(TelephonyManager.NETWORK_TYPE_UNKNOWN); + assertThat(incomingMms.getResult()).isEqualTo(INCOMING_MMS__RESULT__MMS_RESULT_SUCCESS); + assertThat(incomingMms.getRoaming()).isEqualTo(ServiceState.ROAMING_TYPE_NOT_ROAMING); + assertThat(incomingMms.getSimSlotIndex()).isEqualTo( + SubscriptionManager.INVALID_SIM_SLOT_INDEX); + assertThat(incomingMms.getIsMultiSim()).isEqualTo(false); + assertThat(incomingMms.getIsEsim()).isEqualTo(false); + assertThat(incomingMms.getCarrierId()).isEqualTo(TelephonyManager.UNKNOWN_CARRIER_ID); + assertThat(incomingMms.getMmsCount()).isEqualTo(1); + assertThat(incomingMms.getRetryId()).isEqualTo(0); + assertThat(incomingMms.getHandledByCarrierApp()).isEqualTo(false); + assertThat(incomingMms.getIsManagedProfile()).isEqualTo(false); + verifyNoMoreInteractions(mPersistMmsAtomsStorage); + } + + @Test + public void addAtomToStorage_outgoingMms_default() { + doReturn(null).when(mTelephonyManager).getServiceState(); + doReturn(TelephonyManager.UNKNOWN_CARRIER_ID).when(mTelephonyManager).getSimCarrierId(); + int inactiveSubId = 123; + MmsStats mmsStats = new MmsStats(mContext, mPersistMmsAtomsStorage, inactiveSubId, + mTelephonyManager, null, false); + mmsStats.addAtomToStorage(Activity.RESULT_OK); + + ArgumentCaptor<OutgoingMms> outgoingMmsCaptor = ArgumentCaptor.forClass(OutgoingMms.class); + verify(mPersistMmsAtomsStorage).addOutgoingMms(outgoingMmsCaptor.capture()); + OutgoingMms outgoingMms = outgoingMmsCaptor.getValue(); + assertThat(outgoingMms.getRat()).isEqualTo(TelephonyManager.NETWORK_TYPE_UNKNOWN); + assertThat(outgoingMms.getResult()).isEqualTo(OUTGOING_MMS__RESULT__MMS_RESULT_SUCCESS); + assertThat(outgoingMms.getRoaming()).isEqualTo(ServiceState.ROAMING_TYPE_NOT_ROAMING); + assertThat(outgoingMms.getSimSlotIndex()).isEqualTo( + SubscriptionManager.INVALID_SIM_SLOT_INDEX); + assertThat(outgoingMms.getIsMultiSim()).isEqualTo(false); + assertThat(outgoingMms.getIsEsim()).isEqualTo(false); + assertThat(outgoingMms.getCarrierId()).isEqualTo(TelephonyManager.UNKNOWN_CARRIER_ID); + assertThat(outgoingMms.getMmsCount()).isEqualTo(1); + assertThat(outgoingMms.getRetryId()).isEqualTo(0); + assertThat(outgoingMms.getHandledByCarrierApp()).isEqualTo(false); + assertThat(outgoingMms.getIsFromDefaultApp()).isEqualTo(false); + assertThat(outgoingMms.getIsManagedProfile()).isEqualTo(false); + verifyNoMoreInteractions(mPersistMmsAtomsStorage); + } + + @Test + public void getDataRoamingType_serviceState_notNull() { + ServiceState serviceState = mock(ServiceState.class); + doReturn(serviceState).when(mTelephonyManager).getServiceState(); + MmsStats mmsStats = new MmsStats(mContext, mPersistMmsAtomsStorage, 1, + mTelephonyManager, null, true); + mmsStats.addAtomToStorage(Activity.RESULT_OK); + + ArgumentCaptor<IncomingMms> incomingMmsCaptor = ArgumentCaptor.forClass(IncomingMms.class); + verify(mPersistMmsAtomsStorage).addIncomingMms(incomingMmsCaptor.capture()); + IncomingMms incomingMms = incomingMmsCaptor.getValue(); + assertThat(incomingMms.getRoaming()).isEqualTo(ServiceState.ROAMING_TYPE_NOT_ROAMING); + } + + + @Test + public void isDefaultMmsApp_subId_inactive() { + int inactiveSubId = 123; + doReturn(false).when(mSubscriptionManager) + .isActiveSubscriptionId(eq(inactiveSubId)); + + MmsStats mmsStats = new MmsStats(mContext, mPersistMmsAtomsStorage, inactiveSubId, + mTelephonyManager, null, false); + mmsStats.addAtomToStorage(Activity.RESULT_OK); + + // getSubscriptionUserHandle should not be called if subID is inactive. + verify(mSubscriptionManager, never()).getSubscriptionUserHandle(eq(inactiveSubId)); + } +}
\ No newline at end of file diff --git a/tests/unittests/src/com/android/mms/service/metrics/PersistMmsAtomsStorageTest.java b/tests/unittests/src/com/android/mms/service/metrics/PersistMmsAtomsStorageTest.java new file mode 100644 index 0000000..7f604bc --- /dev/null +++ b/tests/unittests/src/com/android/mms/service/metrics/PersistMmsAtomsStorageTest.java @@ -0,0 +1,734 @@ +/* + * Copyright (C) 2022 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.mms.service.metrics; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Build; +import android.telephony.ServiceState; +import android.telephony.TelephonyManager; +import androidx.annotation.Nullable; + +import com.android.mms.IncomingMms; +import com.android.mms.OutgoingMms; +import com.android.mms.PersistMmsAtoms; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; + +import java.io.File; +import java.io.FileOutputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +public class PersistMmsAtomsStorageTest { + private static final String TEST_FILE = "PersistMmsAtomsStorageTest.pb"; + @Rule + public TemporaryFolder mFolder = new TemporaryFolder(); + private File mTestFile; + private static final long START_TIME_MILLIS = 2000L; + private static final int CARRIER1_ID = 1435; + private static final int CARRIER2_ID = 1187; + private TestablePersistMmsAtomsStorage mTestablePersistMmsAtomsStorage; + // IncomingMms + private List<IncomingMms> mIncomingMmsList; + private IncomingMms mIncomingMms1Proto; + private IncomingMms mIncomingMms2Proto; + // OutgoingMms + private List<OutgoingMms> mOutgoingMmsList; + private OutgoingMms mOutgoingMms1Proto; + private OutgoingMms mOutgoingMms2Proto; + // Mocked classes + private Context mContext; + private PackageManager mPackageManager; + private FileOutputStream mTestFileOutputStream; + // Comparator to compare proto objects + private static final Comparator<Object> sProtoComparator = + new Comparator<Object>() { + @Override + public int compare(Object o1, Object o2) { + if (o1 == o2) { + return 0; + } + if (o1 == null) { + return -1; + } + if (o2 == null) { + return 1; + } + assertEquals(o1.getClass(), o2.getClass()); + return o1.toString().compareTo(o2.toString()); + } + }; + + + @Before + public void setUp() throws Exception { + mTestFileOutputStream = mock(FileOutputStream.class); + mContext = mock(Context.class); + mPackageManager = mock(PackageManager.class); + makeTestData(); + + // By default, test loading with real file IO and saving with mocks. + mTestFile = mFolder.newFile(TEST_FILE); + doReturn(false).when(mPackageManager). + hasSystemFeature(PackageManager.FEATURE_RAM_LOW); + doReturn(mPackageManager).when(mContext).getPackageManager(); + doReturn(mTestFileOutputStream).when(mContext).openFileOutput(anyString(), anyInt()); + doReturn(mTestFile).when(mContext).getFileStreamPath(anyString()); + } + + @After + public void tearDown() { + mTestFile.delete(); + mTestFile = null; + mFolder = null; + mIncomingMmsList = null; + mIncomingMms1Proto = null; + mIncomingMms2Proto = null; + mOutgoingMmsList = null; + mOutgoingMms1Proto = null; + mOutgoingMms2Proto = null; + mTestablePersistMmsAtomsStorage = null; + mTestFileOutputStream = null; + mPackageManager = null; + mContext = null; + } + + @Test + public void loadAtoms_fileNotExist() { + mTestFile.delete(); + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + + // No exception should be thrown, storage should be empty, pull time should be start time. + assertAllPullTimestampEquals(START_TIME_MILLIS); + assertStorageIsEmptyForAllAtoms(); + } + + @Test + public void loadAtoms_unreadable() throws Exception { + createEmptyTestFile(); + mTestFile.setReadable(false); + + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + + // No exception should be thrown, storage should be empty, pull time should be start time. + assertAllPullTimestampEquals(START_TIME_MILLIS); + assertStorageIsEmptyForAllAtoms(); + } + + @Test + public void loadAtoms_emptyProto() throws Exception { + createEmptyTestFile(); + + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + + // No exception should be thrown, storage should be empty, pull time should be start time. + assertAllPullTimestampEquals(START_TIME_MILLIS); + assertStorageIsEmptyForAllAtoms(); + } + + @Test + public void loadAtoms_malformedFile() throws Exception { + FileOutputStream stream = new FileOutputStream(mTestFile); + stream.write("This is not a proto file.".getBytes(StandardCharsets.UTF_8)); + stream.close(); + + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + + // No exception should be thrown, storage should be empty, pull time should be start time. + assertAllPullTimestampEquals(START_TIME_MILLIS); + assertStorageIsEmptyForAllAtoms(); + } + + @Test + public void loadAtoms_pullTimeMissing() throws Exception { + // Create test file with lastPullTimeMillis = 0L, i.e. default/unknown. + createTestFile(0L); + + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + + // No exception should be thrown, storage should be match, pull time should be start time. + assertAllPullTimestampEquals(START_TIME_MILLIS); + assertProtoListEqualsIgnoringOrder(mIncomingMmsList, + mTestablePersistMmsAtomsStorage.getIncomingMms(0L)); + assertProtoListEqualsIgnoringOrder(mOutgoingMmsList, + mTestablePersistMmsAtomsStorage.getOutgoingMms(0L)); + } + + @Test + public void loadAtoms_validContents() throws Exception { + createTestFile(100L); + + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + + // No exception should be thrown, storage and pull time should match. + assertAllPullTimestampEquals(100L); + assertProtoListEqualsIgnoringOrder(mIncomingMmsList, + mTestablePersistMmsAtomsStorage.getIncomingMms(0L)); + assertProtoListEqualsIgnoringOrder(mOutgoingMmsList, + mTestablePersistMmsAtomsStorage.getOutgoingMms(0L)); + } + + @Test + public void addIncomingMms_emptyProto() throws Exception { + createEmptyTestFile(); + + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + mTestablePersistMmsAtomsStorage.addIncomingMms(mIncomingMms1Proto); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + + // IncomingMms should be added successfully, there should not be any OutgoingMms, + // changes should be saved. + verifyCurrentStateSavedToFileOnce(); + assertProtoListIsEmpty(mTestablePersistMmsAtomsStorage.getOutgoingMms(0L)); + List<IncomingMms> expectedIncomingMmsList = new ArrayList<>(); + expectedIncomingMmsList.add(mIncomingMms1Proto); + assertProtoListEquals(expectedIncomingMmsList, + mTestablePersistMmsAtomsStorage.getIncomingMms(0L)); + } + + @Test + public void addIncomingMms_withExistingEntries() throws Exception { + createEmptyTestFile(); + + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + mTestablePersistMmsAtomsStorage.addIncomingMms(mIncomingMms1Proto); + mTestablePersistMmsAtomsStorage.addIncomingMms(mIncomingMms2Proto); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + + // IncomingMms should be added successfully. + verifyCurrentStateSavedToFileOnce(); + List<IncomingMms> expectedIncomingMmsList = Arrays.asList(mIncomingMms1Proto, + mIncomingMms2Proto); + assertProtoListEqualsIgnoringOrder(expectedIncomingMmsList, + mTestablePersistMmsAtomsStorage.getIncomingMms(0L)); + } + + @Test + public void addIncomingMms_updateExistingEntries() throws Exception { + createTestFile(START_TIME_MILLIS); + + // Add copy of mIncomingMms1Proto. + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + mTestablePersistMmsAtomsStorage.addIncomingMms(copyOf(mIncomingMms1Proto)); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + + // mIncomingMms1Proto's mms count should be increased by 1 and avgIntervalMillis + // should be updated correctly. + verifyCurrentStateSavedToFileOnce(); + IncomingMms newIncomingMm1Proto = copyOf(mIncomingMms1Proto); + newIncomingMm1Proto = newIncomingMm1Proto.toBuilder() + .setMmsCount(2) + .setAvgIntervalMillis(mIncomingMms1Proto.getAvgIntervalMillis()) + .build(); + List<IncomingMms> expectedIncomingMmsList = Arrays.asList(newIncomingMm1Proto, + mIncomingMms2Proto); + assertProtoListEqualsIgnoringOrder(expectedIncomingMmsList, + mTestablePersistMmsAtomsStorage.getIncomingMms(0L)); + } + + @Test + public void addIncomingMms_tooManyEntries() throws Exception { + createEmptyTestFile(); + + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + // Add 26 mms whereas max size is 25. + IncomingMms mms = IncomingMms.newBuilder() + .setRoaming(ServiceState.ROAMING_TYPE_DOMESTIC) + .setSimSlotIndex(0) + .setIsMultiSim(false) + .setIsEsim(false) + .setCarrierId(CARRIER1_ID) + .setMmsCount(1) + .setAvgIntervalMillis(500L) + .setRetryId(0) + .setHandledByCarrierApp(false) + .build(); + for (int ratType = 0; ratType < 5; ratType++) { + for (int resultType = 0; resultType < 5; resultType++) { + mms = mms.toBuilder().setRat(ratType).setResult(resultType).build(); + mTestablePersistMmsAtomsStorage.addIncomingMms(mms); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + } + } + + // Add 26th mms 5 times + IncomingMms lastMms = copyOf(mms); + lastMms = lastMms.toBuilder().setRat(6).setResult(6).build(); + for (int i = 0; i < 5; i++) { + mTestablePersistMmsAtomsStorage.addIncomingMms(lastMms); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + } + + // Last mms should be present in storage. + assertHasMmsAndCountAvg(mTestablePersistMmsAtomsStorage.getIncomingMms(0L), + lastMms, 5L, lastMms.getAvgIntervalMillis()); + } + + @Test + public void getIncomingMms_tooFrequent() throws Exception { + createTestFile(START_TIME_MILLIS); + + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + // Pull interval less than minimum. + mTestablePersistMmsAtomsStorage.incTimeMillis(50L); + + List<IncomingMms> incomingMmsList = mTestablePersistMmsAtomsStorage + .getIncomingMms(100L); + // Should be denied. + assertNull(incomingMmsList); + } + + @Test + public void getIncomingMms_withSavedAtoms() throws Exception { + createTestFile(START_TIME_MILLIS); + + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + List<IncomingMms> incomingMmsList1 = mTestablePersistMmsAtomsStorage + .getIncomingMms(50L); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + List<IncomingMms> incomingMmsList2 = mTestablePersistMmsAtomsStorage + .getIncomingMms(50L); + + // First set of results should be equal to file contents. + List<IncomingMms> expectedIncomingMmsList = Arrays.asList(mIncomingMms1Proto, + mIncomingMms2Proto); + assertProtoListEqualsIgnoringOrder(expectedIncomingMmsList, incomingMmsList1); + // Second set of results should be empty. + expectedIncomingMmsList = new ArrayList<>(); + assertProtoListEqualsIgnoringOrder(expectedIncomingMmsList, incomingMmsList2); + // Corresponding pull timestamp should be updated and saved. + assertEquals(START_TIME_MILLIS + 200L, mTestablePersistMmsAtomsStorage + .getAtomsProto().getIncomingMmsPullTimestampMillis()); + InOrder inOrder = inOrder(mTestFileOutputStream); + assertEquals(START_TIME_MILLIS + 100L, + getAtomsWritten(inOrder).getIncomingMmsPullTimestampMillis()); + assertEquals(START_TIME_MILLIS + 200L, + getAtomsWritten(inOrder).getIncomingMmsPullTimestampMillis()); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void addOutgoingMms_emptyProto() throws Exception { + createEmptyTestFile(); + + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + mTestablePersistMmsAtomsStorage.addOutgoingMms(mOutgoingMms1Proto); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + + // OutgoingMms should be added successfully, there should not be any IncomingMms, + // changes should be saved. + verifyCurrentStateSavedToFileOnce(); + assertProtoListIsEmpty(mTestablePersistMmsAtomsStorage.getIncomingMms(0L)); + List<OutgoingMms> expectedOutgoingMmsList = new ArrayList<>(); + expectedOutgoingMmsList.add(mOutgoingMms1Proto); + assertProtoListEquals(expectedOutgoingMmsList, + mTestablePersistMmsAtomsStorage.getOutgoingMms(0L)); + } + + @Test + public void addOutgoingMms_withExistingEntries() throws Exception { + createEmptyTestFile(); + + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + mTestablePersistMmsAtomsStorage.addOutgoingMms(mOutgoingMms1Proto); + mTestablePersistMmsAtomsStorage.addOutgoingMms(mOutgoingMms2Proto); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + + // OutgoingMms should be added successfully + verifyCurrentStateSavedToFileOnce(); + List<OutgoingMms> expectedOutgoingMmsList = Arrays.asList(mOutgoingMms1Proto, + mOutgoingMms2Proto); + assertProtoListEqualsIgnoringOrder(expectedOutgoingMmsList, + mTestablePersistMmsAtomsStorage.getOutgoingMms(0L)); + } + + @Test + public void addOutgoingMms_updateExistingEntries() throws Exception { + createTestFile(START_TIME_MILLIS); + + // Add copy of mOutgoingMms1Proto + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + mTestablePersistMmsAtomsStorage.addOutgoingMms(copyOf(mOutgoingMms1Proto)); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + + // mOutgoingMms1Proto's mms count should be increased by 1 and avgIntervalMillis + // should be updated correctly. + verifyCurrentStateSavedToFileOnce(); + OutgoingMms newOutgoingMm1Proto = copyOf(mOutgoingMms1Proto); + newOutgoingMm1Proto = newOutgoingMm1Proto.toBuilder() + .setMmsCount(2) + .setAvgIntervalMillis(mOutgoingMms1Proto.getAvgIntervalMillis()) + .build(); + List<OutgoingMms> expectedOutgoingMmsList = Arrays.asList(newOutgoingMm1Proto, + mOutgoingMms2Proto); + assertProtoListEqualsIgnoringOrder(expectedOutgoingMmsList, + mTestablePersistMmsAtomsStorage.getOutgoingMms(0L)); + } + + @Test + public void addOutgoingMms_tooManyEntries() throws Exception { + createEmptyTestFile(); + + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + // Add 26 mms whereas max size is 25. + OutgoingMms mms = OutgoingMms.newBuilder() + .setRoaming(ServiceState.ROAMING_TYPE_DOMESTIC) + .setSimSlotIndex(0) + .setIsMultiSim(false) + .setIsEsim(false) + .setCarrierId(CARRIER1_ID) + .setMmsCount(1) + .setAvgIntervalMillis(500L) + .setIsFromDefaultApp(true) + .setHandledByCarrierApp(false) + .setRetryId(0) + .build(); + for (int ratType = 0; ratType < 5; ratType++) { + for (int resultType = 0; resultType < 5; resultType++) { + mms = mms.toBuilder().setRat(ratType).setResult(resultType).build(); + mTestablePersistMmsAtomsStorage.addOutgoingMms(mms); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + } + } + + // Add 26th mms 5 times + OutgoingMms lastMms = copyOf(mms); + lastMms = lastMms.toBuilder().setRat(6).setResult(6).build(); + for (int i = 0; i < 5; i++) { + mTestablePersistMmsAtomsStorage.addOutgoingMms(lastMms); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + } + + // Last mms should be present in storage. + assertHasMmsAndCountAvg(mTestablePersistMmsAtomsStorage.getOutgoingMms(0L), + lastMms, 5L, lastMms.getAvgIntervalMillis()); + } + + @Test + public void getOutgoingMms_tooFrequent() throws Exception { + createTestFile(START_TIME_MILLIS); + + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + // Pull interval less than minimum. + mTestablePersistMmsAtomsStorage.incTimeMillis(50L); + + List<OutgoingMms> outgoingMmsList = mTestablePersistMmsAtomsStorage + .getOutgoingMms(100L); + // Should be denied. + assertNull(outgoingMmsList); + } + + @Test + public void getOutgoingMms_withSavedAtoms() throws Exception { + createTestFile(START_TIME_MILLIS); + + mTestablePersistMmsAtomsStorage = new TestablePersistMmsAtomsStorage(mContext); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + List<OutgoingMms> outgoingMmsList1 = mTestablePersistMmsAtomsStorage + .getOutgoingMms(50L); + mTestablePersistMmsAtomsStorage.incTimeMillis(100L); + List<OutgoingMms> outgoingMmsList2 = mTestablePersistMmsAtomsStorage + .getOutgoingMms(50L); + + // First set of results should be equal to file contents. + List<OutgoingMms> expectedOutgoingMmsList = Arrays.asList(mOutgoingMms1Proto, + mOutgoingMms2Proto); + assertProtoListEqualsIgnoringOrder(expectedOutgoingMmsList, outgoingMmsList1); + // Second set of results should be empty. + expectedOutgoingMmsList = new ArrayList<>(); + assertProtoListEqualsIgnoringOrder(expectedOutgoingMmsList, outgoingMmsList2); + // Corresponding pull timestamp should be updated and saved. + assertEquals(START_TIME_MILLIS + 200L, mTestablePersistMmsAtomsStorage + .getAtomsProto().getOutgoingMmsPullTimestampMillis()); + InOrder inOrder = inOrder(mTestFileOutputStream); + assertEquals(START_TIME_MILLIS + 100L, + getAtomsWritten(inOrder).getOutgoingMmsPullTimestampMillis()); + assertEquals(START_TIME_MILLIS + 200L, + getAtomsWritten(inOrder).getOutgoingMmsPullTimestampMillis()); + inOrder.verifyNoMoreInteractions(); + } + + /** Utilities */ + + private void assertAllPullTimestampEquals(long timestamp) { + assertEquals(timestamp, mTestablePersistMmsAtomsStorage.getAtomsProto() + .getIncomingMmsPullTimestampMillis()); + assertEquals(timestamp, mTestablePersistMmsAtomsStorage.getAtomsProto() + .getOutgoingMmsPullTimestampMillis()); + } + + private void assertStorageIsEmptyForAllAtoms() { + assertProtoListIsEmpty(mTestablePersistMmsAtomsStorage.getIncomingMms(0L)); + assertProtoListIsEmpty(mTestablePersistMmsAtomsStorage.getOutgoingMms(0L)); + } + + private static <T> void assertProtoListIsEmpty(@Nullable List<T> list) { + assertNotNull(list); + assertEquals(0, list.size()); + } + + private static <T> void assertProtoListEquals(@Nullable List<T> expected, + @Nullable List<T> actual) { + assertNotNull(expected); + assertNotNull(actual); + String message = + "Expected:\n" + expected.stream().map(Object::toString).collect( + Collectors.joining(", ")) + + "\nGot:\n" + actual.stream().map(Object::toString).collect( + Collectors.joining(", ")); + assertEquals(message, expected.size(), actual.size()); + for (int i = 0; i < expected.size(); i++) { + assertTrue(message, expected.get(i).equals(actual.get(i))); + } + } + + private static <T> void assertProtoListEqualsIgnoringOrder(@Nullable List<T> expected, + @Nullable List<T> actual) { + assertNotNull(expected); + assertNotNull(actual); + expected = new ArrayList<>(expected); + actual = new ArrayList<>(actual); + Collections.sort(expected, sProtoComparator); + Collections.sort(actual, sProtoComparator); + assertProtoListEquals(expected, actual); + } + + private static void assertHasMmsAndCountAvg(@Nullable List<IncomingMms> incomingMmsList, + @Nullable IncomingMms expectedMms, long expectedCount, long expectedAvg) { + assertNotNull(incomingMmsList); + assertNotNull(expectedMms); + long actualCount = -1; + long actualAvg = -1; + for (IncomingMms mms : incomingMmsList) { + if (mms.getRat() == expectedMms.getRat() + && mms.getResult() == expectedMms.getResult() + && mms.getRoaming() == expectedMms.getRoaming() + && mms.getSimSlotIndex() == expectedMms.getSimSlotIndex() + && mms.getIsMultiSim() == expectedMms.getIsMultiSim() + && mms.getIsEsim() == expectedMms.getIsEsim() + && mms.getCarrierId() == expectedMms.getCarrierId() + && mms.getRetryId() == expectedMms.getRetryId() + && mms.getHandledByCarrierApp() == expectedMms.getHandledByCarrierApp()) { + actualCount = mms.getMmsCount(); + actualAvg = mms.getAvgIntervalMillis(); + } + } + + assertEquals(expectedCount, actualCount); + assertEquals(expectedAvg, actualAvg); + } + + private static void assertHasMmsAndCountAvg(@Nullable List<OutgoingMms> outgoingMmsList, + @Nullable OutgoingMms expectedMms, long expectedCount, long expectedAvg) { + assertNotNull(outgoingMmsList); + assertNotNull(expectedMms); + long actualCount = -1; + long actualAvg = -1; + for (OutgoingMms mms : outgoingMmsList) { + if (mms.getRat() == expectedMms.getRat() + && mms.getResult() == expectedMms.getResult() + && mms.getRoaming() == expectedMms.getRoaming() + && mms.getSimSlotIndex() == expectedMms.getSimSlotIndex() + && mms.getIsMultiSim() == expectedMms.getIsMultiSim() + && mms.getIsEsim() == expectedMms.getIsEsim() + && mms.getCarrierId() == expectedMms.getCarrierId() + && mms.getIsFromDefaultApp() == expectedMms.getIsFromDefaultApp() + && mms.getRetryId() == expectedMms.getRetryId() + && mms.getHandledByCarrierApp() == expectedMms.getHandledByCarrierApp()) { + actualCount = mms.getMmsCount(); + actualAvg = mms.getAvgIntervalMillis(); + } + } + + assertEquals(expectedCount, actualCount); + assertEquals(expectedAvg, actualAvg); + } + + private void verifyCurrentStateSavedToFileOnce() throws Exception { + InOrder inOrder = inOrder(mTestFileOutputStream); + inOrder.verify(mTestFileOutputStream, times(1)) + .write(eq(mTestablePersistMmsAtomsStorage.getAtomsProto().toByteArray())); + inOrder.verify(mTestFileOutputStream, times(1)).close(); + inOrder.verifyNoMoreInteractions(); + } + + private PersistMmsAtoms getAtomsWritten(@Nullable InOrder inOrder) throws Exception { + if (inOrder == null) { + inOrder = inOrder(mTestFileOutputStream); + } + ArgumentCaptor bytesCaptor = ArgumentCaptor.forClass(Object.class); + inOrder.verify(mTestFileOutputStream, times(1)) + .write((byte[]) bytesCaptor.capture()); + PersistMmsAtoms savedAtoms = PersistMmsAtoms.parseFrom((byte[]) bytesCaptor.getValue()); + inOrder.verify(mTestFileOutputStream, times(1)).close(); + return savedAtoms; + } + + private static IncomingMms copyOf(IncomingMms source) { + return source.toBuilder().build(); + } + + private static OutgoingMms copyOf(OutgoingMms source) { + return source.toBuilder().build(); + } + + private void makeTestData() { + mIncomingMms1Proto = IncomingMms.newBuilder() + .setRat(TelephonyManager.NETWORK_TYPE_LTE) + .setResult(1) + .setRoaming(ServiceState.ROAMING_TYPE_NOT_ROAMING) + .setSimSlotIndex(0) + .setIsMultiSim(true) + .setIsEsim(false) + .setCarrierId(CARRIER1_ID) + .setAvgIntervalMillis(500L) + .setMmsCount(1) + .setRetryId(0) + .setHandledByCarrierApp(false) + .build(); + + mIncomingMms2Proto = IncomingMms.newBuilder() + .setRat(TelephonyManager.NETWORK_TYPE_LTE) + .setResult(1) + .setRoaming(ServiceState.ROAMING_TYPE_NOT_ROAMING) + .setSimSlotIndex(1) + .setIsMultiSim(false) + .setIsEsim(false) + .setCarrierId(CARRIER2_ID) + .setAvgIntervalMillis(500L) + .setMmsCount(1) + .setRetryId(0) + .setHandledByCarrierApp(false) + .build(); + + mIncomingMmsList = new ArrayList<>(); + mIncomingMmsList.add(mIncomingMms1Proto); + mIncomingMmsList.add(mIncomingMms2Proto); + + mOutgoingMms1Proto = OutgoingMms.newBuilder() + .setRat(0) + .setResult(1) + .setRoaming(0) + .setSimSlotIndex(0) + .setIsMultiSim(true) + .setIsEsim(false) + .setCarrierId(CARRIER1_ID) + .setAvgIntervalMillis(500L) + .setMmsCount(1) + .setIsFromDefaultApp(true) + .setRetryId(0) + .setHandledByCarrierApp(false) + .build(); + + mOutgoingMms2Proto = OutgoingMms.newBuilder() + .setRat(0) + .setResult(1) + .setRoaming(0) + .setSimSlotIndex(0) + .setIsMultiSim(false) + .setIsEsim(false) + .setCarrierId(CARRIER2_ID) + .setAvgIntervalMillis(500L) + .setMmsCount(1) + .setIsFromDefaultApp(true) + .setRetryId(0) + .setHandledByCarrierApp(false) + .build(); + + mOutgoingMmsList = new ArrayList<>(); + mOutgoingMmsList.add(mOutgoingMms1Proto); + mOutgoingMmsList.add(mOutgoingMms2Proto); + } + + private void createEmptyTestFile() throws Exception { + PersistMmsAtoms atoms = PersistMmsAtoms.newBuilder().build(); + FileOutputStream stream = new FileOutputStream(mTestFile); + stream.write(atoms.toByteArray()); + stream.close(); + } + + private void createTestFile(long lastPullTimeMillis) throws Exception { + PersistMmsAtoms atoms = PersistMmsAtoms.newBuilder() + .setBuildFingerprint(Build.FINGERPRINT) + .setIncomingMmsPullTimestampMillis(lastPullTimeMillis) + .setOutgoingMmsPullTimestampMillis(lastPullTimeMillis) + .addAllIncomingMms(mIncomingMmsList) + .addAllOutgoingMms(mOutgoingMmsList) + .build(); + + FileOutputStream stream = new FileOutputStream(mTestFile); + stream.write(atoms.toByteArray()); + stream.close(); + } + + private static class TestablePersistMmsAtomsStorage extends PersistMmsAtomsStorage { + private long mTimeMillis = START_TIME_MILLIS; + + TestablePersistMmsAtomsStorage(Context context) { + super(context); + // Remove delay for saving to persistent storage during tests. + mSaveImmediately = true; + } + + @Override + protected long getWallTimeMillis() { + // NOTE: super class constructor will be executed before private field is set, which + // gives the wrong start time (mTimeMillis will have its default value of 0L). + return mTimeMillis == 0L ? START_TIME_MILLIS : mTimeMillis; + } + + private void incTimeMillis(long timeMillis) { + mTimeMillis += timeMillis; + } + + private PersistMmsAtoms getAtomsProto() { + // NOTE: unlike other methods in PersistAtomsStorage, this is not synchronized, but + // should be fine since the test is single-threaded. + return mPersistMmsAtoms; + } + } +}
\ No newline at end of file |