blob: 3fc89b9ff12d38029f3052aa4cf15524c1617b3a [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
19import android.content.Context;
20import android.net.ConnectivityMetricsEvent;
21import android.net.IIpConnectivityMetrics;
22import android.net.metrics.ApfStats;
23import android.net.metrics.DefaultNetworkEvent;
24import android.net.metrics.DhcpClientEvent;
25import android.net.metrics.IpConnectivityLog;
26import android.net.metrics.IpManagerEvent;
27import android.net.metrics.IpReachabilityEvent;
28import android.net.metrics.RaEvent;
29import android.net.metrics.ValidationProbeEvent;
30import android.os.Parcelable;
31import android.util.Base64;
32import com.android.server.connectivity.metrics.IpConnectivityLogClass;
33import com.google.protobuf.nano.MessageNano;
34import java.io.PrintWriter;
35import java.io.StringWriter;
36import java.util.Collections;
37import java.util.Comparator;
38import java.util.Iterator;
39import java.util.List;
40import junit.framework.TestCase;
41import org.mockito.ArgumentCaptor;
42import org.mockito.Mock;
43import org.mockito.MockitoAnnotations;
44
45import static org.mockito.Mockito.timeout;
46import static org.mockito.Mockito.times;
47import static org.mockito.Mockito.verify;
48
49public class IpConnectivityMetricsTest extends TestCase {
50 static final IpReachabilityEvent FAKE_EV =
51 new IpReachabilityEvent("wlan0", IpReachabilityEvent.NUD_FAILED);
52
53 @Mock Context mCtx;
54 @Mock IIpConnectivityMetrics mMockService;
55
56 IpConnectivityMetrics mService;
57
58 public void setUp() {
59 MockitoAnnotations.initMocks(this);
60 mService = new IpConnectivityMetrics(mCtx);
61 }
62
63 public void testLoggingEvents() throws Exception {
64 IpConnectivityLog logger = new IpConnectivityLog(mMockService);
65
66 assertTrue(logger.log(1, FAKE_EV));
67 assertTrue(logger.log(2, FAKE_EV));
68 assertTrue(logger.log(3, FAKE_EV));
69
70 List<ConnectivityMetricsEvent> got = verifyEvents(3);
71 assertEventsEqual(expectedEvent(1), got.get(0));
72 assertEventsEqual(expectedEvent(2), got.get(1));
73 assertEventsEqual(expectedEvent(3), got.get(2));
74 }
75
76 public void testLoggingEventsWithMultipleCallers() throws Exception {
77 IpConnectivityLog logger = new IpConnectivityLog(mMockService);
78
79 final int nCallers = 10;
80 final int nEvents = 10;
81 for (int n = 0; n < nCallers; n++) {
82 final int i = n;
83 new Thread() {
84 public void run() {
85 for (int j = 0; j < nEvents; j++) {
86 assertTrue(logger.log(i * 100 + j, FAKE_EV));
87 }
88 }
89 }.start();
90 }
91
92 List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 100);
93 Collections.sort(got, EVENT_COMPARATOR);
94 Iterator<ConnectivityMetricsEvent> iter = got.iterator();
95 for (int i = 0; i < nCallers; i++) {
96 for (int j = 0; j < nEvents; j++) {
97 int expectedTimestamp = i * 100 + j;
98 assertEventsEqual(expectedEvent(expectedTimestamp), iter.next());
99 }
100 }
101 }
102
103 public void testBufferFlushing() {
104 String output1 = getdump("flush");
105 assertEquals("", output1);
106
107 new IpConnectivityLog(mService.impl).log(1, FAKE_EV);
108 String output2 = getdump("flush");
109 assertFalse("".equals(output2));
110
111 String output3 = getdump("flush");
112 assertEquals("", output3);
113 }
114
115 public void testEndToEndLogging() {
116 IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
117
118 Parcelable[] events = {
119 new IpReachabilityEvent("wlan0", IpReachabilityEvent.NUD_FAILED),
120 new DhcpClientEvent("wlan0", "SomeState", 192),
121 new DefaultNetworkEvent(102, new int[]{1,2,3}, 101, true, false),
122 new IpManagerEvent("wlan0", IpManagerEvent.PROVISIONING_OK, 5678),
123 new ValidationProbeEvent(120, 40730, ValidationProbeEvent.PROBE_HTTP, 204),
124 new ApfStats(45000, 10, 2, 2, 1, 2, 4, 2048),
125 new RaEvent(2000, 400, 300, -1, 1000, -1)
126 };
127
128 for (int i = 0; i < events.length; i++) {
129 logger.log(100 * (i + 1), events[i]);
130 }
131
132 String want = joinLines(
133 "dropped_events: 0",
134 "events <",
135 " ip_reachability_event <",
136 " event_type: 512",
137 " if_name: \"wlan0\"",
138 " >",
139 " time_ms: 100",
140 ">",
141 "events <",
142 " dhcp_event <",
143 " duration_ms: 192",
144 " error_code: 0",
145 " if_name: \"wlan0\"",
146 " state_transition: \"SomeState\"",
147 " >",
148 " time_ms: 200",
149 ">",
150 "events <",
151 " default_network_event <",
152 " network_id <",
153 " network_id: 102",
154 " >",
155 " previous_network_id <",
156 " network_id: 101",
157 " >",
158 " previous_network_ip_support: 1",
159 " transport_types: 1",
160 " transport_types: 2",
161 " transport_types: 3",
162 " >",
163 " time_ms: 300",
164 ">",
165 "events <",
166 " ip_provisioning_event <",
167 " event_type: 1",
168 " if_name: \"wlan0\"",
169 " latency_ms: 5678",
170 " >",
171 " time_ms: 400",
172 ">",
173 "events <",
174 " time_ms: 500",
175 " validation_probe_event <",
176 " latency_ms: 40730",
177 " network_id <",
178 " network_id: 120",
179 " >",
180 " probe_result: 204",
181 " probe_type: 1",
182 " >",
183 ">",
184 "events <",
185 " apf_statistics <",
186 " dropped_ras: 2",
187 " duration_ms: 45000",
188 " matching_ras: 2",
189 " max_program_size: 2048",
190 " parse_errors: 2",
191 " program_updates: 4",
192 " received_ras: 10",
193 " zero_lifetime_ras: 1",
194 " >",
195 " time_ms: 600",
196 ">",
197 "events <",
198 " ra_event <",
199 " dnssl_lifetime: -1",
200 " prefix_preferred_lifetime: 300",
201 " prefix_valid_lifetime: 400",
202 " rdnss_lifetime: 1000",
203 " route_info_lifetime: -1",
204 " router_lifetime: 2000",
205 " >",
206 " time_ms: 700",
207 ">");
208
209 verifySerialization(want, getdump("flush"));
210 }
211
212 String getdump(String ... command) {
213 StringWriter buffer = new StringWriter();
214 PrintWriter writer = new PrintWriter(buffer);
215 mService.impl.dump(null, writer, command);
216 return buffer.toString();
217 }
218
219 List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
220 ArgumentCaptor<ConnectivityMetricsEvent> captor =
221 ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
222 verify(mMockService, timeout(timeoutMs).times(n)).logEvent(captor.capture());
223 return captor.getAllValues();
224 }
225
226 List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception {
227 return verifyEvents(n, 10);
228 }
229
230 static void verifySerialization(String want, String output) {
231 try {
232 byte[] got = Base64.decode(output, Base64.DEFAULT);
233 IpConnectivityLogClass.IpConnectivityLog log =
234 new IpConnectivityLogClass.IpConnectivityLog();
235 MessageNano.mergeFrom(log, got);
236 assertEquals(want, log.toString());
237 } catch (Exception e) {
238 fail(e.toString());
239 }
240 }
241
242 static String joinLines(String ... elems) {
243 StringBuilder b = new StringBuilder();
244 for (String s : elems) {
245 b.append(s).append("\n");
246 }
247 return b.toString();
248 }
249
250 static ConnectivityMetricsEvent expectedEvent(int timestamp) {
251 return new ConnectivityMetricsEvent((long)timestamp, 0, 0, FAKE_EV);
252 }
253
254 /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
255 static void assertEventsEqual(ConnectivityMetricsEvent expected, ConnectivityMetricsEvent got) {
256 assertEquals(expected.timestamp, got.timestamp);
257 assertEquals(expected.componentTag, got.componentTag);
258 assertEquals(expected.eventTag, got.eventTag);
259 assertEquals(expected.data, got.data);
260 }
261
262 static final Comparator<ConnectivityMetricsEvent> EVENT_COMPARATOR =
263 new Comparator<ConnectivityMetricsEvent>() {
264 @Override
265 public int compare(ConnectivityMetricsEvent ev1, ConnectivityMetricsEvent ev2) {
266 return (int) (ev1.timestamp - ev2.timestamp);
267 }
268 };
269}