NetworkStatsHistoryTest.java revision d37948f6ed1667d077e0e3a38808f42f981ddcc2
175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey/* 275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Copyright (C) 2011 The Android Open Source Project 375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * 475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * you may not use this file except in compliance with the License. 675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * You may obtain a copy of the License at 775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * 875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * 1075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 1175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 1275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * See the License for the specific language governing permissions and 1475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * limitations under the License. 1575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */ 1675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 1775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeypackage android.net; 1875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 1975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport static android.text.format.DateUtils.DAY_IN_MILLIS; 2075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport static android.text.format.DateUtils.HOUR_IN_MILLIS; 2175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport static android.text.format.DateUtils.MINUTE_IN_MILLIS; 2275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport static android.text.format.DateUtils.SECOND_IN_MILLIS; 2375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport static android.text.format.DateUtils.WEEK_IN_MILLIS; 2475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport static android.text.format.DateUtils.YEAR_IN_MILLIS; 2575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 2675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.test.suitebuilder.annotation.SmallTest; 2775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.test.suitebuilder.annotation.Suppress; 2875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.util.Log; 2975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 3075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport junit.framework.TestCase; 3175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 3275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.util.Random; 3375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 3475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey@SmallTest 3575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeypublic class NetworkStatsHistoryTest extends TestCase { 3675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private static final String TAG = "NetworkStatsHistoryTest"; 3775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 3875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private static final long TEST_START = 1194220800000L; 3975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 4075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private NetworkStatsHistory stats; 4175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 4275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey @Override 4375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey protected void tearDown() throws Exception { 4475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey super.tearDown(); 4575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (stats != null) { 4675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey assertConsistent(stats); 4775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 4875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 4975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 5075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void testRecordSingleBucket() throws Exception { 5175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long BUCKET_SIZE = HOUR_IN_MILLIS; 52d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey stats = new NetworkStatsHistory(BUCKET_SIZE); 5375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 5475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // record data into narrow window to get single bucket 5575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS, 1024L, 2048L); 5675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 57d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEquals(1, stats.size()); 58d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 0, 1024L, 2048L); 5975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 6075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 6175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void testRecordEqualBuckets() throws Exception { 6275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long bucketDuration = HOUR_IN_MILLIS; 63d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey stats = new NetworkStatsHistory(bucketDuration); 6475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 6575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // split equally across two buckets 6675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long recordStart = TEST_START + (bucketDuration / 2); 6775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey stats.recordData(recordStart, recordStart + bucketDuration, 1024L, 128L); 6875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 69d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEquals(2, stats.size()); 70d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 0, 512L, 64L); 71d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 1, 512L, 64L); 7275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 7375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 7475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void testRecordTouchingBuckets() throws Exception { 7575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long BUCKET_SIZE = 15 * MINUTE_IN_MILLIS; 76d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey stats = new NetworkStatsHistory(BUCKET_SIZE); 7775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 7875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // split almost completely into middle bucket, but with a few minutes 7975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // overlap into neighboring buckets. total record is 20 minutes. 8075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long recordStart = (TEST_START + BUCKET_SIZE) - MINUTE_IN_MILLIS; 8175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long recordEnd = (TEST_START + (BUCKET_SIZE * 2)) + (MINUTE_IN_MILLIS * 4); 8275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey stats.recordData(recordStart, recordEnd, 1000L, 5000L); 8375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 84d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEquals(3, stats.size()); 8575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // first bucket should have (1/20 of value) 86d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 0, 50L, 250L); 8775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // second bucket should have (15/20 of value) 88d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 1, 750L, 3750L); 8975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // final bucket should have (4/20 of value) 90d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 2, 200L, 1000L); 9175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 9275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 9375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void testRecordGapBuckets() throws Exception { 9475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long BUCKET_SIZE = HOUR_IN_MILLIS; 95d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey stats = new NetworkStatsHistory(BUCKET_SIZE); 9675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 9775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // record some data today and next week with large gap 9875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long firstStart = TEST_START; 9975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long lastStart = TEST_START + WEEK_IN_MILLIS; 10075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey stats.recordData(firstStart, firstStart + SECOND_IN_MILLIS, 128L, 256L); 10175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey stats.recordData(lastStart, lastStart + SECOND_IN_MILLIS, 64L, 512L); 10275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 10375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // we should have two buckets, far apart from each other 104d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEquals(2, stats.size()); 105d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 0, 128L, 256L); 106d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 1, 64L, 512L); 10775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 10875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // now record something in middle, spread across two buckets 10975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long middleStart = TEST_START + DAY_IN_MILLIS; 11075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long middleEnd = middleStart + (HOUR_IN_MILLIS * 2); 11175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey stats.recordData(middleStart, middleEnd, 2048L, 2048L); 11275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 11375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // now should have four buckets, with new record in middle two buckets 114d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEquals(4, stats.size()); 115d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 0, 128L, 256L); 116d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 1, 1024L, 1024L); 117d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 2, 1024L, 1024L); 118d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 3, 64L, 512L); 11975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 12075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 12175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void testRecordOverlapBuckets() throws Exception { 12275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long BUCKET_SIZE = HOUR_IN_MILLIS; 123d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey stats = new NetworkStatsHistory(BUCKET_SIZE); 12475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 12575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // record some data in one bucket, and another overlapping buckets 12675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS, 256L, 256L); 12775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long midStart = TEST_START + (HOUR_IN_MILLIS / 2); 12875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey stats.recordData(midStart, midStart + HOUR_IN_MILLIS, 1024L, 1024L); 12975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 13075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // should have two buckets, with some data mixed together 131d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEquals(2, stats.size()); 132d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 0, 768L, 768L); 133d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 1, 512L, 512L); 13475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 13575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 13619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey public void testRecordEntireGapIdentical() throws Exception { 13719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey final long[] total = new long[2]; 13819862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 13919862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey // first, create two separate histories far apart 14019862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey final NetworkStatsHistory stats1 = new NetworkStatsHistory(HOUR_IN_MILLIS); 14119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats1.recordData(TEST_START, TEST_START + 2 * HOUR_IN_MILLIS, 2000L, 1000L); 14219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 14319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey final long TEST_START_2 = TEST_START + DAY_IN_MILLIS; 14419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey final NetworkStatsHistory stats2 = new NetworkStatsHistory(HOUR_IN_MILLIS); 14519862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats2.recordData(TEST_START_2, TEST_START_2 + 2 * HOUR_IN_MILLIS, 1000L, 500L); 14619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 14719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey // combine together with identical bucket size 14819862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats = new NetworkStatsHistory(HOUR_IN_MILLIS); 14919862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats.recordEntireHistory(stats1); 15019862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats.recordEntireHistory(stats2); 15119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 15219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey // first verify that totals match up 15319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, total); 15419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey assertTotalEquals(total, 3000L, 1500L); 15519862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 15619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey // now inspect internal buckets 157d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 0, 1000L, 500L); 158d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 1, 1000L, 500L); 159d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 2, 500L, 250L); 160d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 3, 500L, 250L); 16119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey } 16219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 16319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey public void testRecordEntireOverlapVaryingBuckets() throws Exception { 16419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey final long[] total = new long[2]; 16519862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 16619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey // create history just over hour bucket boundary 16719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey final NetworkStatsHistory stats1 = new NetworkStatsHistory(HOUR_IN_MILLIS); 16819862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats1.recordData(TEST_START, TEST_START + MINUTE_IN_MILLIS * 60, 600L, 600L); 16919862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 17019862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey final long TEST_START_2 = TEST_START + MINUTE_IN_MILLIS; 17119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey final NetworkStatsHistory stats2 = new NetworkStatsHistory(MINUTE_IN_MILLIS); 17219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats2.recordData(TEST_START_2, TEST_START_2 + MINUTE_IN_MILLIS * 5, 50L, 50L); 17319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 17419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey // combine together with minute bucket size 17519862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats = new NetworkStatsHistory(MINUTE_IN_MILLIS); 17619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats.recordEntireHistory(stats1); 17719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats.recordEntireHistory(stats2); 17819862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 17919862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey // first verify that totals match up 18019862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, total); 18119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey assertTotalEquals(total, 650L, 650L); 18219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 18319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey // now inspect internal buckets 184d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 0, 10L, 10L); 185d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 1, 20L, 20L); 186d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 2, 20L, 20L); 187d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 3, 20L, 20L); 188d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 4, 20L, 20L); 189d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 5, 20L, 20L); 190d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 6, 10L, 10L); 19119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 19219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey // now combine using 15min buckets 19319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats = new NetworkStatsHistory(HOUR_IN_MILLIS / 4); 19419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats.recordEntireHistory(stats1); 19519862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats.recordEntireHistory(stats2); 19619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 19719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey // first verify that totals match up 19819862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, total); 19919862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey assertTotalEquals(total, 650L, 650L); 20019862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 20119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey // and inspect buckets 202d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 0, 200L, 200L); 203d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 1, 150L, 150L); 204d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 2, 150L, 150L); 205d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEntry(stats, 3, 150L, 150L); 20619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey } 20719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 20875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void testRemove() throws Exception { 20919862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats = new NetworkStatsHistory(HOUR_IN_MILLIS); 21075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 21175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // record some data across 24 buckets 21275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey stats.recordData(TEST_START, TEST_START + DAY_IN_MILLIS, 24L, 24L); 213d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEquals(24, stats.size()); 21475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 21575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // try removing far before buckets; should be no change 21675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey stats.removeBucketsBefore(TEST_START - YEAR_IN_MILLIS); 217d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEquals(24, stats.size()); 21875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 21975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // try removing just moments into first bucket; should be no change 22075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // since that bucket contains data beyond the cutoff 22175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey stats.removeBucketsBefore(TEST_START + SECOND_IN_MILLIS); 222d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEquals(24, stats.size()); 22375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 22475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // try removing single bucket 22575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey stats.removeBucketsBefore(TEST_START + HOUR_IN_MILLIS); 226d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEquals(23, stats.size()); 22775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 22875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // try removing multiple buckets 22975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey stats.removeBucketsBefore(TEST_START + (4 * HOUR_IN_MILLIS)); 230d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEquals(20, stats.size()); 23175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 23275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // try removing all buckets 23375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey stats.removeBucketsBefore(TEST_START + YEAR_IN_MILLIS); 234d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEquals(0, stats.size()); 23575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 23675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 23719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey public void testTotalData() throws Exception { 23819862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey final long BUCKET_SIZE = HOUR_IN_MILLIS; 23919862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats = new NetworkStatsHistory(BUCKET_SIZE); 24019862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 24119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey // record uniform data across day 24219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats.recordData(TEST_START, TEST_START + DAY_IN_MILLIS, 2400L, 4800L); 24319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 24419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey final long[] total = new long[2]; 24519862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 24619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey // verify that total outside range is 0 24719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START - DAY_IN_MILLIS, total); 24819862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey assertTotalEquals(total, 0, 0); 24919862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 25019862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey // verify total in first hour 25119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats.getTotalData(TEST_START, TEST_START + HOUR_IN_MILLIS, total); 25219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey assertTotalEquals(total, 100, 200); 25319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 25419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey // verify total across 1.5 hours 25519862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats.getTotalData(TEST_START, TEST_START + (long) (1.5 * HOUR_IN_MILLIS), total); 25619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey assertTotalEquals(total, 150, 300); 25719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 25819862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey // verify total beyond end 25919862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats.getTotalData(TEST_START + (23 * HOUR_IN_MILLIS), TEST_START + WEEK_IN_MILLIS, total); 26019862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey assertTotalEquals(total, 100, 200); 26119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 26219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey // verify everything total 26319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, total); 26419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey assertTotalEquals(total, 2400, 4800); 26519862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 26619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey } 26719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 26875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey @Suppress 26975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey public void testFuzzing() throws Exception { 27075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey try { 27175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // fuzzing with random events, looking for crashes 27275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final Random r = new Random(); 27375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (int i = 0; i < 500; i++) { 274d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey stats = new NetworkStatsHistory(r.nextLong()); 27575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey for (int j = 0; j < 10000; j++) { 27675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey if (r.nextBoolean()) { 27775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // add range 27875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long start = r.nextLong(); 27975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey final long end = start + r.nextInt(); 28075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey stats.recordData(start, end, r.nextLong(), r.nextLong()); 28175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } else { 28275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // trim something 28375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey stats.removeBucketsBefore(r.nextLong()); 28475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 28575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 28675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey assertConsistent(stats); 28775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 28875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } catch (Throwable e) { 28975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey Log.e(TAG, String.valueOf(stats)); 29075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey throw new RuntimeException(e); 29175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 29275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 29375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 29475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey private static void assertConsistent(NetworkStatsHistory stats) { 29575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey // verify timestamps are monotonic 296d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey long lastStart = Long.MIN_VALUE; 297d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey NetworkStatsHistory.Entry entry = null; 298d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey for (int i = 0; i < stats.size(); i++) { 299d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey entry = stats.getValues(i, entry); 300d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertTrue(lastStart < entry.bucketStart); 301d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey lastStart = entry.bucketStart; 30275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 30375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 30475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 305d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private static void assertTotalEquals(long[] total, long rxBytes, long txBytes) { 306d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEquals("unexpected rxBytes", rxBytes, total[0]); 307d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEquals("unexpected txBytes", txBytes, total[1]); 30819862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey } 30919862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey 310d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey private static void assertEntry( 311d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey NetworkStatsHistory stats, int index, long rxBytes, long txBytes) { 312d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey final NetworkStatsHistory.Entry entry = stats.getValues(index, null); 313d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); 314d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey assertEquals("unexpected txBytes", txBytes, entry.txBytes); 31575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey } 31675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey 31775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey} 318