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

Commit 60c116e2 authored by David Hu's avatar David Hu Committed by Android (Google) Code Review
Browse files

Merge "BandwidthTestCase"

parents 52c10554 ca4aab9c
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 * Copyright (C) 2012 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.
@@ -24,8 +24,6 @@ import java.lang.annotation.RetentionPolicy;
 * annotation is present, the test method is profiled for bandwidth metrics and the results
 * written through instrumentation output. It can also be used on the class itself,
 * which is equivalent to tagging all test methods with this annotation.
 *
 * {@hide} Pending approval for public API.
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface BandwidthTest {
+140 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 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.test;

import android.net.NetworkStats;
import android.net.TrafficStats;
import android.os.Bundle;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * A bandwidth test case that collects bandwidth statistics for tests that are
 * annotated with {@link BandwidthTest} otherwise the test is executed
 * as an {@link InstrumentationTestCase}
 */
public class BandwidthTestCase extends InstrumentationTestCase {
    private static final String REPORT_KEY_PACKETS_SENT = "txPackets";
    private static final String REPORT_KEY_PACKETS_RECEIVED = "rxPackets";
    private static final String REPORT_KEY_BYTES_SENT = "txBytes";
    private static final String REPORT_KEY_BYTES_RECEIVED = "rxBytes";
    private static final String REPORT_KEY_OPERATIONS = "operations";

    @Override
    protected void runTest() throws Throwable {
        //This is a copy of {@link InstrumentationTestCase#runTest} with
        //added logic to handle bandwidth measurements
        String fName = getName();
        assertNotNull(fName);
        Method method = null;
        Class testClass = null;
        try {
            // use getMethod to get all public inherited
            // methods. getDeclaredMethods returns all
            // methods of this class but excludes the
            // inherited ones.
            testClass = getClass();
            method = testClass.getMethod(fName, (Class[]) null);
        } catch (NoSuchMethodException e) {
            fail("Method \""+fName+"\" not found");
        }

        if (!Modifier.isPublic(method.getModifiers())) {
            fail("Method \""+fName+"\" should be public");
        }

        int runCount = 1;
        boolean isRepetitive = false;
        if (method.isAnnotationPresent(FlakyTest.class)) {
            runCount = method.getAnnotation(FlakyTest.class).tolerance();
        } else if (method.isAnnotationPresent(RepetitiveTest.class)) {
            runCount = method.getAnnotation(RepetitiveTest.class).numIterations();
            isRepetitive = true;
        }

        if (method.isAnnotationPresent(UiThreadTest.class)) {
            final int tolerance = runCount;
            final boolean repetitive = isRepetitive;
            final Method testMethod = method;
            final Throwable[] exceptions = new Throwable[1];
            getInstrumentation().runOnMainSync(new Runnable() {
                public void run() {
                    try {
                        runMethod(testMethod, tolerance, repetitive);
                    } catch (Throwable throwable) {
                        exceptions[0] = throwable;
                    }
                }
            });
            if (exceptions[0] != null) {
                throw exceptions[0];
            }
        } else if (method.isAnnotationPresent(BandwidthTest.class) ||
                testClass.isAnnotationPresent(BandwidthTest.class)) {
            TrafficStats.startDataProfiling(null);
            runMethod(method, 1, false);
            NetworkStats stats = TrafficStats.stopDataProfiling(null);
            NetworkStats.Entry entry = stats.getTotal(null);
            getInstrumentation().sendStatus(2, getBandwidthStats(entry));
        } else {
            runMethod(method, runCount, isRepetitive);
        }
    }

    private void runMethod(Method runMethod, int tolerance, boolean isRepetitive) throws Throwable {
        //This is a copy of {@link InstrumentationTestCase#runMethod}
        Throwable exception = null;

        int runCount = 0;
        do {
            try {
                runMethod.invoke(this, (Object[]) null);
                exception = null;
            } catch (InvocationTargetException e) {
                e.fillInStackTrace();
                exception = e.getTargetException();
            } catch (IllegalAccessException e) {
                e.fillInStackTrace();
                exception = e;
            } finally {
                runCount++;
                // Report current iteration number, if test is repetitive
                if (isRepetitive) {
                    Bundle iterations = new Bundle();
                    iterations.putInt("currentiterations", runCount);
                    getInstrumentation().sendStatus(2, iterations);
                }
            }
        } while ((runCount < tolerance) && (isRepetitive || exception != null));

        if (exception != null) {
            throw exception;
        }
    }

    private Bundle getBandwidthStats(NetworkStats.Entry entry){
        Bundle bundle = new Bundle();
        bundle.putLong(REPORT_KEY_BYTES_RECEIVED, entry.rxBytes);
        bundle.putLong(REPORT_KEY_BYTES_SENT, entry.txBytes);
        bundle.putLong(REPORT_KEY_PACKETS_RECEIVED, entry.rxPackets);
        bundle.putLong(REPORT_KEY_PACKETS_SENT, entry.txPackets);
        bundle.putLong(REPORT_KEY_OPERATIONS, entry.operations);
        return bundle;
    }
}