From a4abd91a7329d49d7fe542c7a5f27ad07dd7a910 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Mon, 6 Jun 2016 11:31:41 +0900 Subject: [PATCH] Add tests for MetricsLoggerService Bug: 29035129 Change-Id: I9b4e55c20f4ed3a2a642419369a5d95efbbcb54d --- .../server/connectivity/MetricsLoggerService.java | 24 +-- .../connectivity/MetricsLoggerServiceTest.java | 181 +++++++++++++++++++++ 2 files changed, 193 insertions(+), 12 deletions(-) create mode 100644 services/tests/servicestests/src/com/android/server/connectivity/MetricsLoggerServiceTest.java diff --git a/services/core/java/com/android/server/connectivity/MetricsLoggerService.java b/services/core/java/com/android/server/connectivity/MetricsLoggerService.java index 69ef30fbe66a..05f1a6e6a3a4 100644 --- a/services/core/java/com/android/server/connectivity/MetricsLoggerService.java +++ b/services/core/java/com/android/server/connectivity/MetricsLoggerService.java @@ -16,6 +16,7 @@ package com.android.server.connectivity; +import com.android.internal.annotations.VisibleForTesting; import com.android.server.SystemService; import android.app.PendingIntent; @@ -60,17 +61,11 @@ public class MetricsLoggerService extends SystemService { } } - // TODO: read from system property - private final int MAX_NUMBER_OF_EVENTS = 1000; - - // TODO: read from system property - private final int EVENTS_NOTIFICATION_THRESHOLD = 300; - - // TODO: read from system property - private final int THROTTLING_TIME_INTERVAL_MILLIS = 60 * 60 * 1000; // 1 hour - - // TODO: read from system property + // TODO: read these constants from system property + private final int EVENTS_NOTIFICATION_THRESHOLD = 300; + private final int MAX_NUMBER_OF_EVENTS = 1000; private final int THROTTLING_MAX_NUMBER_OF_MESSAGES_PER_COMPONENT = 1000; + private final long THROTTLING_TIME_INTERVAL_MILLIS = DateUtils.HOUR_IN_MILLIS; private int mEventCounter = 0; @@ -127,10 +122,13 @@ public class MetricsLoggerService extends SystemService { mEvents.addLast(e); } + @VisibleForTesting + final MetricsLoggerImpl mBinder = new MetricsLoggerImpl(); + /** * Implementation of the IConnectivityMetricsLogger interface. */ - private final IConnectivityMetricsLogger.Stub mBinder = new IConnectivityMetricsLogger.Stub() { + final class MetricsLoggerImpl extends IConnectivityMetricsLogger.Stub { private final ArrayList mPendingIntents = new ArrayList<>(); @@ -223,7 +221,9 @@ public class MetricsLoggerService extends SystemService { } pw.println(); - mDnsListener.dump(pw); + if (mDnsListener != null) { + mDnsListener.dump(pw); + } } public long logEvent(ConnectivityMetricsEvent event) { diff --git a/services/tests/servicestests/src/com/android/server/connectivity/MetricsLoggerServiceTest.java b/services/tests/servicestests/src/com/android/server/connectivity/MetricsLoggerServiceTest.java new file mode 100644 index 000000000000..5f84ea1bfd96 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/connectivity/MetricsLoggerServiceTest.java @@ -0,0 +1,181 @@ +/* + * 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 com.android.server.connectivity; + +import android.content.Context; +import android.net.ConnectivityMetricsEvent; +import android.os.Bundle; +import android.os.RemoteException; +import static android.net.ConnectivityMetricsEvent.Reference; + +import junit.framework.TestCase; +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertArrayEquals; + +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.io.FileDescriptor; +import java.io.FileOutputStream; +import java.util.Arrays; +import java.util.Comparator; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/* + * TODO: + * - allow overriding MetricsLoggerService constants in tests. + * - test intents are correctly sent after the notification threshold. + * - test oldest events are correctly pushed out when internal deque is full. + * - test throttling triggers correctly. + */ +public class MetricsLoggerServiceTest extends TestCase { + + static final int COMPONENT_TAG = 1; + static final long N_EVENTS = 10L; + static final ConnectivityMetricsEvent EVENTS[] = new ConnectivityMetricsEvent[(int)N_EVENTS]; + static { + for (int i = 0; i < N_EVENTS; i++) { + EVENTS[i] = new ConnectivityMetricsEvent(i, COMPONENT_TAG, i, new Bundle()); + } + } + + static final ConnectivityMetricsEvent NO_EVENTS[] = new ConnectivityMetricsEvent[0]; + + @Mock Context mContext; + MetricsLoggerService mService; + + public void setUp() { + MockitoAnnotations.initMocks(this); + mService = new MetricsLoggerService(mContext); + mService.onStart(); + } + + public void testGetNoEvents() throws Exception { + Reference r = new Reference(0); + assertArrayEquals(NO_EVENTS, mService.mBinder.getEvents(r)); + assertEquals(0, r.getValue()); + } + + public void testLogAndGetEvents() throws Exception { + mService.mBinder.logEvents(EVENTS); + + Reference r = new Reference(0); + + assertArrayEquals(EVENTS, mService.mBinder.getEvents(r)); + assertEquals(N_EVENTS, r.getValue()); + + assertArrayEquals(NO_EVENTS, mService.mBinder.getEvents(r)); + assertEquals(N_EVENTS, r.getValue()); + } + + public void testLogOneByOne() throws Exception { + for (ConnectivityMetricsEvent ev : EVENTS) { + mService.mBinder.logEvent(ev); + } + + Reference r = new Reference(0); + + assertArrayEquals(EVENTS, mService.mBinder.getEvents(r)); + assertEquals(N_EVENTS, r.getValue()); + + assertArrayEquals(NO_EVENTS, mService.mBinder.getEvents(r)); + assertEquals(N_EVENTS, r.getValue()); + } + + public void testInterleavedLogAndGet() throws Exception { + mService.mBinder.logEvents(Arrays.copyOfRange(EVENTS, 0, 3)); + + Reference r = new Reference(0); + + assertArrayEquals(Arrays.copyOfRange(EVENTS, 0, 3), mService.mBinder.getEvents(r)); + assertEquals(3, r.getValue()); + + mService.mBinder.logEvents(Arrays.copyOfRange(EVENTS, 3, 8)); + mService.mBinder.logEvents(Arrays.copyOfRange(EVENTS, 8, 10)); + + assertArrayEquals(Arrays.copyOfRange(EVENTS, 3, 10), mService.mBinder.getEvents(r)); + assertEquals(N_EVENTS, r.getValue()); + + assertArrayEquals(NO_EVENTS, mService.mBinder.getEvents(r)); + assertEquals(N_EVENTS, r.getValue()); + } + + public void testMultipleGetAll() throws Exception { + mService.mBinder.logEvents(Arrays.copyOf(EVENTS, 3)); + + Reference r1 = new Reference(0); + assertArrayEquals(Arrays.copyOf(EVENTS, 3), mService.mBinder.getEvents(r1)); + assertEquals(3, r1.getValue()); + + mService.mBinder.logEvents(Arrays.copyOfRange(EVENTS, 3, 10)); + + Reference r2 = new Reference(0); + assertArrayEquals(EVENTS, mService.mBinder.getEvents(r2)); + assertEquals(N_EVENTS, r2.getValue()); + } + + public void testLogAndDumpConcurrently() throws Exception { + for (int i = 0; i < 50; i++) { + mContext = null; + mService = null; + setUp(); + logAndDumpConcurrently(); + } + } + + public void logAndDumpConcurrently() throws Exception { + final CountDownLatch latch = new CountDownLatch((int)N_EVENTS); + final FileDescriptor fd = new FileOutputStream("/dev/null").getFD(); + + for (ConnectivityMetricsEvent ev : EVENTS) { + new Thread() { + public void run() { + mService.mBinder.logEvent(ev); + latch.countDown(); + } + }.start(); + } + + new Thread() { + public void run() { + while (latch.getCount() > 0) { + mService.mBinder.dump(fd, new String[]{"--all"}); + } + } + }.start(); + + latch.await(100, TimeUnit.MILLISECONDS); + + Reference r = new Reference(0); + ConnectivityMetricsEvent[] got = mService.mBinder.getEvents(r); + Arrays.sort(got, new EventComparator()); + assertArrayEquals(EVENTS, got); + assertEquals(N_EVENTS, r.getValue()); + } + + static class EventComparator implements Comparator { + public int compare(ConnectivityMetricsEvent ev1, ConnectivityMetricsEvent ev2) { + return Long.compare(ev1.timestamp, ev2.timestamp); + } + public boolean equal(Object o) { + return o instanceof EventComparator; + } + }; +} -- 2.11.0