1 /* 2 * Copyright (C) 2019 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 android.net.metrics; 18 19 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 20 import static android.net.NetworkCapabilities.TRANSPORT_WIFI; 21 22 import static com.android.net.module.util.BitUtils.unpackBits; 23 24 import static org.junit.Assert.assertEquals; 25 import static org.junit.Assert.assertTrue; 26 import static org.mockito.Mockito.times; 27 import static org.mockito.Mockito.verify; 28 29 import android.net.ConnectivityMetricsEvent; 30 import android.net.IIpConnectivityMetrics; 31 import android.net.Network; 32 33 import androidx.test.filters.SmallTest; 34 import androidx.test.runner.AndroidJUnit4; 35 36 import org.junit.Before; 37 import org.junit.Test; 38 import org.junit.runner.RunWith; 39 import org.mockito.ArgumentCaptor; 40 import org.mockito.Mock; 41 import org.mockito.MockitoAnnotations; 42 43 import java.util.Collections; 44 import java.util.Comparator; 45 import java.util.Iterator; 46 import java.util.List; 47 48 @RunWith(AndroidJUnit4.class) 49 @SmallTest 50 public class IpConnectivityLogTest { 51 private static final int FAKE_NET_ID = 100; 52 private static final int[] FAKE_TRANSPORT_TYPES = unpackBits(TRANSPORT_WIFI); 53 private static final long FAKE_TIME_STAMP = System.currentTimeMillis(); 54 private static final long THREAD_TIMEOUT_MS = 10_000L; 55 private static final String FAKE_INTERFACE_NAME = "test"; 56 private static final IpReachabilityEvent FAKE_EV = 57 new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED); 58 59 @Mock IIpConnectivityMetrics mMockService; 60 61 @Before setUp()62 public void setUp() { 63 MockitoAnnotations.initMocks(this); 64 } 65 66 @Test testLoggingEvents()67 public void testLoggingEvents() throws Exception { 68 IpConnectivityLog logger = new IpConnectivityLog(mMockService); 69 70 assertTrue(logger.log(FAKE_EV)); 71 assertTrue(logger.log(FAKE_TIME_STAMP, FAKE_EV)); 72 assertTrue(logger.log(FAKE_NET_ID, FAKE_TRANSPORT_TYPES, FAKE_EV)); 73 assertTrue(logger.log(new Network(FAKE_NET_ID), FAKE_TRANSPORT_TYPES, FAKE_EV)); 74 assertTrue(logger.log(FAKE_INTERFACE_NAME, FAKE_EV)); 75 assertTrue(logger.log(makeExpectedEvent(FAKE_TIME_STAMP, FAKE_NET_ID, TRANSPORT_WIFI, 76 FAKE_INTERFACE_NAME))); 77 78 List<ConnectivityMetricsEvent> got = verifyEvents(6); 79 assertEventsEqual(makeExpectedEvent(got.get(0).timestamp, 0, 0, null), got.get(0)); 80 assertEventsEqual(makeExpectedEvent(FAKE_TIME_STAMP, 0, 0, null), got.get(1)); 81 assertEventsEqual(makeExpectedEvent(got.get(2).timestamp, FAKE_NET_ID, 82 TRANSPORT_WIFI, null), got.get(2)); 83 assertEventsEqual(makeExpectedEvent(got.get(3).timestamp, FAKE_NET_ID, 84 TRANSPORT_WIFI, null), got.get(3)); 85 assertEventsEqual(makeExpectedEvent(got.get(4).timestamp, 0, 0, FAKE_INTERFACE_NAME), 86 got.get(4)); 87 assertEventsEqual(makeExpectedEvent(FAKE_TIME_STAMP, FAKE_NET_ID, 88 TRANSPORT_WIFI, FAKE_INTERFACE_NAME), got.get(5)); 89 } 90 91 @Test testLoggingEventsWithMultipleCallers()92 public void testLoggingEventsWithMultipleCallers() throws Exception { 93 IpConnectivityLog logger = new IpConnectivityLog(mMockService); 94 95 final int nCallers = 10; 96 final int nEvents = 10; 97 final Thread[] threads = new Thread[nCallers]; 98 for (int n = 0; n < nCallers; n++) { 99 final int i = n; 100 threads[i] = new Thread(() -> { 101 for (int j = 0; j < nEvents; j++) { 102 assertTrue(logger.log(makeExpectedEvent( 103 FAKE_TIME_STAMP + i * 100 + j, 104 FAKE_NET_ID + i * 100 + j, 105 ((i + j) % 2 == 0) ? TRANSPORT_WIFI : TRANSPORT_CELLULAR, 106 FAKE_INTERFACE_NAME))); 107 } 108 }); 109 threads[i].start(); 110 } 111 // To ensure the events have been sent out on each thread. Wait for the thread to die. 112 for (Thread thread : threads) { 113 thread.join(THREAD_TIMEOUT_MS); 114 } 115 116 final List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents); 117 Collections.sort(got, EVENT_COMPARATOR); 118 Iterator<ConnectivityMetricsEvent> iter = got.iterator(); 119 for (int i = 0; i < nCallers; i++) { 120 for (int j = 0; j < nEvents; j++) { 121 final long expectedTimestamp = FAKE_TIME_STAMP + i * 100 + j; 122 final int expectedNetId = FAKE_NET_ID + i * 100 + j; 123 final long expectedTransports = 124 ((i + j) % 2 == 0) ? TRANSPORT_WIFI : TRANSPORT_CELLULAR; 125 assertEventsEqual(makeExpectedEvent(expectedTimestamp, expectedNetId, 126 expectedTransports, FAKE_INTERFACE_NAME), iter.next()); 127 } 128 } 129 } 130 verifyEvents(int n)131 private List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception { 132 ArgumentCaptor<ConnectivityMetricsEvent> captor = 133 ArgumentCaptor.forClass(ConnectivityMetricsEvent.class); 134 verify(mMockService, times(n)).logEvent(captor.capture()); 135 return captor.getAllValues(); 136 } 137 138 makeExpectedEvent(long timestamp, int netId, long transports, String ifname)139 private ConnectivityMetricsEvent makeExpectedEvent(long timestamp, int netId, long transports, 140 String ifname) { 141 ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent(); 142 ev.timestamp = timestamp; 143 ev.data = FAKE_EV; 144 ev.netId = netId; 145 ev.transports = transports; 146 ev.ifname = ifname; 147 return ev; 148 } 149 150 /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */ assertEventsEqual(ConnectivityMetricsEvent expected, ConnectivityMetricsEvent got)151 private void assertEventsEqual(ConnectivityMetricsEvent expected, 152 ConnectivityMetricsEvent got) { 153 assertEquals(expected.data, got.data); 154 assertEquals(expected.timestamp, got.timestamp); 155 assertEquals(expected.netId, got.netId); 156 assertEquals(expected.transports, got.transports); 157 assertEquals(expected.ifname, got.ifname); 158 } 159 160 static final Comparator<ConnectivityMetricsEvent> EVENT_COMPARATOR = 161 Comparator.comparingLong((ev) -> ev.timestamp); 162 } 163