1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.datausage; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.Mockito.doReturn; 22 import static org.mockito.Mockito.spy; 23 import static org.mockito.Mockito.when; 24 25 import android.content.Context; 26 import android.content.res.Resources; 27 import android.graphics.Typeface; 28 import android.view.LayoutInflater; 29 import android.view.View; 30 import android.view.View.MeasureSpec; 31 import android.widget.TextView; 32 33 import androidx.preference.PreferenceViewHolder; 34 import androidx.test.core.app.ApplicationProvider; 35 import androidx.test.ext.junit.runners.AndroidJUnit4; 36 37 import com.android.settings.testutils.ResourcesUtils; 38 import com.android.settingslib.Utils; 39 40 import org.junit.Before; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 import org.mockito.MockitoAnnotations; 44 45 import java.util.concurrent.TimeUnit; 46 47 @RunWith(AndroidJUnit4.class) 48 public class DataUsageSummaryPreferenceTest { 49 50 private static final long CYCLE_DURATION_MILLIS = 1000000000L; 51 private static final long UPDATE_LAG_MILLIS = 10000000L; 52 private static final String FAKE_CARRIER = "z-mobile"; 53 54 private Context mContext; 55 private Resources mResources; 56 private PreferenceViewHolder mHolder; 57 private DataUsageSummaryPreference mSummaryPreference; 58 59 private long mCycleEnd; 60 private long mUpdateTime; 61 62 63 @Before setUp()64 public void setUp() { 65 MockitoAnnotations.initMocks(this); 66 mContext = spy(ApplicationProvider.getApplicationContext()); 67 mResources = spy(mContext.getResources()); 68 when(mContext.getResources()).thenReturn(mResources); 69 mSummaryPreference = spy(new DataUsageSummaryPreference(mContext, null /* attrs */)); 70 LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class); 71 View view = inflater.inflate( 72 mSummaryPreference.getLayoutResource(), 73 null /* root */, false /* attachToRoot */); 74 75 mHolder = spy(PreferenceViewHolder.createInstanceForTests(view)); 76 assertThat(mSummaryPreference.getDataUsed(mHolder)).isNotNull(); 77 78 final long now = System.currentTimeMillis(); 79 mCycleEnd = now + CYCLE_DURATION_MILLIS; 80 mUpdateTime = now - UPDATE_LAG_MILLIS; 81 } 82 83 @Test testSetUsageInfo_withDataPlans_carrierInfoShown()84 public void testSetUsageInfo_withDataPlans_carrierInfoShown() { 85 mSummaryPreference.setUsageInfo(mCycleEnd, mUpdateTime, FAKE_CARRIER, 1 /* numPlans */); 86 87 mSummaryPreference.onBindViewHolder(mHolder); 88 assertThat(mSummaryPreference.getCarrierInfo(mHolder).getVisibility()) 89 .isEqualTo(View.VISIBLE); 90 } 91 92 @Test testSetUsageInfo_withNoDataPlans_carrierInfoNotShown()93 public void testSetUsageInfo_withNoDataPlans_carrierInfoNotShown() { 94 mSummaryPreference.setUsageInfo(mCycleEnd, -1, FAKE_CARRIER, 0 /* numPlans */); 95 96 mSummaryPreference.onBindViewHolder(mHolder); 97 assertThat(mSummaryPreference.getCarrierInfo(mHolder).getVisibility()) 98 .isEqualTo(View.GONE); 99 } 100 101 @Test testCarrierUpdateTime_shouldFormatDaysCorrectly()102 public void testCarrierUpdateTime_shouldFormatDaysCorrectly() { 103 int baseUnit = 2; 104 int smudge = 6; 105 final long updateTime = System.currentTimeMillis() 106 - TimeUnit.DAYS.toMillis(baseUnit) - TimeUnit.HOURS.toMillis(smudge); 107 mSummaryPreference.setUsageInfo(mCycleEnd, updateTime, FAKE_CARRIER, 1 /* numPlans */); 108 109 mSummaryPreference.onBindViewHolder(mHolder); 110 assertThat(mSummaryPreference.getCarrierInfo(mHolder).getText().toString()) 111 .isEqualTo("Updated by " + FAKE_CARRIER + " " + baseUnit + " days ago"); 112 } 113 114 @Test testCarrierUpdateTime_shouldFormatHoursCorrectly()115 public void testCarrierUpdateTime_shouldFormatHoursCorrectly() { 116 int baseUnit = 2; 117 int smudge = 6; 118 final long updateTime = System.currentTimeMillis() 119 - TimeUnit.HOURS.toMillis(baseUnit) - TimeUnit.MINUTES.toMillis(smudge); 120 mSummaryPreference.setUsageInfo(mCycleEnd, updateTime, FAKE_CARRIER, 1 /* numPlans */); 121 122 mSummaryPreference.onBindViewHolder(mHolder); 123 assertThat(mSummaryPreference.getCarrierInfo(mHolder).getText().toString()) 124 .isEqualTo("Updated by " + FAKE_CARRIER + " " + baseUnit + " hr ago"); 125 } 126 127 @Test testCarrierUpdateTime_shouldFormatMinutesCorrectly()128 public void testCarrierUpdateTime_shouldFormatMinutesCorrectly() { 129 int baseUnit = 2; 130 int smudge = 6; 131 final long updateTime = System.currentTimeMillis() 132 - TimeUnit.MINUTES.toMillis(baseUnit) - TimeUnit.SECONDS.toMillis(smudge); 133 mSummaryPreference.setUsageInfo(mCycleEnd, updateTime, FAKE_CARRIER, 1 /* numPlans */); 134 135 mSummaryPreference.onBindViewHolder(mHolder); 136 assertThat(mSummaryPreference.getCarrierInfo(mHolder).getText().toString()) 137 .isEqualTo("Updated by " + FAKE_CARRIER + " " + baseUnit + " min ago"); 138 } 139 140 @Test testCarrierUpdateTime_shouldFormatLessThanMinuteCorrectly()141 public void testCarrierUpdateTime_shouldFormatLessThanMinuteCorrectly() { 142 final long updateTime = System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(45); 143 mSummaryPreference.setUsageInfo(mCycleEnd, updateTime, FAKE_CARRIER, 1 /* numPlans */); 144 145 mSummaryPreference.onBindViewHolder(mHolder); 146 assertThat(mSummaryPreference.getCarrierInfo(mHolder).getText().toString()) 147 .isEqualTo("Updated by " + FAKE_CARRIER + " just now"); 148 } 149 150 @Test testCarrierUpdateTimeWithNoCarrier_shouldSayJustNow()151 public void testCarrierUpdateTimeWithNoCarrier_shouldSayJustNow() { 152 final long updateTime = System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(45); 153 mSummaryPreference.setUsageInfo(mCycleEnd, updateTime, null /* carrier */, 154 1 /* numPlans */); 155 156 mSummaryPreference.onBindViewHolder(mHolder); 157 assertThat(mSummaryPreference.getCarrierInfo(mHolder).getText().toString()) 158 .isEqualTo("Updated just now"); 159 } 160 161 @Test testCarrierUpdateTimeWithNoCarrier_shouldFormatTime()162 public void testCarrierUpdateTimeWithNoCarrier_shouldFormatTime() { 163 final long updateTime = System.currentTimeMillis() - TimeUnit.MINUTES.toMillis(2); 164 mSummaryPreference.setUsageInfo(mCycleEnd, updateTime, null /* carrier */, 165 1 /* numPlans */); 166 167 mSummaryPreference.onBindViewHolder(mHolder); 168 assertThat(mSummaryPreference.getCarrierInfo(mHolder).getText().toString()) 169 .isEqualTo("Updated 2 min ago"); 170 } 171 172 @Test setUsageInfo_withRecentCarrierUpdate_doesNotSetCarrierInfoWarningColorAndFont()173 public void setUsageInfo_withRecentCarrierUpdate_doesNotSetCarrierInfoWarningColorAndFont() { 174 final long updateTime = System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1); 175 mSummaryPreference.setUsageInfo(mCycleEnd, updateTime, FAKE_CARRIER, 1 /* numPlans */); 176 177 mSummaryPreference.onBindViewHolder(mHolder); 178 TextView carrierInfo = mSummaryPreference.getCarrierInfo(mHolder); 179 assertThat(carrierInfo.getVisibility()).isEqualTo(View.VISIBLE); 180 assertThat(carrierInfo.getCurrentTextColor()).isEqualTo( 181 Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorSecondary)); 182 assertThat(carrierInfo.getTypeface()).isEqualTo(Typeface.SANS_SERIF); 183 } 184 185 @Test testSetUsageInfo_withStaleCarrierUpdate_setsCarrierInfoWarningColorAndFont()186 public void testSetUsageInfo_withStaleCarrierUpdate_setsCarrierInfoWarningColorAndFont() { 187 final long updateTime = System.currentTimeMillis() - TimeUnit.HOURS.toMillis(7); 188 mSummaryPreference.setUsageInfo(mCycleEnd, updateTime, FAKE_CARRIER, 1 /* numPlans */); 189 190 mSummaryPreference.onBindViewHolder(mHolder); 191 TextView carrierInfo = mSummaryPreference.getCarrierInfo(mHolder); 192 assertThat(carrierInfo.getVisibility()).isEqualTo(View.VISIBLE); 193 assertThat(carrierInfo.getCurrentTextColor()).isEqualTo( 194 Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorError)); 195 assertThat(carrierInfo.getTypeface()).isEqualTo( 196 DataUsageSummaryPreference.SANS_SERIF_MEDIUM); 197 } 198 199 @Test testSetUsageInfo_withNoDataPlans_usageTitleNotShown()200 public void testSetUsageInfo_withNoDataPlans_usageTitleNotShown() { 201 mSummaryPreference.setUsageInfo(mCycleEnd, -1, FAKE_CARRIER, 0 /* numPlans */); 202 203 mSummaryPreference.onBindViewHolder(mHolder); 204 assertThat(mSummaryPreference.getUsageTitle(mHolder).getVisibility()).isEqualTo(View.GONE); 205 } 206 207 @Test testSetUsageInfo_withMultipleDataPlans_usageTitleShown()208 public void testSetUsageInfo_withMultipleDataPlans_usageTitleShown() { 209 mSummaryPreference.setUsageInfo(mCycleEnd, mUpdateTime, FAKE_CARRIER, 2 /* numPlans */); 210 211 mSummaryPreference.onBindViewHolder(mHolder); 212 assertThat(mSummaryPreference.getUsageTitle(mHolder).getVisibility()) 213 .isEqualTo(View.VISIBLE); 214 } 215 216 @Test testSetUsageInfo_cycleRemainingTimeIsLessOneDay()217 public void testSetUsageInfo_cycleRemainingTimeIsLessOneDay() { 218 // just under one day 219 final long cycleEnd = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(23); 220 mSummaryPreference.setUsageInfo(cycleEnd, -1, FAKE_CARRIER, 0 /* numPlans */); 221 222 mSummaryPreference.onBindViewHolder(mHolder); 223 assertThat(mSummaryPreference.getCycleTime(mHolder).getVisibility()) 224 .isEqualTo(View.VISIBLE); 225 assertThat(mSummaryPreference.getCycleTime(mHolder).getText()).isEqualTo( 226 ResourcesUtils.getResourcesString( 227 mContext, "billing_cycle_less_than_one_day_left")); 228 } 229 230 @Test testSetUsageInfo_cycleRemainingTimeNegativeDaysLeft_shouldDisplayNoneLeft()231 public void testSetUsageInfo_cycleRemainingTimeNegativeDaysLeft_shouldDisplayNoneLeft() { 232 final long cycleEnd = System.currentTimeMillis() - 1L; 233 mSummaryPreference.setUsageInfo(cycleEnd, -1, FAKE_CARRIER, 0 /* numPlans */); 234 235 mSummaryPreference.onBindViewHolder(mHolder); 236 assertThat(mSummaryPreference.getCycleTime(mHolder).getVisibility()) 237 .isEqualTo(View.VISIBLE); 238 assertThat(mSummaryPreference.getCycleTime(mHolder).getText()).isEqualTo( 239 ResourcesUtils.getResourcesString(mContext, "billing_cycle_none_left")); 240 } 241 242 @Test testSetUsageInfo_cycleRemainingTimeDaysLeft_shouldUsePlurals()243 public void testSetUsageInfo_cycleRemainingTimeDaysLeft_shouldUsePlurals() { 244 final int daysLeft = 3; 245 final long cycleEnd = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(daysLeft) 246 + TimeUnit.HOURS.toMillis(1); 247 mSummaryPreference.setUsageInfo(cycleEnd, -1, FAKE_CARRIER, 0 /* numPlans */); 248 249 mSummaryPreference.onBindViewHolder(mHolder); 250 assertThat(mSummaryPreference.getCycleTime(mHolder).getVisibility()) 251 .isEqualTo(View.VISIBLE); 252 assertThat(mSummaryPreference.getCycleTime(mHolder).getText()) 253 .isEqualTo(daysLeft + " days left"); 254 } 255 256 @Test testSetLimitInfo_withLimitInfo_dataLimitsShown()257 public void testSetLimitInfo_withLimitInfo_dataLimitsShown() { 258 final String limitText = "test limit text"; 259 mSummaryPreference.setLimitInfo(limitText); 260 261 mSummaryPreference.onBindViewHolder(mHolder); 262 assertThat(mSummaryPreference.getDataLimits(mHolder).getVisibility()) 263 .isEqualTo(View.VISIBLE); 264 assertThat(mSummaryPreference.getDataLimits(mHolder).getText()).isEqualTo(limitText); 265 } 266 267 @Test testSetLimitInfo_withNullLimitInfo_dataLimitsNotShown()268 public void testSetLimitInfo_withNullLimitInfo_dataLimitsNotShown() { 269 mSummaryPreference.setLimitInfo(null); 270 271 mSummaryPreference.onBindViewHolder(mHolder); 272 assertThat(mSummaryPreference.getDataLimits(mHolder).getVisibility()).isEqualTo(View.GONE); 273 } 274 275 @Test testSetLimitInfo_withEmptyLimitInfo_dataLimitsNotShown()276 public void testSetLimitInfo_withEmptyLimitInfo_dataLimitsNotShown() { 277 final String emptyLimitText = ""; 278 mSummaryPreference.setLimitInfo(emptyLimitText); 279 280 mSummaryPreference.onBindViewHolder(mHolder); 281 assertThat(mSummaryPreference.getDataLimits(mHolder).getVisibility()).isEqualTo(View.GONE); 282 } 283 284 @Test testSetChartEnabledFalse_hidesLabelBar()285 public void testSetChartEnabledFalse_hidesLabelBar() { 286 setValidLabels(); 287 mSummaryPreference.setChartEnabled(false); 288 289 mSummaryPreference.onBindViewHolder(mHolder); 290 assertThat(mSummaryPreference.getLabelBar(mHolder).getVisibility()).isEqualTo(View.GONE); 291 assertThat(mSummaryPreference.getProgressBar(mHolder).getVisibility()).isEqualTo(View.GONE); 292 } 293 294 @Test testSetEmptyLabels_hidesLabelBar()295 public void testSetEmptyLabels_hidesLabelBar() { 296 mSummaryPreference.setLabels("", ""); 297 298 mSummaryPreference.onBindViewHolder(mHolder); 299 assertThat(mSummaryPreference.getLabelBar(mHolder).getVisibility()).isEqualTo(View.GONE); 300 assertThat(mSummaryPreference.getProgressBar(mHolder).getVisibility()).isEqualTo(View.GONE); 301 } 302 303 @Test testLabelBar_isVisible_whenLabelsSet()304 public void testLabelBar_isVisible_whenLabelsSet() { 305 setValidLabels(); 306 //mChartEnabled defaults to true 307 308 mSummaryPreference.onBindViewHolder(mHolder); 309 assertThat(mSummaryPreference.getLabelBar(mHolder).getVisibility()) 310 .isEqualTo(View.VISIBLE); 311 assertThat(mSummaryPreference.getProgressBar(mHolder).getVisibility()) 312 .isEqualTo(View.VISIBLE); 313 } 314 315 @Test testSetProgress_updatesProgressBar()316 public void testSetProgress_updatesProgressBar() { 317 setValidLabels(); 318 mSummaryPreference.setProgress(.5f); 319 320 mSummaryPreference.onBindViewHolder(mHolder); 321 assertThat(mSummaryPreference.getProgressBar(mHolder).getProgress()).isEqualTo(50); 322 } 323 setValidLabels()324 private void setValidLabels() { 325 mSummaryPreference.setLabels("0.0 GB", "5.0 GB"); 326 } 327 328 @Test testSetUsageAndRemainingInfo_withUsageInfo_dataUsageAndRemainingShown()329 public void testSetUsageAndRemainingInfo_withUsageInfo_dataUsageAndRemainingShown() { 330 mSummaryPreference.setUsageInfo(mCycleEnd, mUpdateTime, FAKE_CARRIER, 1 /* numPlans */); 331 mSummaryPreference.setUsageNumbers( 332 BillingCycleSettings.MIB_IN_BYTES, 333 10 * BillingCycleSettings.MIB_IN_BYTES); 334 335 mSummaryPreference.onBindViewHolder(mHolder); 336 assertThat(mSummaryPreference.getDataUsed(mHolder).getText().toString()) 337 .isEqualTo("1.00 MB used"); 338 assertThat(mSummaryPreference.getDataRemaining(mHolder).getText().toString()) 339 .isEqualTo("9.00 MB left"); 340 assertThat(mSummaryPreference.getDataRemaining(mHolder).getVisibility()) 341 .isEqualTo(View.VISIBLE); 342 final int colorId = Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorAccent); 343 assertThat(mSummaryPreference.getDataRemaining(mHolder).getCurrentTextColor()) 344 .isEqualTo(colorId); 345 } 346 347 @Test testSetUsageInfo_withDataOverusage()348 public void testSetUsageInfo_withDataOverusage() { 349 mSummaryPreference.setUsageInfo(mCycleEnd, mUpdateTime, FAKE_CARRIER, 1 /* numPlans */); 350 mSummaryPreference.setUsageNumbers( 351 11 * BillingCycleSettings.MIB_IN_BYTES, 352 10 * BillingCycleSettings.MIB_IN_BYTES); 353 354 mSummaryPreference.onBindViewHolder(mHolder); 355 assertThat(mSummaryPreference.getDataUsed(mHolder).getText().toString()) 356 .isEqualTo("11.00 MB used"); 357 assertThat(mSummaryPreference.getDataRemaining(mHolder).getText().toString()) 358 .isEqualTo("1.00 MB over"); 359 final int colorId = Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorError); 360 assertThat(mSummaryPreference.getDataRemaining(mHolder).getCurrentTextColor()) 361 .isEqualTo(colorId); 362 } 363 364 @Test testSetUsageInfo_withUsageInfo_dataUsageShown()365 public void testSetUsageInfo_withUsageInfo_dataUsageShown() { 366 mSummaryPreference.setUsageInfo(mCycleEnd, -1, FAKE_CARRIER, 0 /* numPlans */); 367 mSummaryPreference.setUsageNumbers( 368 BillingCycleSettings.MIB_IN_BYTES, -1L); 369 370 mSummaryPreference.onBindViewHolder(mHolder); 371 assertThat(mSummaryPreference.getDataUsed(mHolder).getText().toString()) 372 .isEqualTo("1.00 MB used"); 373 assertThat(mSummaryPreference.getDataRemaining(mHolder).getText()).isEqualTo(""); 374 } 375 376 @Test testSetUsageInfo_withOverflowStrings_dataRemainingNotShown()377 public void testSetUsageInfo_withOverflowStrings_dataRemainingNotShown() { 378 LayoutInflater inflater = LayoutInflater.from(mContext); 379 View view = inflater.inflate(mSummaryPreference.getLayoutResource(), null /* root */, 380 false /* attachToRoot */); 381 382 mSummaryPreference.setUsageInfo(mCycleEnd, mUpdateTime, FAKE_CARRIER, 1 /* numPlans */); 383 mSummaryPreference.setUsageNumbers( 384 BillingCycleSettings.MIB_IN_BYTES, 385 10 * BillingCycleSettings.MIB_IN_BYTES); 386 387 int data_used_formatted_id = ResourcesUtils.getResourcesId( 388 mContext, "string", "data_used_formatted"); 389 int data_remaining_id = ResourcesUtils.getResourcesId( 390 mContext, "string", "data_remaining"); 391 CharSequence data_used_formatted_cs = "^1 ^2 used with long trailing text"; 392 CharSequence data_remaining_cs = "^1 left"; 393 doReturn(data_used_formatted_cs).when(mResources).getText(data_used_formatted_id); 394 doReturn(data_remaining_cs).when(mResources).getText(data_remaining_id); 395 396 mSummaryPreference.onBindViewHolder(mHolder); 397 398 TextView dataUsed = mSummaryPreference.getDataUsed(mHolder); 399 TextView dataRemaining = mSummaryPreference.getDataRemaining(mHolder); 400 int width = MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY); 401 dataUsed.measure(width, MeasureSpec.UNSPECIFIED); 402 dataRemaining.measure(width, MeasureSpec.UNSPECIFIED); 403 404 assertThat(dataRemaining.getVisibility()).isEqualTo(View.VISIBLE); 405 406 MeasurableLinearLayout layout = mSummaryPreference.getLayout(mHolder); 407 layout.measure( 408 MeasureSpec.makeMeasureSpec(800, View.MeasureSpec.EXACTLY), 409 MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY)); 410 411 assertThat(dataUsed.getText().toString()).isEqualTo("1.00 MB used with long trailing text"); 412 // TODO(b/175389659): re-enable this line once cuttlefish device specs are verified. 413 // assertThat(dataRemaining.getVisibility()).isEqualTo(View.GONE); 414 } 415 } 416