Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a4abd91a authored by Hugo Benichi's avatar Hugo Benichi
Browse files

Add tests for MetricsLoggerService

Bug: 29035129
Change-Id: I9b4e55c20f4ed3a2a642419369a5d95efbbcb54d
parent 3bba249c
Loading
Loading
Loading
Loading
+12 −12
Original line number Diff line number Diff line
@@ -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
    // TODO: read these constants 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
    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<PendingIntent> mPendingIntents = new ArrayList<>();

@@ -223,8 +221,10 @@ public class MetricsLoggerService extends SystemService {
            }

            pw.println();
            if (mDnsListener != null) {
                mDnsListener.dump(pw);
            }
        }

        public long logEvent(ConnectivityMetricsEvent event) {
            ConnectivityMetricsEvent[] events = new ConnectivityMetricsEvent[]{event};
+181 −0
Original line number Diff line number Diff line
/*
 * 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<ConnectivityMetricsEvent> {
        public int compare(ConnectivityMetricsEvent ev1, ConnectivityMetricsEvent ev2) {
            return Long.compare(ev1.timestamp, ev2.timestamp);
        }
        public boolean equal(Object o) {
            return o instanceof EventComparator;
        }
    };
}