1 /* 2 * Copyright (C) 2012 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.server.net; 18 19 import static android.net.ConnectivityManager.TYPE_MOBILE; 20 import static android.net.NetworkStats.SET_ALL; 21 import static android.net.NetworkStats.SET_DEFAULT; 22 import static android.net.NetworkStats.TAG_NONE; 23 import static android.net.NetworkStats.UID_ALL; 24 import static android.net.NetworkStatsHistory.FIELD_ALL; 25 import static android.net.NetworkTemplate.buildTemplateMobileAll; 26 import static android.os.Process.myUid; 27 import static android.text.format.DateUtils.HOUR_IN_MILLIS; 28 import static android.text.format.DateUtils.MINUTE_IN_MILLIS; 29 30 import static com.android.server.net.NetworkStatsCollection.multiplySafe; 31 32 import android.content.res.Resources; 33 import android.net.ConnectivityManager; 34 import android.net.NetworkIdentity; 35 import android.net.NetworkStats; 36 import android.net.NetworkStatsHistory; 37 import android.net.NetworkTemplate; 38 import android.os.Process; 39 import android.os.UserHandle; 40 import android.telephony.SubscriptionPlan; 41 import android.telephony.TelephonyManager; 42 import android.test.AndroidTestCase; 43 import android.test.MoreAsserts; 44 import android.test.suitebuilder.annotation.SmallTest; 45 import android.text.format.DateUtils; 46 import android.util.RecurrenceRule; 47 48 import com.android.frameworks.tests.net.R; 49 50 import libcore.io.IoUtils; 51 import libcore.io.Streams; 52 53 import java.io.ByteArrayInputStream; 54 import java.io.ByteArrayOutputStream; 55 import java.io.DataOutputStream; 56 import java.io.File; 57 import java.io.FileOutputStream; 58 import java.io.InputStream; 59 import java.io.OutputStream; 60 import java.time.Clock; 61 import java.time.Instant; 62 import java.time.ZoneId; 63 import java.time.ZonedDateTime; 64 import java.util.ArrayList; 65 import java.util.List; 66 67 /** 68 * Tests for {@link NetworkStatsCollection}. 69 */ 70 @SmallTest 71 public class NetworkStatsCollectionTest extends AndroidTestCase { 72 73 private static final String TEST_FILE = "test.bin"; 74 private static final String TEST_IMSI = "310260000000000"; 75 76 private static final long TIME_A = 1326088800000L; // UTC: Monday 9th January 2012 06:00:00 AM 77 private static final long TIME_B = 1326110400000L; // UTC: Monday 9th January 2012 12:00:00 PM 78 private static final long TIME_C = 1326132000000L; // UTC: Monday 9th January 2012 06:00:00 PM 79 80 private static Clock sOriginalClock; 81 82 @Override 83 public void setUp() throws Exception { 84 super.setUp(); 85 sOriginalClock = RecurrenceRule.sClock; 86 87 // ignore any device overlay while testing 88 NetworkTemplate.forceAllNetworkTypes(); 89 } 90 91 @Override 92 protected void tearDown() throws Exception { 93 super.tearDown(); 94 RecurrenceRule.sClock = sOriginalClock; 95 } 96 97 private void setClock(Instant instant) { 98 RecurrenceRule.sClock = Clock.fixed(instant, ZoneId.systemDefault()); 99 } 100 101 public void testReadLegacyNetwork() throws Exception { 102 final File testFile = new File(getContext().getFilesDir(), TEST_FILE); 103 stageFile(R.raw.netstats_v1, testFile); 104 105 final NetworkStatsCollection collection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS); 106 collection.readLegacyNetwork(testFile); 107 108 // verify that history read correctly 109 assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), 110 636016770L, 709306L, 88038768L, 518836L, NetworkStatsAccess.Level.DEVICE); 111 112 // now export into a unified format 113 final ByteArrayOutputStream bos = new ByteArrayOutputStream(); 114 collection.write(new DataOutputStream(bos)); 115 116 // clear structure completely 117 collection.reset(); 118 assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), 119 0L, 0L, 0L, 0L, NetworkStatsAccess.Level.DEVICE); 120 121 // and read back into structure, verifying that totals are same 122 collection.read(new ByteArrayInputStream(bos.toByteArray())); 123 assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), 124 636016770L, 709306L, 88038768L, 518836L, NetworkStatsAccess.Level.DEVICE); 125 } 126 127 public void testReadLegacyUid() throws Exception { 128 final File testFile = new File(getContext().getFilesDir(), TEST_FILE); 129 stageFile(R.raw.netstats_uid_v4, testFile); 130 131 final NetworkStatsCollection collection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS); 132 collection.readLegacyUid(testFile, false); 133 134 // verify that history read correctly 135 assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), 136 637076152L, 711413L, 88343717L, 521022L, NetworkStatsAccess.Level.DEVICE); 137 138 // now export into a unified format 139 final ByteArrayOutputStream bos = new ByteArrayOutputStream(); 140 collection.write(new DataOutputStream(bos)); 141 142 // clear structure completely 143 collection.reset(); 144 assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), 145 0L, 0L, 0L, 0L, NetworkStatsAccess.Level.DEVICE); 146 147 // and read back into structure, verifying that totals are same 148 collection.read(new ByteArrayInputStream(bos.toByteArray())); 149 assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), 150 637076152L, 711413L, 88343717L, 521022L, NetworkStatsAccess.Level.DEVICE); 151 } 152 153 public void testReadLegacyUidTags() throws Exception { 154 final File testFile = new File(getContext().getFilesDir(), TEST_FILE); 155 stageFile(R.raw.netstats_uid_v4, testFile); 156 157 final NetworkStatsCollection collection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS); 158 collection.readLegacyUid(testFile, true); 159 160 // verify that history read correctly 161 assertSummaryTotalIncludingTags(collection, buildTemplateMobileAll(TEST_IMSI), 162 77017831L, 100995L, 35436758L, 92344L); 163 164 // now export into a unified format 165 final ByteArrayOutputStream bos = new ByteArrayOutputStream(); 166 collection.write(new DataOutputStream(bos)); 167 168 // clear structure completely 169 collection.reset(); 170 assertSummaryTotalIncludingTags(collection, buildTemplateMobileAll(TEST_IMSI), 171 0L, 0L, 0L, 0L); 172 173 // and read back into structure, verifying that totals are same 174 collection.read(new ByteArrayInputStream(bos.toByteArray())); 175 assertSummaryTotalIncludingTags(collection, buildTemplateMobileAll(TEST_IMSI), 176 77017831L, 100995L, 35436758L, 92344L); 177 } 178 179 public void testStartEndAtomicBuckets() throws Exception { 180 final NetworkStatsCollection collection = new NetworkStatsCollection(HOUR_IN_MILLIS); 181 182 // record empty data straddling between buckets 183 final NetworkStats.Entry entry = new NetworkStats.Entry(); 184 entry.rxBytes = 32; 185 collection.recordData(null, UID_ALL, SET_DEFAULT, TAG_NONE, 30 * MINUTE_IN_MILLIS, 186 90 * MINUTE_IN_MILLIS, entry); 187 188 // assert that we report boundary in atomic buckets 189 assertEquals(0, collection.getStartMillis()); 190 assertEquals(2 * HOUR_IN_MILLIS, collection.getEndMillis()); 191 } 192 193 public void testAccessLevels() throws Exception { 194 final NetworkStatsCollection collection = new NetworkStatsCollection(HOUR_IN_MILLIS); 195 final NetworkStats.Entry entry = new NetworkStats.Entry(); 196 final NetworkIdentitySet identSet = new NetworkIdentitySet(); 197 identSet.add(new NetworkIdentity(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, 198 TEST_IMSI, null, false, true)); 199 200 int myUid = Process.myUid(); 201 int otherUidInSameUser = Process.myUid() + 1; 202 int uidInDifferentUser = Process.myUid() + UserHandle.PER_USER_RANGE; 203 204 // Record one entry for the current UID. 205 entry.rxBytes = 32; 206 collection.recordData(identSet, myUid, SET_DEFAULT, TAG_NONE, 0, 60 * MINUTE_IN_MILLIS, 207 entry); 208 209 // Record one entry for another UID in this user. 210 entry.rxBytes = 64; 211 collection.recordData(identSet, otherUidInSameUser, SET_DEFAULT, TAG_NONE, 0, 212 60 * MINUTE_IN_MILLIS, entry); 213 214 // Record one entry for the system UID. 215 entry.rxBytes = 128; 216 collection.recordData(identSet, Process.SYSTEM_UID, SET_DEFAULT, TAG_NONE, 0, 217 60 * MINUTE_IN_MILLIS, entry); 218 219 // Record one entry for a UID in a different user. 220 entry.rxBytes = 256; 221 collection.recordData(identSet, uidInDifferentUser, SET_DEFAULT, TAG_NONE, 0, 222 60 * MINUTE_IN_MILLIS, entry); 223 224 // Verify the set of relevant UIDs for each access level. 225 MoreAsserts.assertEquals(new int[] { myUid }, 226 collection.getRelevantUids(NetworkStatsAccess.Level.DEFAULT)); 227 MoreAsserts.assertEquals(new int[] { Process.SYSTEM_UID, myUid, otherUidInSameUser }, 228 collection.getRelevantUids(NetworkStatsAccess.Level.USER)); 229 MoreAsserts.assertEquals( 230 new int[] { Process.SYSTEM_UID, myUid, otherUidInSameUser, uidInDifferentUser }, 231 collection.getRelevantUids(NetworkStatsAccess.Level.DEVICE)); 232 233 // Verify security check in getHistory. 234 assertNotNull(collection.getHistory(buildTemplateMobileAll(TEST_IMSI), null, myUid, SET_DEFAULT, 235 TAG_NONE, 0, 0L, 0L, NetworkStatsAccess.Level.DEFAULT, myUid)); 236 try { 237 collection.getHistory(buildTemplateMobileAll(TEST_IMSI), null, otherUidInSameUser, 238 SET_DEFAULT, TAG_NONE, 0, 0L, 0L, NetworkStatsAccess.Level.DEFAULT, myUid); 239 fail("Should have thrown SecurityException for accessing different UID"); 240 } catch (SecurityException e) { 241 // expected 242 } 243 244 // Verify appropriate aggregation in getSummary. 245 assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), 32, 0, 0, 0, 246 NetworkStatsAccess.Level.DEFAULT); 247 assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), 32 + 64 + 128, 0, 0, 0, 248 NetworkStatsAccess.Level.USER); 249 assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), 32 + 64 + 128 + 256, 0, 0, 250 0, NetworkStatsAccess.Level.DEVICE); 251 } 252 253 public void testAugmentPlan() throws Exception { 254 final File testFile = new File(getContext().getFilesDir(), TEST_FILE); 255 stageFile(R.raw.netstats_v1, testFile); 256 257 final NetworkStatsCollection emptyCollection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS); 258 final NetworkStatsCollection collection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS); 259 collection.readLegacyNetwork(testFile); 260 261 // We're in the future, but not that far off 262 setClock(Instant.parse("2012-06-01T00:00:00.00Z")); 263 264 // Test a bunch of plans that should result in no augmentation 265 final List<SubscriptionPlan> plans = new ArrayList<>(); 266 267 // No plan 268 plans.add(null); 269 // No usage anchor 270 plans.add(SubscriptionPlan.Builder 271 .createRecurringMonthly(ZonedDateTime.parse("2011-01-14T00:00:00.00Z")).build()); 272 // Usage anchor far in past 273 plans.add(SubscriptionPlan.Builder 274 .createRecurringMonthly(ZonedDateTime.parse("2011-01-14T00:00:00.00Z")) 275 .setDataUsage(1000L, TIME_A - DateUtils.YEAR_IN_MILLIS).build()); 276 // Usage anchor far in future 277 plans.add(SubscriptionPlan.Builder 278 .createRecurringMonthly(ZonedDateTime.parse("2011-01-14T00:00:00.00Z")) 279 .setDataUsage(1000L, TIME_A + DateUtils.YEAR_IN_MILLIS).build()); 280 // Usage anchor near but outside cycle 281 plans.add(SubscriptionPlan.Builder 282 .createNonrecurring(ZonedDateTime.parse("2012-01-09T09:00:00.00Z"), 283 ZonedDateTime.parse("2012-01-09T15:00:00.00Z")) 284 .setDataUsage(1000L, TIME_C).build()); 285 286 for (SubscriptionPlan plan : plans) { 287 int i; 288 NetworkStatsHistory history; 289 290 // Empty collection should be untouched 291 history = getHistory(emptyCollection, plan, TIME_A, TIME_C); 292 assertEquals(0L, history.getTotalBytes()); 293 294 // Normal collection should be untouched 295 history = getHistory(collection, plan, TIME_A, TIME_C); i = 0; 296 assertEntry(100647, 197, 23649, 185, history.getValues(i++, null)); 297 assertEntry(100647, 196, 23648, 185, history.getValues(i++, null)); 298 assertEntry(18323, 76, 15032, 76, history.getValues(i++, null)); 299 assertEntry(18322, 75, 15031, 75, history.getValues(i++, null)); 300 assertEntry(527798, 761, 78570, 652, history.getValues(i++, null)); 301 assertEntry(527797, 760, 78570, 651, history.getValues(i++, null)); 302 assertEntry(10747, 50, 16838, 55, history.getValues(i++, null)); 303 assertEntry(10747, 49, 16838, 54, history.getValues(i++, null)); 304 assertEntry(89191, 151, 18021, 140, history.getValues(i++, null)); 305 assertEntry(89190, 150, 18020, 139, history.getValues(i++, null)); 306 assertEntry(3821, 22, 4525, 26, history.getValues(i++, null)); 307 assertEntry(3820, 22, 4524, 26, history.getValues(i++, null)); 308 assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); 309 assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); 310 assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); 311 assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); 312 assertEntry(113914, 174, 18364, 157, history.getValues(i++, null)); 313 assertEntry(113913, 173, 18364, 157, history.getValues(i++, null)); 314 assertEntry(11378, 49, 9261, 49, history.getValues(i++, null)); 315 assertEntry(11377, 48, 9261, 49, history.getValues(i++, null)); 316 assertEntry(201765, 328, 41808, 291, history.getValues(i++, null)); 317 assertEntry(201765, 328, 41807, 290, history.getValues(i++, null)); 318 assertEntry(106106, 218, 39917, 201, history.getValues(i++, null)); 319 assertEntry(106105, 217, 39917, 201, history.getValues(i++, null)); 320 assertEquals(history.size(), i); 321 322 // Slice from middle should be untouched 323 history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS, 324 TIME_B + HOUR_IN_MILLIS); i = 0; 325 assertEntry(3821, 22, 4525, 26, history.getValues(i++, null)); 326 assertEntry(3820, 22, 4524, 26, history.getValues(i++, null)); 327 assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); 328 assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); 329 assertEquals(history.size(), i); 330 } 331 332 // Lower anchor in the middle of plan 333 { 334 int i; 335 NetworkStatsHistory history; 336 337 final SubscriptionPlan plan = SubscriptionPlan.Builder 338 .createNonrecurring(ZonedDateTime.parse("2012-01-09T09:00:00.00Z"), 339 ZonedDateTime.parse("2012-01-09T15:00:00.00Z")) 340 .setDataUsage(200000L, TIME_B).build(); 341 342 // Empty collection should be augmented 343 history = getHistory(emptyCollection, plan, TIME_A, TIME_C); 344 assertEquals(200000L, history.getTotalBytes()); 345 346 // Normal collection should be augmented 347 history = getHistory(collection, plan, TIME_A, TIME_C); i = 0; 348 assertEntry(100647, 197, 23649, 185, history.getValues(i++, null)); 349 assertEntry(100647, 196, 23648, 185, history.getValues(i++, null)); 350 assertEntry(18323, 76, 15032, 76, history.getValues(i++, null)); 351 assertEntry(18322, 75, 15031, 75, history.getValues(i++, null)); 352 assertEntry(527798, 761, 78570, 652, history.getValues(i++, null)); 353 assertEntry(527797, 760, 78570, 651, history.getValues(i++, null)); 354 // Cycle point; start data normalization 355 assertEntry(7507, 0, 11763, 0, history.getValues(i++, null)); 356 assertEntry(7507, 0, 11763, 0, history.getValues(i++, null)); 357 assertEntry(62309, 0, 12589, 0, history.getValues(i++, null)); 358 assertEntry(62309, 0, 12588, 0, history.getValues(i++, null)); 359 assertEntry(2669, 0, 3161, 0, history.getValues(i++, null)); 360 assertEntry(2668, 0, 3160, 0, history.getValues(i++, null)); 361 // Anchor point; end data normalization 362 assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); 363 assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); 364 assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); 365 assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); 366 assertEntry(113914, 174, 18364, 157, history.getValues(i++, null)); 367 assertEntry(113913, 173, 18364, 157, history.getValues(i++, null)); 368 // Cycle point 369 assertEntry(11378, 49, 9261, 49, history.getValues(i++, null)); 370 assertEntry(11377, 48, 9261, 49, history.getValues(i++, null)); 371 assertEntry(201765, 328, 41808, 291, history.getValues(i++, null)); 372 assertEntry(201765, 328, 41807, 290, history.getValues(i++, null)); 373 assertEntry(106106, 218, 39917, 201, history.getValues(i++, null)); 374 assertEntry(106105, 217, 39917, 201, history.getValues(i++, null)); 375 assertEquals(history.size(), i); 376 377 // Slice from middle should be augmented 378 history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS, 379 TIME_B + HOUR_IN_MILLIS); i = 0; 380 assertEntry(2669, 0, 3161, 0, history.getValues(i++, null)); 381 assertEntry(2668, 0, 3160, 0, history.getValues(i++, null)); 382 assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); 383 assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); 384 assertEquals(history.size(), i); 385 } 386 387 // Higher anchor in the middle of plan 388 { 389 int i; 390 NetworkStatsHistory history; 391 392 final SubscriptionPlan plan = SubscriptionPlan.Builder 393 .createNonrecurring(ZonedDateTime.parse("2012-01-09T09:00:00.00Z"), 394 ZonedDateTime.parse("2012-01-09T15:00:00.00Z")) 395 .setDataUsage(400000L, TIME_B + MINUTE_IN_MILLIS).build(); 396 397 // Empty collection should be augmented 398 history = getHistory(emptyCollection, plan, TIME_A, TIME_C); 399 assertEquals(400000L, history.getTotalBytes()); 400 401 // Normal collection should be augmented 402 history = getHistory(collection, plan, TIME_A, TIME_C); i = 0; 403 assertEntry(100647, 197, 23649, 185, history.getValues(i++, null)); 404 assertEntry(100647, 196, 23648, 185, history.getValues(i++, null)); 405 assertEntry(18323, 76, 15032, 76, history.getValues(i++, null)); 406 assertEntry(18322, 75, 15031, 75, history.getValues(i++, null)); 407 assertEntry(527798, 761, 78570, 652, history.getValues(i++, null)); 408 assertEntry(527797, 760, 78570, 651, history.getValues(i++, null)); 409 // Cycle point; start data normalization 410 assertEntry(15015, 0, 23526, 0, history.getValues(i++, null)); 411 assertEntry(15015, 0, 23526, 0, history.getValues(i++, null)); 412 assertEntry(124619, 0, 25179, 0, history.getValues(i++, null)); 413 assertEntry(124618, 0, 25177, 0, history.getValues(i++, null)); 414 assertEntry(5338, 0, 6322, 0, history.getValues(i++, null)); 415 assertEntry(5337, 0, 6320, 0, history.getValues(i++, null)); 416 // Anchor point; end data normalization 417 assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); 418 assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); 419 assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); 420 assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); 421 assertEntry(113914, 174, 18364, 157, history.getValues(i++, null)); 422 assertEntry(113913, 173, 18364, 157, history.getValues(i++, null)); 423 // Cycle point 424 assertEntry(11378, 49, 9261, 49, history.getValues(i++, null)); 425 assertEntry(11377, 48, 9261, 49, history.getValues(i++, null)); 426 assertEntry(201765, 328, 41808, 291, history.getValues(i++, null)); 427 assertEntry(201765, 328, 41807, 290, history.getValues(i++, null)); 428 assertEntry(106106, 218, 39917, 201, history.getValues(i++, null)); 429 assertEntry(106105, 217, 39917, 201, history.getValues(i++, null)); 430 431 // Slice from middle should be augmented 432 history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS, 433 TIME_B + HOUR_IN_MILLIS); i = 0; 434 assertEntry(5338, 0, 6322, 0, history.getValues(i++, null)); 435 assertEntry(5337, 0, 6320, 0, history.getValues(i++, null)); 436 assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); 437 assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); 438 assertEquals(history.size(), i); 439 } 440 } 441 442 public void testAugmentPlanGigantic() throws Exception { 443 // We're in the future, but not that far off 444 setClock(Instant.parse("2012-06-01T00:00:00.00Z")); 445 446 // Create a simple history with a ton of measured usage 447 final NetworkStatsCollection large = new NetworkStatsCollection(HOUR_IN_MILLIS); 448 final NetworkIdentitySet ident = new NetworkIdentitySet(); 449 ident.add(new NetworkIdentity(ConnectivityManager.TYPE_MOBILE, -1, TEST_IMSI, null, 450 false, true)); 451 large.recordData(ident, UID_ALL, SET_ALL, TAG_NONE, TIME_A, TIME_B, 452 new NetworkStats.Entry(12_730_893_164L, 1, 0, 0, 0)); 453 454 // Verify untouched total 455 assertEquals(12_730_893_164L, getHistory(large, null, TIME_A, TIME_C).getTotalBytes()); 456 457 // Verify anchor that might cause overflows 458 final SubscriptionPlan plan = SubscriptionPlan.Builder 459 .createRecurringMonthly(ZonedDateTime.parse("2012-01-09T00:00:00.00Z")) 460 .setDataUsage(4_939_212_390L, TIME_B).build(); 461 assertEquals(4_939_212_386L, getHistory(large, plan, TIME_A, TIME_C).getTotalBytes()); 462 } 463 464 public void testRounding() throws Exception { 465 final NetworkStatsCollection coll = new NetworkStatsCollection(HOUR_IN_MILLIS); 466 467 // Special values should remain unchanged 468 for (long time : new long[] { 469 Long.MIN_VALUE, Long.MAX_VALUE, SubscriptionPlan.TIME_UNKNOWN 470 }) { 471 assertEquals(time, coll.roundUp(time)); 472 assertEquals(time, coll.roundDown(time)); 473 } 474 475 assertEquals(TIME_A, coll.roundUp(TIME_A)); 476 assertEquals(TIME_A, coll.roundDown(TIME_A)); 477 478 assertEquals(TIME_A + HOUR_IN_MILLIS, coll.roundUp(TIME_A + 1)); 479 assertEquals(TIME_A, coll.roundDown(TIME_A + 1)); 480 481 assertEquals(TIME_A, coll.roundUp(TIME_A - 1)); 482 assertEquals(TIME_A - HOUR_IN_MILLIS, coll.roundDown(TIME_A - 1)); 483 } 484 485 public void testMultiplySafe() { 486 assertEquals(25, multiplySafe(50, 1, 2)); 487 assertEquals(100, multiplySafe(50, 2, 1)); 488 489 assertEquals(-10, multiplySafe(30, -1, 3)); 490 assertEquals(0, multiplySafe(30, 0, 3)); 491 assertEquals(10, multiplySafe(30, 1, 3)); 492 assertEquals(20, multiplySafe(30, 2, 3)); 493 assertEquals(30, multiplySafe(30, 3, 3)); 494 assertEquals(40, multiplySafe(30, 4, 3)); 495 496 assertEquals(100_000_000_000L, 497 multiplySafe(300_000_000_000L, 10_000_000_000L, 30_000_000_000L)); 498 assertEquals(100_000_000_010L, 499 multiplySafe(300_000_000_000L, 10_000_000_001L, 30_000_000_000L)); 500 assertEquals(823_202_048L, 501 multiplySafe(4_939_212_288L, 2_121_815_528L, 12_730_893_165L)); 502 } 503 504 /** 505 * Copy a {@link Resources#openRawResource(int)} into {@link File} for 506 * testing purposes. 507 */ 508 private void stageFile(int rawId, File file) throws Exception { 509 new File(file.getParent()).mkdirs(); 510 InputStream in = null; 511 OutputStream out = null; 512 try { 513 in = getContext().getResources().openRawResource(rawId); 514 out = new FileOutputStream(file); 515 Streams.copy(in, out); 516 } finally { 517 IoUtils.closeQuietly(in); 518 IoUtils.closeQuietly(out); 519 } 520 } 521 522 private static NetworkStatsHistory getHistory(NetworkStatsCollection collection, 523 SubscriptionPlan augmentPlan, long start, long end) { 524 return collection.getHistory(buildTemplateMobileAll(TEST_IMSI), augmentPlan, UID_ALL, 525 SET_ALL, TAG_NONE, FIELD_ALL, start, end, NetworkStatsAccess.Level.DEVICE, myUid()); 526 } 527 528 private static void assertSummaryTotal(NetworkStatsCollection collection, 529 NetworkTemplate template, long rxBytes, long rxPackets, long txBytes, long txPackets, 530 @NetworkStatsAccess.Level int accessLevel) { 531 final NetworkStats.Entry actual = collection.getSummary( 532 template, Long.MIN_VALUE, Long.MAX_VALUE, accessLevel, myUid()) 533 .getTotal(null); 534 assertEntry(rxBytes, rxPackets, txBytes, txPackets, actual); 535 } 536 537 private static void assertSummaryTotalIncludingTags(NetworkStatsCollection collection, 538 NetworkTemplate template, long rxBytes, long rxPackets, long txBytes, long txPackets) { 539 final NetworkStats.Entry actual = collection.getSummary( 540 template, Long.MIN_VALUE, Long.MAX_VALUE, NetworkStatsAccess.Level.DEVICE, myUid()) 541 .getTotalIncludingTags(null); 542 assertEntry(rxBytes, rxPackets, txBytes, txPackets, actual); 543 } 544 545 private static void assertEntry(long rxBytes, long rxPackets, long txBytes, long txPackets, 546 NetworkStats.Entry actual) { 547 assertEntry(new NetworkStats.Entry(rxBytes, rxPackets, txBytes, txPackets, 0L), actual); 548 } 549 550 private static void assertEntry(long rxBytes, long rxPackets, long txBytes, long txPackets, 551 NetworkStatsHistory.Entry actual) { 552 assertEntry(new NetworkStats.Entry(rxBytes, rxPackets, txBytes, txPackets, 0L), actual); 553 } 554 555 private static void assertEntry(NetworkStats.Entry expected, 556 NetworkStatsHistory.Entry actual) { 557 assertEntry(expected, new NetworkStats.Entry(actual.rxBytes, actual.rxPackets, 558 actual.txBytes, actual.txPackets, 0L)); 559 } 560 561 private static void assertEntry(NetworkStats.Entry expected, 562 NetworkStats.Entry actual) { 563 assertEquals("unexpected rxBytes", expected.rxBytes, actual.rxBytes); 564 assertEquals("unexpected rxPackets", expected.rxPackets, actual.rxPackets); 565 assertEquals("unexpected txBytes", expected.txBytes, actual.txBytes); 566 assertEquals("unexpected txPackets", expected.txPackets, actual.txPackets); 567 } 568 } 569