blob: 1a0cb745ff0c99c96ceb2a66617402866fdef8ee [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;
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +090021
Hugo Benichi5eb90532017-03-23 18:38:22 +090022import static org.junit.Assert.assertEquals;
23import static org.junit.Assert.assertFalse;
24import static org.junit.Assert.assertTrue;
25import static org.junit.Assert.fail;
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +090026import static org.mockito.Mockito.mock;
27import static org.mockito.Mockito.timeout;
28import static org.mockito.Mockito.verify;
29import static org.mockito.Mockito.when;
Glen Kuhne07199402016-10-25 15:47:25 -070030
Hugo Benichi00a42d42016-09-13 15:55:09 +090031import android.content.Context;
Hugo Benichi5eb90532017-03-23 18:38:22 +090032import android.net.ConnectivityManager;
Hugo Benichi00a42d42016-09-13 15:55:09 +090033import android.net.ConnectivityMetricsEvent;
34import android.net.IIpConnectivityMetrics;
Hugo Benichi1193a9c2017-10-19 14:58:15 +090035import android.net.IpPrefix;
36import android.net.LinkAddress;
37import android.net.LinkProperties;
Hugo Benichi5eb90532017-03-23 18:38:22 +090038import android.net.Network;
39import android.net.NetworkCapabilities;
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +090040import android.net.RouteInfo;
Hugo Benichie1c173d2016-10-18 10:36:33 +090041import android.net.metrics.ApfProgramEvent;
Hugo Benichi00a42d42016-09-13 15:55:09 +090042import android.net.metrics.ApfStats;
Hugo Benichi00a42d42016-09-13 15:55:09 +090043import 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
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +090058import org.junit.Before;
59import org.junit.Test;
60import org.junit.runner.RunWith;
61import org.mockito.ArgumentCaptor;
62import org.mockito.Mock;
63import org.mockito.MockitoAnnotations;
64
Hugo Benichi00a42d42016-09-13 15:55:09 +090065import java.io.PrintWriter;
66import java.io.StringWriter;
67import java.util.Collections;
68import java.util.Comparator;
69import java.util.Iterator;
70import java.util.List;
Hugo Benichi1193a9c2017-10-19 14:58:15 +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);
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900157 final ApfProgramEvent ev = new ApfProgramEvent.Builder().build();
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
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900307 ApfStats apfStats = new ApfStats.Builder()
308 .setDurationMs(45000)
309 .setReceivedRas(10)
310 .setMatchingRas(2)
311 .setDroppedRas(2)
312 .setParseErrors(2)
313 .setZeroLifetimeRas(1)
314 .setProgramUpdates(4)
315 .setProgramUpdatesAll(7)
316 .setProgramUpdatesAllowingMulticast(3)
317 .setMaxProgramSize(2048)
318 .build();
Hugo Benichif927f0c2017-03-17 15:42:40 +0900319
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900320 final ValidationProbeEvent validationEv = new ValidationProbeEvent.Builder()
321 .setDurationMs(40730)
322 .setProbeType(ValidationProbeEvent.PROBE_HTTP, true)
323 .setReturnCode(204)
324 .build();
Hugo Benichif927f0c2017-03-17 15:42:40 +0900325
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900326 final DhcpClientEvent event = new DhcpClientEvent.Builder()
327 .setMsg("SomeState")
328 .setDurationMs(192)
329 .build();
Hugo Benichi00a42d42016-09-13 15:55:09 +0900330 Parcelable[] events = {
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900331 new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED), event,
Hugo Benichi948a8592017-03-16 16:33:47 +0900332 new IpManagerEvent(IpManagerEvent.PROVISIONING_OK, 5678),
Hugo Benichif927f0c2017-03-17 15:42:40 +0900333 validationEv,
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900334 apfStats,
Hugo Benichi00a42d42016-09-13 15:55:09 +0900335 new RaEvent(2000, 400, 300, -1, 1000, -1)
336 };
337
338 for (int i = 0; i < events.length; i++) {
Hugo Benichi948a8592017-03-16 16:33:47 +0900339 ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
340 ev.timestamp = 100 * (i + 1);
341 ev.ifname = "wlan0";
342 ev.data = events[i];
343 logger.log(ev);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900344 }
345
Hugo Benichi5eb90532017-03-23 18:38:22 +0900346 // netId, errno, latency, destination
347 connectEvent(100, OsConstants.EALREADY, 0, EXAMPLE_IPV4);
348 connectEvent(100, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6);
349 connectEvent(100, 0, 110, EXAMPLE_IPV4);
350 connectEvent(101, 0, 23, EXAMPLE_IPV4);
351 connectEvent(101, 0, 45, EXAMPLE_IPV6);
352 connectEvent(100, OsConstants.EAGAIN, 0, EXAMPLE_IPV4);
353
354 // netId, type, return code, latency
355 dnsEvent(100, EVENT_GETADDRINFO, 0, 3456);
356 dnsEvent(100, EVENT_GETADDRINFO, 3, 45);
357 dnsEvent(100, EVENT_GETHOSTBYNAME, 0, 638);
358 dnsEvent(101, EVENT_GETADDRINFO, 0, 56);
359 dnsEvent(101, EVENT_GETHOSTBYNAME, 0, 34);
360
Hugo Benichi60c9f632017-09-05 13:34:48 +0900361 // iface, uid
Hugo Benichid921bce2017-10-12 21:33:40 +0900362 final byte[] mac = {0x48, 0x7c, 0x2b, 0x6a, 0x3e, 0x4b};
363 final String srcIp = "192.168.2.1";
364 final String dstIp = "192.168.2.23";
365 final int sport = 2356;
366 final int dport = 13489;
367 final long now = 1001L;
368 final int v4 = 0x800;
369 final int tcp = 6;
370 final int udp = 17;
371 wakeupEvent("wlan0", 1000, v4, tcp, mac, srcIp, dstIp, sport, dport, 1001L);
372 wakeupEvent("wlan0", 10123, v4, tcp, mac, srcIp, dstIp, sport, dport, 1001L);
373 wakeupEvent("wlan0", 1000, v4, udp, mac, srcIp, dstIp, sport, dport, 1001L);
374 wakeupEvent("wlan0", 10008, v4, udp, mac, srcIp, dstIp, sport, dport, 1001L);
375 wakeupEvent("wlan0", -1, v4, udp, mac, srcIp, dstIp, sport, dport, 1001L);
376 wakeupEvent("wlan0", 10008, v4, tcp, mac, srcIp, dstIp, sport, dport, 1001L);
Hugo Benichi60c9f632017-09-05 13:34:48 +0900377
Hugo Benichi380a0632017-10-20 09:25:29 +0900378 long timeMs = mService.mDefaultNetworkMetrics.creationTimeMs;
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900379 final long cell = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
380 final long wifi = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_WIFI});
381 NetworkAgentInfo cellNai = makeNai(100, 50, false, true, cell);
382 NetworkAgentInfo wifiNai = makeNai(101, 60, true, false, wifi);
Hugo Benichi380a0632017-10-20 09:25:29 +0900383 mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(timeMs + 200, cellNai, null);
384 mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(timeMs + 300, wifiNai, cellNai);
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900385
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900386 String want = String.join("\n",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900387 "dropped_events: 0",
388 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900389 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900390 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900391 " network_id: 0",
Hugo Benichi80df43e2016-11-24 11:28:06 +0900392 " time_ms: 100",
Hugo Benichif6840502017-03-08 11:59:36 +0900393 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900394 " ip_reachability_event <",
395 " event_type: 512",
Hugo Benichi948a8592017-03-16 16:33:47 +0900396 " if_name: \"\"",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900397 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900398 ">",
399 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900400 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900401 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900402 " network_id: 0",
Hugo Benichi80df43e2016-11-24 11:28:06 +0900403 " time_ms: 200",
Hugo Benichif6840502017-03-08 11:59:36 +0900404 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900405 " dhcp_event <",
406 " duration_ms: 192",
Hugo Benichi948a8592017-03-16 16:33:47 +0900407 " if_name: \"\"",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900408 " state_transition: \"SomeState\"",
409 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900410 ">",
411 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900412 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900413 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900414 " network_id: 0",
Hugo Benichi80df43e2016-11-24 11:28:06 +0900415 " time_ms: 300",
Hugo Benichif6840502017-03-08 11:59:36 +0900416 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900417 " ip_provisioning_event <",
418 " event_type: 1",
Hugo Benichi948a8592017-03-16 16:33:47 +0900419 " if_name: \"\"",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900420 " latency_ms: 5678",
421 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900422 ">",
423 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900424 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900425 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900426 " network_id: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900427 " time_ms: 400",
Hugo Benichif6840502017-03-08 11:59:36 +0900428 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900429 " validation_probe_event <",
430 " latency_ms: 40730",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900431 " probe_result: 204",
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900432 " probe_type: 257",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900433 " >",
434 ">",
435 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900436 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900437 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900438 " network_id: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900439 " time_ms: 500",
Hugo Benichif6840502017-03-08 11:59:36 +0900440 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900441 " apf_statistics <",
442 " dropped_ras: 2",
443 " duration_ms: 45000",
444 " matching_ras: 2",
445 " max_program_size: 2048",
446 " parse_errors: 2",
447 " program_updates: 4",
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900448 " program_updates_all: 7",
449 " program_updates_allowing_multicast: 3",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900450 " received_ras: 10",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900451 " total_packet_dropped: 0",
452 " total_packet_processed: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900453 " zero_lifetime_ras: 1",
454 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900455 ">",
456 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900457 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900458 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900459 " network_id: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900460 " time_ms: 600",
Hugo Benichif6840502017-03-08 11:59:36 +0900461 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900462 " ra_event <",
463 " dnssl_lifetime: -1",
464 " prefix_preferred_lifetime: 300",
465 " prefix_valid_lifetime: 400",
466 " rdnss_lifetime: 1000",
467 " route_info_lifetime: -1",
468 " router_lifetime: 2000",
469 " >",
Hugo Benichid680d4c2016-10-13 13:16:16 +0900470 ">",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900471 "events <",
472 " if_name: \"\"",
Hugo Benichi380a0632017-10-20 09:25:29 +0900473 " link_layer: 5",
474 " network_id: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900475 " time_ms: 0",
476 " transports: 0",
477 " default_network_event <",
Hugo Benichi380a0632017-10-20 09:25:29 +0900478 " default_network_duration_ms: 200",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900479 " final_score: 0",
480 " initial_score: 0",
481 " ip_support: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900482 " no_default_network_duration_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900483 " previous_default_network_link_layer: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900484 " previous_network_ip_support: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900485 " validation_duration_ms: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900486 " >",
487 ">",
488 "events <",
489 " if_name: \"\"",
Hugo Benichi380a0632017-10-20 09:25:29 +0900490 " link_layer: 2",
491 " network_id: 100",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900492 " time_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900493 " transports: 1",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900494 " default_network_event <",
Hugo Benichi380a0632017-10-20 09:25:29 +0900495 " default_network_duration_ms: 100",
496 " final_score: 50",
497 " initial_score: 50",
498 " ip_support: 2",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900499 " no_default_network_duration_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900500 " previous_default_network_link_layer: 0",
501 " previous_network_ip_support: 0",
502 " validation_duration_ms: 100",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900503 " >",
504 ">",
505 "events <",
506 " if_name: \"\"",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900507 " link_layer: 4",
508 " network_id: 100",
509 " time_ms: 0",
510 " transports: 2",
511 " connect_statistics <",
512 " connect_blocking_count: 1",
513 " connect_count: 3",
514 " errnos_counters <",
515 " key: 11",
516 " value: 1",
517 " >",
518 " ipv6_addr_count: 1",
519 " latencies_ms: 110",
520 " >",
521 ">",
522 "events <",
523 " if_name: \"\"",
524 " link_layer: 2",
525 " network_id: 101",
526 " time_ms: 0",
527 " transports: 1",
528 " connect_statistics <",
529 " connect_blocking_count: 2",
530 " connect_count: 2",
531 " ipv6_addr_count: 1",
532 " latencies_ms: 23",
533 " latencies_ms: 45",
534 " >",
535 ">",
536 "events <",
537 " if_name: \"\"",
538 " link_layer: 4",
539 " network_id: 100",
540 " time_ms: 0",
541 " transports: 2",
542 " dns_lookup_batch <",
543 " event_types: 1",
544 " event_types: 1",
545 " event_types: 2",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900546 " getaddrinfo_error_count: 0",
547 " getaddrinfo_query_count: 0",
548 " gethostbyname_error_count: 0",
549 " gethostbyname_query_count: 0",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900550 " latencies_ms: 3456",
551 " latencies_ms: 45",
552 " latencies_ms: 638",
553 " return_codes: 0",
554 " return_codes: 3",
555 " return_codes: 0",
556 " >",
557 ">",
558 "events <",
559 " if_name: \"\"",
560 " link_layer: 2",
561 " network_id: 101",
562 " time_ms: 0",
563 " transports: 1",
564 " dns_lookup_batch <",
565 " event_types: 1",
566 " event_types: 2",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900567 " getaddrinfo_error_count: 0",
568 " getaddrinfo_query_count: 0",
569 " gethostbyname_error_count: 0",
570 " gethostbyname_query_count: 0",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900571 " latencies_ms: 56",
572 " latencies_ms: 34",
573 " return_codes: 0",
574 " return_codes: 0",
575 " >",
576 ">",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900577 "events <",
578 " if_name: \"\"",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900579 " link_layer: 4",
580 " network_id: 0",
581 " time_ms: 0",
582 " transports: 0",
583 " wakeup_stats <",
Hugo Benichid921bce2017-10-12 21:33:40 +0900584 " application_wakeups: 3",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900585 " duration_sec: 0",
Hugo Benichid921bce2017-10-12 21:33:40 +0900586 " ethertype_counts <",
587 " key: 2048",
588 " value: 6",
589 " >",
590 " ip_next_header_counts <",
591 " key: 6",
592 " value: 3",
593 " >",
594 " ip_next_header_counts <",
595 " key: 17",
596 " value: 3",
597 " >",
598 " l2_broadcast_count: 0",
599 " l2_multicast_count: 0",
600 " l2_unicast_count: 6",
Hugo Benichi175b5742017-09-19 13:15:26 +0900601 " no_uid_wakeups: 1",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900602 " non_application_wakeups: 0",
603 " root_wakeups: 0",
604 " system_wakeups: 2",
Hugo Benichid921bce2017-10-12 21:33:40 +0900605 " total_wakeups: 6",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900606 " >",
607 ">",
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900608 "version: 2\n");
Hugo Benichi00a42d42016-09-13 15:55:09 +0900609
610 verifySerialization(want, getdump("flush"));
611 }
612
613 String getdump(String ... command) {
614 StringWriter buffer = new StringWriter();
615 PrintWriter writer = new PrintWriter(buffer);
616 mService.impl.dump(null, writer, command);
617 return buffer.toString();
618 }
619
Hugo Benichi5eb90532017-03-23 18:38:22 +0900620 void connectEvent(int netid, int error, int latencyMs, String ipAddr) throws Exception {
621 mNetdListener.onConnectEvent(netid, error, latencyMs, ipAddr, 80, 1);
622 }
623
624 void dnsEvent(int netId, int type, int result, int latency) throws Exception {
625 mNetdListener.onDnsEvent(netId, type, result, latency, "", null, 0, 0);
626 }
627
Hugo Benichid921bce2017-10-12 21:33:40 +0900628 void wakeupEvent(String iface, int uid, int ether, int ip, byte[] mac, String srcIp,
629 String dstIp, int sport, int dport, long now) throws Exception {
Hugo Benichi60c9f632017-09-05 13:34:48 +0900630 String prefix = NetdEventListenerService.WAKEUP_EVENT_IFACE_PREFIX + iface;
Hugo Benichid921bce2017-10-12 21:33:40 +0900631 mNetdListener.onWakeupEvent(prefix, uid, ether, ip, mac, srcIp, dstIp, sport, dport, now);
Hugo Benichi60c9f632017-09-05 13:34:48 +0900632 }
633
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900634 NetworkAgentInfo makeNai(int netId, int score, boolean ipv4, boolean ipv6, long transports) {
635 NetworkAgentInfo nai = mock(NetworkAgentInfo.class);
636 when(nai.network()).thenReturn(new Network(netId));
637 when(nai.getCurrentScore()).thenReturn(score);
638 nai.linkProperties = new LinkProperties();
639 nai.networkCapabilities = new NetworkCapabilities();
Hugo Benichibb16b752017-12-14 09:56:04 +0900640 nai.lastValidated = true;
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900641 for (int t : BitUtils.unpackBits(transports)) {
642 nai.networkCapabilities.addTransportType(t);
643 }
644 if (ipv4) {
645 nai.linkProperties.addLinkAddress(new LinkAddress("192.0.2.12/24"));
646 nai.linkProperties.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0")));
647 }
648 if (ipv6) {
649 nai.linkProperties.addLinkAddress(new LinkAddress("2001:db8:dead:beef:f00::a0/64"));
650 nai.linkProperties.addRoute(new RouteInfo(new IpPrefix("::/0")));
651 }
652 return nai;
653 }
654
Hugo Benichi00a42d42016-09-13 15:55:09 +0900655 List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
656 ArgumentCaptor<ConnectivityMetricsEvent> captor =
657 ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
658 verify(mMockService, timeout(timeoutMs).times(n)).logEvent(captor.capture());
659 return captor.getAllValues();
660 }
661
662 List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception {
663 return verifyEvents(n, 10);
664 }
665
666 static void verifySerialization(String want, String output) {
667 try {
668 byte[] got = Base64.decode(output, Base64.DEFAULT);
669 IpConnectivityLogClass.IpConnectivityLog log =
Glen Kuhne07199402016-10-25 15:47:25 -0700670 IpConnectivityLogClass.IpConnectivityLog.parseFrom(got);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900671 assertEquals(want, log.toString());
672 } catch (Exception e) {
673 fail(e.toString());
674 }
675 }
676
677 static String joinLines(String ... elems) {
678 StringBuilder b = new StringBuilder();
679 for (String s : elems) {
680 b.append(s).append("\n");
681 }
682 return b.toString();
683 }
684
685 static ConnectivityMetricsEvent expectedEvent(int timestamp) {
Hugo Benichiec27c4d2017-03-15 15:07:42 +0900686 ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
687 ev.timestamp = timestamp;
688 ev.data = FAKE_EV;
689 return ev;
Hugo Benichi00a42d42016-09-13 15:55:09 +0900690 }
691
692 /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
693 static void assertEventsEqual(ConnectivityMetricsEvent expected, ConnectivityMetricsEvent got) {
694 assertEquals(expected.timestamp, got.timestamp);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900695 assertEquals(expected.data, got.data);
696 }
697
698 static final Comparator<ConnectivityMetricsEvent> EVENT_COMPARATOR =
Hugo Benichi0d4a3982016-11-25 11:24:22 +0900699 Comparator.comparingLong((ev) -> ev.timestamp);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900700}