blob: b48ff8da2ba4d54dc9961bec53dc0ed292e1b8a3 [file] [log] [blame]
Hugo Benichi00a42d42016-09-13 15:55:09 +09001/*
2 * Copyright (C) 2016, 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.connectivity;
18
Hugo Benichi5eb90532017-03-23 18:38:22 +090019import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO;
20import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME;
Hugo Benichi1193a9c2017-10-19 14:58:15 +090021import static org.mockito.Mockito.mock;
Glen Kuhne07199402016-10-25 15:47:25 -070022import static org.mockito.Mockito.timeout;
23import static org.mockito.Mockito.verify;
Hugo Benichi5eb90532017-03-23 18:38:22 +090024import static org.mockito.Mockito.when;
25import static org.junit.Assert.assertEquals;
26import static org.junit.Assert.assertFalse;
27import static org.junit.Assert.assertTrue;
28import static org.junit.Assert.fail;
Glen Kuhne07199402016-10-25 15:47:25 -070029
Hugo Benichi00a42d42016-09-13 15:55:09 +090030import android.content.Context;
Hugo Benichi5eb90532017-03-23 18:38:22 +090031import android.net.ConnectivityManager;
Hugo Benichi00a42d42016-09-13 15:55:09 +090032import android.net.ConnectivityMetricsEvent;
33import android.net.IIpConnectivityMetrics;
Hugo Benichi1193a9c2017-10-19 14:58:15 +090034import android.net.IpPrefix;
35import android.net.LinkAddress;
36import android.net.LinkProperties;
37import android.net.RouteInfo;
Hugo Benichi5eb90532017-03-23 18:38:22 +090038import android.net.Network;
39import android.net.NetworkCapabilities;
Hugo Benichie1c173d2016-10-18 10:36:33 +090040import android.net.metrics.ApfProgramEvent;
Hugo Benichi00a42d42016-09-13 15:55:09 +090041import android.net.metrics.ApfStats;
42import android.net.metrics.DefaultNetworkEvent;
43import android.net.metrics.DhcpClientEvent;
44import android.net.metrics.IpConnectivityLog;
45import android.net.metrics.IpManagerEvent;
46import android.net.metrics.IpReachabilityEvent;
47import android.net.metrics.RaEvent;
48import android.net.metrics.ValidationProbeEvent;
49import android.os.Parcelable;
Hugo Benichi5eb90532017-03-23 18:38:22 +090050import android.support.test.runner.AndroidJUnit4;
Hugo Benichi1193a9c2017-10-19 14:58:15 +090051import android.system.OsConstants;
Hugo Benichi80df43e2016-11-24 11:28:06 +090052import android.test.suitebuilder.annotation.SmallTest;
Hugo Benichi00a42d42016-09-13 15:55:09 +090053import android.util.Base64;
Hugo Benichi1193a9c2017-10-19 14:58:15 +090054
55import com.android.internal.util.BitUtils;
Tamas Berghammer383db5eb2016-06-22 15:21:38 +010056import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
Hugo Benichi1193a9c2017-10-19 14:58:15 +090057
Hugo Benichi00a42d42016-09-13 15:55:09 +090058import java.io.PrintWriter;
59import java.io.StringWriter;
60import java.util.Collections;
61import java.util.Comparator;
62import java.util.Iterator;
63import java.util.List;
Hugo Benichi1193a9c2017-10-19 14:58:15 +090064
Hugo Benichi80df43e2016-11-24 11:28:06 +090065import org.mockito.ArgumentCaptor;
66import org.mockito.Mock;
67import org.mockito.MockitoAnnotations;
Hugo Benichi5eb90532017-03-23 18:38:22 +090068import org.junit.Before;
69import org.junit.Test;
70import org.junit.runner.RunWith;
Hugo Benichi00a42d42016-09-13 15:55:09 +090071
Hugo Benichi5eb90532017-03-23 18:38:22 +090072@RunWith(AndroidJUnit4.class)
73@SmallTest
74public class IpConnectivityMetricsTest {
Hugo Benichi00a42d42016-09-13 15:55:09 +090075 static final IpReachabilityEvent FAKE_EV =
Hugo Benichi948a8592017-03-16 16:33:47 +090076 new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED);
Hugo Benichi00a42d42016-09-13 15:55:09 +090077
Hugo Benichi5eb90532017-03-23 18:38:22 +090078 private static final String EXAMPLE_IPV4 = "192.0.2.1";
79 private static final String EXAMPLE_IPV6 = "2001:db8:1200::2:1";
80
Hugo Benichi00a42d42016-09-13 15:55:09 +090081 @Mock Context mCtx;
82 @Mock IIpConnectivityMetrics mMockService;
Hugo Benichi5eb90532017-03-23 18:38:22 +090083 @Mock ConnectivityManager mCm;
Hugo Benichi00a42d42016-09-13 15:55:09 +090084
85 IpConnectivityMetrics mService;
Hugo Benichi5eb90532017-03-23 18:38:22 +090086 NetdEventListenerService mNetdListener;
Hugo Benichi00a42d42016-09-13 15:55:09 +090087
Hugo Benichi5eb90532017-03-23 18:38:22 +090088 @Before
Hugo Benichi00a42d42016-09-13 15:55:09 +090089 public void setUp() {
90 MockitoAnnotations.initMocks(this);
Hugo Benichi05686db2016-10-19 11:17:28 +090091 mService = new IpConnectivityMetrics(mCtx, (ctx) -> 2000);
Hugo Benichi5eb90532017-03-23 18:38:22 +090092 mNetdListener = new NetdEventListenerService(mCm);
93 mService.mNetdListener = mNetdListener;
Hugo Benichi00a42d42016-09-13 15:55:09 +090094 }
95
Hugo Benichi5eb90532017-03-23 18:38:22 +090096 @Test
Hugo Benichi00a42d42016-09-13 15:55:09 +090097 public void testLoggingEvents() throws Exception {
98 IpConnectivityLog logger = new IpConnectivityLog(mMockService);
99
100 assertTrue(logger.log(1, FAKE_EV));
101 assertTrue(logger.log(2, FAKE_EV));
102 assertTrue(logger.log(3, FAKE_EV));
103
104 List<ConnectivityMetricsEvent> got = verifyEvents(3);
105 assertEventsEqual(expectedEvent(1), got.get(0));
106 assertEventsEqual(expectedEvent(2), got.get(1));
107 assertEventsEqual(expectedEvent(3), got.get(2));
108 }
109
Hugo Benichi5eb90532017-03-23 18:38:22 +0900110 @Test
Hugo Benichi00a42d42016-09-13 15:55:09 +0900111 public void testLoggingEventsWithMultipleCallers() throws Exception {
112 IpConnectivityLog logger = new IpConnectivityLog(mMockService);
113
114 final int nCallers = 10;
115 final int nEvents = 10;
116 for (int n = 0; n < nCallers; n++) {
117 final int i = n;
118 new Thread() {
119 public void run() {
120 for (int j = 0; j < nEvents; j++) {
Hugo Benichi946b7e42017-03-15 16:35:26 +0900121 assertTrue(logger.log(1 + i * 100 + j, FAKE_EV));
Hugo Benichi00a42d42016-09-13 15:55:09 +0900122 }
123 }
124 }.start();
125 }
126
Hugo Benichi5eb90532017-03-23 18:38:22 +0900127 List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 200);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900128 Collections.sort(got, EVENT_COMPARATOR);
129 Iterator<ConnectivityMetricsEvent> iter = got.iterator();
130 for (int i = 0; i < nCallers; i++) {
131 for (int j = 0; j < nEvents; j++) {
Hugo Benichi946b7e42017-03-15 16:35:26 +0900132 int expectedTimestamp = 1 + i * 100 + j;
Hugo Benichi00a42d42016-09-13 15:55:09 +0900133 assertEventsEqual(expectedEvent(expectedTimestamp), iter.next());
134 }
135 }
136 }
137
Hugo Benichi5eb90532017-03-23 18:38:22 +0900138 @Test
Hugo Benichi00a42d42016-09-13 15:55:09 +0900139 public void testBufferFlushing() {
140 String output1 = getdump("flush");
141 assertEquals("", output1);
142
143 new IpConnectivityLog(mService.impl).log(1, FAKE_EV);
144 String output2 = getdump("flush");
145 assertFalse("".equals(output2));
146
147 String output3 = getdump("flush");
148 assertEquals("", output3);
149 }
150
Hugo Benichi5eb90532017-03-23 18:38:22 +0900151 @Test
Hugo Benichie1c173d2016-10-18 10:36:33 +0900152 public void testRateLimiting() {
153 final IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900154 final ApfProgramEvent ev = new ApfProgramEvent();
Hugo Benichie1c173d2016-10-18 10:36:33 +0900155 final long fakeTimestamp = 1;
156
157 int attempt = 100; // More than burst quota, but less than buffer size.
158 for (int i = 0; i < attempt; i++) {
159 logger.log(ev);
160 }
161
162 String output1 = getdump("flush");
163 assertFalse("".equals(output1));
164
165 for (int i = 0; i < attempt; i++) {
166 assertFalse("expected event to be dropped", logger.log(fakeTimestamp, ev));
167 }
168
169 String output2 = getdump("flush");
170 assertEquals("", output2);
171 }
172
Hugo Benichi5eb90532017-03-23 18:38:22 +0900173 @Test
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900174 public void testDefaultNetworkEvents() throws Exception {
175 final long cell = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
176 final long wifi = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_WIFI});
177
178 NetworkAgentInfo[][] defaultNetworks = {
179 // nothing -> cell
180 {null, makeNai(100, 10, false, true, cell)},
181 // cell -> wifi
182 {makeNai(100, 50, true, true, cell), makeNai(101, 20, true, false, wifi)},
183 // wifi -> nothing
184 {makeNai(101, 60, true, false, wifi), null},
185 // nothing -> cell
186 {null, makeNai(102, 10, true, true, cell)},
187 // cell -> wifi
188 {makeNai(102, 50, true, true, cell), makeNai(103, 20, true, false, wifi)},
189 };
190
Hugo Benichi380a0632017-10-20 09:25:29 +0900191 long timeMs = mService.mDefaultNetworkMetrics.creationTimeMs;
192 long durationMs = 1001;
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900193 for (NetworkAgentInfo[] pair : defaultNetworks) {
Hugo Benichi380a0632017-10-20 09:25:29 +0900194 timeMs += durationMs;
195 durationMs += durationMs;
196 mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(timeMs, pair[1], pair[0]);
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900197 }
198
199 String want = String.join("\n",
200 "dropped_events: 0",
201 "events <",
202 " if_name: \"\"",
Hugo Benichi380a0632017-10-20 09:25:29 +0900203 " link_layer: 5",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900204 " network_id: 0",
205 " time_ms: 0",
206 " transports: 0",
207 " default_network_event <",
Hugo Benichi380a0632017-10-20 09:25:29 +0900208 " default_network_duration_ms: 1001",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900209 " final_score: 0",
210 " initial_score: 0",
211 " ip_support: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900212 " no_default_network_duration_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900213 " previous_default_network_link_layer: 0",
214 " previous_network_ip_support: 0",
215 " validation_duration_ms: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900216 " >",
217 ">",
218 "events <",
219 " if_name: \"\"",
Hugo Benichi380a0632017-10-20 09:25:29 +0900220 " link_layer: 2",
221 " network_id: 100",
222 " time_ms: 0",
223 " transports: 1",
224 " default_network_event <",
225 " default_network_duration_ms: 2002",
226 " final_score: 50",
227 " initial_score: 10",
228 " ip_support: 3",
229 " no_default_network_duration_ms: 0",
230 " previous_default_network_link_layer: 0",
231 " previous_network_ip_support: 0",
232 " validation_duration_ms: 2002",
233 " >",
234 ">",
235 "events <",
236 " if_name: \"\"",
237 " link_layer: 4",
238 " network_id: 101",
239 " time_ms: 0",
240 " transports: 2",
241 " default_network_event <",
242 " default_network_duration_ms: 4004",
243 " final_score: 60",
244 " initial_score: 20",
245 " ip_support: 1",
246 " no_default_network_duration_ms: 0",
247 " previous_default_network_link_layer: 2",
248 " previous_network_ip_support: 0",
249 " validation_duration_ms: 4004",
250 " >",
251 ">",
252 "events <",
253 " if_name: \"\"",
254 " link_layer: 5",
255 " network_id: 0",
256 " time_ms: 0",
257 " transports: 0",
258 " default_network_event <",
259 " default_network_duration_ms: 8008",
260 " final_score: 0",
261 " initial_score: 0",
262 " ip_support: 0",
263 " no_default_network_duration_ms: 0",
264 " previous_default_network_link_layer: 4",
265 " previous_network_ip_support: 0",
266 " validation_duration_ms: 0",
267 " >",
268 ">",
269 "events <",
270 " if_name: \"\"",
271 " link_layer: 2",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900272 " network_id: 102",
273 " time_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900274 " transports: 1",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900275 " default_network_event <",
Hugo Benichi380a0632017-10-20 09:25:29 +0900276 " default_network_duration_ms: 16016",
277 " final_score: 50",
278 " initial_score: 10",
279 " ip_support: 3",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900280 " no_default_network_duration_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900281 " previous_default_network_link_layer: 4",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900282 " previous_network_ip_support: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900283 " validation_duration_ms: 16016",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900284 " >",
285 ">",
286 "version: 2\n");
287
288 verifySerialization(want, getdump("flush"));
289 }
290
291 @Test
Hugo Benichi5eb90532017-03-23 18:38:22 +0900292 public void testEndToEndLogging() throws Exception {
Hugo Benichif6840502017-03-08 11:59:36 +0900293 // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
Hugo Benichi00a42d42016-09-13 15:55:09 +0900294 IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
295
Hugo Benichi5eb90532017-03-23 18:38:22 +0900296 NetworkCapabilities ncWifi = new NetworkCapabilities();
297 NetworkCapabilities ncCell = new NetworkCapabilities();
298 ncWifi.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
299 ncCell.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
300
301 when(mCm.getNetworkCapabilities(new Network(100))).thenReturn(ncWifi);
302 when(mCm.getNetworkCapabilities(new Network(101))).thenReturn(ncCell);
303
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900304 ApfStats apfStats = new ApfStats();
305 apfStats.durationMs = 45000;
306 apfStats.receivedRas = 10;
307 apfStats.matchingRas = 2;
308 apfStats.droppedRas = 2;
309 apfStats.parseErrors = 2;
310 apfStats.zeroLifetimeRas = 1;
311 apfStats.programUpdates = 4;
312 apfStats.programUpdatesAll = 7;
313 apfStats.programUpdatesAllowingMulticast = 3;
314 apfStats.maxProgramSize = 2048;
Hugo Benichif927f0c2017-03-17 15:42:40 +0900315
316 ValidationProbeEvent validationEv = new ValidationProbeEvent();
317 validationEv.durationMs = 40730;
318 validationEv.probeType = ValidationProbeEvent.PROBE_HTTP;
319 validationEv.returnCode = 204;
320
Hugo Benichi00a42d42016-09-13 15:55:09 +0900321 Parcelable[] events = {
Hugo Benichi948a8592017-03-16 16:33:47 +0900322 new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED),
323 new DhcpClientEvent("SomeState", 192),
Hugo Benichi948a8592017-03-16 16:33:47 +0900324 new IpManagerEvent(IpManagerEvent.PROVISIONING_OK, 5678),
Hugo Benichif927f0c2017-03-17 15:42:40 +0900325 validationEv,
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900326 apfStats,
Hugo Benichi00a42d42016-09-13 15:55:09 +0900327 new RaEvent(2000, 400, 300, -1, 1000, -1)
328 };
329
330 for (int i = 0; i < events.length; i++) {
Hugo Benichi948a8592017-03-16 16:33:47 +0900331 ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
332 ev.timestamp = 100 * (i + 1);
333 ev.ifname = "wlan0";
334 ev.data = events[i];
335 logger.log(ev);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900336 }
337
Hugo Benichi5eb90532017-03-23 18:38:22 +0900338 // netId, errno, latency, destination
339 connectEvent(100, OsConstants.EALREADY, 0, EXAMPLE_IPV4);
340 connectEvent(100, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6);
341 connectEvent(100, 0, 110, EXAMPLE_IPV4);
342 connectEvent(101, 0, 23, EXAMPLE_IPV4);
343 connectEvent(101, 0, 45, EXAMPLE_IPV6);
344 connectEvent(100, OsConstants.EAGAIN, 0, EXAMPLE_IPV4);
345
346 // netId, type, return code, latency
347 dnsEvent(100, EVENT_GETADDRINFO, 0, 3456);
348 dnsEvent(100, EVENT_GETADDRINFO, 3, 45);
349 dnsEvent(100, EVENT_GETHOSTBYNAME, 0, 638);
350 dnsEvent(101, EVENT_GETADDRINFO, 0, 56);
351 dnsEvent(101, EVENT_GETHOSTBYNAME, 0, 34);
352
Hugo Benichi60c9f632017-09-05 13:34:48 +0900353 // iface, uid
354 wakeupEvent("wlan0", 1000);
355 wakeupEvent("rmnet0", 10123);
356 wakeupEvent("wlan0", 1000);
357 wakeupEvent("rmnet0", 10008);
358 wakeupEvent("wlan0", -1);
359 wakeupEvent("wlan0", 10008);
360 wakeupEvent("rmnet0", 1000);
361
Hugo Benichi380a0632017-10-20 09:25:29 +0900362 long timeMs = mService.mDefaultNetworkMetrics.creationTimeMs;
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900363 final long cell = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
364 final long wifi = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_WIFI});
365 NetworkAgentInfo cellNai = makeNai(100, 50, false, true, cell);
366 NetworkAgentInfo wifiNai = makeNai(101, 60, true, false, wifi);
Hugo Benichi380a0632017-10-20 09:25:29 +0900367 mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(timeMs + 200, cellNai, null);
368 mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(timeMs + 300, wifiNai, cellNai);
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900369
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900370 String want = String.join("\n",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900371 "dropped_events: 0",
372 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900373 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900374 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900375 " network_id: 0",
Hugo Benichi80df43e2016-11-24 11:28:06 +0900376 " time_ms: 100",
Hugo Benichif6840502017-03-08 11:59:36 +0900377 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900378 " ip_reachability_event <",
379 " event_type: 512",
Hugo Benichi948a8592017-03-16 16:33:47 +0900380 " if_name: \"\"",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900381 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900382 ">",
383 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900384 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900385 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900386 " network_id: 0",
Hugo Benichi80df43e2016-11-24 11:28:06 +0900387 " time_ms: 200",
Hugo Benichif6840502017-03-08 11:59:36 +0900388 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900389 " dhcp_event <",
390 " duration_ms: 192",
Hugo Benichi948a8592017-03-16 16:33:47 +0900391 " if_name: \"\"",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900392 " state_transition: \"SomeState\"",
393 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900394 ">",
395 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900396 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900397 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900398 " network_id: 0",
Hugo Benichi80df43e2016-11-24 11:28:06 +0900399 " time_ms: 300",
Hugo Benichif6840502017-03-08 11:59:36 +0900400 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900401 " ip_provisioning_event <",
402 " event_type: 1",
Hugo Benichi948a8592017-03-16 16:33:47 +0900403 " if_name: \"\"",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900404 " latency_ms: 5678",
405 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900406 ">",
407 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900408 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900409 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900410 " network_id: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900411 " time_ms: 400",
Hugo Benichif6840502017-03-08 11:59:36 +0900412 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900413 " validation_probe_event <",
414 " latency_ms: 40730",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900415 " probe_result: 204",
416 " probe_type: 1",
417 " >",
418 ">",
419 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900420 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900421 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900422 " network_id: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900423 " time_ms: 500",
Hugo Benichif6840502017-03-08 11:59:36 +0900424 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900425 " apf_statistics <",
426 " dropped_ras: 2",
427 " duration_ms: 45000",
428 " matching_ras: 2",
429 " max_program_size: 2048",
430 " parse_errors: 2",
431 " program_updates: 4",
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900432 " program_updates_all: 7",
433 " program_updates_allowing_multicast: 3",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900434 " received_ras: 10",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900435 " total_packet_dropped: 0",
436 " total_packet_processed: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900437 " zero_lifetime_ras: 1",
438 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900439 ">",
440 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900441 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900442 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900443 " network_id: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900444 " time_ms: 600",
Hugo Benichif6840502017-03-08 11:59:36 +0900445 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900446 " ra_event <",
447 " dnssl_lifetime: -1",
448 " prefix_preferred_lifetime: 300",
449 " prefix_valid_lifetime: 400",
450 " rdnss_lifetime: 1000",
451 " route_info_lifetime: -1",
452 " router_lifetime: 2000",
453 " >",
Hugo Benichid680d4c2016-10-13 13:16:16 +0900454 ">",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900455 "events <",
456 " if_name: \"\"",
Hugo Benichi380a0632017-10-20 09:25:29 +0900457 " link_layer: 5",
458 " network_id: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900459 " time_ms: 0",
460 " transports: 0",
461 " default_network_event <",
Hugo Benichi380a0632017-10-20 09:25:29 +0900462 " default_network_duration_ms: 200",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900463 " final_score: 0",
464 " initial_score: 0",
465 " ip_support: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900466 " no_default_network_duration_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900467 " previous_default_network_link_layer: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900468 " previous_network_ip_support: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900469 " validation_duration_ms: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900470 " >",
471 ">",
472 "events <",
473 " if_name: \"\"",
Hugo Benichi380a0632017-10-20 09:25:29 +0900474 " link_layer: 2",
475 " network_id: 100",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900476 " time_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900477 " transports: 1",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900478 " default_network_event <",
Hugo Benichi380a0632017-10-20 09:25:29 +0900479 " default_network_duration_ms: 100",
480 " final_score: 50",
481 " initial_score: 50",
482 " ip_support: 2",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900483 " no_default_network_duration_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900484 " previous_default_network_link_layer: 0",
485 " previous_network_ip_support: 0",
486 " validation_duration_ms: 100",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900487 " >",
488 ">",
489 "events <",
490 " if_name: \"\"",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900491 " link_layer: 4",
492 " network_id: 100",
493 " time_ms: 0",
494 " transports: 2",
495 " connect_statistics <",
496 " connect_blocking_count: 1",
497 " connect_count: 3",
498 " errnos_counters <",
499 " key: 11",
500 " value: 1",
501 " >",
502 " ipv6_addr_count: 1",
503 " latencies_ms: 110",
504 " >",
505 ">",
506 "events <",
507 " if_name: \"\"",
508 " link_layer: 2",
509 " network_id: 101",
510 " time_ms: 0",
511 " transports: 1",
512 " connect_statistics <",
513 " connect_blocking_count: 2",
514 " connect_count: 2",
515 " ipv6_addr_count: 1",
516 " latencies_ms: 23",
517 " latencies_ms: 45",
518 " >",
519 ">",
520 "events <",
521 " if_name: \"\"",
522 " link_layer: 4",
523 " network_id: 100",
524 " time_ms: 0",
525 " transports: 2",
526 " dns_lookup_batch <",
527 " event_types: 1",
528 " event_types: 1",
529 " event_types: 2",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900530 " getaddrinfo_error_count: 0",
531 " getaddrinfo_query_count: 0",
532 " gethostbyname_error_count: 0",
533 " gethostbyname_query_count: 0",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900534 " latencies_ms: 3456",
535 " latencies_ms: 45",
536 " latencies_ms: 638",
537 " return_codes: 0",
538 " return_codes: 3",
539 " return_codes: 0",
540 " >",
541 ">",
542 "events <",
543 " if_name: \"\"",
544 " link_layer: 2",
545 " network_id: 101",
546 " time_ms: 0",
547 " transports: 1",
548 " dns_lookup_batch <",
549 " event_types: 1",
550 " event_types: 2",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900551 " getaddrinfo_error_count: 0",
552 " getaddrinfo_query_count: 0",
553 " gethostbyname_error_count: 0",
554 " gethostbyname_query_count: 0",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900555 " latencies_ms: 56",
556 " latencies_ms: 34",
557 " return_codes: 0",
558 " return_codes: 0",
559 " >",
560 ">",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900561 "events <",
562 " if_name: \"\"",
563 " link_layer: 2",
564 " network_id: 0",
565 " time_ms: 0",
566 " transports: 0",
567 " wakeup_stats <",
568 " application_wakeups: 2",
569 " duration_sec: 0",
Hugo Benichi175b5742017-09-19 13:15:26 +0900570 " no_uid_wakeups: 0",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900571 " non_application_wakeups: 0",
572 " root_wakeups: 0",
573 " system_wakeups: 1",
574 " total_wakeups: 3",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900575 " >",
576 ">",
577 "events <",
578 " if_name: \"\"",
579 " link_layer: 4",
580 " network_id: 0",
581 " time_ms: 0",
582 " transports: 0",
583 " wakeup_stats <",
584 " application_wakeups: 1",
585 " duration_sec: 0",
Hugo Benichi175b5742017-09-19 13:15:26 +0900586 " no_uid_wakeups: 1",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900587 " non_application_wakeups: 0",
588 " root_wakeups: 0",
589 " system_wakeups: 2",
590 " total_wakeups: 4",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900591 " >",
592 ">",
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900593 "version: 2\n");
Hugo Benichi00a42d42016-09-13 15:55:09 +0900594
595 verifySerialization(want, getdump("flush"));
596 }
597
598 String getdump(String ... command) {
599 StringWriter buffer = new StringWriter();
600 PrintWriter writer = new PrintWriter(buffer);
601 mService.impl.dump(null, writer, command);
602 return buffer.toString();
603 }
604
Hugo Benichi5eb90532017-03-23 18:38:22 +0900605 void connectEvent(int netid, int error, int latencyMs, String ipAddr) throws Exception {
606 mNetdListener.onConnectEvent(netid, error, latencyMs, ipAddr, 80, 1);
607 }
608
609 void dnsEvent(int netId, int type, int result, int latency) throws Exception {
610 mNetdListener.onDnsEvent(netId, type, result, latency, "", null, 0, 0);
611 }
612
Hugo Benichi60c9f632017-09-05 13:34:48 +0900613 void wakeupEvent(String iface, int uid) throws Exception {
614 String prefix = NetdEventListenerService.WAKEUP_EVENT_IFACE_PREFIX + iface;
615 mNetdListener.onWakeupEvent(prefix, uid, uid, 0);
616 }
617
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900618 NetworkAgentInfo makeNai(int netId, int score, boolean ipv4, boolean ipv6, long transports) {
619 NetworkAgentInfo nai = mock(NetworkAgentInfo.class);
620 when(nai.network()).thenReturn(new Network(netId));
621 when(nai.getCurrentScore()).thenReturn(score);
622 nai.linkProperties = new LinkProperties();
623 nai.networkCapabilities = new NetworkCapabilities();
624 for (int t : BitUtils.unpackBits(transports)) {
625 nai.networkCapabilities.addTransportType(t);
626 }
627 if (ipv4) {
628 nai.linkProperties.addLinkAddress(new LinkAddress("192.0.2.12/24"));
629 nai.linkProperties.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0")));
630 }
631 if (ipv6) {
632 nai.linkProperties.addLinkAddress(new LinkAddress("2001:db8:dead:beef:f00::a0/64"));
633 nai.linkProperties.addRoute(new RouteInfo(new IpPrefix("::/0")));
634 }
635 return nai;
636 }
637
Hugo Benichi00a42d42016-09-13 15:55:09 +0900638 List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
639 ArgumentCaptor<ConnectivityMetricsEvent> captor =
640 ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
641 verify(mMockService, timeout(timeoutMs).times(n)).logEvent(captor.capture());
642 return captor.getAllValues();
643 }
644
645 List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception {
646 return verifyEvents(n, 10);
647 }
648
649 static void verifySerialization(String want, String output) {
650 try {
651 byte[] got = Base64.decode(output, Base64.DEFAULT);
652 IpConnectivityLogClass.IpConnectivityLog log =
Glen Kuhne07199402016-10-25 15:47:25 -0700653 IpConnectivityLogClass.IpConnectivityLog.parseFrom(got);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900654 assertEquals(want, log.toString());
655 } catch (Exception e) {
656 fail(e.toString());
657 }
658 }
659
660 static String joinLines(String ... elems) {
661 StringBuilder b = new StringBuilder();
662 for (String s : elems) {
663 b.append(s).append("\n");
664 }
665 return b.toString();
666 }
667
668 static ConnectivityMetricsEvent expectedEvent(int timestamp) {
Hugo Benichiec27c4d2017-03-15 15:07:42 +0900669 ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
670 ev.timestamp = timestamp;
671 ev.data = FAKE_EV;
672 return ev;
Hugo Benichi00a42d42016-09-13 15:55:09 +0900673 }
674
675 /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
676 static void assertEventsEqual(ConnectivityMetricsEvent expected, ConnectivityMetricsEvent got) {
677 assertEquals(expected.timestamp, got.timestamp);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900678 assertEquals(expected.data, got.data);
679 }
680
681 static final Comparator<ConnectivityMetricsEvent> EVENT_COMPARATOR =
Hugo Benichi0d4a3982016-11-25 11:24:22 +0900682 Comparator.comparingLong((ev) -> ev.timestamp);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900683}