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