1 /* 2 * Copyright (C) 2011 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 android.net; 18 19 import static android.net.NetworkStats.DEFAULT_NETWORK_NO; 20 import static android.net.NetworkStats.IFACE_ALL; 21 import static android.net.NetworkStats.METERED_NO; 22 import static android.net.NetworkStats.ROAMING_NO; 23 import static android.net.NetworkStats.SET_DEFAULT; 24 import static android.net.NetworkStats.TAG_NONE; 25 import static android.net.NetworkStats.UID_ALL; 26 import static android.net.NetworkStatsHistory.DataStreamUtils.readVarLong; 27 import static android.net.NetworkStatsHistory.DataStreamUtils.writeVarLong; 28 import static android.net.NetworkStatsHistory.Entry.UNKNOWN; 29 import static android.net.NetworkStatsHistory.FIELD_ALL; 30 import static android.net.NetworkStatsHistory.FIELD_OPERATIONS; 31 import static android.net.NetworkStatsHistory.FIELD_RX_BYTES; 32 import static android.net.NetworkStatsHistory.FIELD_RX_PACKETS; 33 import static android.net.NetworkStatsHistory.FIELD_TX_BYTES; 34 import static android.net.TrafficStats.GB_IN_BYTES; 35 import static android.net.TrafficStats.MB_IN_BYTES; 36 import static android.text.format.DateUtils.DAY_IN_MILLIS; 37 import static android.text.format.DateUtils.HOUR_IN_MILLIS; 38 import static android.text.format.DateUtils.MINUTE_IN_MILLIS; 39 import static android.text.format.DateUtils.SECOND_IN_MILLIS; 40 import static android.text.format.DateUtils.WEEK_IN_MILLIS; 41 import static android.text.format.DateUtils.YEAR_IN_MILLIS; 42 43 import static org.junit.Assert.assertEquals; 44 import static org.junit.Assert.assertFalse; 45 import static org.junit.Assert.assertTrue; 46 47 import android.content.Context; 48 import android.os.Build; 49 import android.util.Log; 50 51 import androidx.test.InstrumentationRegistry; 52 import androidx.test.filters.SmallTest; 53 54 import com.android.frameworks.tests.net.R; 55 import com.android.testutils.DevSdkIgnoreRule; 56 import com.android.testutils.DevSdkIgnoreRunner; 57 58 import org.junit.After; 59 import org.junit.Test; 60 import org.junit.runner.RunWith; 61 62 import java.io.ByteArrayInputStream; 63 import java.io.ByteArrayOutputStream; 64 import java.io.DataInputStream; 65 import java.io.DataOutputStream; 66 import java.util.Random; 67 68 @RunWith(DevSdkIgnoreRunner.class) 69 @SmallTest 70 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2) 71 public class NetworkStatsHistoryTest { 72 private static final String TAG = "NetworkStatsHistoryTest"; 73 74 private static final long TEST_START = 1194220800000L; 75 76 private NetworkStatsHistory stats; 77 78 @After tearDown()79 public void tearDown() throws Exception { 80 if (stats != null) { 81 assertConsistent(stats); 82 } 83 } 84 85 @Test testReadOriginalVersion()86 public void testReadOriginalVersion() throws Exception { 87 final Context context = InstrumentationRegistry.getContext(); 88 final DataInputStream in = 89 new DataInputStream(context.getResources().openRawResource(R.raw.history_v1)); 90 91 NetworkStatsHistory.Entry entry = null; 92 try { 93 final NetworkStatsHistory history = new NetworkStatsHistory(in); 94 assertEquals(15 * SECOND_IN_MILLIS, history.getBucketDuration()); 95 96 entry = history.getValues(0, entry); 97 assertEquals(29143L, entry.rxBytes); 98 assertEquals(6223L, entry.txBytes); 99 100 entry = history.getValues(history.size() - 1, entry); 101 assertEquals(1476L, entry.rxBytes); 102 assertEquals(838L, entry.txBytes); 103 104 entry = history.getValues(Long.MIN_VALUE, Long.MAX_VALUE, entry); 105 assertEquals(332401L, entry.rxBytes); 106 assertEquals(64314L, entry.txBytes); 107 108 } finally { 109 in.close(); 110 } 111 } 112 113 @Test testRecordSingleBucket()114 public void testRecordSingleBucket() throws Exception { 115 final long BUCKET_SIZE = HOUR_IN_MILLIS; 116 stats = new NetworkStatsHistory(BUCKET_SIZE); 117 118 // record data into narrow window to get single bucket 119 stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS, 120 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 121 ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 10L, 2048L, 20L, 2L)); 122 123 assertEquals(1, stats.size()); 124 assertValues(stats, 0, SECOND_IN_MILLIS, 1024L, 10L, 2048L, 20L, 2L); 125 } 126 127 @Test testRecordEqualBuckets()128 public void testRecordEqualBuckets() throws Exception { 129 final long bucketDuration = HOUR_IN_MILLIS; 130 stats = new NetworkStatsHistory(bucketDuration); 131 132 // split equally across two buckets 133 final long recordStart = TEST_START + (bucketDuration / 2); 134 stats.recordData(recordStart, recordStart + bucketDuration, 135 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 136 ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 10L, 128L, 2L, 2L)); 137 138 assertEquals(2, stats.size()); 139 assertValues(stats, 0, HOUR_IN_MILLIS / 2, 512L, 5L, 64L, 1L, 1L); 140 assertValues(stats, 1, HOUR_IN_MILLIS / 2, 512L, 5L, 64L, 1L, 1L); 141 } 142 143 @Test testRecordTouchingBuckets()144 public void testRecordTouchingBuckets() throws Exception { 145 final long BUCKET_SIZE = 15 * MINUTE_IN_MILLIS; 146 stats = new NetworkStatsHistory(BUCKET_SIZE); 147 148 // split almost completely into middle bucket, but with a few minutes 149 // overlap into neighboring buckets. total record is 20 minutes. 150 final long recordStart = (TEST_START + BUCKET_SIZE) - MINUTE_IN_MILLIS; 151 final long recordEnd = (TEST_START + (BUCKET_SIZE * 2)) + (MINUTE_IN_MILLIS * 4); 152 stats.recordData(recordStart, recordEnd, 153 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 154 ROAMING_NO, DEFAULT_NETWORK_NO, 1000L, 2000L, 5000L, 10000L, 100L)); 155 156 assertEquals(3, stats.size()); 157 // first bucket should have (1/20 of value) 158 assertValues(stats, 0, MINUTE_IN_MILLIS, 50L, 100L, 250L, 500L, 5L); 159 // second bucket should have (15/20 of value) 160 assertValues(stats, 1, 15 * MINUTE_IN_MILLIS, 750L, 1500L, 3750L, 7500L, 75L); 161 // final bucket should have (4/20 of value) 162 assertValues(stats, 2, 4 * MINUTE_IN_MILLIS, 200L, 400L, 1000L, 2000L, 20L); 163 } 164 165 @Test testRecordGapBuckets()166 public void testRecordGapBuckets() throws Exception { 167 final long BUCKET_SIZE = HOUR_IN_MILLIS; 168 stats = new NetworkStatsHistory(BUCKET_SIZE); 169 170 // record some data today and next week with large gap 171 final long firstStart = TEST_START; 172 final long lastStart = TEST_START + WEEK_IN_MILLIS; 173 stats.recordData(firstStart, firstStart + SECOND_IN_MILLIS, 174 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 175 ROAMING_NO, DEFAULT_NETWORK_NO, 128L, 2L, 256L, 4L, 1L)); 176 stats.recordData(lastStart, lastStart + SECOND_IN_MILLIS, 177 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 178 ROAMING_NO, DEFAULT_NETWORK_NO, 64L, 1L, 512L, 8L, 2L)); 179 180 // we should have two buckets, far apart from each other 181 assertEquals(2, stats.size()); 182 assertValues(stats, 0, SECOND_IN_MILLIS, 128L, 2L, 256L, 4L, 1L); 183 assertValues(stats, 1, SECOND_IN_MILLIS, 64L, 1L, 512L, 8L, 2L); 184 185 // now record something in middle, spread across two buckets 186 final long middleStart = TEST_START + DAY_IN_MILLIS; 187 final long middleEnd = middleStart + (HOUR_IN_MILLIS * 2); 188 stats.recordData(middleStart, middleEnd, 189 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 190 ROAMING_NO, DEFAULT_NETWORK_NO, 2048L, 4L, 2048L, 4L, 2L)); 191 192 // now should have four buckets, with new record in middle two buckets 193 assertEquals(4, stats.size()); 194 assertValues(stats, 0, SECOND_IN_MILLIS, 128L, 2L, 256L, 4L, 1L); 195 assertValues(stats, 1, HOUR_IN_MILLIS, 1024L, 2L, 1024L, 2L, 1L); 196 assertValues(stats, 2, HOUR_IN_MILLIS, 1024L, 2L, 1024L, 2L, 1L); 197 assertValues(stats, 3, SECOND_IN_MILLIS, 64L, 1L, 512L, 8L, 2L); 198 } 199 200 @Test testRecordOverlapBuckets()201 public void testRecordOverlapBuckets() throws Exception { 202 final long BUCKET_SIZE = HOUR_IN_MILLIS; 203 stats = new NetworkStatsHistory(BUCKET_SIZE); 204 205 // record some data in one bucket, and another overlapping buckets 206 stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS, 207 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 208 ROAMING_NO, DEFAULT_NETWORK_NO, 256L, 2L, 256L, 2L, 1L)); 209 final long midStart = TEST_START + (HOUR_IN_MILLIS / 2); 210 stats.recordData(midStart, midStart + HOUR_IN_MILLIS, 211 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 212 ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 10L, 1024L, 10L, 10L)); 213 214 // should have two buckets, with some data mixed together 215 assertEquals(2, stats.size()); 216 assertValues(stats, 0, SECOND_IN_MILLIS + (HOUR_IN_MILLIS / 2), 768L, 7L, 768L, 7L, 6L); 217 assertValues(stats, 1, (HOUR_IN_MILLIS / 2), 512L, 5L, 512L, 5L, 5L); 218 } 219 220 @Test testRecordEntireGapIdentical()221 public void testRecordEntireGapIdentical() throws Exception { 222 // first, create two separate histories far apart 223 final NetworkStatsHistory stats1 = new NetworkStatsHistory(HOUR_IN_MILLIS); 224 stats1.recordData(TEST_START, TEST_START + 2 * HOUR_IN_MILLIS, 2000L, 1000L); 225 226 final long TEST_START_2 = TEST_START + DAY_IN_MILLIS; 227 final NetworkStatsHistory stats2 = new NetworkStatsHistory(HOUR_IN_MILLIS); 228 stats2.recordData(TEST_START_2, TEST_START_2 + 2 * HOUR_IN_MILLIS, 1000L, 500L); 229 230 // combine together with identical bucket size 231 stats = new NetworkStatsHistory(HOUR_IN_MILLIS); 232 stats.recordEntireHistory(stats1); 233 stats.recordEntireHistory(stats2); 234 235 // first verify that totals match up 236 assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 3000L, 1500L); 237 238 // now inspect internal buckets 239 assertValues(stats, 0, 1000L, 500L); 240 assertValues(stats, 1, 1000L, 500L); 241 assertValues(stats, 2, 500L, 250L); 242 assertValues(stats, 3, 500L, 250L); 243 } 244 245 @Test testRecordEntireOverlapVaryingBuckets()246 public void testRecordEntireOverlapVaryingBuckets() throws Exception { 247 // create history just over hour bucket boundary 248 final NetworkStatsHistory stats1 = new NetworkStatsHistory(HOUR_IN_MILLIS); 249 stats1.recordData(TEST_START, TEST_START + MINUTE_IN_MILLIS * 60, 600L, 600L); 250 251 final long TEST_START_2 = TEST_START + MINUTE_IN_MILLIS; 252 final NetworkStatsHistory stats2 = new NetworkStatsHistory(MINUTE_IN_MILLIS); 253 stats2.recordData(TEST_START_2, TEST_START_2 + MINUTE_IN_MILLIS * 5, 50L, 50L); 254 255 // combine together with minute bucket size 256 stats = new NetworkStatsHistory(MINUTE_IN_MILLIS); 257 stats.recordEntireHistory(stats1); 258 stats.recordEntireHistory(stats2); 259 260 // first verify that totals match up 261 assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 650L, 650L); 262 263 // now inspect internal buckets 264 assertValues(stats, 0, 10L, 10L); 265 assertValues(stats, 1, 20L, 20L); 266 assertValues(stats, 2, 20L, 20L); 267 assertValues(stats, 3, 20L, 20L); 268 assertValues(stats, 4, 20L, 20L); 269 assertValues(stats, 5, 20L, 20L); 270 assertValues(stats, 6, 10L, 10L); 271 272 // now combine using 15min buckets 273 stats = new NetworkStatsHistory(HOUR_IN_MILLIS / 4); 274 stats.recordEntireHistory(stats1); 275 stats.recordEntireHistory(stats2); 276 277 // first verify that totals match up 278 assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 650L, 650L); 279 280 // and inspect buckets 281 assertValues(stats, 0, 200L, 200L); 282 assertValues(stats, 1, 150L, 150L); 283 assertValues(stats, 2, 150L, 150L); 284 assertValues(stats, 3, 150L, 150L); 285 } 286 287 @Test testRemoveStartingBefore()288 public void testRemoveStartingBefore() throws Exception { 289 stats = new NetworkStatsHistory(HOUR_IN_MILLIS); 290 291 // record some data across 24 buckets 292 stats.recordData(TEST_START, TEST_START + DAY_IN_MILLIS, 24L, 24L); 293 assertEquals(24, stats.size()); 294 295 // try removing invalid data; should be no change 296 stats.removeBucketsStartingBefore(0 - DAY_IN_MILLIS); 297 assertEquals(24, stats.size()); 298 299 // try removing far before buckets; should be no change 300 stats.removeBucketsStartingBefore(TEST_START - YEAR_IN_MILLIS); 301 assertEquals(24, stats.size()); 302 303 // try removing just moments into first bucket; should be no change 304 // since that bucket doesn't contain data starts before the cutoff 305 stats.removeBucketsStartingBefore(TEST_START); 306 assertEquals(24, stats.size()); 307 308 // try removing single bucket 309 stats.removeBucketsStartingBefore(TEST_START + HOUR_IN_MILLIS); 310 assertEquals(23, stats.size()); 311 312 // try removing multiple buckets 313 stats.removeBucketsStartingBefore(TEST_START + (4 * HOUR_IN_MILLIS)); 314 assertEquals(20, stats.size()); 315 316 // try removing all buckets 317 stats.removeBucketsStartingBefore(TEST_START + YEAR_IN_MILLIS); 318 assertEquals(0, stats.size()); 319 } 320 321 @Test testTotalData()322 public void testTotalData() throws Exception { 323 final long BUCKET_SIZE = HOUR_IN_MILLIS; 324 stats = new NetworkStatsHistory(BUCKET_SIZE); 325 326 // record uniform data across day 327 stats.recordData(TEST_START, TEST_START + DAY_IN_MILLIS, 2400L, 4800L); 328 329 // verify that total outside range is 0 330 assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START - DAY_IN_MILLIS, 0L, 0L); 331 332 // verify total in first hour 333 assertValues(stats, TEST_START, TEST_START + HOUR_IN_MILLIS, 100L, 200L); 334 335 // verify total across 1.5 hours 336 assertValues(stats, TEST_START, TEST_START + (long) (1.5 * HOUR_IN_MILLIS), 150L, 300L); 337 338 // verify total beyond end 339 assertValues(stats, TEST_START + (23 * HOUR_IN_MILLIS), TEST_START + WEEK_IN_MILLIS, 100L, 200L); 340 341 // verify everything total 342 assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 2400L, 4800L); 343 344 } 345 346 @Test testFuzzing()347 public void testFuzzing() throws Exception { 348 try { 349 // fuzzing with random events, looking for crashes 350 final NetworkStats.Entry entry = new NetworkStats.Entry(); 351 final Random r = new Random(); 352 for (int i = 0; i < 500; i++) { 353 stats = new NetworkStatsHistory(r.nextLong()); 354 for (int j = 0; j < 10000; j++) { 355 if (r.nextBoolean()) { 356 // add range 357 final long start = r.nextLong(); 358 final long end = start + r.nextInt(); 359 entry.rxBytes = nextPositiveLong(r); 360 entry.rxPackets = nextPositiveLong(r); 361 entry.txBytes = nextPositiveLong(r); 362 entry.txPackets = nextPositiveLong(r); 363 entry.operations = nextPositiveLong(r); 364 stats.recordData(start, end, entry); 365 } else { 366 // trim something 367 stats.removeBucketsStartingBefore(r.nextLong()); 368 } 369 } 370 assertConsistent(stats); 371 } 372 } catch (Throwable e) { 373 Log.e(TAG, String.valueOf(stats)); 374 throw new RuntimeException(e); 375 } 376 } 377 nextPositiveLong(Random r)378 private static long nextPositiveLong(Random r) { 379 final long value = r.nextLong(); 380 return value < 0 ? -value : value; 381 } 382 383 @Test testIgnoreFields()384 public void testIgnoreFields() throws Exception { 385 final NetworkStatsHistory history = new NetworkStatsHistory( 386 MINUTE_IN_MILLIS, 0, FIELD_RX_BYTES | FIELD_TX_BYTES); 387 388 history.recordData(0, MINUTE_IN_MILLIS, 389 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 390 ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 10L, 2048L, 20L, 4L)); 391 history.recordData(0, 2 * MINUTE_IN_MILLIS, 392 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 393 ROAMING_NO, DEFAULT_NETWORK_NO, 2L, 2L, 2L, 2L, 2L)); 394 395 assertFullValues(history, UNKNOWN, 1026L, UNKNOWN, 2050L, UNKNOWN, UNKNOWN); 396 } 397 398 @Test testIgnoreFieldsRecordIn()399 public void testIgnoreFieldsRecordIn() throws Exception { 400 final NetworkStatsHistory full = new NetworkStatsHistory(MINUTE_IN_MILLIS, 0, FIELD_ALL); 401 final NetworkStatsHistory partial = new NetworkStatsHistory( 402 MINUTE_IN_MILLIS, 0, FIELD_RX_PACKETS | FIELD_OPERATIONS); 403 404 full.recordData(0, MINUTE_IN_MILLIS, 405 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 406 ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 10L, 2048L, 20L, 4L)); 407 partial.recordEntireHistory(full); 408 409 assertFullValues(partial, UNKNOWN, UNKNOWN, 10L, UNKNOWN, UNKNOWN, 4L); 410 } 411 412 @Test testIgnoreFieldsRecordOut()413 public void testIgnoreFieldsRecordOut() throws Exception { 414 final NetworkStatsHistory full = new NetworkStatsHistory(MINUTE_IN_MILLIS, 0, FIELD_ALL); 415 final NetworkStatsHistory partial = new NetworkStatsHistory( 416 MINUTE_IN_MILLIS, 0, FIELD_RX_PACKETS | FIELD_OPERATIONS); 417 418 partial.recordData(0, MINUTE_IN_MILLIS, 419 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 420 ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 10L, 2048L, 20L, 4L)); 421 full.recordEntireHistory(partial); 422 423 assertFullValues(full, MINUTE_IN_MILLIS, 0L, 10L, 0L, 0L, 4L); 424 } 425 426 @Test testSerialize()427 public void testSerialize() throws Exception { 428 final NetworkStatsHistory before = new NetworkStatsHistory(MINUTE_IN_MILLIS, 40, FIELD_ALL); 429 before.recordData(0, 4 * MINUTE_IN_MILLIS, 430 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 431 ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 10L, 2048L, 20L, 4L)); 432 before.recordData(DAY_IN_MILLIS, DAY_IN_MILLIS + MINUTE_IN_MILLIS, 433 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 434 ROAMING_NO, DEFAULT_NETWORK_NO, 10L, 20L, 30L, 40L, 50L)); 435 436 final ByteArrayOutputStream out = new ByteArrayOutputStream(); 437 before.writeToStream(new DataOutputStream(out)); 438 out.close(); 439 440 final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); 441 final NetworkStatsHistory after = new NetworkStatsHistory(new DataInputStream(in)); 442 443 // must have identical totals before and after 444 assertFullValues(before, 5 * MINUTE_IN_MILLIS, 1034L, 30L, 2078L, 60L, 54L); 445 assertFullValues(after, 5 * MINUTE_IN_MILLIS, 1034L, 30L, 2078L, 60L, 54L); 446 } 447 448 @Test testVarLong()449 public void testVarLong() throws Exception { 450 assertEquals(0L, performVarLong(0L)); 451 assertEquals(-1L, performVarLong(-1L)); 452 assertEquals(1024L, performVarLong(1024L)); 453 assertEquals(-1024L, performVarLong(-1024L)); 454 assertEquals(40 * MB_IN_BYTES, performVarLong(40 * MB_IN_BYTES)); 455 assertEquals(512 * GB_IN_BYTES, performVarLong(512 * GB_IN_BYTES)); 456 assertEquals(Long.MIN_VALUE, performVarLong(Long.MIN_VALUE)); 457 assertEquals(Long.MAX_VALUE, performVarLong(Long.MAX_VALUE)); 458 assertEquals(Long.MIN_VALUE + 40, performVarLong(Long.MIN_VALUE + 40)); 459 assertEquals(Long.MAX_VALUE - 40, performVarLong(Long.MAX_VALUE - 40)); 460 } 461 462 @Test testIndexBeforeAfter()463 public void testIndexBeforeAfter() throws Exception { 464 final long BUCKET_SIZE = HOUR_IN_MILLIS; 465 stats = new NetworkStatsHistory(BUCKET_SIZE); 466 467 final long FIRST_START = TEST_START; 468 final long FIRST_END = FIRST_START + (2 * HOUR_IN_MILLIS); 469 final long SECOND_START = TEST_START + WEEK_IN_MILLIS; 470 final long SECOND_END = SECOND_START + HOUR_IN_MILLIS; 471 final long THIRD_START = TEST_START + (2 * WEEK_IN_MILLIS); 472 final long THIRD_END = THIRD_START + (2 * HOUR_IN_MILLIS); 473 474 stats.recordData(FIRST_START, FIRST_END, 475 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 476 ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 10L, 2048L, 20L, 2L)); 477 stats.recordData(SECOND_START, SECOND_END, 478 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 479 ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 10L, 2048L, 20L, 2L)); 480 stats.recordData(THIRD_START, THIRD_END, 481 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 482 ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 10L, 2048L, 20L, 2L)); 483 484 // should have buckets: 2+1+2 485 assertEquals(5, stats.size()); 486 487 assertIndexBeforeAfter(stats, 0, 0, Long.MIN_VALUE); 488 assertIndexBeforeAfter(stats, 0, 1, FIRST_START); 489 assertIndexBeforeAfter(stats, 0, 1, FIRST_START + MINUTE_IN_MILLIS); 490 assertIndexBeforeAfter(stats, 0, 2, FIRST_START + HOUR_IN_MILLIS); 491 assertIndexBeforeAfter(stats, 1, 2, FIRST_START + HOUR_IN_MILLIS + MINUTE_IN_MILLIS); 492 assertIndexBeforeAfter(stats, 1, 2, FIRST_END - MINUTE_IN_MILLIS); 493 assertIndexBeforeAfter(stats, 1, 2, FIRST_END); 494 assertIndexBeforeAfter(stats, 1, 2, FIRST_END + MINUTE_IN_MILLIS); 495 assertIndexBeforeAfter(stats, 1, 2, SECOND_START - MINUTE_IN_MILLIS); 496 assertIndexBeforeAfter(stats, 1, 3, SECOND_START); 497 assertIndexBeforeAfter(stats, 2, 3, SECOND_END); 498 assertIndexBeforeAfter(stats, 2, 3, SECOND_END + MINUTE_IN_MILLIS); 499 assertIndexBeforeAfter(stats, 2, 3, THIRD_START - MINUTE_IN_MILLIS); 500 assertIndexBeforeAfter(stats, 2, 4, THIRD_START); 501 assertIndexBeforeAfter(stats, 3, 4, THIRD_START + MINUTE_IN_MILLIS); 502 assertIndexBeforeAfter(stats, 3, 4, THIRD_START + HOUR_IN_MILLIS); 503 assertIndexBeforeAfter(stats, 4, 4, THIRD_END); 504 assertIndexBeforeAfter(stats, 4, 4, THIRD_END + MINUTE_IN_MILLIS); 505 assertIndexBeforeAfter(stats, 4, 4, Long.MAX_VALUE); 506 } 507 508 @Test testIntersects()509 public void testIntersects() throws Exception { 510 final long BUCKET_SIZE = HOUR_IN_MILLIS; 511 stats = new NetworkStatsHistory(BUCKET_SIZE); 512 513 final long FIRST_START = TEST_START; 514 final long FIRST_END = FIRST_START + (2 * HOUR_IN_MILLIS); 515 final long SECOND_START = TEST_START + WEEK_IN_MILLIS; 516 final long SECOND_END = SECOND_START + HOUR_IN_MILLIS; 517 final long THIRD_START = TEST_START + (2 * WEEK_IN_MILLIS); 518 final long THIRD_END = THIRD_START + (2 * HOUR_IN_MILLIS); 519 520 stats.recordData(FIRST_START, FIRST_END, 521 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 522 ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 10L, 2048L, 20L, 2L)); 523 stats.recordData(SECOND_START, SECOND_END, 524 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 525 ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 10L, 2048L, 20L, 2L)); 526 stats.recordData(THIRD_START, THIRD_END, 527 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 528 ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 10L, 2048L, 20L, 2L)); 529 530 assertFalse(stats.intersects(10, 20)); 531 assertFalse(stats.intersects(TEST_START + YEAR_IN_MILLIS, TEST_START + YEAR_IN_MILLIS + 1)); 532 assertFalse(stats.intersects(Long.MAX_VALUE, Long.MIN_VALUE)); 533 534 assertTrue(stats.intersects(Long.MIN_VALUE, Long.MAX_VALUE)); 535 assertTrue(stats.intersects(10, TEST_START + YEAR_IN_MILLIS)); 536 assertTrue(stats.intersects(TEST_START, TEST_START)); 537 assertTrue(stats.intersects(TEST_START + DAY_IN_MILLIS, TEST_START + DAY_IN_MILLIS + 1)); 538 assertTrue(stats.intersects(TEST_START + DAY_IN_MILLIS, Long.MAX_VALUE)); 539 assertTrue(stats.intersects(TEST_START + 1, Long.MAX_VALUE)); 540 541 assertFalse(stats.intersects(Long.MIN_VALUE, TEST_START - 1)); 542 assertTrue(stats.intersects(Long.MIN_VALUE, TEST_START)); 543 assertTrue(stats.intersects(Long.MIN_VALUE, TEST_START + 1)); 544 } 545 546 @Test testSetValues()547 public void testSetValues() throws Exception { 548 stats = new NetworkStatsHistory(HOUR_IN_MILLIS); 549 stats.recordData(TEST_START, TEST_START + 1, 550 new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, 551 ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 10L, 2048L, 20L, 2L)); 552 553 assertEquals(1024L + 2048L, stats.getTotalBytes()); 554 555 final NetworkStatsHistory.Entry entry = stats.getValues(0, null); 556 entry.rxBytes /= 2; 557 entry.txBytes *= 2; 558 stats.setValues(0, entry); 559 560 assertEquals(512L + 4096L, stats.getTotalBytes()); 561 } 562 assertIndexBeforeAfter( NetworkStatsHistory stats, int before, int after, long time)563 private static void assertIndexBeforeAfter( 564 NetworkStatsHistory stats, int before, int after, long time) { 565 assertEquals("unexpected before", before, stats.getIndexBefore(time)); 566 assertEquals("unexpected after", after, stats.getIndexAfter(time)); 567 } 568 performVarLong(long before)569 private static long performVarLong(long before) throws Exception { 570 final ByteArrayOutputStream out = new ByteArrayOutputStream(); 571 writeVarLong(new DataOutputStream(out), before); 572 573 final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); 574 return readVarLong(new DataInputStream(in)); 575 } 576 assertConsistent(NetworkStatsHistory stats)577 private static void assertConsistent(NetworkStatsHistory stats) { 578 // verify timestamps are monotonic 579 long lastStart = Long.MIN_VALUE; 580 NetworkStatsHistory.Entry entry = null; 581 for (int i = 0; i < stats.size(); i++) { 582 entry = stats.getValues(i, entry); 583 assertTrue(lastStart < entry.bucketStart); 584 lastStart = entry.bucketStart; 585 } 586 } 587 588 private static void assertValues( 589 NetworkStatsHistory stats, int index, long rxBytes, long txBytes) { 590 final NetworkStatsHistory.Entry entry = stats.getValues(index, null); 591 assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); 592 assertEquals("unexpected txBytes", txBytes, entry.txBytes); 593 } 594 595 private static void assertValues( 596 NetworkStatsHistory stats, long start, long end, long rxBytes, long txBytes) { 597 final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null); 598 assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); 599 assertEquals("unexpected txBytes", txBytes, entry.txBytes); 600 } 601 602 private static void assertValues(NetworkStatsHistory stats, int index, long activeTime, 603 long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { 604 final NetworkStatsHistory.Entry entry = stats.getValues(index, null); 605 assertEquals("unexpected activeTime", activeTime, entry.activeTime); 606 assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); 607 assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); 608 assertEquals("unexpected txBytes", txBytes, entry.txBytes); 609 assertEquals("unexpected txPackets", txPackets, entry.txPackets); 610 assertEquals("unexpected operations", operations, entry.operations); 611 } 612 613 private static void assertFullValues(NetworkStatsHistory stats, long activeTime, long rxBytes, 614 long rxPackets, long txBytes, long txPackets, long operations) { 615 assertValues(stats, Long.MIN_VALUE, Long.MAX_VALUE, activeTime, rxBytes, rxPackets, txBytes, 616 txPackets, operations); 617 } 618 619 private static void assertValues(NetworkStatsHistory stats, long start, long end, 620 long activeTime, long rxBytes, long rxPackets, long txBytes, long txPackets, 621 long operations) { 622 final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null); 623 assertEquals("unexpected activeTime", activeTime, entry.activeTime); 624 assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); 625 assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); 626 assertEquals("unexpected txBytes", txBytes, entry.txBytes); 627 assertEquals("unexpected txPackets", txPackets, entry.txPackets); 628 assertEquals("unexpected operations", operations, entry.operations); 629 } 630 } 631