fix: 引入Settings的Module

This commit is contained in:
2024-12-10 14:57:24 +08:00
parent ad8fc8731d
commit df105485bd
6934 changed files with 896168 additions and 2 deletions

View File

@@ -0,0 +1,98 @@
/*
* 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.content.pm.PackageManager
import android.content.pm.ResolveInfo
import androidx.lifecycle.testing.TestLifecycleOwner
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceManager
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.argThat
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.stub
@RunWith(AndroidJUnit4::class)
class AppDataUsageAppSettingsControllerTest {
private val packageManager = mock<PackageManager>()
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
on { packageManager } doReturn packageManager
}
private val controller = AppDataUsageAppSettingsController(context, KEY)
private val preference = PreferenceCategory(context).apply { key = KEY }
private val preferenceScreen = PreferenceManager(context).createPreferenceScreen(context)
@Before
fun setUp() {
preferenceScreen.addPreference(preference)
}
@Test
fun onViewCreated_noSettingsActivity_hidePreference(): Unit = runBlocking {
controller.init(listOf(PACKAGE_NAME), USER_ID)
controller.displayPreference(preferenceScreen)
controller.onViewCreated(TestLifecycleOwner())
delay(100)
assertThat(preference.isVisible).isFalse()
}
@Test
fun onViewCreated_hasSettingsActivity_showPreference(): Unit = runBlocking {
packageManager.stub {
on {
resolveActivityAsUser(
argThat {
action == Intent.ACTION_MANAGE_NETWORK_USAGE && getPackage() == PACKAGE_NAME
},
eq(0),
eq(USER_ID),
)
} doReturn ResolveInfo()
}
controller.init(listOf(PACKAGE_NAME), USER_ID)
controller.displayPreference(preferenceScreen)
controller.onViewCreated(TestLifecycleOwner())
delay(100)
assertThat(preference.isVisible).isTrue()
}
private companion object {
const val KEY = "test_key"
const val PACKAGE_NAME = "package.name"
const val USER_ID = 0
}
}

View File

@@ -0,0 +1,107 @@
/*
* 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.util.Range
import androidx.lifecycle.testing.TestLifecycleOwner
import androidx.preference.PreferenceManager
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.datausage.lib.IAppDataUsageDetailsRepository
import com.android.settings.datausage.lib.NetworkUsageDetailsData
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.spy
import org.mockito.kotlin.verify
@RunWith(AndroidJUnit4::class)
class AppDataUsageCycleControllerTest {
private val context: Context = ApplicationProvider.getApplicationContext()
private val preference = spy(SpinnerPreference(context, null).apply { key = KEY })
private val preferenceScreen = PreferenceManager(context).createPreferenceScreen(context)
private val controller = AppDataUsageCycleController(context, KEY)
@Before
fun setUp() {
preferenceScreen.addPreference(preference)
}
@Test
fun onViewCreated_noUsage_hidePreference(): Unit = runBlocking {
val repository = object : IAppDataUsageDetailsRepository {
override suspend fun queryDetailsForCycles() = emptyList<NetworkUsageDetailsData>()
}
controller.displayPreference(preferenceScreen)
controller.init(repository) {}
controller.onViewCreated(TestLifecycleOwner())
delay(100)
assertThat(preference.isVisible).isFalse()
}
@Test
fun onViewCreated_hasUsage_showPreference(): Unit = runBlocking {
val detailsData = NetworkUsageDetailsData(
range = Range(1, 2),
totalUsage = 11,
foregroundUsage = 1,
backgroundUsage = 10,
)
val repository = object : IAppDataUsageDetailsRepository {
override suspend fun queryDetailsForCycles() = listOf(detailsData)
}
controller.displayPreference(preferenceScreen)
controller.init(repository) {}
controller.onViewCreated(TestLifecycleOwner())
delay(100)
assertThat(preference.isVisible).isTrue()
}
@Test
fun setInitialCycles() {
val repository = object : IAppDataUsageDetailsRepository {
override suspend fun queryDetailsForCycles() = emptyList<NetworkUsageDetailsData>()
}
controller.displayPreference(preferenceScreen)
controller.init(repository) {}
controller.setInitialCycles(
initialCycles = listOf(CYCLE2_END_TIME, CYCLE1_END_TIME, CYCLE1_START_TIME),
initialSelectedEndTime = CYCLE1_END_TIME,
)
verify(preference).setSelection(1)
}
private companion object {
const val KEY = "test_key"
const val CYCLE1_START_TIME = 1694444444000L
const val CYCLE1_END_TIME = 1695555555000L
const val CYCLE2_END_TIME = 1695566666000L
}
}

View File

@@ -0,0 +1,91 @@
/*
* 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 androidx.lifecycle.testing.TestLifecycleOwner
import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceManager
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.datausage.lib.AppPreferenceRepository
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.mock
@RunWith(AndroidJUnit4::class)
class AppDataUsageListControllerTest {
private val context: Context = ApplicationProvider.getApplicationContext()
private val repository = mock<AppPreferenceRepository> {
on { loadAppPreferences(any()) } doAnswer {
val uids = it.arguments[0] as List<*>
uids.map { Preference(context) }
}
}
private val controller = AppDataUsageListController(
context = context,
preferenceKey = KEY,
repository = repository,
)
private val preference = PreferenceCategory(context).apply { key = KEY }
private val preferenceScreen = PreferenceManager(context).createPreferenceScreen(context)
@Before
fun setUp() {
preferenceScreen.addPreference(preference)
}
@Test
fun onViewCreated_singleUid_hidePreference(): Unit = runBlocking {
controller.init(listOf(UID_0))
controller.displayPreference(preferenceScreen)
controller.onViewCreated(TestLifecycleOwner())
delay(100)
assertThat(preference.isVisible).isFalse()
}
@Test
fun onViewCreated_twoUid_showPreference(): Unit = runBlocking {
controller.init(listOf(UID_0, UID_1))
controller.displayPreference(preferenceScreen)
controller.onViewCreated(TestLifecycleOwner())
delay(100)
assertThat(preference.isVisible).isTrue()
assertThat(preference.preferenceCount).isEqualTo(2)
}
private companion object {
const val KEY = "test_key"
const val UID_0 = 10000
const val UID_1 = 10001
}
}

View File

@@ -0,0 +1,89 @@
/*
* 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.net.NetworkTemplate
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.R
import com.android.settings.datausage.lib.BillingCycleRepository
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.stub
@RunWith(AndroidJUnit4::class)
class BillingCyclePreferenceTest {
@get:Rule
val composeTestRule = createComposeRule()
private val mockBillingCycleRepository = mock<BillingCycleRepository>()
private val context: Context = ApplicationProvider.getApplicationContext()
private val preference = BillingCyclePreference(context, null, mockBillingCycleRepository)
@Test
fun setTemplate_titleDisplayed() {
setTemplate()
composeTestRule.onNodeWithText(context.getString(R.string.billing_cycle))
.assertIsDisplayed()
}
@Test
fun setTemplate_modifiable_enabled() {
mockBillingCycleRepository.stub {
on { isModifiable(SUB_ID) } doReturn true
}
setTemplate()
composeTestRule.onNodeWithText(context.getString(R.string.billing_cycle)).assertIsEnabled()
}
@Test
fun setTemplate_notModifiable_notEnabled() {
mockBillingCycleRepository.stub {
on { isModifiable(SUB_ID) } doReturn false
}
setTemplate()
composeTestRule.onNodeWithText(context.getString(R.string.billing_cycle))
.assertIsNotEnabled()
}
private fun setTemplate() {
preference.setTemplate(mock<NetworkTemplate>(), SUB_ID)
composeTestRule.setContent {
preference.Content()
}
}
private companion object {
const val SUB_ID = 1
}
}

View File

@@ -0,0 +1,67 @@
/*
* 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 androidx.lifecycle.testing.TestLifecycleOwner
import androidx.preference.PreferenceScreen
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.datausage.lib.NetworkCycleChartData
import com.android.settings.datausage.lib.NetworkUsageData
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
@RunWith(AndroidJUnit4::class)
class ChartDataUsagePreferenceControllerTest {
private val context: Context = ApplicationProvider.getApplicationContext()
private val preference = mock<ChartDataUsagePreference>()
private val preferenceScreen = mock<PreferenceScreen> {
onGeneric { findPreference(KEY) } doReturn preference
}
private val controller = ChartDataUsagePreferenceController(context, KEY)
@Before
fun setUp() {
controller.displayPreference(preferenceScreen)
controller.onViewCreated(TestLifecycleOwner())
}
@Test
fun update() {
controller.update(CycleChartDate)
verify(preference).setTime(START_TIME, END_TIME)
verify(preference).setNetworkCycleData(CycleChartDate)
}
private companion object {
const val KEY = "test_key"
const val START_TIME = 1L
const val END_TIME = 2L
val UsageData = NetworkUsageData(startTime = START_TIME, endTime = END_TIME, usage = 10)
val CycleChartDate =
NetworkCycleChartData(total = UsageData, dailyUsage = listOf(UsageData))
}
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright (C) 2024 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.net.NetworkPolicy
import android.telephony.SubscriptionPlan
import android.util.Range
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.datausage.lib.INetworkCycleDataRepository
import com.android.settings.datausage.lib.NetworkUsageData
import com.android.settings.testutils.zonedDateTime
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
@RunWith(AndroidJUnit4::class)
class DataPlanRepositoryTest {
private object FakeNetworkCycleDataRepository : INetworkCycleDataRepository {
override fun getCycles(): List<Range<Long>> = emptyList()
override fun getPolicy() = null
override fun queryUsage(range: Range<Long>) = NetworkUsageData(
startTime = CYCLE_CYCLE_START_TIME,
endTime = CYCLE_CYCLE_END_TIME,
usage = CYCLE_BYTES,
)
}
private val repository = DataPlanRepositoryImpl(FakeNetworkCycleDataRepository)
private val policy = mock<NetworkPolicy> {
on { cycleIterator() } doReturn listOf(
Range(zonedDateTime(CYCLE_CYCLE_START_TIME), zonedDateTime(CYCLE_CYCLE_END_TIME)),
).iterator()
}
@Test
fun getDataPlanInfo_hasSubscriptionPlan() {
val dataPlanInfo = repository.getDataPlanInfo(policy, listOf(SUBSCRIPTION_PLAN))
assertThat(dataPlanInfo).isEqualTo(
DataPlanInfo(
dataPlanCount = 1,
dataPlanSize = DATA_LIMIT_BYTES,
dataBarSize = DATA_LIMIT_BYTES,
dataPlanUse = DATA_USAGE_BYTES,
cycleEnd = PLAN_CYCLE_END_TIME,
snapshotTime = DATA_USAGE_TIME,
)
)
}
@Test
fun getDataPlanInfo_noSubscriptionPlan() {
val dataPlanInfo = repository.getDataPlanInfo(policy, emptyList())
assertThat(dataPlanInfo).isEqualTo(
DataPlanInfo(
dataPlanCount = 0,
dataPlanSize = SubscriptionPlan.BYTES_UNKNOWN,
dataBarSize = CYCLE_BYTES,
dataPlanUse = CYCLE_BYTES,
cycleEnd = CYCLE_CYCLE_END_TIME,
snapshotTime = SubscriptionPlan.TIME_UNKNOWN,
)
)
}
private companion object {
const val CYCLE_CYCLE_START_TIME = 1L
const val CYCLE_CYCLE_END_TIME = 2L
const val CYCLE_BYTES = 11L
const val PLAN_CYCLE_START_TIME = 100L
const val PLAN_CYCLE_END_TIME = 200L
const val DATA_LIMIT_BYTES = 300L
const val DATA_USAGE_BYTES = 400L
const val DATA_USAGE_TIME = 500L
val SUBSCRIPTION_PLAN: SubscriptionPlan = SubscriptionPlan.Builder.createNonrecurring(
zonedDateTime(PLAN_CYCLE_START_TIME),
zonedDateTime(PLAN_CYCLE_END_TIME),
).apply {
setDataLimit(DATA_LIMIT_BYTES, SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
setDataUsage(DATA_USAGE_BYTES, DATA_USAGE_TIME)
}.build()
}
}

View File

@@ -0,0 +1,50 @@
/*
* 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 androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.datausage.DataUsageFormatter.getBytesDisplayUnit
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class DataUsageFormatterTest {
private val context: Context = ApplicationProvider.getApplicationContext()
@Test
fun getUnitDisplayName_megaByte() {
val displayName = context.resources.getBytesDisplayUnit(ONE_MEGA_BYTE_IN_BYTES)
assertThat(displayName).isEqualTo("MB")
}
@Test
fun getUnitDisplayName_gigaByte() {
val displayName = context.resources.getBytesDisplayUnit(ONE_GIGA_BYTE_IN_BYTES)
assertThat(displayName).isEqualTo("GB")
}
private companion object {
const val ONE_MEGA_BYTE_IN_BYTES = 1024L * 1024
const val ONE_GIGA_BYTE_IN_BYTES = 1024L * 1024 * 1024
}
}

View File

@@ -0,0 +1,73 @@
/*
* 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 androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.SettingsActivity
import com.android.settings.datausage.lib.NetworkUsageData
import com.android.settingslib.AppItem
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.doNothing
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class DataUsageListAppsControllerTest {
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
doNothing().whenever(mock).startActivity(any())
}
private val controller = DataUsageListAppsController(context, "test_key")
@Before
fun setUp() {
controller.init(mock<NetworkTemplate>())
val data = NetworkUsageData(START_TIME, END_TIME, 0)
controller.updateCycles(listOf(data))
}
@Test
fun startAppDataUsage_shouldAddCyclesInfoToLaunchArguments() {
controller.startAppDataUsage(AppItem(), END_TIME)
val intent = argumentCaptor<Intent> {
verify(context).startActivity(capture())
}.firstValue
val arguments = intent.getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)!!
assertThat(arguments.getLong(AppDataUsage.ARG_SELECTED_CYCLE)).isEqualTo(END_TIME)
assertThat(
arguments.getSerializable(AppDataUsage.ARG_NETWORK_CYCLES, ArrayList::class.java)
).containsExactly(END_TIME, START_TIME).inOrder()
}
private companion object {
const val START_TIME = 1521583200000L
const val END_TIME = 1521676800000L
}
}

View File

@@ -0,0 +1,92 @@
/*
* 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.net.NetworkTemplate
import android.view.LayoutInflater
import android.view.View
import android.widget.Spinner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.testing.TestLifecycleOwner
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.R
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.runBlocking
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.doNothing
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class DataUsageListHeaderControllerTest {
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
doNothing().whenever(mock).startActivity(any())
}
private val header =
LayoutInflater.from(context).inflate(R.layout.apps_filter_spinner, null, false)
private val configureButton: View = header.requireViewById(R.id.filter_settings)
private val spinner: Spinner = header.requireViewById(R.id.filter_spinner)
private val testLifecycleOwner = TestLifecycleOwner(initialState = Lifecycle.State.CREATED)
private val controller = DataUsageListHeaderController(
header = header,
template = mock<NetworkTemplate>(),
sourceMetricsCategory = 0,
viewLifecycleOwner = testLifecycleOwner,
cyclesFlow = flowOf(emptyList()),
updateSelectedCycle = {},
)
@Test
fun onViewCreated_shouldHideCycleSpinner() {
assertThat(spinner.visibility).isEqualTo(View.GONE)
}
@Test
fun updateCycleData_shouldShowCycleSpinner() = runBlocking {
testLifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_START)
delay(100)
assertThat(spinner.visibility).isEqualTo(View.VISIBLE)
}
@Test
fun setConfigButtonVisible_setToTrue_shouldShowConfigureButton() {
controller.setConfigButtonVisible(true)
assertThat(configureButton.visibility).isEqualTo(View.VISIBLE)
}
@Test
fun setConfigButtonVisible_setToFalse_shouldHideConfigureButton() {
controller.setConfigButtonVisible(false)
assertThat(configureButton.visibility).isEqualTo(View.GONE)
}
}

View File

@@ -0,0 +1,131 @@
/*
* 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.UserManager
import android.provider.Settings
import android.telephony.SubscriptionManager
import androidx.core.os.bundleOf
import androidx.fragment.app.testing.launchFragment
import androidx.fragment.app.testing.withFragment
import androidx.lifecycle.Lifecycle
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spaprivileged.framework.common.userManager
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.stub
private val mockUserManager: UserManager = mock<UserManager>()
private val mockContext: Context = spy(ApplicationProvider.getApplicationContext()) {
on { userManager } doReturn mockUserManager
}
private var fakeIntent = Intent()
@RunWith(AndroidJUnit4::class)
class DataUsageListTest {
@Before
fun setUp() {
mockUserManager.stub {
on { isGuestUser } doReturn false
}
fakeIntent = Intent()
}
@Test
fun launchFragment_withoutArguments_finish() {
val scenario = launchFragment<TestDataUsageList>(initialState = Lifecycle.State.CREATED)
scenario.withFragment {
assertThat(template).isNull()
assertThat(subId).isEqualTo(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
assertThat(activity!!.isFinishing).isTrue()
}
}
@Test
fun launchFragment_isGuestUser_finish() {
mockUserManager.stub {
on { isGuestUser } doReturn true
}
val fragmentArgs = bundleOf(
DataUsageList.EXTRA_NETWORK_TEMPLATE to mock<NetworkTemplate>(),
DataUsageList.EXTRA_SUB_ID to 3,
)
val scenario = launchFragment<TestDataUsageList>(
fragmentArgs = fragmentArgs,
initialState = Lifecycle.State.CREATED,
)
scenario.withFragment {
assertThat(activity!!.isFinishing).isTrue()
}
}
@Test
fun launchFragment_withArguments_getTemplateFromArgument() {
val fragmentArgs = bundleOf(
DataUsageList.EXTRA_NETWORK_TEMPLATE to mock<NetworkTemplate>(),
DataUsageList.EXTRA_SUB_ID to 3,
)
val scenario = launchFragment<TestDataUsageList>(
fragmentArgs = fragmentArgs,
initialState = Lifecycle.State.CREATED,
)
scenario.withFragment {
assertThat(template).isNotNull()
assertThat(subId).isEqualTo(3)
assertThat(activity!!.isFinishing).isFalse()
}
}
@Test
fun launchFragment_withIntent_getTemplateFromIntent() {
fakeIntent = Intent().apply {
putExtra(Settings.EXTRA_NETWORK_TEMPLATE, mock<NetworkTemplate>())
putExtra(Settings.EXTRA_SUB_ID, 2)
}
val scenario = launchFragment<TestDataUsageList>(initialState = Lifecycle.State.CREATED)
scenario.withFragment {
assertThat(template).isNotNull()
assertThat(subId).isEqualTo(2)
assertThat(activity!!.isFinishing).isFalse()
}
}
}
class TestDataUsageList : DataUsageList() {
override fun getContext() = mockContext
override fun getIntent() = fakeIntent
}

View File

@@ -0,0 +1,274 @@
/*
* Copyright (C) 2024 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.net.NetworkPolicy
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager
import android.telephony.SubscriptionPlan
import android.telephony.TelephonyManager
import android.util.Range
import androidx.lifecycle.testing.TestLifecycleOwner
import androidx.preference.PreferenceManager
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.core.BasePreferenceController.AVAILABLE
import com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE
import com.android.settings.datausage.lib.INetworkCycleDataRepository
import com.android.settings.datausage.lib.NetworkUsageData
import com.android.settings.network.ProxySubscriptionManager
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.clearInvocations
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.spy
import org.mockito.kotlin.stub
import org.mockito.kotlin.verify
@RunWith(AndroidJUnit4::class)
class DataUsageSummaryPreferenceControllerTest {
private var policy: NetworkPolicy? = mock<NetworkPolicy>()
private val mockTelephonyManager = mock<TelephonyManager> {
on { isDataCapable } doReturn true
}
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
}
private val mockSubscriptionManager = mock<SubscriptionManager> {
on { getSubscriptionPlans(any()) } doReturn emptyList()
}
private val mockProxySubscriptionManager = mock<ProxySubscriptionManager> {
on { get() } doReturn mockSubscriptionManager
}
private val fakeNetworkCycleDataRepository = object : INetworkCycleDataRepository {
override fun getCycles(): List<Range<Long>> = emptyList()
override fun getPolicy() = policy
override fun queryUsage(range: Range<Long>) = NetworkUsageData.AllZero
}
private var dataPlanInfo = EMPTY_DATA_PLAN_INFO
private val fakeDataPlanRepository = object : DataPlanRepository {
override fun getDataPlanInfo(policy: NetworkPolicy, plans: List<SubscriptionPlan>) =
dataPlanInfo
}
private val controller = DataUsageSummaryPreferenceController(
context = context,
subId = SUB_ID,
proxySubscriptionManager = mockProxySubscriptionManager,
networkCycleDataRepositoryFactory = { fakeNetworkCycleDataRepository },
dataPlanRepositoryFactory = { fakeDataPlanRepository },
)
private val preference = mock<DataUsageSummaryPreference> {
on { key } doReturn controller.preferenceKey
}
private val preferenceScreen = PreferenceManager(context).createPreferenceScreen(context)
@Before
fun setUp() {
preferenceScreen.addPreference(preference)
}
@Test
fun getAvailabilityStatus_noMobileData_conditionallyUnavailable() {
mockTelephonyManager.stub {
on { isDataCapable } doReturn false
}
val availabilityStatus = controller.getAvailabilityStatus(SUB_ID)
assertThat(availabilityStatus).isEqualTo(CONDITIONALLY_UNAVAILABLE)
}
@Test
fun getAvailabilityStatus_hasSubInfoAndPolicy_available() {
mockProxySubscriptionManager.stub {
on { getAccessibleSubscriptionInfo(SUB_ID) } doReturn SubscriptionInfo.Builder().build()
}
val availabilityStatus = controller.getAvailabilityStatus(SUB_ID)
assertThat(availabilityStatus).isEqualTo(AVAILABLE)
}
@Test
fun getAvailabilityStatus_noSubInfo_conditionallyUnavailable() {
mockProxySubscriptionManager.stub {
on { getAccessibleSubscriptionInfo(SUB_ID) } doReturn null
}
val availabilityStatus = controller.getAvailabilityStatus(SUB_ID)
assertThat(availabilityStatus).isEqualTo(CONDITIONALLY_UNAVAILABLE)
}
@Test
fun getAvailabilityStatus_noPolicy_conditionallyUnavailable() {
policy = null
val availabilityStatus = controller.getAvailabilityStatus(SUB_ID)
assertThat(availabilityStatus).isEqualTo(CONDITIONALLY_UNAVAILABLE)
}
@Test
fun displayPreference_policyHasNoLimitInfo() {
policy = mock<NetworkPolicy>().apply {
warningBytes = NetworkPolicy.WARNING_DISABLED
limitBytes = NetworkPolicy.LIMIT_DISABLED
}
controller.displayPreference(preferenceScreen)
verify(preference).setLimitInfo(null)
verify(preference, never()).setLabels(any(), any())
}
@Test
fun displayPreference_policyWarningOnly() {
policy = mock<NetworkPolicy>().apply {
warningBytes = 1L
limitBytes = NetworkPolicy.LIMIT_DISABLED
}
controller.displayPreference(preferenceScreen)
val limitInfo = argumentCaptor {
verify(preference).setLimitInfo(capture())
}.firstValue.toString()
assertThat(limitInfo).isEqualTo("1 B data warning")
verify(preference).setLabels("0 B", "1 B")
}
@Test
fun displayPreference_policyLimitOnly() {
policy = mock<NetworkPolicy>().apply {
warningBytes = NetworkPolicy.WARNING_DISABLED
limitBytes = 1L
}
controller.displayPreference(preferenceScreen)
val limitInfo = argumentCaptor {
verify(preference).setLimitInfo(capture())
}.firstValue.toString()
assertThat(limitInfo).isEqualTo("1 B data limit")
verify(preference).setLabels("0 B", "1 B")
}
@Test
fun displayPreference_policyHasWarningAndLimit() {
policy = mock<NetworkPolicy>().apply {
warningBytes = BillingCycleSettings.GIB_IN_BYTES / 2
limitBytes = BillingCycleSettings.GIB_IN_BYTES
}
controller.displayPreference(preferenceScreen)
val limitInfo = argumentCaptor {
verify(preference).setLimitInfo(capture())
}.firstValue.toString()
assertThat(limitInfo).isEqualTo("512 MB data warning / 1.00 GB data limit")
verify(preference).setLabels("0 B", "1.00 GB")
}
@Test
fun onViewCreated_emptyDataPlanInfo() = runBlocking {
dataPlanInfo = EMPTY_DATA_PLAN_INFO
controller.displayPreference(preferenceScreen)
clearInvocations(preference)
controller.onViewCreated(TestLifecycleOwner())
delay(100)
verify(preference).setUsageNumbers(
EMPTY_DATA_PLAN_INFO.dataPlanUse,
EMPTY_DATA_PLAN_INFO.dataPlanSize,
)
verify(preference).setChartEnabled(false)
verify(preference).setUsageInfo(
EMPTY_DATA_PLAN_INFO.cycleEnd,
EMPTY_DATA_PLAN_INFO.snapshotTime,
null,
EMPTY_DATA_PLAN_INFO.dataPlanCount,
)
}
@Test
fun onViewCreated_positiveDataPlanInfo() = runBlocking {
dataPlanInfo = POSITIVE_DATA_PLAN_INFO
controller.displayPreference(preferenceScreen)
clearInvocations(preference)
controller.onViewCreated(TestLifecycleOwner())
delay(100)
verify(preference).setUsageNumbers(
POSITIVE_DATA_PLAN_INFO.dataPlanUse,
POSITIVE_DATA_PLAN_INFO.dataPlanSize,
)
verify(preference).setChartEnabled(true)
verify(preference).setLabels("0 B", "9 B")
val progress = argumentCaptor {
verify(preference).setProgress(capture())
}.firstValue
assertThat(progress).isEqualTo(0.8888889f)
verify(preference).setUsageInfo(
POSITIVE_DATA_PLAN_INFO.cycleEnd,
POSITIVE_DATA_PLAN_INFO.snapshotTime,
null,
POSITIVE_DATA_PLAN_INFO.dataPlanCount,
)
}
private companion object {
const val SUB_ID = 1234
val EMPTY_DATA_PLAN_INFO = DataPlanInfo(
dataPlanCount = 0,
dataPlanSize = SubscriptionPlan.BYTES_UNKNOWN,
dataBarSize = SubscriptionPlan.BYTES_UNKNOWN,
dataPlanUse = 0,
cycleEnd = null,
snapshotTime = SubscriptionPlan.TIME_UNKNOWN,
)
val POSITIVE_DATA_PLAN_INFO = DataPlanInfo(
dataPlanCount = 0,
dataPlanSize = 10L,
dataBarSize = 9L,
dataPlanUse = 8L,
cycleEnd = 7L,
snapshotTime = 6L,
)
}
}

View File

@@ -0,0 +1,137 @@
/*
* 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.lib
import android.app.usage.NetworkStats
import android.content.Context
import android.net.NetworkTemplate
import android.util.Range
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.runBlocking
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.stub
import com.android.settings.datausage.lib.NetworkStatsRepository.Companion.Bucket
@RunWith(AndroidJUnit4::class)
class AppDataUsageDetailsRepositoryTest {
private val context: Context = ApplicationProvider.getApplicationContext()
private val template = mock<NetworkTemplate>()
private val networkCycleDataRepository = mock<INetworkCycleDataRepository> {
on { getCycles() } doReturn listOf(Range(CYCLE1_END_TIME, CYCLE2_END_TIME))
}
private val networkStatsRepository = mock<NetworkStatsRepository>()
@Test
fun queryDetailsForCycles_hasCycles(): Unit = runBlocking {
networkStatsRepository.stub {
on { queryBuckets(CYCLE1_START_TIME, CYCLE1_END_TIME) } doReturn listOf(
Bucket(
uid = UID,
bytes = BACKGROUND_USAGE,
state = NetworkStats.Bucket.STATE_DEFAULT,
startTimeStamp = 0L,
endTimeStamp = 0L,
),
Bucket(
uid = UID,
bytes = FOREGROUND_USAGE,
state = NetworkStats.Bucket.STATE_FOREGROUND,
startTimeStamp = 0L,
endTimeStamp = 0L,
),
)
}
val repository = AppDataUsageDetailsRepository(
context = context,
cycles = listOf(CYCLE1_END_TIME, CYCLE1_START_TIME),
template = template,
uids = listOf(UID),
networkCycleDataRepository = networkCycleDataRepository,
networkStatsRepository = networkStatsRepository,
)
val detailsForCycles = repository.queryDetailsForCycles()
assertThat(detailsForCycles).containsExactly(
NetworkUsageDetailsData(
range = Range(CYCLE1_START_TIME, CYCLE1_END_TIME),
totalUsage = BACKGROUND_USAGE + FOREGROUND_USAGE,
foregroundUsage = FOREGROUND_USAGE,
backgroundUsage = BACKGROUND_USAGE,
)
)
}
@Test
fun queryDetailsForCycles_defaultCycles(): Unit = runBlocking {
networkStatsRepository.stub {
on { queryBuckets(CYCLE1_END_TIME, CYCLE2_END_TIME) } doReturn listOf(
Bucket(
uid = UID,
bytes = BACKGROUND_USAGE,
state = NetworkStats.Bucket.STATE_DEFAULT,
startTimeStamp = 0L,
endTimeStamp = 0L,
),
Bucket(
uid = UID,
bytes = FOREGROUND_USAGE,
state = NetworkStats.Bucket.STATE_FOREGROUND,
startTimeStamp = 0L,
endTimeStamp = 0L,
),
)
}
val repository = AppDataUsageDetailsRepository(
context = context,
cycles = null,
template = template,
uids = listOf(UID),
networkCycleDataRepository = networkCycleDataRepository,
networkStatsRepository = networkStatsRepository,
)
val detailsForCycles = repository.queryDetailsForCycles()
assertThat(detailsForCycles).containsExactly(
NetworkUsageDetailsData(
range = Range(CYCLE1_END_TIME, CYCLE2_END_TIME),
totalUsage = BACKGROUND_USAGE + FOREGROUND_USAGE,
foregroundUsage = FOREGROUND_USAGE,
backgroundUsage = BACKGROUND_USAGE,
)
)
}
private companion object {
const val CYCLE1_START_TIME = 1694444444000L
const val CYCLE1_END_TIME = 1695555555000L
const val CYCLE2_END_TIME = 1695566666000L
const val UID = 10000
const val BACKGROUND_USAGE = 8L
const val FOREGROUND_USAGE = 2L
}
}

View File

@@ -0,0 +1,134 @@
/*
* 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.lib
import android.content.Context
import android.content.pm.UserInfo
import android.content.res.Resources
import android.net.NetworkPolicyManager
import android.net.NetworkTemplate
import android.os.UserHandle
import android.os.UserManager
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.R
import com.android.settings.datausage.lib.NetworkStatsRepository.Companion.Bucket
import com.android.settingslib.AppItem
import com.android.settingslib.spaprivileged.framework.common.userManager
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
@RunWith(AndroidJUnit4::class)
class AppDataUsageRepositoryTest {
@get:Rule
val mockito: MockitoRule = MockitoJUnit.rule()
private val mockUserManager = mock<UserManager> {
on { userProfiles } doReturn listOf(UserHandle.of(USER_ID))
on { getUserInfo(USER_ID) } doReturn UserInfo(USER_ID, "", 0)
}
private val mockNetworkPolicyManager = mock<NetworkPolicyManager> {
on { getUidsWithPolicy(NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND) } doReturn
intArrayOf()
}
private val mockResources = mock<Resources> {
on { getIntArray(R.array.datausage_hiding_carrier_service_carrier_id) } doReturn
intArrayOf(HIDING_CARRIER_ID)
on { getStringArray(R.array.datausage_hiding_carrier_service_package_names) } doReturn
arrayOf(HIDING_PACKAGE_NAME)
}
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
on { userManager } doReturn mockUserManager
on { getSystemService(NetworkPolicyManager::class.java) } doReturn mockNetworkPolicyManager
on { resources } doReturn mockResources
}
@Test
fun getAppPercent_noAppToHide() {
val repository = AppDataUsageRepository(
context = context,
currentUserId = USER_ID,
template = Template,
getPackageName = { null },
)
val buckets = listOf(
Bucket(uid = APP_ID_1, bytes = 1, startTimeStamp = 0, endTimeStamp = 0),
Bucket(uid = APP_ID_2, bytes = 2, startTimeStamp = 0, endTimeStamp = 0),
)
val appPercentList = repository.getAppPercent(null, buckets)
assertThat(appPercentList).hasSize(2)
appPercentList[0].first.apply {
assertThat(key).isEqualTo(APP_ID_2)
assertThat(category).isEqualTo(AppItem.CATEGORY_APP)
assertThat(total).isEqualTo(2)
}
assertThat(appPercentList[0].second).isEqualTo(100)
appPercentList[1].first.apply {
assertThat(key).isEqualTo(APP_ID_1)
assertThat(category).isEqualTo(AppItem.CATEGORY_APP)
assertThat(total).isEqualTo(1)
}
assertThat(appPercentList[1].second).isEqualTo(50)
}
@Test
fun getAppPercent_hasAppToHide() {
val repository = AppDataUsageRepository(
context = context,
currentUserId = USER_ID,
template = Template,
getPackageName = { if (it.key == APP_ID_1) HIDING_PACKAGE_NAME else null },
)
val buckets = listOf(
Bucket(uid = APP_ID_1, bytes = 1, startTimeStamp = 0, endTimeStamp = 0),
Bucket(uid = APP_ID_2, bytes = 2, startTimeStamp = 0, endTimeStamp = 0),
)
val appPercentList = repository.getAppPercent(HIDING_CARRIER_ID, buckets)
assertThat(appPercentList).hasSize(1)
appPercentList[0].first.apply {
assertThat(key).isEqualTo(APP_ID_2)
assertThat(category).isEqualTo(AppItem.CATEGORY_APP)
assertThat(total).isEqualTo(2)
}
assertThat(appPercentList[0].second).isEqualTo(100)
}
private companion object {
const val USER_ID = 1
const val APP_ID_1 = 110001
const val APP_ID_2 = 110002
const val HIDING_CARRIER_ID = 4
const val HIDING_PACKAGE_NAME = "hiding.package.name"
val Template: NetworkTemplate = mock<NetworkTemplate>()
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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.lib
import android.content.Context
import android.net.NetworkTemplate
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.runBlocking
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
@RunWith(AndroidJUnit4::class)
class AppDataUsageSummaryRepositoryTest {
private val context: Context = ApplicationProvider.getApplicationContext()
private val template = mock<NetworkTemplate>()
private val networkStatsRepository = mock<NetworkStatsRepository> {
on {
queryAggregateForUid(range = NetworkStatsRepository.AllTimeRange, uid = APP_UID)
} doReturn NetworkUsageData(APP_START_TIME, APP_END_TIME, APP_USAGE)
on {
queryAggregateForUid(range = NetworkStatsRepository.AllTimeRange, uid = SDK_SANDBOX_UID)
} doReturn NetworkUsageData(SDK_SANDBOX_START_TIME, SDK_SANDBOX_END_TIME, SDK_SANDBOX_USAGE)
}
private val repository =
AppDataUsageSummaryRepository(context, template, networkStatsRepository)
@Test
fun querySummary(): Unit = runBlocking {
val networkUsageData = repository.querySummary(APP_UID)
assertThat(networkUsageData).isEqualTo(
NetworkUsageData(
startTime = APP_START_TIME,
endTime = SDK_SANDBOX_END_TIME,
usage = APP_USAGE + SDK_SANDBOX_USAGE,
)
)
}
private companion object {
const val APP_UID = 10000
const val APP_START_TIME = 10L
const val APP_END_TIME = 30L
const val APP_USAGE = 3L
const val SDK_SANDBOX_UID = 20000
const val SDK_SANDBOX_START_TIME = 20L
const val SDK_SANDBOX_END_TIME = 40L
const val SDK_SANDBOX_USAGE = 5L
}
}

View File

@@ -0,0 +1,94 @@
/*
* 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.lib
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import android.os.UserHandle
import android.util.IconDrawableFactory
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.doThrow
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.stub
@RunWith(AndroidJUnit4::class)
class AppPreferenceRepositoryTest {
private val packageManager = mock<PackageManager> {
on { getPackagesForUid(UID) } doReturn arrayOf(PACKAGE_NAME)
}
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
on { packageManager } doReturn packageManager
}
private val mockIconDrawableFactory = mock<IconDrawableFactory>()
private val repository = AppPreferenceRepository(context, mockIconDrawableFactory)
@Test
fun loadAppPreferences_packageNotFound_returnEmpty() {
packageManager.stub {
on {
getApplicationInfoAsUser(PACKAGE_NAME, 0, UserHandle.getUserId(UID))
} doThrow PackageManager.NameNotFoundException()
}
val preferences = repository.loadAppPreferences(listOf(UID))
assertThat(preferences).isEmpty()
}
@Test
fun loadAppPreferences_packageFound_returnPreference() {
val app = mock<ApplicationInfo> {
on { loadLabel(any()) } doReturn LABEL
}
mockIconDrawableFactory.stub {
on { getBadgedIcon(app) } doReturn UNBADGED_ICON
}
packageManager.stub {
on {
getApplicationInfoAsUser(PACKAGE_NAME, 0, UserHandle.getUserId(UID))
} doReturn app
}
val preferences = repository.loadAppPreferences(listOf(UID))
assertThat(preferences).hasSize(1)
preferences[0].apply {
assertThat(title).isEqualTo(LABEL)
assertThat(icon).isNotNull()
assertThat(isSelectable).isFalse()
}
}
private companion object {
const val UID = 10000
const val PACKAGE_NAME = "package.name"
const val LABEL = "Label"
val UNBADGED_ICON = mock<Drawable>()
}
}

View File

@@ -0,0 +1,120 @@
/*
* 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.lib
import android.content.Context
import android.os.INetworkManagementService
import android.os.UserManager
import android.telephony.TelephonyManager
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spaprivileged.framework.common.userManager
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class BillingCycleRepositoryTest {
private val mockNetworkManagementService = mock<INetworkManagementService> {
on { isBandwidthControlEnabled } doReturn true
}
private val mockUserManager = mock<UserManager> {
on { isAdminUser } doReturn true
}
private val mockTelephonyManager = mock<TelephonyManager> {
on { createForSubscriptionId(SUB_ID) } doReturn mock
on { isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER) } doReturn false
}
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
on { userManager } doReturn mockUserManager
on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
}
private val repository = BillingCycleRepository(context, mockNetworkManagementService)
@Test
fun isModifiable_bandwidthControlDisabled_returnFalse() {
whenever(mockNetworkManagementService.isBandwidthControlEnabled).thenReturn(false)
val modifiable = repository.isModifiable(SUB_ID)
assertThat(modifiable).isFalse()
}
@Test
fun isModifiable_notAdminUser_returnFalse() {
whenever(mockUserManager.isAdminUser).thenReturn(false)
val modifiable = repository.isModifiable(SUB_ID)
assertThat(modifiable).isFalse()
}
@Test
fun isModifiable_dataDisabled_returnFalse() {
whenever(
mockTelephonyManager.isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER)
).thenReturn(false)
val modifiable = repository.isModifiable(SUB_ID)
assertThat(modifiable).isFalse()
}
@Test
fun isModifiable_meetAllRequirements_returnTrue() {
whenever(mockNetworkManagementService.isBandwidthControlEnabled).thenReturn(true)
whenever(mockUserManager.isAdminUser).thenReturn(true)
whenever(
mockTelephonyManager.isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER)
).thenReturn(true)
val modifiable = repository.isModifiable(SUB_ID)
assertThat(modifiable).isTrue()
}
@Test
fun isBandwidthControlEnabled_bandwidthControlDisabled_returnFalse() {
whenever(mockNetworkManagementService.isBandwidthControlEnabled).thenReturn(false)
val enabled = repository.isBandwidthControlEnabled()
assertThat(enabled).isFalse()
}
@Test
fun isBandwidthControlEnabled_bandwidthControlEnabled_returnTrue() {
whenever(mockNetworkManagementService.isBandwidthControlEnabled).thenReturn(true)
val enabled = repository.isBandwidthControlEnabled()
assertThat(enabled).isTrue()
}
private companion object {
const val SUB_ID = 1
}
}

View File

@@ -0,0 +1,158 @@
/*
* 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.lib
import android.content.Context
import android.net.NetworkStats
import android.net.NetworkTemplate
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
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.Mock
import org.mockito.Spy
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class DataUsageLibTest {
@get:Rule
val mockito: MockitoRule = MockitoJUnit.rule()
@Spy
private val context: Context = ApplicationProvider.getApplicationContext()
@Mock
private lateinit var telephonyManager: TelephonyManager
@Mock
private lateinit var subscriptionManager: SubscriptionManager
@Before
fun setUp() {
whenever(context.getSystemService(TelephonyManager::class.java))
.thenReturn(telephonyManager)
whenever(context.getSystemService(SubscriptionManager::class.java))
.thenReturn(subscriptionManager)
whenever(telephonyManager.subscriptionId).thenReturn(DEFAULT_SUB_ID)
whenever(telephonyManager.getSubscriberId(SUB_ID)).thenReturn(SUBSCRIBER_ID)
whenever(telephonyManager.getSubscriberId(DEFAULT_SUB_ID)).thenReturn(DEFAULT_SUBSCRIBER_ID)
whenever(telephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(telephonyManager)
}
@Test
fun getMobileTemplate_availableSubscriptionInfoListIsNull_returnDefaultSub() {
whenever(subscriptionManager.availableSubscriptionInfoList).thenReturn(null)
val mobileTemplate = DataUsageLib.getMobileTemplate(context, SUB_ID)
assertThat(mobileTemplate.matchRule).isEqualTo(NetworkTemplate.MATCH_CARRIER)
assertThat(mobileTemplate.subscriberIds).containsExactly(DEFAULT_SUBSCRIBER_ID)
assertThat(mobileTemplate.meteredness).isEqualTo(NetworkStats.METERED_YES)
}
@Test
fun getMobileTemplate_subscriptionNotActive_returnDefaultSub() {
whenever(subscriptionManager.availableSubscriptionInfoList).thenReturn(listOf(null))
val mobileTemplate = DataUsageLib.getMobileTemplate(context, SUB_ID)
assertThat(mobileTemplate.matchRule).isEqualTo(NetworkTemplate.MATCH_CARRIER)
assertThat(mobileTemplate.subscriberIds).containsExactly(DEFAULT_SUBSCRIBER_ID)
assertThat(mobileTemplate.meteredness).isEqualTo(NetworkStats.METERED_YES)
}
@Test
fun getMobileTemplate_mergedImsisFromGroupEmpty_returnRequestedSub() {
whenever(subscriptionManager.availableSubscriptionInfoList)
.thenReturn(listOf(SUBSCRIBER_INFO))
whenever(telephonyManager.mergedImsisFromGroup).thenReturn(emptyArray())
val mobileTemplate = DataUsageLib.getMobileTemplate(context, SUB_ID)
assertThat(mobileTemplate.matchRule).isEqualTo(NetworkTemplate.MATCH_CARRIER)
assertThat(mobileTemplate.subscriberIds).containsExactly(SUBSCRIBER_ID)
assertThat(mobileTemplate.meteredness).isEqualTo(NetworkStats.METERED_YES)
}
@Test
fun getMobileTemplate_mergedImsisFromGroupNotContainSub_returnRequestedSub() {
whenever(subscriptionManager.availableSubscriptionInfoList)
.thenReturn(listOf(SUBSCRIBER_INFO))
whenever(telephonyManager.mergedImsisFromGroup).thenReturn(arrayOf(DEFAULT_SUBSCRIBER_ID))
val mobileTemplate = DataUsageLib.getMobileTemplate(context, SUB_ID)
assertThat(mobileTemplate.matchRule).isEqualTo(NetworkTemplate.MATCH_CARRIER)
assertThat(mobileTemplate.subscriberIds).containsExactly(SUBSCRIBER_ID)
assertThat(mobileTemplate.meteredness).isEqualTo(NetworkStats.METERED_YES)
}
@Test
fun getMobileTemplate_mergedImsisFromGroupContainSub_returnRequestedSub() {
whenever(subscriptionManager.availableSubscriptionInfoList)
.thenReturn(listOf(SUBSCRIBER_INFO))
whenever(telephonyManager.mergedImsisFromGroup)
.thenReturn(arrayOf(DEFAULT_SUBSCRIBER_ID, SUBSCRIBER_ID))
val mobileTemplate = DataUsageLib.getMobileTemplate(context, SUB_ID)
assertThat(mobileTemplate.matchRule).isEqualTo(NetworkTemplate.MATCH_CARRIER)
assertThat(mobileTemplate.subscriberIds)
.containsExactly(SUBSCRIBER_ID, DEFAULT_SUBSCRIBER_ID)
assertThat(mobileTemplate.meteredness).isEqualTo(NetworkStats.METERED_YES)
}
@Test
fun getMobileTemplateForSubId_subscriberIdNotNull() {
whenever(telephonyManager.getSubscriberId(SUB_ID)).thenReturn(SUBSCRIBER_ID)
val mobileTemplate = DataUsageLib.getMobileTemplateForSubId(telephonyManager, SUB_ID)
assertThat(mobileTemplate.matchRule).isEqualTo(NetworkTemplate.MATCH_CARRIER)
assertThat(mobileTemplate.subscriberIds).containsExactly(SUBSCRIBER_ID)
assertThat(mobileTemplate.meteredness).isEqualTo(NetworkStats.METERED_YES)
}
@Test
fun getMobileTemplateForSubId_subscriberIdIsNull() {
whenever(telephonyManager.getSubscriberId(SUB_ID)).thenReturn(null)
val mobileTemplate = DataUsageLib.getMobileTemplateForSubId(telephonyManager, SUB_ID)
assertThat(mobileTemplate.matchRule).isEqualTo(NetworkTemplate.MATCH_MOBILE)
assertThat(mobileTemplate.subscriberIds).isEmpty()
assertThat(mobileTemplate.meteredness).isEqualTo(NetworkStats.METERED_YES)
}
private companion object {
const val DEFAULT_SUB_ID = 0
const val SUB_ID = 1
const val DEFAULT_SUBSCRIBER_ID = "Default Test Subscriber"
const val SUBSCRIBER_ID = "Test Subscriber"
val SUBSCRIBER_INFO: SubscriptionInfo = SubscriptionInfo.Builder().setId(SUB_ID).build()
}
}

View File

@@ -0,0 +1,178 @@
/*
* 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.lib
import android.content.Context
import android.net.NetworkPolicy
import android.net.NetworkTemplate
import android.text.format.DateUtils
import android.util.Range
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.datausage.lib.NetworkStatsRepository.Companion.Bucket
import com.google.common.truth.Truth.assertThat
import java.time.Instant
import java.time.ZoneId
import java.time.ZonedDateTime
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.stub
@RunWith(AndroidJUnit4::class)
class NetworkCycleBucketRepositoryTest {
private val context: Context = ApplicationProvider.getApplicationContext()
private val template = mock<NetworkTemplate>()
private val mockNetworkCycleDataRepository = mock<NetworkCycleDataRepository>()
@Test
fun loadCycles_byPolicy() {
val policy = mock<NetworkPolicy> {
on { cycleIterator() } doReturn listOf(
Range(zonedDateTime(CYCLE1_START_TIME), zonedDateTime(CYCLE1_END_TIME)),
).iterator()
}
mockNetworkCycleDataRepository.stub {
on { getPolicy() } doReturn policy
}
val repository = NetworkCycleBucketRepository(
context = context,
networkTemplate = template,
buckets = listOf(
Bucket(
uid = 0,
bytes = CYCLE1_BYTES,
startTimeStamp = CYCLE1_START_TIME,
endTimeStamp = CYCLE1_END_TIME,
)
),
networkCycleDataRepository = mockNetworkCycleDataRepository,
)
val cycles = repository.loadCycles()
assertThat(cycles).containsExactly(
NetworkUsageData(
startTime = CYCLE1_START_TIME,
endTime = CYCLE1_END_TIME,
usage = CYCLE1_BYTES,
),
)
}
@Test
fun loadCycles_asFourWeeks() {
mockNetworkCycleDataRepository.stub {
on { getPolicy() } doReturn null
}
val repository = NetworkCycleBucketRepository(
context = context,
networkTemplate = template,
buckets = listOf(
Bucket(
uid = 0,
bytes = CYCLE2_BYTES,
startTimeStamp = CYCLE2_START_TIME,
endTimeStamp = CYCLE2_END_TIME,
)
),
networkCycleDataRepository = mockNetworkCycleDataRepository,
)
val cycles = repository.loadCycles()
assertThat(cycles).containsExactly(
NetworkUsageData(
startTime = CYCLE2_END_TIME - DateUtils.WEEK_IN_MILLIS * 4,
endTime = CYCLE2_END_TIME,
usage = CYCLE2_BYTES,
),
)
}
@Test
fun queryChartData() {
val cycle = NetworkUsageData(
startTime = CYCLE3_START_TIME,
endTime = CYCLE4_END_TIME,
usage = CYCLE3_BYTES + CYCLE4_BYTES,
)
val repository = NetworkCycleBucketRepository(
context = context,
networkTemplate = template,
buckets = listOf(
Bucket(
uid = 0,
bytes = CYCLE3_BYTES,
startTimeStamp = CYCLE3_START_TIME,
endTimeStamp = CYCLE3_END_TIME,
),
Bucket(
uid = 0,
bytes = CYCLE4_BYTES,
startTimeStamp = CYCLE4_START_TIME,
endTimeStamp = CYCLE4_END_TIME,
),
),
networkCycleDataRepository = mockNetworkCycleDataRepository,
)
val summary = repository.queryChartData(cycle)
assertThat(summary).isEqualTo(
NetworkCycleChartData(
total = cycle,
dailyUsage = listOf(
NetworkUsageData(
startTime = CYCLE3_START_TIME,
endTime = CYCLE3_END_TIME,
usage = CYCLE3_BYTES,
),
NetworkUsageData(
startTime = CYCLE4_START_TIME,
endTime = CYCLE4_END_TIME,
usage = CYCLE4_BYTES,
),
),
)
)
}
private fun zonedDateTime(epochMilli: Long): ZonedDateTime? =
ZonedDateTime.ofInstant(Instant.ofEpochMilli(epochMilli), ZoneId.systemDefault())
private companion object {
const val CYCLE1_START_TIME = 1L
const val CYCLE1_END_TIME = 2L
const val CYCLE1_BYTES = 11L
const val CYCLE2_START_TIME = 1695555555000L
const val CYCLE2_END_TIME = 1695566666000L
const val CYCLE2_BYTES = 22L
const val CYCLE3_START_TIME = 1695555555000L
const val CYCLE3_END_TIME = CYCLE3_START_TIME + DateUtils.DAY_IN_MILLIS
const val CYCLE3_BYTES = 33L
const val CYCLE4_START_TIME = CYCLE3_END_TIME
const val CYCLE4_END_TIME = CYCLE4_START_TIME + DateUtils.DAY_IN_MILLIS
const val CYCLE4_BYTES = 44L
}
}

View File

@@ -0,0 +1,114 @@
/*
* 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.lib
import android.content.Context
import android.net.NetworkPolicy
import android.net.NetworkTemplate
import android.text.format.DateUtils
import android.util.Range
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.testutils.zonedDateTime
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.stub
import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class NetworkCycleDataRepositoryTest {
private val mockNetworkStatsRepository = mock<NetworkStatsRepository> {
on { querySummaryForDevice(CYCLE1_START_TIME, CYCLE1_END_TIME) } doReturn CYCLE1_BYTES
on {
querySummaryForDevice(
startTime = CYCLE2_END_TIME - DateUtils.WEEK_IN_MILLIS * 4,
endTime = CYCLE2_END_TIME,
)
} doReturn CYCLE2_BYTES
on { querySummaryForDevice(CYCLE3_START_TIME, CYCLE4_END_TIME) } doReturn
CYCLE3_BYTES + CYCLE4_BYTES
on { querySummaryForDevice(CYCLE3_START_TIME, CYCLE3_END_TIME) } doReturn CYCLE3_BYTES
on { querySummaryForDevice(CYCLE4_START_TIME, CYCLE4_END_TIME) } doReturn CYCLE4_BYTES
}
private val context: Context = ApplicationProvider.getApplicationContext()
private val template = mock<NetworkTemplate>()
private val repository =
spy(NetworkCycleDataRepository(context, template, mockNetworkStatsRepository))
@Test
fun loadFirstCycle_byPolicy() = runTest {
val policy = mock<NetworkPolicy> {
on { cycleIterator() } doReturn listOf(
Range(zonedDateTime(CYCLE1_START_TIME), zonedDateTime(CYCLE1_END_TIME))
).iterator()
}
doReturn(policy).whenever(repository).getPolicy()
val firstCycle = repository.loadFirstCycle()
assertThat(firstCycle).isEqualTo(
NetworkUsageData(startTime = 1, endTime = 2, usage = CYCLE1_BYTES),
)
}
@Test
fun loadFirstCycle_asFourWeeks() = runTest {
doReturn(null).whenever(repository).getPolicy()
mockNetworkStatsRepository.stub {
on { getTimeRange() } doReturn Range(CYCLE2_START_TIME, CYCLE2_END_TIME)
}
val firstCycle = repository.loadFirstCycle()
assertThat(firstCycle).isEqualTo(
NetworkUsageData(
startTime = CYCLE2_END_TIME - DateUtils.WEEK_IN_MILLIS * 4,
endTime = CYCLE2_END_TIME,
usage = CYCLE2_BYTES,
),
)
}
private companion object {
const val CYCLE1_START_TIME = 1L
const val CYCLE1_END_TIME = 2L
const val CYCLE1_BYTES = 11L
const val CYCLE2_START_TIME = 1695555555000L
const val CYCLE2_END_TIME = 1695566666000L
const val CYCLE2_BYTES = 22L
const val CYCLE3_START_TIME = 1695555555000L
const val CYCLE3_END_TIME = CYCLE3_START_TIME + DateUtils.DAY_IN_MILLIS
const val CYCLE3_BYTES = 33L
const val CYCLE4_START_TIME = CYCLE3_END_TIME
const val CYCLE4_END_TIME = CYCLE4_START_TIME + DateUtils.DAY_IN_MILLIS
const val CYCLE4_BYTES = 44L
}
}

View File

@@ -0,0 +1,62 @@
/*
* 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.lib
import android.app.usage.NetworkStats
import android.app.usage.NetworkStatsManager
import android.content.Context
import android.net.NetworkTemplate
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
@RunWith(AndroidJUnit4::class)
class NetworkStatsRepositoryTest {
private val template = mock<NetworkTemplate>()
private val mockNetworkStatsManager = mock<NetworkStatsManager> {
on { querySummaryForDevice(template, START_TIME, END_TIME) } doReturn BUCKET
}
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
on { getSystemService(NetworkStatsManager::class.java) } doReturn mockNetworkStatsManager
}
private val repository = NetworkStatsRepository(context, template)
@Test
fun querySummaryForDevice() {
val bytes = repository.querySummaryForDevice(START_TIME, END_TIME)
assertThat(bytes).isEqualTo(11)
}
private companion object {
const val START_TIME = 1L
const val END_TIME = 2L
val BUCKET = mock<NetworkStats.Bucket> {
on { rxBytes } doReturn 1
on { txBytes } doReturn 10
}
}
}