fix: 引入Settings的Module
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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>()
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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>()
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user