1 /* 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 17 package com.android.server.connectivity; 18 19 import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO; 20 import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME; 21 import static com.android.server.connectivity.MetricsTestUtil.aBool; 22 import static com.android.server.connectivity.MetricsTestUtil.aByteArray; 23 import static com.android.server.connectivity.MetricsTestUtil.aLong; 24 import static com.android.server.connectivity.MetricsTestUtil.aString; 25 import static com.android.server.connectivity.MetricsTestUtil.aType; 26 import static com.android.server.connectivity.MetricsTestUtil.anInt; 27 import static com.android.server.connectivity.MetricsTestUtil.anIntArray; 28 import static com.android.server.connectivity.MetricsTestUtil.b; 29 import static com.android.server.connectivity.MetricsTestUtil.describeIpEvent; 30 import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog; 31 import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.BLUETOOTH; 32 import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.CELLULAR; 33 import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.ETHERNET; 34 import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.MULTIPLE; 35 import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.WIFI; 36 import static org.junit.Assert.assertEquals; 37 import static org.junit.Assert.fail; 38 39 import android.net.ConnectivityMetricsEvent; 40 import android.net.metrics.ApfProgramEvent; 41 import android.net.metrics.ApfStats; 42 import android.net.metrics.ConnectStats; 43 import android.net.metrics.DefaultNetworkEvent; 44 import android.net.metrics.DhcpClientEvent; 45 import android.net.metrics.DhcpErrorEvent; 46 import android.net.metrics.DnsEvent; 47 import android.net.metrics.DnsEvent; 48 import android.net.metrics.IpManagerEvent; 49 import android.net.metrics.IpReachabilityEvent; 50 import android.net.metrics.NetworkEvent; 51 import android.net.metrics.RaEvent; 52 import android.net.metrics.ValidationProbeEvent; 53 import android.net.metrics.WakeupStats; 54 import android.support.test.runner.AndroidJUnit4; 55 import android.test.suitebuilder.annotation.SmallTest; 56 57 import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent; 58 59 import java.util.Arrays; 60 import java.util.List; 61 62 import org.junit.runner.RunWith; 63 import org.junit.Test; 64 65 // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto. 66 @RunWith(AndroidJUnit4.class) 67 @SmallTest 68 public class IpConnectivityEventBuilderTest { 69 70 @Test 71 public void testLinkLayerInferrence() { 72 ConnectivityMetricsEvent ev = describeIpEvent( 73 aType(IpReachabilityEvent.class), 74 anInt(IpReachabilityEvent.NUD_FAILED)); 75 76 String want = String.join("\n", 77 "dropped_events: 0", 78 "events <", 79 " if_name: \"\"", 80 " link_layer: 0", 81 " network_id: 0", 82 " time_ms: 1", 83 " transports: 0", 84 " ip_reachability_event <", 85 " event_type: 512", 86 " if_name: \"\"", 87 " >", 88 ">", 89 "version: 2\n"); 90 verifySerialization(want, ev); 91 92 ev.netId = 123; 93 ev.transports = 3; // transports have priority for inferrence of link layer 94 ev.ifname = "wlan0"; 95 want = String.join("\n", 96 "dropped_events: 0", 97 "events <", 98 " if_name: \"\"", 99 String.format(" link_layer: %d", MULTIPLE), 100 " network_id: 123", 101 " time_ms: 1", 102 " transports: 3", 103 " ip_reachability_event <", 104 " event_type: 512", 105 " if_name: \"\"", 106 " >", 107 ">", 108 "version: 2\n"); 109 verifySerialization(want, ev); 110 111 ev.transports = 1; 112 ev.ifname = null; 113 want = String.join("\n", 114 "dropped_events: 0", 115 "events <", 116 " if_name: \"\"", 117 String.format(" link_layer: %d", CELLULAR), 118 " network_id: 123", 119 " time_ms: 1", 120 " transports: 1", 121 " ip_reachability_event <", 122 " event_type: 512", 123 " if_name: \"\"", 124 " >", 125 ">", 126 "version: 2\n"); 127 verifySerialization(want, ev); 128 129 ev.transports = 0; 130 ev.ifname = "not_inferred"; 131 want = String.join("\n", 132 "dropped_events: 0", 133 "events <", 134 " if_name: \"not_inferred\"", 135 " link_layer: 0", 136 " network_id: 123", 137 " time_ms: 1", 138 " transports: 0", 139 " ip_reachability_event <", 140 " event_type: 512", 141 " if_name: \"\"", 142 " >", 143 ">", 144 "version: 2\n"); 145 verifySerialization(want, ev); 146 147 ev.ifname = "bt-pan"; 148 want = String.join("\n", 149 "dropped_events: 0", 150 "events <", 151 " if_name: \"\"", 152 String.format(" link_layer: %d", BLUETOOTH), 153 " network_id: 123", 154 " time_ms: 1", 155 " transports: 0", 156 " ip_reachability_event <", 157 " event_type: 512", 158 " if_name: \"\"", 159 " >", 160 ">", 161 "version: 2\n"); 162 verifySerialization(want, ev); 163 164 ev.ifname = "rmnet_ipa0"; 165 want = String.join("\n", 166 "dropped_events: 0", 167 "events <", 168 " if_name: \"\"", 169 String.format(" link_layer: %d", CELLULAR), 170 " network_id: 123", 171 " time_ms: 1", 172 " transports: 0", 173 " ip_reachability_event <", 174 " event_type: 512", 175 " if_name: \"\"", 176 " >", 177 ">", 178 "version: 2\n"); 179 verifySerialization(want, ev); 180 181 ev.ifname = "wlan0"; 182 want = String.join("\n", 183 "dropped_events: 0", 184 "events <", 185 " if_name: \"\"", 186 String.format(" link_layer: %d", WIFI), 187 " network_id: 123", 188 " time_ms: 1", 189 " transports: 0", 190 " ip_reachability_event <", 191 " event_type: 512", 192 " if_name: \"\"", 193 " >", 194 ">", 195 "version: 2\n"); 196 verifySerialization(want, ev); 197 } 198 199 @Test 200 public void testDefaultNetworkEventSerialization() { 201 DefaultNetworkEvent ev = new DefaultNetworkEvent(1001); 202 ev.netId = 102; 203 ev.transports = 2; 204 ev.previousTransports = 4; 205 ev.ipv4 = true; 206 ev.initialScore = 20; 207 ev.finalScore = 60; 208 ev.durationMs = 54; 209 ev.validatedMs = 27; 210 211 String want = String.join("\n", 212 "dropped_events: 0", 213 "events <", 214 " if_name: \"\"", 215 " link_layer: 4", 216 " network_id: 102", 217 " time_ms: 0", 218 " transports: 2", 219 " default_network_event <", 220 " default_network_duration_ms: 54", 221 " final_score: 60", 222 " initial_score: 20", 223 " ip_support: 1", 224 " no_default_network_duration_ms: 0", 225 " previous_default_network_link_layer: 1", 226 " previous_network_ip_support: 0", 227 " validation_duration_ms: 27", 228 " >", 229 ">", 230 "version: 2\n"); 231 232 verifySerialization(want, IpConnectivityEventBuilder.toProto(ev)); 233 } 234 235 @Test 236 public void testDhcpClientEventSerialization() { 237 ConnectivityMetricsEvent ev = describeIpEvent( 238 aType(DhcpClientEvent.class), 239 aString("SomeState"), 240 anInt(192)); 241 242 String want = String.join("\n", 243 "dropped_events: 0", 244 "events <", 245 " if_name: \"\"", 246 " link_layer: 0", 247 " network_id: 0", 248 " time_ms: 1", 249 " transports: 0", 250 " dhcp_event <", 251 " duration_ms: 192", 252 " if_name: \"\"", 253 " state_transition: \"SomeState\"", 254 " >", 255 ">", 256 "version: 2\n"); 257 258 verifySerialization(want, ev); 259 } 260 261 @Test 262 public void testDhcpErrorEventSerialization() { 263 ConnectivityMetricsEvent ev = describeIpEvent( 264 aType(DhcpErrorEvent.class), 265 anInt(DhcpErrorEvent.L4_NOT_UDP)); 266 267 String want = String.join("\n", 268 "dropped_events: 0", 269 "events <", 270 " if_name: \"\"", 271 " link_layer: 0", 272 " network_id: 0", 273 " time_ms: 1", 274 " transports: 0", 275 " dhcp_event <", 276 " duration_ms: 0", 277 " if_name: \"\"", 278 " error_code: 50397184", 279 " >", 280 ">", 281 "version: 2\n"); 282 283 verifySerialization(want, ev); 284 } 285 286 @Test 287 public void testIpManagerEventSerialization() { 288 ConnectivityMetricsEvent ev = describeIpEvent( 289 aType(IpManagerEvent.class), 290 anInt(IpManagerEvent.PROVISIONING_OK), 291 aLong(5678)); 292 293 String want = String.join("\n", 294 "dropped_events: 0", 295 "events <", 296 " if_name: \"\"", 297 " link_layer: 0", 298 " network_id: 0", 299 " time_ms: 1", 300 " transports: 0", 301 " ip_provisioning_event <", 302 " event_type: 1", 303 " if_name: \"\"", 304 " latency_ms: 5678", 305 " >", 306 ">", 307 "version: 2\n"); 308 309 verifySerialization(want, ev); 310 } 311 312 @Test 313 public void testIpReachabilityEventSerialization() { 314 ConnectivityMetricsEvent ev = describeIpEvent( 315 aType(IpReachabilityEvent.class), 316 anInt(IpReachabilityEvent.NUD_FAILED)); 317 318 String want = String.join("\n", 319 "dropped_events: 0", 320 "events <", 321 " if_name: \"\"", 322 " link_layer: 0", 323 " network_id: 0", 324 " time_ms: 1", 325 " transports: 0", 326 " ip_reachability_event <", 327 " event_type: 512", 328 " if_name: \"\"", 329 " >", 330 ">", 331 "version: 2\n"); 332 333 verifySerialization(want, ev); 334 } 335 336 @Test 337 public void testNetworkEventSerialization() { 338 ConnectivityMetricsEvent ev = describeIpEvent( 339 aType(NetworkEvent.class), 340 anInt(5), 341 aLong(20410)); 342 343 String want = String.join("\n", 344 "dropped_events: 0", 345 "events <", 346 " if_name: \"\"", 347 " link_layer: 0", 348 " network_id: 0", 349 " time_ms: 1", 350 " transports: 0", 351 " network_event <", 352 " event_type: 5", 353 " latency_ms: 20410", 354 " >", 355 ">", 356 "version: 2\n"); 357 358 verifySerialization(want, ev); 359 } 360 361 @Test 362 public void testValidationProbeEventSerialization() { 363 ConnectivityMetricsEvent ev = describeIpEvent( 364 aType(ValidationProbeEvent.class), 365 aLong(40730), 366 anInt(ValidationProbeEvent.PROBE_HTTP), 367 anInt(204)); 368 369 String want = String.join("\n", 370 "dropped_events: 0", 371 "events <", 372 " if_name: \"\"", 373 " link_layer: 0", 374 " network_id: 0", 375 " time_ms: 1", 376 " transports: 0", 377 " validation_probe_event <", 378 " latency_ms: 40730", 379 " probe_result: 204", 380 " probe_type: 1", 381 " >", 382 ">", 383 "version: 2\n"); 384 385 verifySerialization(want, ev); 386 } 387 388 @Test 389 public void testApfProgramEventSerialization() { 390 ConnectivityMetricsEvent ev = describeIpEvent( 391 aType(ApfProgramEvent.class), 392 aLong(200), 393 aLong(18), 394 anInt(7), 395 anInt(9), 396 anInt(2048), 397 anInt(3)); 398 399 String want = String.join("\n", 400 "dropped_events: 0", 401 "events <", 402 " if_name: \"\"", 403 " link_layer: 0", 404 " network_id: 0", 405 " time_ms: 1", 406 " transports: 0", 407 " apf_program_event <", 408 " current_ras: 9", 409 " drop_multicast: true", 410 " effective_lifetime: 18", 411 " filtered_ras: 7", 412 " has_ipv4_addr: true", 413 " lifetime: 200", 414 " program_length: 2048", 415 " >", 416 ">", 417 "version: 2\n"); 418 419 verifySerialization(want, ev); 420 } 421 422 @Test 423 public void testApfStatsSerialization() { 424 ConnectivityMetricsEvent ev = describeIpEvent( 425 aType(ApfStats.class), 426 aLong(45000), 427 anInt(10), 428 anInt(2), 429 anInt(2), 430 anInt(1), 431 anInt(2), 432 anInt(4), 433 anInt(7), 434 anInt(3), 435 anInt(2048)); 436 437 String want = String.join("\n", 438 "dropped_events: 0", 439 "events <", 440 " if_name: \"\"", 441 " link_layer: 0", 442 " network_id: 0", 443 " time_ms: 1", 444 " transports: 0", 445 " apf_statistics <", 446 " dropped_ras: 2", 447 " duration_ms: 45000", 448 " matching_ras: 2", 449 " max_program_size: 2048", 450 " parse_errors: 2", 451 " program_updates: 4", 452 " program_updates_all: 7", 453 " program_updates_allowing_multicast: 3", 454 " received_ras: 10", 455 " total_packet_dropped: 0", 456 " total_packet_processed: 0", 457 " zero_lifetime_ras: 1", 458 " >", 459 ">", 460 "version: 2\n"); 461 462 verifySerialization(want, ev); 463 } 464 465 @Test 466 public void testRaEventSerialization() { 467 ConnectivityMetricsEvent ev = describeIpEvent( 468 aType(RaEvent.class), 469 aLong(2000), 470 aLong(400), 471 aLong(300), 472 aLong(-1), 473 aLong(1000), 474 aLong(-1)); 475 476 String want = String.join("\n", 477 "dropped_events: 0", 478 "events <", 479 " if_name: \"\"", 480 " link_layer: 0", 481 " network_id: 0", 482 " time_ms: 1", 483 " transports: 0", 484 " ra_event <", 485 " dnssl_lifetime: -1", 486 " prefix_preferred_lifetime: 300", 487 " prefix_valid_lifetime: 400", 488 " rdnss_lifetime: 1000", 489 " route_info_lifetime: -1", 490 " router_lifetime: 2000", 491 " >", 492 ">", 493 "version: 2\n"); 494 495 verifySerialization(want, ev); 496 } 497 498 @Test 499 public void testWakeupStatsSerialization() { 500 WakeupStats stats = new WakeupStats("wlan0"); 501 stats.totalWakeups = 14; 502 stats.applicationWakeups = 5; 503 stats.nonApplicationWakeups = 1; 504 stats.rootWakeups = 2; 505 stats.systemWakeups = 3; 506 stats.noUidWakeups = 3; 507 stats.l2UnicastCount = 5; 508 stats.l2MulticastCount = 1; 509 stats.l2BroadcastCount = 2; 510 stats.ethertypes.put(0x800, 3); 511 stats.ethertypes.put(0x86dd, 3); 512 stats.ipNextHeaders.put(6, 5); 513 514 515 IpConnectivityEvent got = IpConnectivityEventBuilder.toProto(stats); 516 String want = String.join("\n", 517 "dropped_events: 0", 518 "events <", 519 " if_name: \"\"", 520 " link_layer: 4", 521 " network_id: 0", 522 " time_ms: 0", 523 " transports: 0", 524 " wakeup_stats <", 525 " application_wakeups: 5", 526 " duration_sec: 0", 527 " ethertype_counts <", 528 " key: 2048", 529 " value: 3", 530 " >", 531 " ethertype_counts <", 532 " key: 34525", 533 " value: 3", 534 " >", 535 " ip_next_header_counts <", 536 " key: 6", 537 " value: 5", 538 " >", 539 " l2_broadcast_count: 2", 540 " l2_multicast_count: 1", 541 " l2_unicast_count: 5", 542 " no_uid_wakeups: 3", 543 " non_application_wakeups: 1", 544 " root_wakeups: 2", 545 " system_wakeups: 3", 546 " total_wakeups: 14", 547 " >", 548 ">", 549 "version: 2\n"); 550 551 verifySerialization(want, got); 552 } 553 554 static void verifySerialization(String want, ConnectivityMetricsEvent... input) { 555 List<IpConnectivityEvent> protoInput = 556 IpConnectivityEventBuilder.toProto(Arrays.asList(input)); 557 verifySerialization(want, protoInput.toArray(new IpConnectivityEvent[0])); 558 } 559 560 static void verifySerialization(String want, IpConnectivityEvent... input) { 561 try { 562 byte[] got = IpConnectivityEventBuilder.serialize(0, Arrays.asList(input)); 563 IpConnectivityLog log = IpConnectivityLog.parseFrom(got); 564 assertEquals(want, log.toString()); 565 } catch (Exception e) { 566 fail(e.toString()); 567 } 568 } 569 } 570