From 1885f027d86f9673c70ea0d4381ef2d12e3e30e2 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sun, 13 Sep 2020 21:20:18 -0400 Subject: [PATCH] [Testing] AndroidJunit Enhanced4gLteSliceHelperTest Test: atest -c Enhanced4gLteSliceHelperTest Change-Id: I548ffe60f00cea76d0c4af33ca4ec6f38cbf6247 --- .../network/ims/MockVolteQueryImsState.java | 105 +++++++ .../Enhanced4gLteSliceHelperTest.java | 295 ++++++++++++++++++ .../testutils/FakeFeatureFactory.java | 220 +++++++++++++ 3 files changed, 620 insertions(+) create mode 100644 tests/unit/src/com/android/settings/network/ims/MockVolteQueryImsState.java create mode 100644 tests/unit/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java create mode 100644 tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java diff --git a/tests/unit/src/com/android/settings/network/ims/MockVolteQueryImsState.java b/tests/unit/src/com/android/settings/network/ims/MockVolteQueryImsState.java new file mode 100644 index 00000000000..515ab5b659b --- /dev/null +++ b/tests/unit/src/com/android/settings/network/ims/MockVolteQueryImsState.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2020 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.network.ims; + +import android.content.Context; +import android.telephony.ims.ImsException; + +/** + * Controller class for mock VoLte status + */ +public class MockVolteQueryImsState extends VolteQueryImsState { + + private Boolean mIsTtyOnVolteEnabled; + private Boolean mIsSupported; + private Boolean mIsProvisionedOnDevice; + private Boolean mIsServiceStateReady; + private Boolean mIsEnabledByUser; + + /** + * Constructor + * + * @param context {@link Context} + * @param subId subscription's id + */ + public MockVolteQueryImsState(Context context, int subId) { + super(context, subId); + } + + public void setIsTtyOnVolteEnabled(boolean enabled) { + mIsTtyOnVolteEnabled = enabled; + } + + @Override + boolean isTtyOnVolteEnabled(int subId) { + if (mIsTtyOnVolteEnabled != null) { + return mIsTtyOnVolteEnabled; + } + return super.isTtyOnVolteEnabled(subId); + } + + public void setEnabledByPlatform(boolean isSupported) { + mIsSupported = isSupported; + } + + @Override + boolean isEnabledByPlatform(int subId) throws InterruptedException, ImsException, + IllegalArgumentException { + if (mIsSupported != null) { + return mIsSupported; + } + return super.isEnabledByPlatform(subId); + } + + public void setIsProvisionedOnDevice(boolean isProvisioned) { + mIsProvisionedOnDevice = isProvisioned; + } + + @Override + boolean isProvisionedOnDevice(int subId) { + if (mIsProvisionedOnDevice != null) { + return mIsProvisionedOnDevice; + } + return super.isProvisionedOnDevice(subId); + } + + public void setServiceStateReady(boolean isReady) { + mIsServiceStateReady = isReady; + } + + @Override + boolean isServiceStateReady(int subId) throws InterruptedException, ImsException, + IllegalArgumentException { + if (mIsServiceStateReady != null) { + return mIsServiceStateReady; + } + return super.isServiceStateReady(subId); + } + + public void setIsEnabledByUser(boolean enabled) { + mIsEnabledByUser = enabled; + } + + @Override + boolean isEnabledByUser(int subId) { + if (mIsEnabledByUser != null) { + return mIsEnabledByUser; + } + return super.isEnabledByUser(subId); + } + +} diff --git a/tests/unit/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java b/tests/unit/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java new file mode 100644 index 00000000000..95f1ee12eae --- /dev/null +++ b/tests/unit/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2020 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.network.telephony; + +import static android.app.slice.Slice.EXTRA_TOGGLE_STATE; +import static android.app.slice.Slice.HINT_TITLE; +import static android.app.slice.SliceItem.FORMAT_TEXT; + +import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.telephony.CarrierConfigManager; +import android.telephony.ims.ProvisioningManager; + +import androidx.slice.Slice; +import androidx.slice.SliceItem; +import androidx.slice.SliceMetadata; +import androidx.slice.SliceProvider; +import androidx.slice.core.SliceAction; +import androidx.slice.core.SliceQuery; +import androidx.slice.widget.SliceLiveData; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.settings.network.ims.MockVolteQueryImsState; +import com.android.settings.network.ims.VolteQueryImsState; +import com.android.settings.slices.CustomSliceRegistry; +import com.android.settings.slices.SettingsSliceProvider; +import com.android.settings.slices.SliceBroadcastReceiver; +import com.android.settings.slices.SlicesFeatureProvider; +import com.android.settings.testutils.FakeFeatureFactory; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.List; + +@RunWith(AndroidJUnit4.class) +public class Enhanced4gLteSliceHelperTest { + private static final int SUB_ID = 1; + + @Mock + private CarrierConfigManager mMockCarrierConfigManager; + + @Mock + private ProvisioningManager mProvisioningManager; + + private MockVolteQueryImsState mQueryImsState; + + private Context mContext; + private FakeEnhanced4gLteSliceHelper mEnhanced4gLteSliceHelper; + private SettingsSliceProvider mProvider; + private SliceBroadcastReceiver mReceiver; + private FakeFeatureFactory mFeatureFactory; + private SlicesFeatureProvider mSlicesFeatureProvider; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(ApplicationProvider.getApplicationContext()); + mFeatureFactory = FakeFeatureFactory.setupForTest(); + mSlicesFeatureProvider = mFeatureFactory.getSlicesFeatureProvider(); + + //setup for SettingsSliceProvider tests + mProvider = new SettingsSliceProvider(); + mProvider.attachInfo(mContext, null); + mProvider.onCreateSliceProvider(); + + + //setup for SliceBroadcastReceiver test + mReceiver = spy(new SliceBroadcastReceiver()); + + mQueryImsState = spy(new MockVolteQueryImsState(mContext, SUB_ID)); + mQueryImsState.setEnabledByPlatform(true); + mQueryImsState.setIsProvisionedOnDevice(true); + mQueryImsState.setIsTtyOnVolteEnabled(true); + mQueryImsState.setServiceStateReady(true); + mQueryImsState.setIsEnabledByUser(true); + + mEnhanced4gLteSliceHelper = spy(new FakeEnhanced4gLteSliceHelper(mContext)); + + // Set-up specs for SliceMetadata. + SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS); + } + + @Test + public void createEnhanced4gLteSlice_invalidSubId_nullSlice() { + mQueryImsState.setEnabledByPlatform(false); + mQueryImsState.setIsProvisionedOnDevice(false); + mQueryImsState.setIsEnabledByUser(false); + + final Slice slice = mEnhanced4gLteSliceHelper.createEnhanced4gLteSlice( + CustomSliceRegistry.ENHANCED_4G_SLICE_URI); + + assertThat(slice).isNull(); + } + + @Test + public void createEnhanced4gLteSlice_enhanced4gLteNotSupported_nullSlice() { + mQueryImsState.setEnabledByPlatform(false); + + final Slice slice = mEnhanced4gLteSliceHelper.createEnhanced4gLteSlice( + CustomSliceRegistry.ENHANCED_4G_SLICE_URI); + + assertThat(mEnhanced4gLteSliceHelper.getDefaultVoiceSubId()).isEqualTo(1); + assertThat(slice).isNull(); + } + + @Test + public void createEnhanced4gLteSlice_success() { + mQueryImsState.setEnabledByPlatform(true); + mQueryImsState.setIsProvisionedOnDevice(true); + when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null); + + final Slice slice = mEnhanced4gLteSliceHelper.createEnhanced4gLteSlice( + CustomSliceRegistry.ENHANCED_4G_SLICE_URI); + + assertThat(mEnhanced4gLteSliceHelper.getDefaultVoiceSubId()).isEqualTo(1); + testEnhanced4gLteSettingsToggleSlice(slice); + } + + @Test + public void sttingSliceProvider_enhanced4gLteHelper_getsRightSlice() { + mQueryImsState.setEnabledByPlatform(true); + mQueryImsState.setIsProvisionedOnDevice(true); + when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null); + when(mSlicesFeatureProvider.getNewEnhanced4gLteSliceHelper(mContext)) + .thenReturn(mEnhanced4gLteSliceHelper); + + final Slice slice = mProvider.onBindSlice(CustomSliceRegistry.ENHANCED_4G_SLICE_URI); + + assertThat(mEnhanced4gLteSliceHelper.getDefaultVoiceSubId()).isEqualTo(1); + testEnhanced4gLteSettingsToggleSlice(slice); + } + + @Test + @Ignore + public void sliceBroadcastReceiver_toggleOffEnhanced4gLte() { + mQueryImsState.setEnabledByPlatform(true); + mQueryImsState.setIsProvisionedOnDevice(true); + mQueryImsState.setIsEnabledByUser(false); + when(mSlicesFeatureProvider.getNewEnhanced4gLteSliceHelper(mContext)) + .thenReturn(mEnhanced4gLteSliceHelper); + + final ArgumentCaptor mEnhanced4gLteSettingCaptor = ArgumentCaptor.forClass( + Boolean.class); + + // turn on Enhanced4gLte setting + final Intent intent = new Intent(Enhanced4gLteSliceHelper.ACTION_ENHANCED_4G_LTE_CHANGED); + intent.putExtra(EXTRA_TOGGLE_STATE, true); + + // change the setting + mReceiver.onReceive(mContext, intent); + + verify(mEnhanced4gLteSliceHelper).setEnhanced4gLteModeSetting(anyInt(), + mEnhanced4gLteSettingCaptor.capture()); + + // assert the change + assertThat(mEnhanced4gLteSettingCaptor.getValue()).isTrue(); + } + + private void testEnhanced4gLteSettingsUnavailableSlice(Slice slice, + PendingIntent expectedPrimaryAction) { + final SliceMetadata metadata = SliceMetadata.from(mContext, slice); + + //Check there is no toggle action + final List toggles = metadata.getToggles(); + assertThat(toggles).isEmpty(); + + // Check whether the primary action is to open Enhanced4gLte settings activity + final PendingIntent primaryPendingIntent = + metadata.getPrimaryAction().getAction(); + assertThat(primaryPendingIntent).isEqualTo(expectedPrimaryAction); + + // Check the title + final List sliceItems = slice.getItems(); + assertTitle(sliceItems, resourceString("enhanced_4g_lte_mode_title")); + } + + private void testEnhanced4gLteSettingsToggleSlice(Slice slice) { + final SliceMetadata metadata = SliceMetadata.from(mContext, slice); + + final List toggles = metadata.getToggles(); + assertThat(toggles).hasSize(1); + + final SliceAction mainToggleAction = toggles.get(0); + + // Check intent in Toggle Action + final PendingIntent togglePendingIntent = mainToggleAction.getAction(); + final PendingIntent expectedToggleIntent = getBroadcastIntent( + Enhanced4gLteSliceHelper.ACTION_ENHANCED_4G_LTE_CHANGED); + assertThat(togglePendingIntent).isEqualTo(expectedToggleIntent); + + // Check primary intent + final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction(); + final PendingIntent expectedPendingIntent = + getActivityIntent(Enhanced4gLteSliceHelper.ACTION_MOBILE_NETWORK_SETTINGS_ACTIVITY); + assertThat(primaryPendingIntent).isEqualTo(expectedPendingIntent); + + // Check the title + final List sliceItems = slice.getItems(); + assertTitle(sliceItems, resourceString("enhanced_4g_lte_mode_title")); + } + + private PendingIntent getBroadcastIntent(String action) { + final Intent intent = new Intent(action); + intent.setClass(mContext, SliceBroadcastReceiver.class); + return PendingIntent.getBroadcast(mContext, 0 /* requestCode */, intent, + PendingIntent.FLAG_NO_CREATE); + } + + private PendingIntent getActivityIntent(String action) { + final Intent intent = new Intent(action); + intent.setPackage(SETTINGS_PACKAGE_NAME); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */); + } + + private void assertTitle(List sliceItems, String title) { + boolean hasTitle = false; + for (SliceItem item : sliceItems) { + final List titleItems = SliceQuery.findAll(item, FORMAT_TEXT, HINT_TITLE, + null /* non-hints */); + if (titleItems == null) { + continue; + } + + hasTitle = true; + for (SliceItem subTitleItem : titleItems) { + assertThat(subTitleItem.getText()).isEqualTo(title); + } + } + assertThat(hasTitle).isTrue(); + } + + public class FakeEnhanced4gLteSliceHelper extends Enhanced4gLteSliceHelper { + int mSubId = SUB_ID; + + FakeEnhanced4gLteSliceHelper(Context context) { + super(context); + } + + @Override + protected CarrierConfigManager getCarrierConfigManager() { + return mMockCarrierConfigManager; + } + + protected int getDefaultVoiceSubId() { + return mSubId; + } + + private void setDefaultVoiceSubId(int id) { + mSubId = id; + } + + @Override + protected VolteQueryImsState queryImsState(int subId) { + return mQueryImsState; + } + } + + public String resourceString(String name) { + final Resources res = mContext.getResources(); + return res.getString(res.getIdentifier(name, "string", mContext.getPackageName())); + } +} diff --git a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java new file mode 100644 index 00000000000..47851b9a737 --- /dev/null +++ b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2020 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.testutils; + +import static org.mockito.Mockito.mock; + +import android.content.Context; + +import com.android.settings.accounts.AccountFeatureProvider; +import com.android.settings.applications.ApplicationFeatureProvider; +import com.android.settings.aware.AwareFeatureProvider; +import com.android.settings.biometrics.face.FaceFeatureProvider; +import com.android.settings.bluetooth.BluetoothFeatureProvider; +import com.android.settings.dashboard.DashboardFeatureProvider; +import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider; +import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider; +import com.android.settings.fuelgauge.BatteryStatusFeatureProvider; +import com.android.settings.fuelgauge.PowerUsageFeatureProvider; +import com.android.settings.gestures.AssistGestureFeatureProvider; +import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider; +import com.android.settings.localepicker.LocaleFeatureProvider; +import com.android.settings.overlay.DockUpdaterFeatureProvider; +import com.android.settings.overlay.FeatureFactory; +import com.android.settings.overlay.SupportFeatureProvider; +import com.android.settings.overlay.SurveyFeatureProvider; +import com.android.settings.panel.PanelFeatureProvider; +import com.android.settings.search.SearchFeatureProvider; +import com.android.settings.security.SecurityFeatureProvider; +import com.android.settings.slices.SlicesFeatureProvider; +import com.android.settings.users.UserFeatureProvider; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; + +/** + * Test util to provide fake FeatureFactory. To use this factory, call {@code setupForTest} in + * {@code @Before} method of the test class. + */ +public class FakeFeatureFactory extends FeatureFactory { + public final SupportFeatureProvider supportFeatureProvider; + public final MetricsFeatureProvider metricsFeatureProvider; + public final BatteryStatusFeatureProvider batteryStatusFeatureProvider; + public final PowerUsageFeatureProvider powerUsageFeatureProvider; + public final DashboardFeatureProvider dashboardFeatureProvider; + public final DockUpdaterFeatureProvider dockUpdaterFeatureProvider; + public final LocaleFeatureProvider localeFeatureProvider; + public final ApplicationFeatureProvider applicationFeatureProvider; + public final EnterprisePrivacyFeatureProvider enterprisePrivacyFeatureProvider; + public final SurveyFeatureProvider surveyFeatureProvider; + public final SecurityFeatureProvider securityFeatureProvider; + public final SuggestionFeatureProvider suggestionsFeatureProvider; + public final UserFeatureProvider userFeatureProvider; + public final AssistGestureFeatureProvider assistGestureFeatureProvider; + public final AccountFeatureProvider mAccountFeatureProvider; + public final BluetoothFeatureProvider mBluetoothFeatureProvider; + public final AwareFeatureProvider mAwareFeatureProvider; + public final FaceFeatureProvider mFaceFeatureProvider; + + public PanelFeatureProvider panelFeatureProvider; + public SlicesFeatureProvider slicesFeatureProvider; + public SearchFeatureProvider searchFeatureProvider; + public ContextualCardFeatureProvider mContextualCardFeatureProvider; + + /** + * Call this in {@code @Before} method of the test class to use fake factory. + */ + public static FakeFeatureFactory setupForTest() { + sFactory = new FakeFeatureFactory(); + return (FakeFeatureFactory) sFactory; + } + + /** + * FeatureFactory constructor. + */ + public FakeFeatureFactory() { + supportFeatureProvider = mock(SupportFeatureProvider.class); + metricsFeatureProvider = mock(MetricsFeatureProvider.class); + batteryStatusFeatureProvider = mock(BatteryStatusFeatureProvider.class); + powerUsageFeatureProvider = mock(PowerUsageFeatureProvider.class); + dashboardFeatureProvider = mock(DashboardFeatureProvider.class); + dockUpdaterFeatureProvider = mock(DockUpdaterFeatureProvider.class); + localeFeatureProvider = mock(LocaleFeatureProvider.class); + applicationFeatureProvider = mock(ApplicationFeatureProvider.class); + enterprisePrivacyFeatureProvider = mock(EnterprisePrivacyFeatureProvider.class); + searchFeatureProvider = mock(SearchFeatureProvider.class); + surveyFeatureProvider = mock(SurveyFeatureProvider.class); + securityFeatureProvider = mock(SecurityFeatureProvider.class); + suggestionsFeatureProvider = mock(SuggestionFeatureProvider.class); + userFeatureProvider = mock(UserFeatureProvider.class); + assistGestureFeatureProvider = mock(AssistGestureFeatureProvider.class); + slicesFeatureProvider = mock(SlicesFeatureProvider.class); + mAccountFeatureProvider = mock(AccountFeatureProvider.class); + mContextualCardFeatureProvider = mock(ContextualCardFeatureProvider.class); + panelFeatureProvider = mock(PanelFeatureProvider.class); + mBluetoothFeatureProvider = mock(BluetoothFeatureProvider.class); + mAwareFeatureProvider = mock(AwareFeatureProvider.class); + mFaceFeatureProvider = mock(FaceFeatureProvider.class); + } + + @Override + public SuggestionFeatureProvider getSuggestionFeatureProvider(Context context) { + return suggestionsFeatureProvider; + } + + @Override + public SupportFeatureProvider getSupportFeatureProvider(Context context) { + return supportFeatureProvider; + } + + @Override + public MetricsFeatureProvider getMetricsFeatureProvider() { + return metricsFeatureProvider; + } + + @Override + public BatteryStatusFeatureProvider getBatteryStatusFeatureProvider(Context context) { + return batteryStatusFeatureProvider; + } + + @Override + public PowerUsageFeatureProvider getPowerUsageFeatureProvider(Context context) { + return powerUsageFeatureProvider; + } + + @Override + public DashboardFeatureProvider getDashboardFeatureProvider(Context context) { + return dashboardFeatureProvider; + } + + @Override + public DockUpdaterFeatureProvider getDockUpdaterFeatureProvider() { + return dockUpdaterFeatureProvider; + } + + @Override + public ApplicationFeatureProvider getApplicationFeatureProvider(Context context) { + return applicationFeatureProvider; + } + + @Override + public LocaleFeatureProvider getLocaleFeatureProvider() { + return localeFeatureProvider; + } + + @Override + public EnterprisePrivacyFeatureProvider getEnterprisePrivacyFeatureProvider(Context context) { + return enterprisePrivacyFeatureProvider; + } + + @Override + public SearchFeatureProvider getSearchFeatureProvider() { + return searchFeatureProvider; + } + + @Override + public SurveyFeatureProvider getSurveyFeatureProvider(Context context) { + return surveyFeatureProvider; + } + + @Override + public SecurityFeatureProvider getSecurityFeatureProvider() { + return securityFeatureProvider; + } + + @Override + public UserFeatureProvider getUserFeatureProvider(Context context) { + return userFeatureProvider; + } + + @Override + public AssistGestureFeatureProvider getAssistGestureFeatureProvider() { + return assistGestureFeatureProvider; + } + + @Override + public SlicesFeatureProvider getSlicesFeatureProvider() { + return slicesFeatureProvider; + } + + @Override + public AccountFeatureProvider getAccountFeatureProvider() { + return mAccountFeatureProvider; + } + + @Override + public PanelFeatureProvider getPanelFeatureProvider() { + return panelFeatureProvider; + } + + @Override + public ContextualCardFeatureProvider getContextualCardFeatureProvider(Context context) { + return mContextualCardFeatureProvider; + } + + @Override + public BluetoothFeatureProvider getBluetoothFeatureProvider(Context context) { + return mBluetoothFeatureProvider; + } + + @Override + public AwareFeatureProvider getAwareFeatureProvider() { + return mAwareFeatureProvider; + } + + @Override + public FaceFeatureProvider getFaceFeatureProvider() { + return mFaceFeatureProvider; + } +}