blob: a395c480f57ac0100cb4bcb7eb806110f84f04d1 [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;
Glen Kuhne07199402016-10-25 15:47:25 -070021import static org.mockito.Mockito.timeout;
22import static org.mockito.Mockito.verify;
Hugo Benichi5eb90532017-03-23 18:38:22 +090023import static org.mockito.Mockito.when;
24import static org.junit.Assert.assertEquals;
25import static org.junit.Assert.assertFalse;
26import static org.junit.Assert.assertTrue;
27import static org.junit.Assert.fail;
Glen Kuhne07199402016-10-25 15:47:25 -070028
Hugo Benichi00a42d42016-09-13 15:55:09 +090029import android.content.Context;
Hugo Benichi5eb90532017-03-23 18:38:22 +090030import android.net.ConnectivityManager;
Hugo Benichi00a42d42016-09-13 15:55:09 +090031import android.net.ConnectivityMetricsEvent;
32import android.net.IIpConnectivityMetrics;
Hugo Benichi5eb90532017-03-23 18:38:22 +090033import android.net.Network;
34import android.net.NetworkCapabilities;
Hugo Benichie1c173d2016-10-18 10:36:33 +090035import android.net.metrics.ApfProgramEvent;
Hugo Benichi00a42d42016-09-13 15:55:09 +090036import android.net.metrics.ApfStats;
37import android.net.metrics.DefaultNetworkEvent;
38import android.net.metrics.DhcpClientEvent;
39import android.net.metrics.IpConnectivityLog;
40import android.net.metrics.IpManagerEvent;
41import android.net.metrics.IpReachabilityEvent;
42import android.net.metrics.RaEvent;
43import android.net.metrics.ValidationProbeEvent;
Hugo Benichi5eb90532017-03-23 18:38:22 +090044import android.system.OsConstants;
Hugo Benichi00a42d42016-09-13 15:55:09 +090045import android.os.Parcelable;
Hugo Benichi5eb90532017-03-23 18:38:22 +090046import android.support.test.runner.AndroidJUnit4;
Hugo Benichi80df43e2016-11-24 11:28:06 +090047import android.test.suitebuilder.annotation.SmallTest;
Hugo Benichi00a42d42016-09-13 15:55:09 +090048import android.util.Base64;
Tamas Berghammer383db5eb2016-06-22 15:21:38 +010049import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
Hugo Benichi00a42d42016-09-13 15:55:09 +090050import java.io.PrintWriter;
51import java.io.StringWriter;
52import java.util.Collections;
53import java.util.Comparator;
54import java.util.Iterator;
55import java.util.List;
Hugo Benichi80df43e2016-11-24 11:28:06 +090056import org.mockito.ArgumentCaptor;
57import org.mockito.Mock;
58import org.mockito.MockitoAnnotations;
Hugo Benichi5eb90532017-03-23 18:38:22 +090059import org.junit.Before;
60import org.junit.Test;
61import org.junit.runner.RunWith;
Hugo Benichi00a42d42016-09-13 15:55:09 +090062
Hugo Benichi5eb90532017-03-23 18:38:22 +090063@RunWith(AndroidJUnit4.class)
64@SmallTest
65public class IpConnectivityMetricsTest {
Hugo Benichi00a42d42016-09-13 15:55:09 +090066 static final IpReachabilityEvent FAKE_EV =
Hugo Benichi948a8592017-03-16 16:33:47 +090067 new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED);
Hugo Benichi00a42d42016-09-13 15:55:09 +090068
Hugo Benichi5eb90532017-03-23 18:38:22 +090069 private static final String EXAMPLE_IPV4 = "192.0.2.1";
70 private static final String EXAMPLE_IPV6 = "2001:db8:1200::2:1";
71
Hugo Benichi00a42d42016-09-13 15:55:09 +090072 @Mock Context mCtx;
73 @Mock IIpConnectivityMetrics mMockService;
Hugo Benichi5eb90532017-03-23 18:38:22 +090074 @Mock ConnectivityManager mCm;
Hugo Benichi00a42d42016-09-13 15:55:09 +090075
76 IpConnectivityMetrics mService;
Hugo Benichi5eb90532017-03-23 18:38:22 +090077 NetdEventListenerService mNetdListener;
Hugo Benichi00a42d42016-09-13 15:55:09 +090078
Hugo Benichi5eb90532017-03-23 18:38:22 +090079 @Before
Hugo Benichi00a42d42016-09-13 15:55:09 +090080 public void setUp() {
81 MockitoAnnotations.initMocks(this);
Hugo Benichi05686db2016-10-19 11:17:28 +090082 mService = new IpConnectivityMetrics(mCtx, (ctx) -> 2000);
Hugo Benichi5eb90532017-03-23 18:38:22 +090083 mNetdListener = new NetdEventListenerService(mCm);
84 mService.mNetdListener = mNetdListener;
Hugo Benichi00a42d42016-09-13 15:55:09 +090085 }
86
Hugo Benichi5eb90532017-03-23 18:38:22 +090087 @Test
Hugo Benichi00a42d42016-09-13 15:55:09 +090088 public void testLoggingEvents() throws Exception {
89 IpConnectivityLog logger = new IpConnectivityLog(mMockService);
90
91 assertTrue(logger.log(1, FAKE_EV));
92 assertTrue(logger.log(2, FAKE_EV));
93 assertTrue(logger.log(3, FAKE_EV));
94
95 List<ConnectivityMetricsEvent> got = verifyEvents(3);
96 assertEventsEqual(expectedEvent(1), got.get(0));
97 assertEventsEqual(expectedEvent(2), got.get(1));
98 assertEventsEqual(expectedEvent(3), got.get(2));
99 }
100
Hugo Benichi5eb90532017-03-23 18:38:22 +0900101 @Test
Hugo Benichi00a42d42016-09-13 15:55:09 +0900102 public void testLoggingEventsWithMultipleCallers() throws Exception {
103 IpConnectivityLog logger = new IpConnectivityLog(mMockService);
104
105 final int nCallers = 10;
106 final int nEvents = 10;
107 for (int n = 0; n < nCallers; n++) {
108 final int i = n;
109 new Thread() {
110 public void run() {
111 for (int j = 0; j < nEvents; j++) {
Hugo Benichi946b7e42017-03-15 16:35:26 +0900112 assertTrue(logger.log(1 + i * 100 + j, FAKE_EV));
Hugo Benichi00a42d42016-09-13 15:55:09 +0900113 }
114 }
115 }.start();
116 }
117
Hugo Benichi5eb90532017-03-23 18:38:22 +0900118 List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 200);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900119 Collections.sort(got, EVENT_COMPARATOR);
120 Iterator<ConnectivityMetricsEvent> iter = got.iterator();
121 for (int i = 0; i < nCallers; i++) {
122 for (int j = 0; j < nEvents; j++) {
Hugo Benichi946b7e42017-03-15 16:35:26 +0900123 int expectedTimestamp = 1 + i * 100 + j;
Hugo Benichi00a42d42016-09-13 15:55:09 +0900124 assertEventsEqual(expectedEvent(expectedTimestamp), iter.next());
125 }
126 }
127 }
128
Hugo Benichi5eb90532017-03-23 18:38:22 +0900129 @Test
Hugo Benichi00a42d42016-09-13 15:55:09 +0900130 public void testBufferFlushing() {
131 String output1 = getdump("flush");
132 assertEquals("", output1);
133
134 new IpConnectivityLog(mService.impl).log(1, FAKE_EV);
135 String output2 = getdump("flush");
136 assertFalse("".equals(output2));
137
138 String output3 = getdump("flush");
139 assertEquals("", output3);
140 }
141
Hugo Benichi5eb90532017-03-23 18:38:22 +0900142 @Test
Hugo Benichie1c173d2016-10-18 10:36:33 +0900143 public void testRateLimiting() {
144 final IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900145 final ApfProgramEvent ev = new ApfProgramEvent();
Hugo Benichie1c173d2016-10-18 10:36:33 +0900146 final long fakeTimestamp = 1;
147
148 int attempt = 100; // More than burst quota, but less than buffer size.
149 for (int i = 0; i < attempt; i++) {
150 logger.log(ev);
151 }
152
153 String output1 = getdump("flush");
154 assertFalse("".equals(output1));
155
156 for (int i = 0; i < attempt; i++) {
157 assertFalse("expected event to be dropped", logger.log(fakeTimestamp, ev));
158 }
159
160 String output2 = getdump("flush");
161 assertEquals("", output2);
162 }
163
Hugo Benichi5eb90532017-03-23 18:38:22 +0900164 @Test
165 public void testEndToEndLogging() throws Exception {
Hugo Benichif6840502017-03-08 11:59:36 +0900166 // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
Hugo Benichi00a42d42016-09-13 15:55:09 +0900167 IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
168
Hugo Benichi5eb90532017-03-23 18:38:22 +0900169 NetworkCapabilities ncWifi = new NetworkCapabilities();
170 NetworkCapabilities ncCell = new NetworkCapabilities();
171 ncWifi.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
172 ncCell.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
173
174 when(mCm.getNetworkCapabilities(new Network(100))).thenReturn(ncWifi);
175 when(mCm.getNetworkCapabilities(new Network(101))).thenReturn(ncCell);
176
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900177 ApfStats apfStats = new ApfStats();
178 apfStats.durationMs = 45000;
179 apfStats.receivedRas = 10;
180 apfStats.matchingRas = 2;
181 apfStats.droppedRas = 2;
182 apfStats.parseErrors = 2;
183 apfStats.zeroLifetimeRas = 1;
184 apfStats.programUpdates = 4;
185 apfStats.programUpdatesAll = 7;
186 apfStats.programUpdatesAllowingMulticast = 3;
187 apfStats.maxProgramSize = 2048;
Hugo Benichif927f0c2017-03-17 15:42:40 +0900188
189 ValidationProbeEvent validationEv = new ValidationProbeEvent();
190 validationEv.durationMs = 40730;
191 validationEv.probeType = ValidationProbeEvent.PROBE_HTTP;
192 validationEv.returnCode = 204;
193
Hugo Benichi00a42d42016-09-13 15:55:09 +0900194 Parcelable[] events = {
Hugo Benichi948a8592017-03-16 16:33:47 +0900195 new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED),
196 new DhcpClientEvent("SomeState", 192),
Hugo Benichi00a42d42016-09-13 15:55:09 +0900197 new DefaultNetworkEvent(102, new int[]{1,2,3}, 101, true, false),
Hugo Benichi948a8592017-03-16 16:33:47 +0900198 new IpManagerEvent(IpManagerEvent.PROVISIONING_OK, 5678),
Hugo Benichif927f0c2017-03-17 15:42:40 +0900199 validationEv,
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900200 apfStats,
Hugo Benichi00a42d42016-09-13 15:55:09 +0900201 new RaEvent(2000, 400, 300, -1, 1000, -1)
202 };
203
204 for (int i = 0; i < events.length; i++) {
Hugo Benichi948a8592017-03-16 16:33:47 +0900205 ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
206 ev.timestamp = 100 * (i + 1);
207 ev.ifname = "wlan0";
208 ev.data = events[i];
209 logger.log(ev);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900210 }
211
Hugo Benichi5eb90532017-03-23 18:38:22 +0900212 // netId, errno, latency, destination
213 connectEvent(100, OsConstants.EALREADY, 0, EXAMPLE_IPV4);
214 connectEvent(100, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6);
215 connectEvent(100, 0, 110, EXAMPLE_IPV4);
216 connectEvent(101, 0, 23, EXAMPLE_IPV4);
217 connectEvent(101, 0, 45, EXAMPLE_IPV6);
218 connectEvent(100, OsConstants.EAGAIN, 0, EXAMPLE_IPV4);
219
220 // netId, type, return code, latency
221 dnsEvent(100, EVENT_GETADDRINFO, 0, 3456);
222 dnsEvent(100, EVENT_GETADDRINFO, 3, 45);
223 dnsEvent(100, EVENT_GETHOSTBYNAME, 0, 638);
224 dnsEvent(101, EVENT_GETADDRINFO, 0, 56);
225 dnsEvent(101, EVENT_GETHOSTBYNAME, 0, 34);
226
Hugo Benichi60c9f632017-09-05 13:34:48 +0900227 // iface, uid
228 wakeupEvent("wlan0", 1000);
229 wakeupEvent("rmnet0", 10123);
230 wakeupEvent("wlan0", 1000);
231 wakeupEvent("rmnet0", 10008);
232 wakeupEvent("wlan0", -1);
233 wakeupEvent("wlan0", 10008);
234 wakeupEvent("rmnet0", 1000);
235
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900236 String want = String.join("\n",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900237 "dropped_events: 0",
238 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900239 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900240 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900241 " network_id: 0",
Hugo Benichi80df43e2016-11-24 11:28:06 +0900242 " time_ms: 100",
Hugo Benichif6840502017-03-08 11:59:36 +0900243 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900244 " ip_reachability_event <",
245 " event_type: 512",
Hugo Benichi948a8592017-03-16 16:33:47 +0900246 " if_name: \"\"",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900247 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900248 ">",
249 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900250 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900251 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900252 " network_id: 0",
Hugo Benichi80df43e2016-11-24 11:28:06 +0900253 " time_ms: 200",
Hugo Benichif6840502017-03-08 11:59:36 +0900254 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900255 " dhcp_event <",
256 " duration_ms: 192",
Hugo Benichi948a8592017-03-16 16:33:47 +0900257 " if_name: \"\"",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900258 " state_transition: \"SomeState\"",
259 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900260 ">",
261 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900262 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900263 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900264 " network_id: 0",
Hugo Benichi80df43e2016-11-24 11:28:06 +0900265 " time_ms: 300",
Hugo Benichif6840502017-03-08 11:59:36 +0900266 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900267 " default_network_event <",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900268 " default_network_duration_ms: 0",
269 " final_score: 0",
270 " initial_score: 0",
271 " ip_support: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900272 " network_id <",
273 " network_id: 102",
274 " >",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900275 " no_default_network_duration_ms: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900276 " previous_network_id <",
277 " network_id: 101",
278 " >",
279 " previous_network_ip_support: 1",
280 " transport_types: 1",
281 " transport_types: 2",
282 " transport_types: 3",
283 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900284 ">",
285 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900286 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900287 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900288 " network_id: 0",
Hugo Benichi80df43e2016-11-24 11:28:06 +0900289 " time_ms: 400",
Hugo Benichif6840502017-03-08 11:59:36 +0900290 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900291 " ip_provisioning_event <",
292 " event_type: 1",
Hugo Benichi948a8592017-03-16 16:33:47 +0900293 " if_name: \"\"",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900294 " latency_ms: 5678",
295 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900296 ">",
297 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900298 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900299 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900300 " network_id: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900301 " time_ms: 500",
Hugo Benichif6840502017-03-08 11:59:36 +0900302 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900303 " validation_probe_event <",
304 " latency_ms: 40730",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900305 " probe_result: 204",
306 " probe_type: 1",
307 " >",
308 ">",
309 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900310 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900311 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900312 " network_id: 0",
Hugo Benichi80df43e2016-11-24 11:28:06 +0900313 " time_ms: 600",
Hugo Benichif6840502017-03-08 11:59:36 +0900314 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900315 " apf_statistics <",
316 " dropped_ras: 2",
317 " duration_ms: 45000",
318 " matching_ras: 2",
319 " max_program_size: 2048",
320 " parse_errors: 2",
321 " program_updates: 4",
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900322 " program_updates_all: 7",
323 " program_updates_allowing_multicast: 3",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900324 " received_ras: 10",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900325 " total_packet_dropped: 0",
326 " total_packet_processed: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900327 " zero_lifetime_ras: 1",
328 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900329 ">",
330 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900331 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900332 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900333 " network_id: 0",
Hugo Benichi80df43e2016-11-24 11:28:06 +0900334 " time_ms: 700",
Hugo Benichif6840502017-03-08 11:59:36 +0900335 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900336 " ra_event <",
337 " dnssl_lifetime: -1",
338 " prefix_preferred_lifetime: 300",
339 " prefix_valid_lifetime: 400",
340 " rdnss_lifetime: 1000",
341 " route_info_lifetime: -1",
342 " router_lifetime: 2000",
343 " >",
Hugo Benichid680d4c2016-10-13 13:16:16 +0900344 ">",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900345 "events <",
346 " if_name: \"\"",
347 " link_layer: 4",
348 " network_id: 100",
349 " time_ms: 0",
350 " transports: 2",
351 " connect_statistics <",
352 " connect_blocking_count: 1",
353 " connect_count: 3",
354 " errnos_counters <",
355 " key: 11",
356 " value: 1",
357 " >",
358 " ipv6_addr_count: 1",
359 " latencies_ms: 110",
360 " >",
361 ">",
362 "events <",
363 " if_name: \"\"",
364 " link_layer: 2",
365 " network_id: 101",
366 " time_ms: 0",
367 " transports: 1",
368 " connect_statistics <",
369 " connect_blocking_count: 2",
370 " connect_count: 2",
371 " ipv6_addr_count: 1",
372 " latencies_ms: 23",
373 " latencies_ms: 45",
374 " >",
375 ">",
376 "events <",
377 " if_name: \"\"",
378 " link_layer: 4",
379 " network_id: 100",
380 " time_ms: 0",
381 " transports: 2",
382 " dns_lookup_batch <",
383 " event_types: 1",
384 " event_types: 1",
385 " event_types: 2",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900386 " getaddrinfo_error_count: 0",
387 " getaddrinfo_query_count: 0",
388 " gethostbyname_error_count: 0",
389 " gethostbyname_query_count: 0",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900390 " latencies_ms: 3456",
391 " latencies_ms: 45",
392 " latencies_ms: 638",
393 " return_codes: 0",
394 " return_codes: 3",
395 " return_codes: 0",
396 " >",
397 ">",
398 "events <",
399 " if_name: \"\"",
400 " link_layer: 2",
401 " network_id: 101",
402 " time_ms: 0",
403 " transports: 1",
404 " dns_lookup_batch <",
405 " event_types: 1",
406 " event_types: 2",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900407 " getaddrinfo_error_count: 0",
408 " getaddrinfo_query_count: 0",
409 " gethostbyname_error_count: 0",
410 " gethostbyname_query_count: 0",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900411 " latencies_ms: 56",
412 " latencies_ms: 34",
413 " return_codes: 0",
414 " return_codes: 0",
415 " >",
416 ">",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900417 "events <",
418 " if_name: \"\"",
419 " link_layer: 2",
420 " network_id: 0",
421 " time_ms: 0",
422 " transports: 0",
423 " wakeup_stats <",
424 " application_wakeups: 2",
425 " duration_sec: 0",
Hugo Benichi175b5742017-09-19 13:15:26 +0900426 " no_uid_wakeups: 0",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900427 " non_application_wakeups: 0",
428 " root_wakeups: 0",
429 " system_wakeups: 1",
430 " total_wakeups: 3",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900431 " >",
432 ">",
433 "events <",
434 " if_name: \"\"",
435 " link_layer: 4",
436 " network_id: 0",
437 " time_ms: 0",
438 " transports: 0",
439 " wakeup_stats <",
440 " application_wakeups: 1",
441 " duration_sec: 0",
Hugo Benichi175b5742017-09-19 13:15:26 +0900442 " no_uid_wakeups: 1",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900443 " non_application_wakeups: 0",
444 " root_wakeups: 0",
445 " system_wakeups: 2",
446 " total_wakeups: 4",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900447 " >",
448 ">",
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900449 "version: 2\n");
Hugo Benichi00a42d42016-09-13 15:55:09 +0900450
451 verifySerialization(want, getdump("flush"));
452 }
453
454 String getdump(String ... command) {
455 StringWriter buffer = new StringWriter();
456 PrintWriter writer = new PrintWriter(buffer);
457 mService.impl.dump(null, writer, command);
458 return buffer.toString();
459 }
460
Hugo Benichi5eb90532017-03-23 18:38:22 +0900461 void connectEvent(int netid, int error, int latencyMs, String ipAddr) throws Exception {
462 mNetdListener.onConnectEvent(netid, error, latencyMs, ipAddr, 80, 1);
463 }
464
465 void dnsEvent(int netId, int type, int result, int latency) throws Exception {
466 mNetdListener.onDnsEvent(netId, type, result, latency, "", null, 0, 0);
467 }
468
Hugo Benichi60c9f632017-09-05 13:34:48 +0900469 void wakeupEvent(String iface, int uid) throws Exception {
470 String prefix = NetdEventListenerService.WAKEUP_EVENT_IFACE_PREFIX + iface;
471 mNetdListener.onWakeupEvent(prefix, uid, uid, 0);
472 }
473
Hugo Benichi00a42d42016-09-13 15:55:09 +0900474 List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
475 ArgumentCaptor<ConnectivityMetricsEvent> captor =
476 ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
477 verify(mMockService, timeout(timeoutMs).times(n)).logEvent(captor.capture());
478 return captor.getAllValues();
479 }
480
481 List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception {
482 return verifyEvents(n, 10);
483 }
484
485 static void verifySerialization(String want, String output) {
486 try {
487 byte[] got = Base64.decode(output, Base64.DEFAULT);
488 IpConnectivityLogClass.IpConnectivityLog log =
Glen Kuhne07199402016-10-25 15:47:25 -0700489 IpConnectivityLogClass.IpConnectivityLog.parseFrom(got);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900490 assertEquals(want, log.toString());
491 } catch (Exception e) {
492 fail(e.toString());
493 }
494 }
495
496 static String joinLines(String ... elems) {
497 StringBuilder b = new StringBuilder();
498 for (String s : elems) {
499 b.append(s).append("\n");
500 }
501 return b.toString();
502 }
503
504 static ConnectivityMetricsEvent expectedEvent(int timestamp) {
Hugo Benichiec27c4d2017-03-15 15:07:42 +0900505 ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
506 ev.timestamp = timestamp;
507 ev.data = FAKE_EV;
508 return ev;
Hugo Benichi00a42d42016-09-13 15:55:09 +0900509 }
510
511 /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
512 static void assertEventsEqual(ConnectivityMetricsEvent expected, ConnectivityMetricsEvent got) {
513 assertEquals(expected.timestamp, got.timestamp);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900514 assertEquals(expected.data, got.data);
515 }
516
517 static final Comparator<ConnectivityMetricsEvent> EVENT_COMPARATOR =
Hugo Benichi0d4a3982016-11-25 11:24:22 +0900518 Comparator.comparingLong((ev) -> ev.timestamp);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900519}