Home | History | Annotate | Download | only in test
      1 /*
      2  * Copyright (C) 2012 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 package android.test;
     17 
     18 import android.net.NetworkStats;
     19 import android.net.TrafficStats;
     20 import android.os.Bundle;
     21 import android.util.Log;
     22 
     23 import java.lang.reflect.InvocationTargetException;
     24 import java.lang.reflect.Method;
     25 import java.lang.reflect.Modifier;
     26 
     27 /**
     28  * A bandwidth test case that collects bandwidth statistics for tests that are
     29  * annotated with {@link BandwidthTest} otherwise the test is executed
     30  * as an {@link InstrumentationTestCase}
     31  */
     32 public class BandwidthTestCase extends InstrumentationTestCase {
     33     private static final String TAG = "BandwidthTestCase";
     34     private static final String REPORT_KEY_PACKETS_SENT = "txPackets";
     35     private static final String REPORT_KEY_PACKETS_RECEIVED = "rxPackets";
     36     private static final String REPORT_KEY_BYTES_SENT = "txBytes";
     37     private static final String REPORT_KEY_BYTES_RECEIVED = "rxBytes";
     38     private static final String REPORT_KEY_OPERATIONS = "operations";
     39 
     40     @Override
     41     protected void runTest() throws Throwable {
     42         //This is a copy of {@link InstrumentationTestCase#runTest} with
     43         //added logic to handle bandwidth measurements
     44         String fName = getName();
     45         assertNotNull(fName);
     46         Method method = null;
     47         Class testClass = null;
     48         try {
     49             // use getMethod to get all public inherited
     50             // methods. getDeclaredMethods returns all
     51             // methods of this class but excludes the
     52             // inherited ones.
     53             testClass = getClass();
     54             method = testClass.getMethod(fName, (Class[]) null);
     55         } catch (NoSuchMethodException e) {
     56             fail("Method \""+fName+"\" not found");
     57         }
     58 
     59         if (!Modifier.isPublic(method.getModifiers())) {
     60             fail("Method \""+fName+"\" should be public");
     61         }
     62 
     63         int runCount = 1;
     64         boolean isRepetitive = false;
     65         if (method.isAnnotationPresent(FlakyTest.class)) {
     66             runCount = method.getAnnotation(FlakyTest.class).tolerance();
     67         } else if (method.isAnnotationPresent(RepetitiveTest.class)) {
     68             runCount = method.getAnnotation(RepetitiveTest.class).numIterations();
     69             isRepetitive = true;
     70         }
     71 
     72         if (method.isAnnotationPresent(UiThreadTest.class)) {
     73             final int tolerance = runCount;
     74             final boolean repetitive = isRepetitive;
     75             final Method testMethod = method;
     76             final Throwable[] exceptions = new Throwable[1];
     77             getInstrumentation().runOnMainSync(new Runnable() {
     78                 public void run() {
     79                     try {
     80                         runMethod(testMethod, tolerance, repetitive);
     81                     } catch (Throwable throwable) {
     82                         exceptions[0] = throwable;
     83                     }
     84                 }
     85             });
     86             if (exceptions[0] != null) {
     87                 throw exceptions[0];
     88             }
     89         } else if (method.isAnnotationPresent(BandwidthTest.class) ||
     90                 testClass.isAnnotationPresent(BandwidthTest.class)) {
     91             /**
     92              * If bandwidth profiling fails for whatever reason the test
     93              * should be allow to execute to its completion.
     94              * Typically bandwidth profiling would fail when a lower level
     95              * component is missing, such as the kernel module, for a newly
     96              * introduced hardware.
     97              */
     98             try{
     99                 TrafficStats.startDataProfiling(null);
    100             } catch(IllegalStateException isx){
    101                 Log.w(TAG, "Failed to start bandwidth profiling");
    102             }
    103             runMethod(method, 1, false);
    104             try{
    105                 NetworkStats stats = TrafficStats.stopDataProfiling(null);
    106                 NetworkStats.Entry entry = stats.getTotal(null);
    107                 getInstrumentation().sendStatus(2, getBandwidthStats(entry));
    108             } catch (IllegalStateException isx){
    109                 Log.w(TAG, "Failed to collect bandwidth stats");
    110             }
    111         } else {
    112             runMethod(method, runCount, isRepetitive);
    113         }
    114     }
    115 
    116     private void runMethod(Method runMethod, int tolerance, boolean isRepetitive) throws Throwable {
    117         //This is a copy of {@link InstrumentationTestCase#runMethod}
    118         Throwable exception = null;
    119 
    120         int runCount = 0;
    121         do {
    122             try {
    123                 runMethod.invoke(this, (Object[]) null);
    124                 exception = null;
    125             } catch (InvocationTargetException e) {
    126                 e.fillInStackTrace();
    127                 exception = e.getTargetException();
    128             } catch (IllegalAccessException e) {
    129                 e.fillInStackTrace();
    130                 exception = e;
    131             } finally {
    132                 runCount++;
    133                 // Report current iteration number, if test is repetitive
    134                 if (isRepetitive) {
    135                     Bundle iterations = new Bundle();
    136                     iterations.putInt("currentiterations", runCount);
    137                     getInstrumentation().sendStatus(2, iterations);
    138                 }
    139             }
    140         } while ((runCount < tolerance) && (isRepetitive || exception != null));
    141 
    142         if (exception != null) {
    143             throw exception;
    144         }
    145     }
    146 
    147     private Bundle getBandwidthStats(NetworkStats.Entry entry){
    148         Bundle bundle = new Bundle();
    149         bundle.putLong(REPORT_KEY_BYTES_RECEIVED, entry.rxBytes);
    150         bundle.putLong(REPORT_KEY_BYTES_SENT, entry.txBytes);
    151         bundle.putLong(REPORT_KEY_PACKETS_RECEIVED, entry.rxPackets);
    152         bundle.putLong(REPORT_KEY_PACKETS_SENT, entry.txPackets);
    153         bundle.putLong(REPORT_KEY_OPERATIONS, entry.operations);
    154         return bundle;
    155     }
    156 }
    157 
    158