blob: 67805c944943ec5bf619bfe542d147f4c40a5bbf [file] [log] [blame]
Hugo Benichi5e055182016-06-01 08:50:38 +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 Benichi2a5cfb92017-03-22 22:21:44 +090019import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO;
20import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME;
21import static org.junit.Assert.assertEquals;
Hugo Benichif562ac32017-09-04 13:24:43 +090022import static org.junit.Assert.assertTrue;
Hugo Benichi2a5cfb92017-03-22 22:21:44 +090023import static org.junit.Assert.fail;
Hugo Benichi5e055182016-06-01 08:50:38 +090024import static org.mockito.Mockito.any;
Hugo Benichi2a5cfb92017-03-22 22:21:44 +090025import static org.mockito.Mockito.mock;
Hugo Benichi5e055182016-06-01 08:50:38 +090026import static org.mockito.Mockito.anyInt;
27import static org.mockito.Mockito.eq;
28import static org.mockito.Mockito.timeout;
29import static org.mockito.Mockito.times;
30import static org.mockito.Mockito.verify;
Hugo Benichi2a5cfb92017-03-22 22:21:44 +090031import static org.mockito.Mockito.when;
Hugo Benichi5e055182016-06-01 08:50:38 +090032
Hugo Benichi2a5cfb92017-03-22 22:21:44 +090033import android.content.Context;
34import android.net.ConnectivityManager;
35import android.net.Network;
36import android.net.NetworkCapabilities;
37import android.support.test.runner.AndroidJUnit4;
38import android.system.OsConstants;
39import android.test.suitebuilder.annotation.SmallTest;
40import android.util.Base64;
Hugo Benichi60c9f632017-09-05 13:34:48 +090041
Hugo Benichi2a5cfb92017-03-22 22:21:44 +090042import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.DNSLookupBatch;
43import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
44import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
Hugo Benichi60c9f632017-09-05 13:34:48 +090045
Hugo Benichi2a5cfb92017-03-22 22:21:44 +090046import java.io.FileOutputStream;
47import java.io.PrintWriter;
48import java.io.StringWriter;
49import java.util.ArrayList;
50import java.util.Arrays;
51import java.util.Comparator;
52import java.util.List;
Hugo Benichi60c9f632017-09-05 13:34:48 +090053
Hugo Benichi2a5cfb92017-03-22 22:21:44 +090054import org.junit.Before;
55import org.junit.Test;
56import org.junit.runner.RunWith;
Hugo Benichi5e055182016-06-01 08:50:38 +090057
Hugo Benichi2a5cfb92017-03-22 22:21:44 +090058@RunWith(AndroidJUnit4.class)
59@SmallTest
60public class NetdEventListenerServiceTest {
Hugo Benichi0d4a3982016-11-25 11:24:22 +090061 private static final String EXAMPLE_IPV4 = "192.0.2.1";
62 private static final String EXAMPLE_IPV6 = "2001:db8:1200::2:1";
63
Hugo Benichid921bce2017-10-12 21:33:40 +090064 private static final byte[] MAC_ADDR =
65 {(byte)0x84, (byte)0xc9, (byte)0xb2, (byte)0x6a, (byte)0xed, (byte)0x4b};
66
67 NetdEventListenerService mService;
Hugo Benichi2a5cfb92017-03-22 22:21:44 +090068 ConnectivityManager mCm;
Hugo Benichi5e055182016-06-01 08:50:38 +090069
Hugo Benichi2a5cfb92017-03-22 22:21:44 +090070 @Before
Hugo Benichi5e055182016-06-01 08:50:38 +090071 public void setUp() {
Hugo Benichi2a5cfb92017-03-22 22:21:44 +090072 NetworkCapabilities ncWifi = new NetworkCapabilities();
73 NetworkCapabilities ncCell = new NetworkCapabilities();
74 ncWifi.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
75 ncCell.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
Hugo Benichi5e055182016-06-01 08:50:38 +090076
Hugo Benichi5eb90532017-03-23 18:38:22 +090077 mCm = mock(ConnectivityManager.class);
Hugo Benichi2a5cfb92017-03-22 22:21:44 +090078 when(mCm.getNetworkCapabilities(new Network(100))).thenReturn(ncWifi);
79 when(mCm.getNetworkCapabilities(new Network(101))).thenReturn(ncCell);
Hugo Benichi5e055182016-06-01 08:50:38 +090080
Hugo Benichid921bce2017-10-12 21:33:40 +090081 mService = new NetdEventListenerService(mCm);
Hugo Benichi5eb90532017-03-23 18:38:22 +090082 }
83
84 @Test
Hugo Benichif562ac32017-09-04 13:24:43 +090085 public void testWakeupEventLogging() throws Exception {
86 final int BUFFER_LENGTH = NetdEventListenerService.WAKEUP_EVENT_BUFFER_LENGTH;
Hugo Benichid921bce2017-10-12 21:33:40 +090087 final long now = System.currentTimeMillis();
88 final String iface = "wlan0";
89 final byte[] mac = MAC_ADDR;
90 final String srcIp = "192.168.2.1";
91 final String dstIp = "192.168.2.23";
92 final String srcIp6 = "2001:db8:4:fd00:a585:13d1:6a23:4fb4";
93 final String dstIp6 = "2001:db8:4006:807::200a";
94 final int sport = 2356;
95 final int dport = 13489;
96
97 final int v4 = 0x800;
98 final int v6 = 0x86dd;
99 final int tcp = 6;
100 final int udp = 17;
101 final int icmp6 = 58;
Hugo Benichif562ac32017-09-04 13:24:43 +0900102
Hugo Benichi380a0632017-10-20 09:25:29 +0900103 // Baseline without any event
104 String[] baseline = listNetdEvent();
Hugo Benichif562ac32017-09-04 13:24:43 +0900105
Hugo Benichid921bce2017-10-12 21:33:40 +0900106 int[] uids = {10001, 10002, 10004, 1000, 10052, 10023, 10002, 10123, 10004};
107 wakeupEvent(iface, uids[0], v4, tcp, mac, srcIp, dstIp, sport, dport, now);
108 wakeupEvent(iface, uids[1], v6, udp, mac, srcIp6, dstIp6, sport, dport, now);
109 wakeupEvent(iface, uids[2], v6, udp, mac, srcIp6, dstIp6, sport, dport, now);
110 wakeupEvent(iface, uids[3], v4, icmp6, mac, srcIp, dstIp, sport, dport, now);
111 wakeupEvent(iface, uids[4], v6, tcp, mac, srcIp6, dstIp6, sport, dport, now);
112 wakeupEvent(iface, uids[5], v4, tcp, mac, srcIp, dstIp, sport, dport, now);
113 wakeupEvent(iface, uids[6], v6, udp, mac, srcIp6, dstIp6, sport, dport, now);
114 wakeupEvent(iface, uids[7], v6, tcp, mac, srcIp6, dstIp6, sport, dport, now);
115 wakeupEvent(iface, uids[8], v6, udp, mac, srcIp6, dstIp6, sport, dport, now);
Hugo Benichif562ac32017-09-04 13:24:43 +0900116
Hugo Benichi380a0632017-10-20 09:25:29 +0900117 String[] events2 = remove(listNetdEvent(), baseline);
Hugo Benichi60c9f632017-09-05 13:34:48 +0900118 int expectedLength2 = uids.length + 1; // +1 for the WakeupStats line
119 assertEquals(expectedLength2, events2.length);
120 assertContains(events2[0], "WakeupStats");
121 assertContains(events2[0], "wlan0");
Hugo Benichid921bce2017-10-12 21:33:40 +0900122 assertContains(events2[0], "0x800");
123 assertContains(events2[0], "0x86dd");
Hugo Benichif562ac32017-09-04 13:24:43 +0900124 for (int i = 0; i < uids.length; i++) {
Hugo Benichi60c9f632017-09-05 13:34:48 +0900125 String got = events2[i+1];
126 assertContains(got, "WakeupEvent");
Hugo Benichif562ac32017-09-04 13:24:43 +0900127 assertContains(got, "wlan0");
128 assertContains(got, "uid: " + uids[i]);
129 }
130
131 int uid = 20000;
132 for (int i = 0; i < BUFFER_LENGTH * 2; i++) {
133 long ts = now + 10;
Hugo Benichid921bce2017-10-12 21:33:40 +0900134 wakeupEvent(iface, uid, 0x800, 6, mac, srcIp, dstIp, 23, 24, ts);
Hugo Benichif562ac32017-09-04 13:24:43 +0900135 }
136
Hugo Benichi380a0632017-10-20 09:25:29 +0900137 String[] events3 = remove(listNetdEvent(), baseline);
Hugo Benichi60c9f632017-09-05 13:34:48 +0900138 int expectedLength3 = BUFFER_LENGTH + 1; // +1 for the WakeupStats line
139 assertEquals(expectedLength3, events3.length);
140 assertContains(events2[0], "WakeupStats");
141 assertContains(events2[0], "wlan0");
142 for (int i = 1; i < expectedLength3; i++) {
143 String got = events3[i];
144 assertContains(got, "WakeupEvent");
Hugo Benichif562ac32017-09-04 13:24:43 +0900145 assertContains(got, "wlan0");
146 assertContains(got, "uid: " + uid);
147 }
148
149 uid = 45678;
Hugo Benichid921bce2017-10-12 21:33:40 +0900150 wakeupEvent(iface, uid, 0x800, 6, mac, srcIp, dstIp, 23, 24, now);
Hugo Benichif562ac32017-09-04 13:24:43 +0900151
Hugo Benichi380a0632017-10-20 09:25:29 +0900152 String[] events4 = remove(listNetdEvent(), baseline);
Hugo Benichif562ac32017-09-04 13:24:43 +0900153 String lastEvent = events4[events4.length - 1];
Hugo Benichi60c9f632017-09-05 13:34:48 +0900154 assertContains(lastEvent, "WakeupEvent");
Hugo Benichif562ac32017-09-04 13:24:43 +0900155 assertContains(lastEvent, "wlan0");
156 assertContains(lastEvent, "uid: " + uid);
157 }
158
159 @Test
Hugo Benichi60c9f632017-09-05 13:34:48 +0900160 public void testWakeupStatsLogging() throws Exception {
Hugo Benichid921bce2017-10-12 21:33:40 +0900161 final byte[] mac = MAC_ADDR;
162 final String srcIp = "192.168.2.1";
163 final String dstIp = "192.168.2.23";
164 final String srcIp6 = "2401:fa00:4:fd00:a585:13d1:6a23:4fb4";
165 final String dstIp6 = "2404:6800:4006:807::200a";
166 final int sport = 2356;
167 final int dport = 13489;
168 final long now = 1001L;
169
170 final int v4 = 0x800;
171 final int v6 = 0x86dd;
172 final int tcp = 6;
173 final int udp = 17;
174 final int icmp6 = 58;
175
176 wakeupEvent("wlan0", 1000, v4, tcp, mac, srcIp, dstIp, sport, dport, now);
177 wakeupEvent("rmnet0", 10123, v4, tcp, mac, srcIp, dstIp, sport, dport, now);
178 wakeupEvent("wlan0", 1000, v4, udp, mac, srcIp, dstIp, sport, dport, now);
179 wakeupEvent("rmnet0", 10008, v4, tcp, mac, srcIp, dstIp, sport, dport, now);
180 wakeupEvent("wlan0", -1, v6, icmp6, mac, srcIp6, dstIp6, sport, dport, now);
181 wakeupEvent("wlan0", 10008, v4, tcp, mac, srcIp, dstIp, sport, dport, now);
182 wakeupEvent("rmnet0", 1000, v4, tcp, mac, srcIp, dstIp, sport, dport, now);
183 wakeupEvent("wlan0", 10004, v4, udp, mac, srcIp, dstIp, sport, dport, now);
184 wakeupEvent("wlan0", 1000, v6, tcp, mac, srcIp6, dstIp6, sport, dport, now);
185 wakeupEvent("wlan0", 0, v6, udp, mac, srcIp6, dstIp6, sport, dport, now);
186 wakeupEvent("wlan0", -1, v6, icmp6, mac, srcIp6, dstIp6, sport, dport, now);
187 wakeupEvent("rmnet0", 10052, v4, tcp, mac, srcIp, dstIp, sport, dport, now);
188 wakeupEvent("wlan0", 0, v6, udp, mac, srcIp6, dstIp6, sport, dport, now);
189 wakeupEvent("rmnet0", 1000, v6, tcp, mac, srcIp6, dstIp6, sport, dport, now);
190 wakeupEvent("wlan0", 1010, v4, udp, mac, srcIp, dstIp, sport, dport, now);
Hugo Benichi60c9f632017-09-05 13:34:48 +0900191
192 String got = flushStatistics();
193 String want = String.join("\n",
194 "dropped_events: 0",
195 "events <",
196 " if_name: \"\"",
197 " link_layer: 2",
198 " network_id: 0",
199 " time_ms: 0",
200 " transports: 0",
201 " wakeup_stats <",
202 " application_wakeups: 3",
203 " duration_sec: 0",
Hugo Benichid921bce2017-10-12 21:33:40 +0900204 " ethertype_counts <",
205 " key: 2048",
206 " value: 4",
207 " >",
208 " ethertype_counts <",
209 " key: 34525",
210 " value: 1",
211 " >",
212 " ip_next_header_counts <",
213 " key: 6",
214 " value: 5",
215 " >",
216 " l2_broadcast_count: 0",
217 " l2_multicast_count: 0",
218 " l2_unicast_count: 5",
Hugo Benichi175b5742017-09-19 13:15:26 +0900219 " no_uid_wakeups: 0",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900220 " non_application_wakeups: 0",
221 " root_wakeups: 0",
222 " system_wakeups: 2",
223 " total_wakeups: 5",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900224 " >",
225 ">",
226 "events <",
227 " if_name: \"\"",
228 " link_layer: 4",
229 " network_id: 0",
230 " time_ms: 0",
231 " transports: 0",
232 " wakeup_stats <",
233 " application_wakeups: 2",
234 " duration_sec: 0",
Hugo Benichid921bce2017-10-12 21:33:40 +0900235 " ethertype_counts <",
236 " key: 2048",
237 " value: 5",
238 " >",
239 " ethertype_counts <",
240 " key: 34525",
241 " value: 5",
242 " >",
243 " ip_next_header_counts <",
244 " key: 6",
245 " value: 3",
246 " >",
247 " ip_next_header_counts <",
248 " key: 17",
249 " value: 5",
250 " >",
251 " ip_next_header_counts <",
252 " key: 58",
253 " value: 2",
254 " >",
255 " l2_broadcast_count: 0",
256 " l2_multicast_count: 0",
257 " l2_unicast_count: 10",
Hugo Benichi175b5742017-09-19 13:15:26 +0900258 " no_uid_wakeups: 2",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900259 " non_application_wakeups: 1",
260 " root_wakeups: 2",
261 " system_wakeups: 3",
262 " total_wakeups: 10",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900263 " >",
264 ">",
265 "version: 2\n");
266 assertEquals(want, got);
267 }
268
269 @Test
Hugo Benichi5eb90532017-03-23 18:38:22 +0900270 public void testDnsLogging() throws Exception {
271 asyncDump(100);
272
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900273 dnsEvent(100, EVENT_GETADDRINFO, 0, 3456);
274 dnsEvent(100, EVENT_GETADDRINFO, 0, 267);
275 dnsEvent(100, EVENT_GETHOSTBYNAME, 22, 1230);
276 dnsEvent(100, EVENT_GETADDRINFO, 3, 45);
277 dnsEvent(100, EVENT_GETADDRINFO, 1, 2111);
278 dnsEvent(100, EVENT_GETADDRINFO, 0, 450);
279 dnsEvent(100, EVENT_GETHOSTBYNAME, 200, 638);
280 dnsEvent(100, EVENT_GETHOSTBYNAME, 178, 1300);
281 dnsEvent(101, EVENT_GETADDRINFO, 0, 56);
282 dnsEvent(101, EVENT_GETADDRINFO, 0, 78);
283 dnsEvent(101, EVENT_GETADDRINFO, 0, 14);
284 dnsEvent(101, EVENT_GETHOSTBYNAME, 0, 56);
285 dnsEvent(101, EVENT_GETADDRINFO, 0, 78);
286 dnsEvent(101, EVENT_GETADDRINFO, 0, 14);
Hugo Benichi5e055182016-06-01 08:50:38 +0900287
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900288 String got = flushStatistics();
289 String want = String.join("\n",
290 "dropped_events: 0",
291 "events <",
292 " if_name: \"\"",
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900293 " link_layer: 4",
294 " network_id: 100",
295 " time_ms: 0",
296 " transports: 2",
297 " dns_lookup_batch <",
298 " event_types: 1",
299 " event_types: 1",
300 " event_types: 2",
301 " event_types: 1",
302 " event_types: 1",
303 " event_types: 1",
304 " event_types: 2",
305 " event_types: 2",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900306 " getaddrinfo_error_count: 0",
307 " getaddrinfo_query_count: 0",
308 " gethostbyname_error_count: 0",
309 " gethostbyname_query_count: 0",
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900310 " latencies_ms: 3456",
311 " latencies_ms: 267",
312 " latencies_ms: 1230",
313 " latencies_ms: 45",
314 " latencies_ms: 2111",
315 " latencies_ms: 450",
316 " latencies_ms: 638",
317 " latencies_ms: 1300",
318 " return_codes: 0",
319 " return_codes: 0",
320 " return_codes: 22",
321 " return_codes: 3",
322 " return_codes: 1",
323 " return_codes: 0",
324 " return_codes: 200",
325 " return_codes: 178",
326 " >",
327 ">",
328 "events <",
329 " if_name: \"\"",
330 " link_layer: 2",
331 " network_id: 101",
332 " time_ms: 0",
333 " transports: 1",
334 " dns_lookup_batch <",
335 " event_types: 1",
336 " event_types: 1",
337 " event_types: 1",
338 " event_types: 2",
339 " event_types: 1",
340 " event_types: 1",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900341 " getaddrinfo_error_count: 0",
342 " getaddrinfo_query_count: 0",
343 " gethostbyname_error_count: 0",
344 " gethostbyname_query_count: 0",
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900345 " latencies_ms: 56",
346 " latencies_ms: 78",
347 " latencies_ms: 14",
348 " latencies_ms: 56",
349 " latencies_ms: 78",
350 " latencies_ms: 14",
351 " return_codes: 0",
352 " return_codes: 0",
353 " return_codes: 0",
354 " return_codes: 0",
355 " return_codes: 0",
356 " return_codes: 0",
357 " >",
358 ">",
359 "version: 2\n");
360 assertEquals(want, got);
Hugo Benichi5e055182016-06-01 08:50:38 +0900361 }
362
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900363 @Test
Hugo Benichi0d4a3982016-11-25 11:24:22 +0900364 public void testConnectLogging() throws Exception {
Hugo Benichi5eb90532017-03-23 18:38:22 +0900365 asyncDump(100);
366
Hugo Benichi0d4a3982016-11-25 11:24:22 +0900367 final int OK = 0;
368 Thread[] logActions = {
369 // ignored
Hugo Benichi5eb90532017-03-23 18:38:22 +0900370 connectEventAction(100, OsConstants.EALREADY, 0, EXAMPLE_IPV4),
371 connectEventAction(100, OsConstants.EALREADY, 0, EXAMPLE_IPV6),
372 connectEventAction(100, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV4),
373 connectEventAction(101, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6),
374 connectEventAction(101, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6),
Hugo Benichi0d4a3982016-11-25 11:24:22 +0900375 // valid latencies
Hugo Benichi5eb90532017-03-23 18:38:22 +0900376 connectEventAction(100, OK, 110, EXAMPLE_IPV4),
377 connectEventAction(100, OK, 23, EXAMPLE_IPV4),
378 connectEventAction(100, OK, 45, EXAMPLE_IPV4),
379 connectEventAction(101, OK, 56, EXAMPLE_IPV4),
380 connectEventAction(101, OK, 523, EXAMPLE_IPV6),
381 connectEventAction(101, OK, 214, EXAMPLE_IPV6),
382 connectEventAction(101, OK, 67, EXAMPLE_IPV6),
Hugo Benichi0d4a3982016-11-25 11:24:22 +0900383 // errors
Hugo Benichi5eb90532017-03-23 18:38:22 +0900384 connectEventAction(100, OsConstants.EPERM, 0, EXAMPLE_IPV4),
385 connectEventAction(101, OsConstants.EPERM, 0, EXAMPLE_IPV4),
386 connectEventAction(100, OsConstants.EAGAIN, 0, EXAMPLE_IPV4),
387 connectEventAction(100, OsConstants.EACCES, 0, EXAMPLE_IPV4),
388 connectEventAction(101, OsConstants.EACCES, 0, EXAMPLE_IPV4),
389 connectEventAction(101, OsConstants.EACCES, 0, EXAMPLE_IPV6),
390 connectEventAction(100, OsConstants.EADDRINUSE, 0, EXAMPLE_IPV4),
391 connectEventAction(101, OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV4),
392 connectEventAction(100, OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV6),
393 connectEventAction(100, OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV6),
394 connectEventAction(101, OsConstants.ECONNREFUSED, 0, EXAMPLE_IPV4),
Hugo Benichi0d4a3982016-11-25 11:24:22 +0900395 };
396
397 for (Thread t : logActions) {
398 t.start();
399 }
400 for (Thread t : logActions) {
401 t.join();
402 }
403
Hugo Benichi5eb90532017-03-23 18:38:22 +0900404 String got = flushStatistics();
Hugo Benichi0d4a3982016-11-25 11:24:22 +0900405 String want = String.join("\n",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900406 "dropped_events: 0",
407 "events <",
408 " if_name: \"\"",
409 " link_layer: 4",
410 " network_id: 100",
411 " time_ms: 0",
412 " transports: 2",
413 " connect_statistics <",
414 " connect_blocking_count: 3",
415 " connect_count: 6",
416 " errnos_counters <",
417 " key: 1",
418 " value: 1",
419 " >",
420 " errnos_counters <",
421 " key: 11",
422 " value: 1",
423 " >",
424 " errnos_counters <",
425 " key: 13",
426 " value: 1",
427 " >",
428 " errnos_counters <",
429 " key: 98",
430 " value: 1",
431 " >",
432 " errnos_counters <",
433 " key: 110",
434 " value: 2",
435 " >",
436 " ipv6_addr_count: 1",
437 " latencies_ms: 23",
438 " latencies_ms: 45",
439 " latencies_ms: 110",
Hugo Benichi0d4a3982016-11-25 11:24:22 +0900440 " >",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900441 ">",
442 "events <",
443 " if_name: \"\"",
444 " link_layer: 2",
445 " network_id: 101",
446 " time_ms: 0",
447 " transports: 1",
448 " connect_statistics <",
449 " connect_blocking_count: 4",
450 " connect_count: 6",
451 " errnos_counters <",
452 " key: 1",
453 " value: 1",
454 " >",
455 " errnos_counters <",
456 " key: 13",
457 " value: 2",
458 " >",
459 " errnos_counters <",
460 " key: 110",
461 " value: 1",
462 " >",
463 " errnos_counters <",
464 " key: 111",
465 " value: 1",
466 " >",
467 " ipv6_addr_count: 5",
468 " latencies_ms: 56",
469 " latencies_ms: 67",
470 " latencies_ms: 214",
471 " latencies_ms: 523",
Hugo Benichi0d4a3982016-11-25 11:24:22 +0900472 " >",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900473 ">",
474 "version: 2\n");
475 assertEquals(want, got);
Hugo Benichi0d4a3982016-11-25 11:24:22 +0900476 }
477
Hugo Benichi5eb90532017-03-23 18:38:22 +0900478 Thread connectEventAction(int netId, int error, int latencyMs, String ipAddr) {
Hugo Benichi0d4a3982016-11-25 11:24:22 +0900479 return new Thread(() -> {
480 try {
Hugo Benichid921bce2017-10-12 21:33:40 +0900481 mService.onConnectEvent(netId, error, latencyMs, ipAddr, 80, 1);
Hugo Benichi0d4a3982016-11-25 11:24:22 +0900482 } catch (Exception e) {
483 fail(e.toString());
484 }
485 });
486 }
487
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900488 void dnsEvent(int netId, int type, int result, int latency) throws Exception {
Hugo Benichid921bce2017-10-12 21:33:40 +0900489 mService.onDnsEvent(netId, type, result, latency, "", null, 0, 0);
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900490 }
491
Hugo Benichid921bce2017-10-12 21:33:40 +0900492 void wakeupEvent(String iface, int uid, int ether, int ip, byte[] mac, String srcIp,
493 String dstIp, int sport, int dport, long now) throws Exception {
Hugo Benichi60c9f632017-09-05 13:34:48 +0900494 String prefix = NetdEventListenerService.WAKEUP_EVENT_IFACE_PREFIX + iface;
Hugo Benichid921bce2017-10-12 21:33:40 +0900495 mService.onWakeupEvent(prefix, uid, ether, ip, mac, srcIp, dstIp, sport, dport, now);
Hugo Benichi60c9f632017-09-05 13:34:48 +0900496 }
497
Hugo Benichi5eb90532017-03-23 18:38:22 +0900498 void asyncDump(long durationMs) throws Exception {
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900499 final long stop = System.currentTimeMillis() + durationMs;
500 final PrintWriter pw = new PrintWriter(new FileOutputStream("/dev/null"));
Hugo Benichi5eb90532017-03-23 18:38:22 +0900501 new Thread(() -> {
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900502 while (System.currentTimeMillis() < stop) {
Hugo Benichid921bce2017-10-12 21:33:40 +0900503 mService.list(pw);
Michal Karpinskidd9bb4f2016-10-12 14:59:26 +0100504 }
Hugo Benichi5eb90532017-03-23 18:38:22 +0900505 }).start();
Hugo Benichi0d4a3982016-11-25 11:24:22 +0900506 }
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900507
508 // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
509 String flushStatistics() throws Exception {
510 IpConnectivityMetrics metricsService =
511 new IpConnectivityMetrics(mock(Context.class), (ctx) -> 2000);
Hugo Benichid921bce2017-10-12 21:33:40 +0900512 metricsService.mNetdListener = mService;
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900513
514 StringWriter buffer = new StringWriter();
515 PrintWriter writer = new PrintWriter(buffer);
516 metricsService.impl.dump(null, writer, new String[]{"flush"});
517 byte[] bytes = Base64.decode(buffer.toString(), Base64.DEFAULT);
Hugo Benichi5eb90532017-03-23 18:38:22 +0900518 IpConnectivityLog log = IpConnectivityLog.parseFrom(bytes);
519 for (IpConnectivityEvent ev : log.events) {
520 if (ev.getConnectStatistics() == null) {
521 continue;
522 }
523 // Sort repeated fields of connect() events arriving in non-deterministic order.
524 Arrays.sort(ev.getConnectStatistics().latenciesMs);
525 Arrays.sort(ev.getConnectStatistics().errnosCounters,
526 Comparator.comparingInt((p) -> p.key));
527 }
528 return log.toString();
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900529 }
Hugo Benichif562ac32017-09-04 13:24:43 +0900530
531 String[] listNetdEvent() throws Exception {
532 StringWriter buffer = new StringWriter();
533 PrintWriter writer = new PrintWriter(buffer);
Hugo Benichid921bce2017-10-12 21:33:40 +0900534 mService.list(writer);
Hugo Benichif562ac32017-09-04 13:24:43 +0900535 return buffer.toString().split("\\n");
536 }
537
538 static void assertContains(String got, String want) {
539 assertTrue(got + " did not contain \"" + want + "\"", got.contains(want));
540 }
Hugo Benichi380a0632017-10-20 09:25:29 +0900541
542 static <T> T[] remove(T[] array, T[] filtered) {
543 List<T> c = Arrays.asList(filtered);
544 int next = 0;
545 for (int i = 0; i < array.length; i++) {
546 if (c.contains(array[i])) {
547 continue;
548 }
549 array[next++] = array[i];
550 }
551 return Arrays.copyOf(array, next);
552 }
Hugo Benichi5e055182016-06-01 08:50:38 +0900553}