blob: 8359fe2a8fb4bdb4c4ed359955a7d9d8c1751f5c [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 Benichid921bce2017-10-12 21:33:40 +090081 private static final byte[] MAC_ADDR =
82 {(byte)0x84, (byte)0xc9, (byte)0xb2, (byte)0x6a, (byte)0xed, (byte)0x4b};
83
Hugo Benichi00a42d42016-09-13 15:55:09 +090084 @Mock Context mCtx;
85 @Mock IIpConnectivityMetrics mMockService;
Hugo Benichi5eb90532017-03-23 18:38:22 +090086 @Mock ConnectivityManager mCm;
Hugo Benichi00a42d42016-09-13 15:55:09 +090087
88 IpConnectivityMetrics mService;
Hugo Benichi5eb90532017-03-23 18:38:22 +090089 NetdEventListenerService mNetdListener;
Hugo Benichi00a42d42016-09-13 15:55:09 +090090
Hugo Benichi5eb90532017-03-23 18:38:22 +090091 @Before
Hugo Benichi00a42d42016-09-13 15:55:09 +090092 public void setUp() {
93 MockitoAnnotations.initMocks(this);
Hugo Benichi05686db2016-10-19 11:17:28 +090094 mService = new IpConnectivityMetrics(mCtx, (ctx) -> 2000);
Hugo Benichi5eb90532017-03-23 18:38:22 +090095 mNetdListener = new NetdEventListenerService(mCm);
96 mService.mNetdListener = mNetdListener;
Hugo Benichi00a42d42016-09-13 15:55:09 +090097 }
98
Hugo Benichi5eb90532017-03-23 18:38:22 +090099 @Test
Hugo Benichi00a42d42016-09-13 15:55:09 +0900100 public void testLoggingEvents() throws Exception {
101 IpConnectivityLog logger = new IpConnectivityLog(mMockService);
102
103 assertTrue(logger.log(1, FAKE_EV));
104 assertTrue(logger.log(2, FAKE_EV));
105 assertTrue(logger.log(3, FAKE_EV));
106
107 List<ConnectivityMetricsEvent> got = verifyEvents(3);
108 assertEventsEqual(expectedEvent(1), got.get(0));
109 assertEventsEqual(expectedEvent(2), got.get(1));
110 assertEventsEqual(expectedEvent(3), got.get(2));
111 }
112
Hugo Benichi5eb90532017-03-23 18:38:22 +0900113 @Test
Hugo Benichi00a42d42016-09-13 15:55:09 +0900114 public void testLoggingEventsWithMultipleCallers() throws Exception {
115 IpConnectivityLog logger = new IpConnectivityLog(mMockService);
116
117 final int nCallers = 10;
118 final int nEvents = 10;
119 for (int n = 0; n < nCallers; n++) {
120 final int i = n;
121 new Thread() {
122 public void run() {
123 for (int j = 0; j < nEvents; j++) {
Hugo Benichi946b7e42017-03-15 16:35:26 +0900124 assertTrue(logger.log(1 + i * 100 + j, FAKE_EV));
Hugo Benichi00a42d42016-09-13 15:55:09 +0900125 }
126 }
127 }.start();
128 }
129
Hugo Benichi5eb90532017-03-23 18:38:22 +0900130 List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 200);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900131 Collections.sort(got, EVENT_COMPARATOR);
132 Iterator<ConnectivityMetricsEvent> iter = got.iterator();
133 for (int i = 0; i < nCallers; i++) {
134 for (int j = 0; j < nEvents; j++) {
Hugo Benichi946b7e42017-03-15 16:35:26 +0900135 int expectedTimestamp = 1 + i * 100 + j;
Hugo Benichi00a42d42016-09-13 15:55:09 +0900136 assertEventsEqual(expectedEvent(expectedTimestamp), iter.next());
137 }
138 }
139 }
140
Hugo Benichi5eb90532017-03-23 18:38:22 +0900141 @Test
Hugo Benichi00a42d42016-09-13 15:55:09 +0900142 public void testBufferFlushing() {
143 String output1 = getdump("flush");
144 assertEquals("", output1);
145
146 new IpConnectivityLog(mService.impl).log(1, FAKE_EV);
147 String output2 = getdump("flush");
148 assertFalse("".equals(output2));
149
150 String output3 = getdump("flush");
151 assertEquals("", output3);
152 }
153
Hugo Benichi5eb90532017-03-23 18:38:22 +0900154 @Test
Hugo Benichie1c173d2016-10-18 10:36:33 +0900155 public void testRateLimiting() {
156 final IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900157 final ApfProgramEvent ev = new ApfProgramEvent();
Hugo Benichie1c173d2016-10-18 10:36:33 +0900158 final long fakeTimestamp = 1;
159
160 int attempt = 100; // More than burst quota, but less than buffer size.
161 for (int i = 0; i < attempt; i++) {
162 logger.log(ev);
163 }
164
165 String output1 = getdump("flush");
166 assertFalse("".equals(output1));
167
168 for (int i = 0; i < attempt; i++) {
169 assertFalse("expected event to be dropped", logger.log(fakeTimestamp, ev));
170 }
171
172 String output2 = getdump("flush");
173 assertEquals("", output2);
174 }
175
Hugo Benichi5eb90532017-03-23 18:38:22 +0900176 @Test
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900177 public void testDefaultNetworkEvents() throws Exception {
178 final long cell = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
179 final long wifi = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_WIFI});
180
181 NetworkAgentInfo[][] defaultNetworks = {
182 // nothing -> cell
183 {null, makeNai(100, 10, false, true, cell)},
184 // cell -> wifi
185 {makeNai(100, 50, true, true, cell), makeNai(101, 20, true, false, wifi)},
186 // wifi -> nothing
187 {makeNai(101, 60, true, false, wifi), null},
188 // nothing -> cell
189 {null, makeNai(102, 10, true, true, cell)},
190 // cell -> wifi
191 {makeNai(102, 50, true, true, cell), makeNai(103, 20, true, false, wifi)},
192 };
193
Hugo Benichi380a0632017-10-20 09:25:29 +0900194 long timeMs = mService.mDefaultNetworkMetrics.creationTimeMs;
195 long durationMs = 1001;
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900196 for (NetworkAgentInfo[] pair : defaultNetworks) {
Hugo Benichi380a0632017-10-20 09:25:29 +0900197 timeMs += durationMs;
198 durationMs += durationMs;
199 mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(timeMs, pair[1], pair[0]);
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900200 }
201
202 String want = String.join("\n",
203 "dropped_events: 0",
204 "events <",
205 " if_name: \"\"",
Hugo Benichi380a0632017-10-20 09:25:29 +0900206 " link_layer: 5",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900207 " network_id: 0",
208 " time_ms: 0",
209 " transports: 0",
210 " default_network_event <",
Hugo Benichi380a0632017-10-20 09:25:29 +0900211 " default_network_duration_ms: 1001",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900212 " final_score: 0",
213 " initial_score: 0",
214 " ip_support: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900215 " no_default_network_duration_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900216 " previous_default_network_link_layer: 0",
217 " previous_network_ip_support: 0",
218 " validation_duration_ms: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900219 " >",
220 ">",
221 "events <",
222 " if_name: \"\"",
Hugo Benichi380a0632017-10-20 09:25:29 +0900223 " link_layer: 2",
224 " network_id: 100",
225 " time_ms: 0",
226 " transports: 1",
227 " default_network_event <",
228 " default_network_duration_ms: 2002",
229 " final_score: 50",
230 " initial_score: 10",
231 " ip_support: 3",
232 " no_default_network_duration_ms: 0",
233 " previous_default_network_link_layer: 0",
234 " previous_network_ip_support: 0",
235 " validation_duration_ms: 2002",
236 " >",
237 ">",
238 "events <",
239 " if_name: \"\"",
240 " link_layer: 4",
241 " network_id: 101",
242 " time_ms: 0",
243 " transports: 2",
244 " default_network_event <",
245 " default_network_duration_ms: 4004",
246 " final_score: 60",
247 " initial_score: 20",
248 " ip_support: 1",
249 " no_default_network_duration_ms: 0",
250 " previous_default_network_link_layer: 2",
251 " previous_network_ip_support: 0",
252 " validation_duration_ms: 4004",
253 " >",
254 ">",
255 "events <",
256 " if_name: \"\"",
257 " link_layer: 5",
258 " network_id: 0",
259 " time_ms: 0",
260 " transports: 0",
261 " default_network_event <",
262 " default_network_duration_ms: 8008",
263 " final_score: 0",
264 " initial_score: 0",
265 " ip_support: 0",
266 " no_default_network_duration_ms: 0",
267 " previous_default_network_link_layer: 4",
268 " previous_network_ip_support: 0",
269 " validation_duration_ms: 0",
270 " >",
271 ">",
272 "events <",
273 " if_name: \"\"",
274 " link_layer: 2",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900275 " network_id: 102",
276 " time_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900277 " transports: 1",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900278 " default_network_event <",
Hugo Benichi380a0632017-10-20 09:25:29 +0900279 " default_network_duration_ms: 16016",
280 " final_score: 50",
281 " initial_score: 10",
282 " ip_support: 3",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900283 " no_default_network_duration_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900284 " previous_default_network_link_layer: 4",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900285 " previous_network_ip_support: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900286 " validation_duration_ms: 16016",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900287 " >",
288 ">",
289 "version: 2\n");
290
291 verifySerialization(want, getdump("flush"));
292 }
293
294 @Test
Hugo Benichi5eb90532017-03-23 18:38:22 +0900295 public void testEndToEndLogging() throws Exception {
Hugo Benichif6840502017-03-08 11:59:36 +0900296 // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
Hugo Benichi00a42d42016-09-13 15:55:09 +0900297 IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
298
Hugo Benichi5eb90532017-03-23 18:38:22 +0900299 NetworkCapabilities ncWifi = new NetworkCapabilities();
300 NetworkCapabilities ncCell = new NetworkCapabilities();
301 ncWifi.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
302 ncCell.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
303
304 when(mCm.getNetworkCapabilities(new Network(100))).thenReturn(ncWifi);
305 when(mCm.getNetworkCapabilities(new Network(101))).thenReturn(ncCell);
306
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900307 ApfStats apfStats = new ApfStats();
308 apfStats.durationMs = 45000;
309 apfStats.receivedRas = 10;
310 apfStats.matchingRas = 2;
311 apfStats.droppedRas = 2;
312 apfStats.parseErrors = 2;
313 apfStats.zeroLifetimeRas = 1;
314 apfStats.programUpdates = 4;
315 apfStats.programUpdatesAll = 7;
316 apfStats.programUpdatesAllowingMulticast = 3;
317 apfStats.maxProgramSize = 2048;
Hugo Benichif927f0c2017-03-17 15:42:40 +0900318
319 ValidationProbeEvent validationEv = new ValidationProbeEvent();
320 validationEv.durationMs = 40730;
321 validationEv.probeType = ValidationProbeEvent.PROBE_HTTP;
322 validationEv.returnCode = 204;
323
Hugo Benichi00a42d42016-09-13 15:55:09 +0900324 Parcelable[] events = {
Hugo Benichi948a8592017-03-16 16:33:47 +0900325 new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED),
326 new DhcpClientEvent("SomeState", 192),
Hugo Benichi948a8592017-03-16 16:33:47 +0900327 new IpManagerEvent(IpManagerEvent.PROVISIONING_OK, 5678),
Hugo Benichif927f0c2017-03-17 15:42:40 +0900328 validationEv,
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900329 apfStats,
Hugo Benichi00a42d42016-09-13 15:55:09 +0900330 new RaEvent(2000, 400, 300, -1, 1000, -1)
331 };
332
333 for (int i = 0; i < events.length; i++) {
Hugo Benichi948a8592017-03-16 16:33:47 +0900334 ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
335 ev.timestamp = 100 * (i + 1);
336 ev.ifname = "wlan0";
337 ev.data = events[i];
338 logger.log(ev);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900339 }
340
Hugo Benichi5eb90532017-03-23 18:38:22 +0900341 // netId, errno, latency, destination
342 connectEvent(100, OsConstants.EALREADY, 0, EXAMPLE_IPV4);
343 connectEvent(100, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6);
344 connectEvent(100, 0, 110, EXAMPLE_IPV4);
345 connectEvent(101, 0, 23, EXAMPLE_IPV4);
346 connectEvent(101, 0, 45, EXAMPLE_IPV6);
347 connectEvent(100, OsConstants.EAGAIN, 0, EXAMPLE_IPV4);
348
349 // netId, type, return code, latency
350 dnsEvent(100, EVENT_GETADDRINFO, 0, 3456);
351 dnsEvent(100, EVENT_GETADDRINFO, 3, 45);
352 dnsEvent(100, EVENT_GETHOSTBYNAME, 0, 638);
353 dnsEvent(101, EVENT_GETADDRINFO, 0, 56);
354 dnsEvent(101, EVENT_GETHOSTBYNAME, 0, 34);
355
Hugo Benichi60c9f632017-09-05 13:34:48 +0900356 // iface, uid
Hugo Benichid921bce2017-10-12 21:33:40 +0900357 final byte[] mac = {0x48, 0x7c, 0x2b, 0x6a, 0x3e, 0x4b};
358 final String srcIp = "192.168.2.1";
359 final String dstIp = "192.168.2.23";
360 final int sport = 2356;
361 final int dport = 13489;
362 final long now = 1001L;
363 final int v4 = 0x800;
364 final int tcp = 6;
365 final int udp = 17;
366 wakeupEvent("wlan0", 1000, v4, tcp, mac, srcIp, dstIp, sport, dport, 1001L);
367 wakeupEvent("wlan0", 10123, v4, tcp, mac, srcIp, dstIp, sport, dport, 1001L);
368 wakeupEvent("wlan0", 1000, v4, udp, mac, srcIp, dstIp, sport, dport, 1001L);
369 wakeupEvent("wlan0", 10008, v4, udp, mac, srcIp, dstIp, sport, dport, 1001L);
370 wakeupEvent("wlan0", -1, v4, udp, mac, srcIp, dstIp, sport, dport, 1001L);
371 wakeupEvent("wlan0", 10008, v4, tcp, mac, srcIp, dstIp, sport, dport, 1001L);
Hugo Benichi60c9f632017-09-05 13:34:48 +0900372
Hugo Benichi380a0632017-10-20 09:25:29 +0900373 long timeMs = mService.mDefaultNetworkMetrics.creationTimeMs;
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900374 final long cell = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
375 final long wifi = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_WIFI});
376 NetworkAgentInfo cellNai = makeNai(100, 50, false, true, cell);
377 NetworkAgentInfo wifiNai = makeNai(101, 60, true, false, wifi);
Hugo Benichi380a0632017-10-20 09:25:29 +0900378 mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(timeMs + 200, cellNai, null);
379 mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(timeMs + 300, wifiNai, cellNai);
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900380
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900381 String want = String.join("\n",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900382 "dropped_events: 0",
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: 100",
Hugo Benichif6840502017-03-08 11:59:36 +0900388 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900389 " ip_reachability_event <",
390 " event_type: 512",
Hugo Benichi948a8592017-03-16 16:33:47 +0900391 " if_name: \"\"",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900392 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900393 ">",
394 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900395 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900396 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900397 " network_id: 0",
Hugo Benichi80df43e2016-11-24 11:28:06 +0900398 " time_ms: 200",
Hugo Benichif6840502017-03-08 11:59:36 +0900399 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900400 " dhcp_event <",
401 " duration_ms: 192",
Hugo Benichi948a8592017-03-16 16:33:47 +0900402 " if_name: \"\"",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900403 " state_transition: \"SomeState\"",
404 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900405 ">",
406 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900407 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900408 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900409 " network_id: 0",
Hugo Benichi80df43e2016-11-24 11:28:06 +0900410 " time_ms: 300",
Hugo Benichif6840502017-03-08 11:59:36 +0900411 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900412 " ip_provisioning_event <",
413 " event_type: 1",
Hugo Benichi948a8592017-03-16 16:33:47 +0900414 " if_name: \"\"",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900415 " latency_ms: 5678",
416 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900417 ">",
418 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900419 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900420 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900421 " network_id: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900422 " time_ms: 400",
Hugo Benichif6840502017-03-08 11:59:36 +0900423 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900424 " validation_probe_event <",
425 " latency_ms: 40730",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900426 " probe_result: 204",
427 " probe_type: 1",
428 " >",
429 ">",
430 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900431 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900432 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900433 " network_id: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900434 " time_ms: 500",
Hugo Benichif6840502017-03-08 11:59:36 +0900435 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900436 " apf_statistics <",
437 " dropped_ras: 2",
438 " duration_ms: 45000",
439 " matching_ras: 2",
440 " max_program_size: 2048",
441 " parse_errors: 2",
442 " program_updates: 4",
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900443 " program_updates_all: 7",
444 " program_updates_allowing_multicast: 3",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900445 " received_ras: 10",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900446 " total_packet_dropped: 0",
447 " total_packet_processed: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900448 " zero_lifetime_ras: 1",
449 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900450 ">",
451 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900452 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900453 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900454 " network_id: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900455 " time_ms: 600",
Hugo Benichif6840502017-03-08 11:59:36 +0900456 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900457 " ra_event <",
458 " dnssl_lifetime: -1",
459 " prefix_preferred_lifetime: 300",
460 " prefix_valid_lifetime: 400",
461 " rdnss_lifetime: 1000",
462 " route_info_lifetime: -1",
463 " router_lifetime: 2000",
464 " >",
Hugo Benichid680d4c2016-10-13 13:16:16 +0900465 ">",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900466 "events <",
467 " if_name: \"\"",
Hugo Benichi380a0632017-10-20 09:25:29 +0900468 " link_layer: 5",
469 " network_id: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900470 " time_ms: 0",
471 " transports: 0",
472 " default_network_event <",
Hugo Benichi380a0632017-10-20 09:25:29 +0900473 " default_network_duration_ms: 200",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900474 " final_score: 0",
475 " initial_score: 0",
476 " ip_support: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900477 " no_default_network_duration_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900478 " previous_default_network_link_layer: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900479 " previous_network_ip_support: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900480 " validation_duration_ms: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900481 " >",
482 ">",
483 "events <",
484 " if_name: \"\"",
Hugo Benichi380a0632017-10-20 09:25:29 +0900485 " link_layer: 2",
486 " network_id: 100",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900487 " time_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900488 " transports: 1",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900489 " default_network_event <",
Hugo Benichi380a0632017-10-20 09:25:29 +0900490 " default_network_duration_ms: 100",
491 " final_score: 50",
492 " initial_score: 50",
493 " ip_support: 2",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900494 " no_default_network_duration_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900495 " previous_default_network_link_layer: 0",
496 " previous_network_ip_support: 0",
497 " validation_duration_ms: 100",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900498 " >",
499 ">",
500 "events <",
501 " if_name: \"\"",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900502 " link_layer: 4",
503 " network_id: 100",
504 " time_ms: 0",
505 " transports: 2",
506 " connect_statistics <",
507 " connect_blocking_count: 1",
508 " connect_count: 3",
509 " errnos_counters <",
510 " key: 11",
511 " value: 1",
512 " >",
513 " ipv6_addr_count: 1",
514 " latencies_ms: 110",
515 " >",
516 ">",
517 "events <",
518 " if_name: \"\"",
519 " link_layer: 2",
520 " network_id: 101",
521 " time_ms: 0",
522 " transports: 1",
523 " connect_statistics <",
524 " connect_blocking_count: 2",
525 " connect_count: 2",
526 " ipv6_addr_count: 1",
527 " latencies_ms: 23",
528 " latencies_ms: 45",
529 " >",
530 ">",
531 "events <",
532 " if_name: \"\"",
533 " link_layer: 4",
534 " network_id: 100",
535 " time_ms: 0",
536 " transports: 2",
537 " dns_lookup_batch <",
538 " event_types: 1",
539 " event_types: 1",
540 " event_types: 2",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900541 " getaddrinfo_error_count: 0",
542 " getaddrinfo_query_count: 0",
543 " gethostbyname_error_count: 0",
544 " gethostbyname_query_count: 0",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900545 " latencies_ms: 3456",
546 " latencies_ms: 45",
547 " latencies_ms: 638",
548 " return_codes: 0",
549 " return_codes: 3",
550 " return_codes: 0",
551 " >",
552 ">",
553 "events <",
554 " if_name: \"\"",
555 " link_layer: 2",
556 " network_id: 101",
557 " time_ms: 0",
558 " transports: 1",
559 " dns_lookup_batch <",
560 " event_types: 1",
561 " event_types: 2",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900562 " getaddrinfo_error_count: 0",
563 " getaddrinfo_query_count: 0",
564 " gethostbyname_error_count: 0",
565 " gethostbyname_query_count: 0",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900566 " latencies_ms: 56",
567 " latencies_ms: 34",
568 " return_codes: 0",
569 " return_codes: 0",
570 " >",
571 ">",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900572 "events <",
573 " if_name: \"\"",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900574 " link_layer: 4",
575 " network_id: 0",
576 " time_ms: 0",
577 " transports: 0",
578 " wakeup_stats <",
Hugo Benichid921bce2017-10-12 21:33:40 +0900579 " application_wakeups: 3",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900580 " duration_sec: 0",
Hugo Benichid921bce2017-10-12 21:33:40 +0900581 " ethertype_counts <",
582 " key: 2048",
583 " value: 6",
584 " >",
585 " ip_next_header_counts <",
586 " key: 6",
587 " value: 3",
588 " >",
589 " ip_next_header_counts <",
590 " key: 17",
591 " value: 3",
592 " >",
593 " l2_broadcast_count: 0",
594 " l2_multicast_count: 0",
595 " l2_unicast_count: 6",
Hugo Benichi175b5742017-09-19 13:15:26 +0900596 " no_uid_wakeups: 1",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900597 " non_application_wakeups: 0",
598 " root_wakeups: 0",
599 " system_wakeups: 2",
Hugo Benichid921bce2017-10-12 21:33:40 +0900600 " total_wakeups: 6",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900601 " >",
602 ">",
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900603 "version: 2\n");
Hugo Benichi00a42d42016-09-13 15:55:09 +0900604
605 verifySerialization(want, getdump("flush"));
606 }
607
608 String getdump(String ... command) {
609 StringWriter buffer = new StringWriter();
610 PrintWriter writer = new PrintWriter(buffer);
611 mService.impl.dump(null, writer, command);
612 return buffer.toString();
613 }
614
Hugo Benichi5eb90532017-03-23 18:38:22 +0900615 void connectEvent(int netid, int error, int latencyMs, String ipAddr) throws Exception {
616 mNetdListener.onConnectEvent(netid, error, latencyMs, ipAddr, 80, 1);
617 }
618
619 void dnsEvent(int netId, int type, int result, int latency) throws Exception {
620 mNetdListener.onDnsEvent(netId, type, result, latency, "", null, 0, 0);
621 }
622
Hugo Benichid921bce2017-10-12 21:33:40 +0900623 void wakeupEvent(String iface, int uid, int ether, int ip, byte[] mac, String srcIp,
624 String dstIp, int sport, int dport, long now) throws Exception {
Hugo Benichi60c9f632017-09-05 13:34:48 +0900625 String prefix = NetdEventListenerService.WAKEUP_EVENT_IFACE_PREFIX + iface;
Hugo Benichid921bce2017-10-12 21:33:40 +0900626 mNetdListener.onWakeupEvent(prefix, uid, ether, ip, mac, srcIp, dstIp, sport, dport, now);
Hugo Benichi60c9f632017-09-05 13:34:48 +0900627 }
628
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900629 NetworkAgentInfo makeNai(int netId, int score, boolean ipv4, boolean ipv6, long transports) {
630 NetworkAgentInfo nai = mock(NetworkAgentInfo.class);
631 when(nai.network()).thenReturn(new Network(netId));
632 when(nai.getCurrentScore()).thenReturn(score);
633 nai.linkProperties = new LinkProperties();
634 nai.networkCapabilities = new NetworkCapabilities();
Hugo Benichibb16b752017-12-14 09:56:04 +0900635 nai.lastValidated = true;
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900636 for (int t : BitUtils.unpackBits(transports)) {
637 nai.networkCapabilities.addTransportType(t);
638 }
639 if (ipv4) {
640 nai.linkProperties.addLinkAddress(new LinkAddress("192.0.2.12/24"));
641 nai.linkProperties.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0")));
642 }
643 if (ipv6) {
644 nai.linkProperties.addLinkAddress(new LinkAddress("2001:db8:dead:beef:f00::a0/64"));
645 nai.linkProperties.addRoute(new RouteInfo(new IpPrefix("::/0")));
646 }
647 return nai;
648 }
649
Hugo Benichi00a42d42016-09-13 15:55:09 +0900650 List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
651 ArgumentCaptor<ConnectivityMetricsEvent> captor =
652 ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
653 verify(mMockService, timeout(timeoutMs).times(n)).logEvent(captor.capture());
654 return captor.getAllValues();
655 }
656
657 List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception {
658 return verifyEvents(n, 10);
659 }
660
661 static void verifySerialization(String want, String output) {
662 try {
663 byte[] got = Base64.decode(output, Base64.DEFAULT);
664 IpConnectivityLogClass.IpConnectivityLog log =
Glen Kuhne07199402016-10-25 15:47:25 -0700665 IpConnectivityLogClass.IpConnectivityLog.parseFrom(got);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900666 assertEquals(want, log.toString());
667 } catch (Exception e) {
668 fail(e.toString());
669 }
670 }
671
672 static String joinLines(String ... elems) {
673 StringBuilder b = new StringBuilder();
674 for (String s : elems) {
675 b.append(s).append("\n");
676 }
677 return b.toString();
678 }
679
680 static ConnectivityMetricsEvent expectedEvent(int timestamp) {
Hugo Benichiec27c4d2017-03-15 15:07:42 +0900681 ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
682 ev.timestamp = timestamp;
683 ev.data = FAKE_EV;
684 return ev;
Hugo Benichi00a42d42016-09-13 15:55:09 +0900685 }
686
687 /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
688 static void assertEventsEqual(ConnectivityMetricsEvent expected, ConnectivityMetricsEvent got) {
689 assertEquals(expected.timestamp, got.timestamp);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900690 assertEquals(expected.data, got.data);
691 }
692
693 static final Comparator<ConnectivityMetricsEvent> EVENT_COMPARATOR =
Hugo Benichi0d4a3982016-11-25 11:24:22 +0900694 Comparator.comparingLong((ev) -> ev.timestamp);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900695}