Improve the latency of DataUsageList

Up to 30x faster.

Currently it load the usage detail for every day at the beginning, so
it's quite slow.

To fix,
- Not load the usage detail for every day at the beginning
- Load only the cycles first
- And only load the daily detail for the selected month

Fix: 290856342
Test: manual - on DataUsageList (cell & wifi)
Test: unit tests
Change-Id: Ie18fa68f801743389bd6b6a28e236dcf1fea00e4
This commit is contained in:
Chaohui Wang
2023-09-15 13:50:11 +08:00
parent db9fdb0de8
commit 2205762482
19 changed files with 1185 additions and 727 deletions

View File

@@ -31,9 +31,9 @@ import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
import com.android.settings.datausage.ChartDataUsagePreference.DataUsageSummaryNode;
import com.android.settings.datausage.lib.NetworkCycleChartData;
import com.android.settings.datausage.lib.NetworkUsageData;
import com.android.settings.widget.UsageView;
import com.android.settingslib.net.NetworkCycleChartData;
import com.android.settingslib.net.NetworkCycleData;
import org.junit.Before;
import org.junit.Test;
@@ -55,7 +55,7 @@ public class ChartDataUsagePreferenceTest {
// Test bucket end date, 22 Mar 2018 00:00:00
private static final long TIMESTAMP_END = 1521676800000L;
private List<NetworkCycleData> mNetworkCycleData;
private List<NetworkUsageData> mNetworkCycleData;
private NetworkCycleChartData mNetworkCycleChartData;
private ChartDataUsagePreference mPreference;
private Activity mActivity;
@@ -79,6 +79,9 @@ public class ChartDataUsagePreferenceTest {
final ArgumentCaptor<SparseIntArray> pointsCaptor =
ArgumentCaptor.forClass(SparseIntArray.class);
createTestNetworkData();
mPreference.setTime(
mNetworkCycleChartData.getTotal().getStartTime(),
mNetworkCycleChartData.getTotal().getEndTime());
mPreference.setNetworkCycleData(mNetworkCycleChartData);
mPreference.calcPoints(usageView, mNetworkCycleData.subList(0, 5));
@@ -95,6 +98,9 @@ public class ChartDataUsagePreferenceTest {
final ArgumentCaptor<SparseIntArray> pointsCaptor =
ArgumentCaptor.forClass(SparseIntArray.class);
createTestNetworkData();
mPreference.setTime(
mNetworkCycleChartData.getTotal().getStartTime(),
mNetworkCycleChartData.getTotal().getEndTime());
mPreference.setNetworkCycleData(mNetworkCycleChartData);
mPreference.calcPoints(usageView, mNetworkCycleData.subList(2, 7));
@@ -110,39 +116,62 @@ public class ChartDataUsagePreferenceTest {
public void calcPoints_shouldNotDrawPointForFutureDate() {
final UsageView usageView = mock(UsageView.class);
final ArgumentCaptor<SparseIntArray> pointsCaptor =
ArgumentCaptor.forClass(SparseIntArray.class);
ArgumentCaptor.forClass(SparseIntArray.class);
final long tonight = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(12);
mNetworkCycleData = new ArrayList<>();
// add test usage data for last 5 days
mNetworkCycleData.add(createNetworkCycleData(
tonight - TimeUnit.DAYS.toMillis(5), tonight - TimeUnit.DAYS.toMillis(4), 743823454L));
mNetworkCycleData.add(createNetworkCycleData(
tonight - TimeUnit.DAYS.toMillis(4), tonight - TimeUnit.DAYS.toMillis(3), 64396L));
mNetworkCycleData.add(createNetworkCycleData(
tonight - TimeUnit.DAYS.toMillis(3), tonight - TimeUnit.DAYS.toMillis(2), 2832L));
mNetworkCycleData.add(createNetworkCycleData(
tonight - TimeUnit.DAYS.toMillis(2), tonight - TimeUnit.DAYS.toMillis(1), 83849690L));
mNetworkCycleData.add(createNetworkCycleData(
tonight - TimeUnit.DAYS.toMillis(1), tonight, 1883657L));
mNetworkCycleData.add(new NetworkUsageData(
tonight - TimeUnit.DAYS.toMillis(5),
tonight - TimeUnit.DAYS.toMillis(4),
743823454L));
mNetworkCycleData.add(new NetworkUsageData(
tonight - TimeUnit.DAYS.toMillis(4),
tonight - TimeUnit.DAYS.toMillis(3),
64396L));
mNetworkCycleData.add(new NetworkUsageData(
tonight - TimeUnit.DAYS.toMillis(3),
tonight - TimeUnit.DAYS.toMillis(2),
2832L));
mNetworkCycleData.add(new NetworkUsageData(
tonight - TimeUnit.DAYS.toMillis(2),
tonight - TimeUnit.DAYS.toMillis(1),
83849690L));
mNetworkCycleData.add(new NetworkUsageData(
tonight - TimeUnit.DAYS.toMillis(1), tonight, 1883657L));
// add test usage data for next 5 days
mNetworkCycleData.add(createNetworkCycleData(
tonight, tonight + TimeUnit.DAYS.toMillis(1), 0L));
mNetworkCycleData.add(createNetworkCycleData(
tonight + TimeUnit.DAYS.toMillis(1), tonight + TimeUnit.DAYS.toMillis(2), 0L));
mNetworkCycleData.add(createNetworkCycleData(
tonight + TimeUnit.DAYS.toMillis(2), tonight + TimeUnit.DAYS.toMillis(3), 0L));
mNetworkCycleData.add(createNetworkCycleData(
tonight + TimeUnit.DAYS.toMillis(3), tonight + TimeUnit.DAYS.toMillis(4), 0L));
mNetworkCycleData.add(createNetworkCycleData(
tonight + TimeUnit.DAYS.toMillis(4), tonight + TimeUnit.DAYS.toMillis(5), 0L));
mNetworkCycleData.add(createNetworkCycleData(
tonight + TimeUnit.DAYS.toMillis(5), tonight + TimeUnit.DAYS.toMillis(6), 0L));
mNetworkCycleData.add(new NetworkUsageData(
tonight, tonight + TimeUnit.DAYS.toMillis(1), 0L));
mNetworkCycleData.add(new NetworkUsageData(
tonight + TimeUnit.DAYS.toMillis(1),
tonight + TimeUnit.DAYS.toMillis(2),
0L));
mNetworkCycleData.add(new NetworkUsageData(
tonight + TimeUnit.DAYS.toMillis(2),
tonight + TimeUnit.DAYS.toMillis(3),
0L));
mNetworkCycleData.add(new NetworkUsageData(
tonight + TimeUnit.DAYS.toMillis(3),
tonight + TimeUnit.DAYS.toMillis(4),
0L));
mNetworkCycleData.add(new NetworkUsageData(
tonight + TimeUnit.DAYS.toMillis(4),
tonight + TimeUnit.DAYS.toMillis(5),
0L));
mNetworkCycleData.add(new NetworkUsageData(
tonight + TimeUnit.DAYS.toMillis(5),
tonight + TimeUnit.DAYS.toMillis(6),
0L));
final NetworkCycleChartData.Builder builder = new NetworkCycleChartData.Builder();
builder.setUsageBuckets(mNetworkCycleData)
.setStartTime(tonight - TimeUnit.DAYS.toMillis(5))
.setEndTime(tonight + TimeUnit.DAYS.toMillis(6));
mNetworkCycleChartData = builder.build();
mNetworkCycleChartData = new NetworkCycleChartData(
new NetworkUsageData(
tonight - TimeUnit.DAYS.toMillis(5),
tonight + TimeUnit.DAYS.toMillis(6),
0),
mNetworkCycleData
);
mPreference.setTime(
mNetworkCycleChartData.getTotal().getStartTime(),
mNetworkCycleChartData.getTotal().getEndTime());
mPreference.setNetworkCycleData(mNetworkCycleChartData);
mPreference.calcPoints(usageView, mNetworkCycleData);
@@ -170,6 +199,9 @@ public class ChartDataUsagePreferenceTest {
final TextView labelStart = (TextView) mHolder.findViewById(R.id.label_start);
final TextView labelEnd = (TextView) mHolder.findViewById(R.id.label_end);
createTestNetworkData();
mPreference.setTime(
mNetworkCycleChartData.getTotal().getStartTime(),
mNetworkCycleChartData.getTotal().getEndTime());
mPreference.setNetworkCycleData(mNetworkCycleChartData);
mPreference.onBindViewHolder(mHolder);
@@ -198,38 +230,33 @@ public class ChartDataUsagePreferenceTest {
private void createTestNetworkData() {
mNetworkCycleData = new ArrayList<>();
// create 10 arbitrary network data
mNetworkCycleData.add(createNetworkCycleData(1521583200000L, 1521586800000L, 743823454L));
mNetworkCycleData.add(createNetworkCycleData(1521586800000L, 1521590400000L, 64396L));
mNetworkCycleData.add(createNetworkCycleData(1521590400000L, 1521655200000L, 2832L));
mNetworkCycleData.add(createNetworkCycleData(1521655200000L, 1521658800000L, 83849690L));
mNetworkCycleData.add(createNetworkCycleData(1521658800000L, 1521662400000L, 1883657L));
mNetworkCycleData.add(createNetworkCycleData(1521662400000L, 1521666000000L, 705259L));
mNetworkCycleData.add(createNetworkCycleData(1521666000000L, 1521669600000L, 216169L));
mNetworkCycleData.add(createNetworkCycleData(1521669600000L, 1521673200000L, 6069175L));
mNetworkCycleData.add(createNetworkCycleData(1521673200000L, 1521676800000L, 120389L));
mNetworkCycleData.add(createNetworkCycleData(1521676800000L, 1521678800000L, 29947L));
mNetworkCycleData.add(new NetworkUsageData(1521583200000L, 1521586800000L, 743823454L));
mNetworkCycleData.add(new NetworkUsageData(1521586800000L, 1521590400000L, 64396L));
mNetworkCycleData.add(new NetworkUsageData(1521590400000L, 1521655200000L, 2832L));
mNetworkCycleData.add(new NetworkUsageData(1521655200000L, 1521658800000L, 83849690L));
mNetworkCycleData.add(new NetworkUsageData(1521658800000L, 1521662400000L, 1883657L));
mNetworkCycleData.add(new NetworkUsageData(1521662400000L, 1521666000000L, 705259L));
mNetworkCycleData.add(new NetworkUsageData(1521666000000L, 1521669600000L, 216169L));
mNetworkCycleData.add(new NetworkUsageData(1521669600000L, 1521673200000L, 6069175L));
mNetworkCycleData.add(new NetworkUsageData(1521673200000L, 1521676800000L, 120389L));
mNetworkCycleData.add(new NetworkUsageData(1521676800000L, 1521678800000L, 29947L));
final NetworkCycleChartData.Builder builder = new NetworkCycleChartData.Builder();
builder.setUsageBuckets(mNetworkCycleData)
.setStartTime(TIMESTAMP_START)
.setEndTime(TIMESTAMP_END);
mNetworkCycleChartData = builder.build();
mNetworkCycleChartData = new NetworkCycleChartData(
new NetworkUsageData(TIMESTAMP_START, TIMESTAMP_END, 0),
mNetworkCycleData
);
}
private void createSomeSamePercentageNetworkData() {
mNetworkCycleData = new ArrayList<>();
mNetworkCycleData.add(createNetworkCycleData(1521583200000L, 1521586800000L, 100));//33%
mNetworkCycleData.add(createNetworkCycleData(1521586800000L, 1521590400000L, 1)); //33%
mNetworkCycleData.add(createNetworkCycleData(1521590400000L, 1521655200000L, 0)); //33%
mNetworkCycleData.add(createNetworkCycleData(1521655200000L, 1521658800000L, 0)); //33%
mNetworkCycleData.add(createNetworkCycleData(1521658800000L, 1521662400000L, 200));//99%
mNetworkCycleData.add(createNetworkCycleData(1521662400000L, 1521666000000L, 1)); //99%
mNetworkCycleData.add(createNetworkCycleData(1521666000000L, 1521669600000L, 1)); //100
mNetworkCycleData.add(createNetworkCycleData(1521669600000L, 1521673200000L, 0)); //100%
mNetworkCycleData.add(new NetworkUsageData(1521583200000L, 1521586800000L, 100)); //33%
mNetworkCycleData.add(new NetworkUsageData(1521586800000L, 1521590400000L, 1)); //33%
mNetworkCycleData.add(new NetworkUsageData(1521590400000L, 1521655200000L, 0)); //33%
mNetworkCycleData.add(new NetworkUsageData(1521655200000L, 1521658800000L, 0)); //33%
mNetworkCycleData.add(new NetworkUsageData(1521658800000L, 1521662400000L, 200)); //99%
mNetworkCycleData.add(new NetworkUsageData(1521662400000L, 1521666000000L, 1)); //99%
mNetworkCycleData.add(new NetworkUsageData(1521666000000L, 1521669600000L, 1)); //100
mNetworkCycleData.add(new NetworkUsageData(1521669600000L, 1521673200000L, 0)); //100%
}
private NetworkCycleData createNetworkCycleData(long start, long end, long usage) {
return new NetworkCycleData.Builder()
.setStartTime(start).setEndTime(end).setTotalUsage(usage).build();
}
}

View File

@@ -1,249 +0,0 @@
/*
* Copyright (C) 2018 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.settings.datausage;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doNothing;
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.app.Activity;
import android.content.Intent;
import android.net.NetworkTemplate;
import android.os.Bundle;
import android.os.UserManager;
import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.loader.app.LoaderManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import com.android.settings.datausage.lib.BillingCycleRepository;
import com.android.settings.network.MobileDataEnabledListener;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.widget.LoadingViewController;
import com.android.settingslib.NetworkPolicyEditor;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
import com.android.settingslib.net.NetworkCycleChartData;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.util.ReflectionHelpers;
import java.util.Collections;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = DataUsageListTest.ShadowDataUsageBaseFragment.class)
public class DataUsageListTest {
@Rule
public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock
private MobileDataEnabledListener mMobileDataEnabledListener;
@Mock
private TemplatePreference.NetworkServices mNetworkServices;
@Mock
private LoaderManager mLoaderManager;
@Mock
private UserManager mUserManager;
@Mock
private BillingCycleRepository mBillingCycleRepository;
@Mock
private DataUsageListHeaderController mDataUsageListHeaderController;
private Activity mActivity;
@Spy
private TestDataUsageList mDataUsageList;
@Before
public void setUp() {
FakeFeatureFactory.setupForTest();
final ActivityController<Activity> mActivityController =
Robolectric.buildActivity(Activity.class);
mActivity = spy(mActivityController.get());
mNetworkServices.mPolicyEditor = mock(NetworkPolicyEditor.class);
mDataUsageList.mDataStateListener = mMobileDataEnabledListener;
doReturn(mActivity).when(mDataUsageList).getContext();
doReturn(mUserManager).when(mActivity).getSystemService(UserManager.class);
doReturn(false).when(mUserManager).isGuestUser();
ReflectionHelpers.setField(mDataUsageList, "mDataStateListener",
mMobileDataEnabledListener);
ReflectionHelpers.setField(mDataUsageList, "services", mNetworkServices);
doReturn(mLoaderManager).when(mDataUsageList).getLoaderManager();
mDataUsageList.mLoadingViewController = mock(LoadingViewController.class);
doNothing().when(mDataUsageList).updateSubscriptionInfoEntity();
when(mBillingCycleRepository.isBandwidthControlEnabled()).thenReturn(true);
mDataUsageList.mDataUsageListHeaderController = mDataUsageListHeaderController;
}
@Test
public void onCreate_isNotGuestUser_shouldNotFinish() {
mDataUsageList.mTemplate = mock(NetworkTemplate.class);
doReturn(false).when(mUserManager).isGuestUser();
doNothing().when(mDataUsageList).processArgument();
mDataUsageList.onCreate(null);
verify(mDataUsageList, never()).finish();
}
@Test
public void onCreate_isGuestUser_shouldFinish() {
doReturn(true).when(mUserManager).isGuestUser();
mDataUsageList.onCreate(null);
verify(mDataUsageList).finish();
}
@Test
public void resume_shouldListenDataStateChange() {
mDataUsageList.onCreate(null);
ReflectionHelpers.setField(
mDataUsageList, "mVisibilityLoggerMixin", mock(VisibilityLoggerMixin.class));
ReflectionHelpers.setField(
mDataUsageList, "mPreferenceManager", mock(PreferenceManager.class));
mDataUsageList.onResume();
verify(mMobileDataEnabledListener).start(anyInt());
mDataUsageList.onPause();
}
@Test
public void pause_shouldUnlistenDataStateChange() {
mDataUsageList.onCreate(null);
ReflectionHelpers.setField(
mDataUsageList, "mVisibilityLoggerMixin", mock(VisibilityLoggerMixin.class));
ReflectionHelpers.setField(
mDataUsageList, "mPreferenceManager", mock(PreferenceManager.class));
mDataUsageList.onResume();
mDataUsageList.onPause();
verify(mMobileDataEnabledListener).stop();
}
@Test
public void processArgument_shouldGetTemplateFromArgument() {
final Bundle args = new Bundle();
args.putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, mock(NetworkTemplate.class));
args.putInt(DataUsageList.EXTRA_SUB_ID, 3);
mDataUsageList.setArguments(args);
mDataUsageList.processArgument();
assertThat(mDataUsageList.mTemplate).isNotNull();
assertThat(mDataUsageList.mSubId).isEqualTo(3);
}
@Test
public void processArgument_fromIntent_shouldGetTemplateFromIntent() {
final Intent intent = new Intent();
intent.putExtra(Settings.EXTRA_NETWORK_TEMPLATE, mock(NetworkTemplate.class));
intent.putExtra(Settings.EXTRA_SUB_ID, 3);
doReturn(intent).when(mDataUsageList).getIntent();
mDataUsageList.processArgument();
assertThat(mDataUsageList.mTemplate).isNotNull();
assertThat(mDataUsageList.mSubId).isEqualTo(3);
}
@Test
public void onLoadFinished_networkCycleDataCallback_shouldShowCycleSpinner() {
mDataUsageList.mTemplate = mock(NetworkTemplate.class);
mDataUsageList.onCreate(null);
mDataUsageList.updatePolicy();
List<NetworkCycleChartData> mockData = Collections.emptyList();
mDataUsageList.mNetworkCycleDataCallbacks.onLoadFinished(null, mockData);
verify(mDataUsageListHeaderController).updateCycleData(mockData);
verify(mDataUsageListHeaderController).setConfigButtonVisible(true);
}
@Test
public void onPause_shouldDestroyLoaders() {
mDataUsageList.onPause();
verify(mLoaderManager).destroyLoader(DataUsageList.LOADER_CHART_DATA);
}
@Implements(DataUsageBaseFragment.class)
public static class ShadowDataUsageBaseFragment {
@Implementation
public void onCreate(Bundle icicle) {
// do nothing
}
}
public class TestDataUsageList extends DataUsageList {
@Override
protected <T extends AbstractPreferenceController> T use(Class<T> clazz) {
return mock(clazz);
}
@Override
public <T extends Preference> T findPreference(CharSequence key) {
if (key.toString().equals("chart_data")) {
return (T) mock(ChartDataUsagePreference.class);
}
return (T) mock(Preference.class);
}
@Override
public Intent getIntent() {
return new Intent();
}
@NonNull
@Override
BillingCycleRepository createBillingCycleRepository() {
return mBillingCycleRepository;
}
@Override
boolean isBillingCycleModifiable() {
return true;
}
}
}

View File

@@ -0,0 +1,216 @@
/*
* 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.settings.datausage
import android.content.Context
import android.content.Intent
import android.net.NetworkTemplate
import android.os.Bundle
import android.os.UserManager
import android.provider.Settings
import androidx.preference.Preference
import androidx.preference.PreferenceManager
import androidx.test.core.app.ApplicationProvider
import com.android.settings.datausage.DataUsageListTest.ShadowDataUsageBaseFragment
import com.android.settings.datausage.TemplatePreference.NetworkServices
import com.android.settings.datausage.lib.BillingCycleRepository
import com.android.settings.network.MobileDataEnabledListener
import com.android.settings.testutils.FakeFeatureFactory
import com.android.settingslib.NetworkPolicyEditor
import com.android.settingslib.core.AbstractPreferenceController
import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers
import org.mockito.Mock
import org.mockito.Mockito.doNothing
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.Spy
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.robolectric.annotation.Implementation
import org.robolectric.annotation.Implements
import org.robolectric.util.ReflectionHelpers
@RunWith(RobolectricTestRunner::class)
@Config(shadows = [ShadowDataUsageBaseFragment::class])
class DataUsageListTest {
@get:Rule
val mockito: MockitoRule = MockitoJUnit.rule()
@Mock
private lateinit var mobileDataEnabledListener: MobileDataEnabledListener
@Mock
private lateinit var networkServices: NetworkServices
@Mock
private lateinit var userManager: UserManager
@Mock
private lateinit var billingCycleRepository: BillingCycleRepository
@Mock
private lateinit var dataUsageListHeaderController: DataUsageListHeaderController
@Spy
private val context: Context = ApplicationProvider.getApplicationContext()
@Spy
private val dataUsageList = TestDataUsageList()
@Before
fun setUp() {
FakeFeatureFactory.setupForTest()
networkServices.mPolicyEditor = mock(NetworkPolicyEditor::class.java)
dataUsageList.dataStateListener = mobileDataEnabledListener
doReturn(context).`when`(dataUsageList).context
doReturn(userManager).`when`(context).getSystemService(UserManager::class.java)
doReturn(false).`when`(userManager).isGuestUser
ReflectionHelpers.setField(dataUsageList, "services", networkServices)
doNothing().`when`(dataUsageList).updateSubscriptionInfoEntity()
`when`(billingCycleRepository.isBandwidthControlEnabled()).thenReturn(true)
dataUsageList.dataUsageListHeaderController = dataUsageListHeaderController
}
@Test
fun onCreate_isNotGuestUser_shouldNotFinish() {
dataUsageList.template = mock<NetworkTemplate>(NetworkTemplate::class.java)
doReturn(false).`when`(userManager).isGuestUser
doNothing().`when`(dataUsageList).processArgument()
dataUsageList.onCreate(null)
verify(dataUsageList, never()).finish()
}
@Test
fun onCreate_isGuestUser_shouldFinish() {
doReturn(true).`when`(userManager).isGuestUser
dataUsageList.onCreate(null)
verify(dataUsageList).finish()
}
@Test
fun resume_shouldListenDataStateChange() {
dataUsageList.template = mock(NetworkTemplate::class.java)
dataUsageList.onCreate(null)
dataUsageList.dataStateListener = mobileDataEnabledListener
ReflectionHelpers.setField(
dataUsageList,
"mVisibilityLoggerMixin",
mock(VisibilityLoggerMixin::class.java),
)
ReflectionHelpers.setField(
dataUsageList,
"mPreferenceManager",
mock(PreferenceManager::class.java),
)
dataUsageList.onResume()
verify(mobileDataEnabledListener).start(ArgumentMatchers.anyInt())
dataUsageList.onPause()
}
@Test
fun pause_shouldUnlistenDataStateChange() {
dataUsageList.template = mock(NetworkTemplate::class.java)
dataUsageList.onCreate(null)
dataUsageList.dataStateListener = mobileDataEnabledListener
ReflectionHelpers.setField(
dataUsageList, "mVisibilityLoggerMixin", mock(
VisibilityLoggerMixin::class.java
)
)
ReflectionHelpers.setField(
dataUsageList, "mPreferenceManager", mock(
PreferenceManager::class.java
)
)
dataUsageList.onResume()
dataUsageList.onPause()
verify(mobileDataEnabledListener).stop()
}
@Test
fun processArgument_shouldGetTemplateFromArgument() {
val args = Bundle()
args.putParcelable(
DataUsageList.EXTRA_NETWORK_TEMPLATE, mock(
NetworkTemplate::class.java
)
)
args.putInt(DataUsageList.EXTRA_SUB_ID, 3)
dataUsageList.arguments = args
dataUsageList.processArgument()
assertThat(dataUsageList.template).isNotNull()
assertThat(dataUsageList.subId).isEqualTo(3)
}
@Test
fun processArgument_fromIntent_shouldGetTemplateFromIntent() {
val intent = Intent()
intent.putExtra(
Settings.EXTRA_NETWORK_TEMPLATE, mock(
NetworkTemplate::class.java
)
)
intent.putExtra(Settings.EXTRA_SUB_ID, 3)
doReturn(intent).`when`(dataUsageList).intent
dataUsageList.processArgument()
assertThat(dataUsageList.template).isNotNull()
assertThat(dataUsageList.subId).isEqualTo(3)
}
@Test
fun updatePolicy_setConfigButtonVisible() {
dataUsageList.template = mock(NetworkTemplate::class.java)
dataUsageList.onCreate(null)
dataUsageList.updatePolicy()
verify(dataUsageListHeaderController).setConfigButtonVisible(true)
}
@Implements(DataUsageBaseFragment::class)
class ShadowDataUsageBaseFragment {
@Implementation
fun onCreate(@Suppress("UNUSED_PARAMETER") icicle: Bundle?) {
// do nothing
}
}
open inner class TestDataUsageList : DataUsageList() {
override fun <T : AbstractPreferenceController?> use(clazz: Class<T>): T = mock(clazz)
@Suppress("UNCHECKED_CAST")
override fun <T : Preference?> findPreference(key: CharSequence): T =
mock(Preference::class.java) as T
public override fun getIntent() = Intent()
override fun createBillingCycleRepository() = billingCycleRepository
override fun isBillingCycleModifiable() = true
}
}