diff options
| author | 2016-05-30 14:42:29 +0900 | |
|---|---|---|
| committer | 2016-06-28 11:43:03 +0900 | |
| commit | 3bba249c4711b10b2ba5335c7b6653dc570aae64 (patch) | |
| tree | 8f8fa8be3f0cf5fd24d5552322bf8236840ebe9c | |
| parent | 2cd8281a236a9c58bfdb22ce1e2e37303fdcd987 (diff) | |
Tests for IpConnectivityMetricsLog
Bug: 28204408
Bug: 29035129
Change-Id: I429562a00904188947b11da9928ec5c01296ff97
3 files changed, 188 insertions, 5 deletions
diff --git a/core/java/android/net/ConnectivityMetricsLogger.java b/core/java/android/net/ConnectivityMetricsLogger.java index 73734958f512..029c5bdccd41 100644 --- a/core/java/android/net/ConnectivityMetricsLogger.java +++ b/core/java/android/net/ConnectivityMetricsLogger.java @@ -23,6 +23,8 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; + /** {@hide} */ @SystemApi public class ConnectivityMetricsLogger { @@ -49,8 +51,14 @@ public class ConnectivityMetricsLogger { private int mNumSkippedEvents; public ConnectivityMetricsLogger() { - mService = IConnectivityMetricsLogger.Stub.asInterface(ServiceManager.getService( - CONNECTIVITY_METRICS_LOGGER_SERVICE)); + this(IConnectivityMetricsLogger.Stub.asInterface( + ServiceManager.getService(CONNECTIVITY_METRICS_LOGGER_SERVICE))); + } + + /** {@hide} */ + @VisibleForTesting + public ConnectivityMetricsLogger(IConnectivityMetricsLogger service) { + mService = service; } /** @@ -153,11 +161,10 @@ public class ConnectivityMetricsLogger { public boolean unregister(PendingIntent newEventsIntent) { try { mService.unregister(newEventsIntent); + return true; } catch (RemoteException e) { Log.e(TAG, "IConnectivityMetricsLogger.unregister", e); return false; } - - return true; } } diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java index 233ff74a145b..0126a8793111 100644 --- a/core/java/android/net/metrics/IpConnectivityLog.java +++ b/core/java/android/net/metrics/IpConnectivityLog.java @@ -18,18 +18,29 @@ package android.net.metrics; import android.net.ConnectivityMetricsEvent; import android.net.ConnectivityMetricsLogger; +import android.net.IConnectivityMetricsLogger; import android.os.Parcelable; import android.os.RemoteException; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; + /** * Specialization of the ConnectivityMetricsLogger class for recording IP connectivity events. * {@hide} */ -class IpConnectivityLog extends ConnectivityMetricsLogger { +public class IpConnectivityLog extends ConnectivityMetricsLogger { private static String TAG = "IpConnectivityMetricsLogger"; private static final boolean DBG = false; + public IpConnectivityLog() { + } + + @VisibleForTesting + public IpConnectivityLog(IConnectivityMetricsLogger service) { + super(service); + } + /** * Log an IpConnectivity event. Contrary to logEvent(), this method does not * keep track of skipped events and is thread-safe for callers. diff --git a/services/tests/servicestests/src/android/net/metrics/IpConnectivityLogTest.java b/services/tests/servicestests/src/android/net/metrics/IpConnectivityLogTest.java new file mode 100644 index 000000000000..17ac9fe3e282 --- /dev/null +++ b/services/tests/servicestests/src/android/net/metrics/IpConnectivityLogTest.java @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.metrics; + +import android.os.Parcel; +import android.os.Parcelable; +import android.net.ConnectivityMetricsEvent; +import android.net.IConnectivityMetricsLogger; + +import junit.framework.TestCase; +import org.junit.Before; +import org.junit.Test; + +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.List; + +public class IpConnectivityLogTest extends TestCase { + + static class FakeEvent extends IpConnectivityEvent implements Parcelable { + public int describeContents() { return 0; } + public void writeToParcel(Parcel p, int flag) { } + } + static final FakeEvent FAKE_EV = new FakeEvent(); + + @Mock IConnectivityMetricsLogger mService; + ArgumentCaptor<ConnectivityMetricsEvent> evCaptor; + + IpConnectivityLog mLog; + + public void setUp() { + MockitoAnnotations.initMocks(this); + evCaptor = ArgumentCaptor.forClass(ConnectivityMetricsEvent.class); + mLog = new IpConnectivityLog(mService); + } + + public void testLogEvents() throws Exception { + assertTrue(mLog.log(1, FAKE_EV)); + assertTrue(mLog.log(2, FAKE_EV)); + assertTrue(mLog.log(3, FAKE_EV)); + + List<ConnectivityMetricsEvent> gotEvents = verifyEvents(3); + assertEventsEqual(expectedEvent(1), gotEvents.get(0)); + assertEventsEqual(expectedEvent(2), gotEvents.get(1)); + assertEventsEqual(expectedEvent(3), gotEvents.get(2)); + } + + public void testLogEventTriggerThrottling() throws Exception { + when(mService.logEvent(any())).thenReturn(1234L); + + assertFalse(mLog.log(1, FAKE_EV)); + } + + public void testLogEventFails() throws Exception { + when(mService.logEvent(any())).thenReturn(-1L); // Error. + + assertFalse(mLog.log(1, FAKE_EV)); + } + + public void testLogEventWhenThrottling() throws Exception { + when(mService.logEvent(any())).thenReturn(Long.MAX_VALUE); // Throttled + + // No events are logged. The service is only called once + // After that, throttling state is maintained locally. + assertFalse(mLog.log(1, FAKE_EV)); + assertFalse(mLog.log(2, FAKE_EV)); + + List<ConnectivityMetricsEvent> gotEvents = verifyEvents(1); + assertEventsEqual(expectedEvent(1), gotEvents.get(0)); + } + + public void testLogEventRecoverFromThrottling() throws Exception { + final long throttleTimeout = System.currentTimeMillis() + 50; + when(mService.logEvent(any())).thenReturn(throttleTimeout, 0L); + + assertFalse(mLog.log(1, FAKE_EV)); + new Thread() { + public void run() { + busySpinLog(FAKE_EV); + } + }.start(); + + List<ConnectivityMetricsEvent> gotEvents = verifyEvents(2, 200); + assertEventsEqual(expectedEvent(1), gotEvents.get(0)); + assertEventsEqual(expectedEvent(2), gotEvents.get(1)); + } + + public void testLogEventRecoverFromThrottlingWithMultipleCallers() throws Exception { + final long throttleTimeout = System.currentTimeMillis() + 50; + when(mService.logEvent(any())).thenReturn(throttleTimeout, 0L); + + assertFalse(mLog.log(1, FAKE_EV)); + final int nCallers = 10; + for (int i = 0; i < nCallers; i++) { + new Thread() { + public void run() { + busySpinLog(FAKE_EV); + } + }.start(); + } + + List<ConnectivityMetricsEvent> gotEvents = verifyEvents(1 + nCallers, 200); + assertEventsEqual(expectedEvent(1), gotEvents.get(0)); + for (int i = 0; i < nCallers; i++) { + assertEventsEqual(expectedEvent(2), gotEvents.get(1 + i)); + } + } + + void busySpinLog(Parcelable ev) { + final long timeout = 200; + final long stop = System.currentTimeMillis() + timeout; + try { + while (System.currentTimeMillis() < stop) { + if (mLog.log(2, FAKE_EV)) { + return; + } + Thread.sleep(10); + } + } catch (InterruptedException e) { } + } + + List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception { + verify(mService, times(n)).logEvent(evCaptor.capture()); + return evCaptor.getAllValues(); + } + + List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception { + verify(mService, timeout(timeoutMs).times(n)).logEvent(evCaptor.capture()); + return evCaptor.getAllValues(); + } + + static ConnectivityMetricsEvent expectedEvent(int timestamp) { + return new ConnectivityMetricsEvent((long)timestamp, 0, 0, FAKE_EV); + } + + /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */ + static void assertEventsEqual(ConnectivityMetricsEvent expected, ConnectivityMetricsEvent got) { + assertEquals(expected.timestamp, got.timestamp); + assertEquals(expected.componentTag, got.componentTag); + assertEquals(expected.eventTag, got.eventTag); + assertEquals(expected.data, got.data); + } +} |