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
17package com.android.server.net;
18
19import static android.net.NetworkStats.SET_DEFAULT;
20import static android.net.NetworkStats.TAG_NONE;
21import static android.net.NetworkStats.UID_ALL;
22import static android.net.NetworkTemplate.buildTemplateMobileAll;
23import static android.text.format.DateUtils.HOUR_IN_MILLIS;
24import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
25
26import android.content.res.Resources;
27import android.net.NetworkStats;
28import android.net.NetworkTemplate;
29import android.test.AndroidTestCase;
30import android.test.suitebuilder.annotation.MediumTest;
31
32import com.android.frameworks.servicestests.R;
33
34import java.io.ByteArrayInputStream;
35import java.io.ByteArrayOutputStream;
36import java.io.DataOutputStream;
37import java.io.File;
38import java.io.FileOutputStream;
39import java.io.InputStream;
40import java.io.OutputStream;
41
42import libcore.io.IoUtils;
43import libcore.io.Streams;
44
45/**
46 * Tests for {@link NetworkStatsCollection}.
47 */
48@MediumTest
49public class NetworkStatsCollectionTest extends AndroidTestCase {
50
51    private static final String TEST_FILE = "test.bin";
52    private static final String TEST_IMSI = "310260000000000";
53
54    @Override
55    public void setUp() throws Exception {
56        super.setUp();
57
58        // ignore any device overlay while testing
59        NetworkTemplate.forceAllNetworkTypes();
60    }
61
62    public void testReadLegacyNetwork() throws Exception {
63        final File testFile = new File(getContext().getFilesDir(), TEST_FILE);
64        stageFile(R.raw.netstats_v1, testFile);
65
66        final NetworkStatsCollection collection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS);
67        collection.readLegacyNetwork(testFile);
68
69        // verify that history read correctly
70        assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI),
71                636016770L, 709306L, 88038768L, 518836L);
72
73        // now export into a unified format
74        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
75        collection.write(new DataOutputStream(bos));
76
77        // clear structure completely
78        collection.reset();
79        assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI),
80                0L, 0L, 0L, 0L);
81
82        // and read back into structure, verifying that totals are same
83        collection.read(new ByteArrayInputStream(bos.toByteArray()));
84        assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI),
85                636016770L, 709306L, 88038768L, 518836L);
86    }
87
88    public void testReadLegacyUid() throws Exception {
89        final File testFile = new File(getContext().getFilesDir(), TEST_FILE);
90        stageFile(R.raw.netstats_uid_v4, testFile);
91
92        final NetworkStatsCollection collection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS);
93        collection.readLegacyUid(testFile, false);
94
95        // verify that history read correctly
96        assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI),
97                637076152L, 711413L, 88343717L, 521022L);
98
99        // now export into a unified format
100        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
101        collection.write(new DataOutputStream(bos));
102
103        // clear structure completely
104        collection.reset();
105        assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI),
106                0L, 0L, 0L, 0L);
107
108        // and read back into structure, verifying that totals are same
109        collection.read(new ByteArrayInputStream(bos.toByteArray()));
110        assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI),
111                637076152L, 711413L, 88343717L, 521022L);
112    }
113
114    public void testReadLegacyUidTags() throws Exception {
115        final File testFile = new File(getContext().getFilesDir(), TEST_FILE);
116        stageFile(R.raw.netstats_uid_v4, testFile);
117
118        final NetworkStatsCollection collection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS);
119        collection.readLegacyUid(testFile, true);
120
121        // verify that history read correctly
122        assertSummaryTotalIncludingTags(collection, buildTemplateMobileAll(TEST_IMSI),
123                77017831L, 100995L, 35436758L, 92344L);
124
125        // now export into a unified format
126        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
127        collection.write(new DataOutputStream(bos));
128
129        // clear structure completely
130        collection.reset();
131        assertSummaryTotalIncludingTags(collection, buildTemplateMobileAll(TEST_IMSI),
132                0L, 0L, 0L, 0L);
133
134        // and read back into structure, verifying that totals are same
135        collection.read(new ByteArrayInputStream(bos.toByteArray()));
136        assertSummaryTotalIncludingTags(collection, buildTemplateMobileAll(TEST_IMSI),
137                77017831L, 100995L, 35436758L, 92344L);
138    }
139
140    public void testStartEndAtomicBuckets() throws Exception {
141        final NetworkStatsCollection collection = new NetworkStatsCollection(HOUR_IN_MILLIS);
142
143        // record empty data straddling between buckets
144        final NetworkStats.Entry entry = new NetworkStats.Entry();
145        entry.rxBytes = 32;
146        collection.recordData(null, UID_ALL, SET_DEFAULT, TAG_NONE, 30 * MINUTE_IN_MILLIS,
147                90 * MINUTE_IN_MILLIS, entry);
148
149        // assert that we report boundary in atomic buckets
150        assertEquals(0, collection.getStartMillis());
151        assertEquals(2 * HOUR_IN_MILLIS, collection.getEndMillis());
152    }
153
154    /**
155     * Copy a {@link Resources#openRawResource(int)} into {@link File} for
156     * testing purposes.
157     */
158    private void stageFile(int rawId, File file) throws Exception {
159        new File(file.getParent()).mkdirs();
160        InputStream in = null;
161        OutputStream out = null;
162        try {
163            in = getContext().getResources().openRawResource(rawId);
164            out = new FileOutputStream(file);
165            Streams.copy(in, out);
166        } finally {
167            IoUtils.closeQuietly(in);
168            IoUtils.closeQuietly(out);
169        }
170    }
171
172    private static void assertSummaryTotal(NetworkStatsCollection collection,
173            NetworkTemplate template, long rxBytes, long rxPackets, long txBytes, long txPackets) {
174        final NetworkStats.Entry entry = collection.getSummary(
175                template, Long.MIN_VALUE, Long.MAX_VALUE).getTotal(null);
176        assertEntry(entry, rxBytes, rxPackets, txBytes, txPackets);
177    }
178
179    private static void assertSummaryTotalIncludingTags(NetworkStatsCollection collection,
180            NetworkTemplate template, long rxBytes, long rxPackets, long txBytes, long txPackets) {
181        final NetworkStats.Entry entry = collection.getSummary(
182                template, Long.MIN_VALUE, Long.MAX_VALUE).getTotalIncludingTags(null);
183        assertEntry(entry, rxBytes, rxPackets, txBytes, txPackets);
184    }
185
186    private static void assertEntry(
187            NetworkStats.Entry entry, long rxBytes, long rxPackets, long txBytes, long txPackets) {
188        assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
189        assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets);
190        assertEquals("unexpected txBytes", txBytes, entry.txBytes);
191        assertEquals("unexpected txPackets", txPackets, entry.txPackets);
192    }
193}
194