1ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu/*
2ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu * Copyright (C) 2012 The Android Open Source Project
3ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu *
4ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu * Licensed under the Apache License, Version 2.0 (the "License");
5ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu * you may not use this file except in compliance with the License.
6ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu * You may obtain a copy of the License at
7ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu *
8ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu *      http://www.apache.org/licenses/LICENSE-2.0
9ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu *
10ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu * Unless required by applicable law or agreed to in writing, software
11ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu * distributed under the License is distributed on an "AS IS" BASIS,
12ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu * See the License for the specific language governing permissions and
14ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu * limitations under the License.
15ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu */
16ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hupackage android.test;
17ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu
18ca4aab9cd724708af30abb4bfcb2f9b45087f449David Huimport android.net.NetworkStats;
19ca4aab9cd724708af30abb4bfcb2f9b45087f449David Huimport android.net.TrafficStats;
20ca4aab9cd724708af30abb4bfcb2f9b45087f449David Huimport android.os.Bundle;
2171a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Huimport android.util.Log;
22ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu
23ca4aab9cd724708af30abb4bfcb2f9b45087f449David Huimport java.lang.reflect.InvocationTargetException;
24ca4aab9cd724708af30abb4bfcb2f9b45087f449David Huimport java.lang.reflect.Method;
25ca4aab9cd724708af30abb4bfcb2f9b45087f449David Huimport java.lang.reflect.Modifier;
26ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu
27ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu/**
28ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu * A bandwidth test case that collects bandwidth statistics for tests that are
29ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu * annotated with {@link BandwidthTest} otherwise the test is executed
30ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu * as an {@link InstrumentationTestCase}
31ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu */
32ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hupublic class BandwidthTestCase extends InstrumentationTestCase {
3371a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu    private static final String TAG = "BandwidthTestCase";
34ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu    private static final String REPORT_KEY_PACKETS_SENT = "txPackets";
35ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu    private static final String REPORT_KEY_PACKETS_RECEIVED = "rxPackets";
36ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu    private static final String REPORT_KEY_BYTES_SENT = "txBytes";
37ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu    private static final String REPORT_KEY_BYTES_RECEIVED = "rxBytes";
38ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu    private static final String REPORT_KEY_OPERATIONS = "operations";
39ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu
40ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu    @Override
41ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu    protected void runTest() throws Throwable {
42ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        //This is a copy of {@link InstrumentationTestCase#runTest} with
43ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        //added logic to handle bandwidth measurements
44ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        String fName = getName();
45ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        assertNotNull(fName);
46ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        Method method = null;
47ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        Class testClass = null;
48ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        try {
49ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            // use getMethod to get all public inherited
50ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            // methods. getDeclaredMethods returns all
51ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            // methods of this class but excludes the
52ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            // inherited ones.
53ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            testClass = getClass();
54ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            method = testClass.getMethod(fName, (Class[]) null);
55ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        } catch (NoSuchMethodException e) {
56ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            fail("Method \""+fName+"\" not found");
57ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        }
58ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu
59ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        if (!Modifier.isPublic(method.getModifiers())) {
60ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            fail("Method \""+fName+"\" should be public");
61ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        }
62ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu
63ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        int runCount = 1;
64ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        boolean isRepetitive = false;
65ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        if (method.isAnnotationPresent(FlakyTest.class)) {
66ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            runCount = method.getAnnotation(FlakyTest.class).tolerance();
67ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        } else if (method.isAnnotationPresent(RepetitiveTest.class)) {
68ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            runCount = method.getAnnotation(RepetitiveTest.class).numIterations();
69ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            isRepetitive = true;
70ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        }
71ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu
72ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        if (method.isAnnotationPresent(UiThreadTest.class)) {
73ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            final int tolerance = runCount;
74ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            final boolean repetitive = isRepetitive;
75ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            final Method testMethod = method;
76ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            final Throwable[] exceptions = new Throwable[1];
77ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            getInstrumentation().runOnMainSync(new Runnable() {
78ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                public void run() {
79ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                    try {
80ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                        runMethod(testMethod, tolerance, repetitive);
81ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                    } catch (Throwable throwable) {
82ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                        exceptions[0] = throwable;
83ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                    }
84ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                }
85ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            });
86ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            if (exceptions[0] != null) {
87ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                throw exceptions[0];
88ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            }
89ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        } else if (method.isAnnotationPresent(BandwidthTest.class) ||
90ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                testClass.isAnnotationPresent(BandwidthTest.class)) {
9171a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu            /**
9271a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu             * If bandwidth profiling fails for whatever reason the test
9371a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu             * should be allow to execute to its completion.
9471a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu             * Typically bandwidth profiling would fail when a lower level
9571a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu             * component is missing, such as the kernel module, for a newly
9671a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu             * introduced hardware.
9771a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu             */
9871a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu            try{
9971a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu                TrafficStats.startDataProfiling(null);
10071a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu            } catch(IllegalStateException isx){
10171a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu                Log.w(TAG, "Failed to start bandwidth profiling");
10271a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu            }
103ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            runMethod(method, 1, false);
10471a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu            try{
10571a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu                NetworkStats stats = TrafficStats.stopDataProfiling(null);
10671a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu                NetworkStats.Entry entry = stats.getTotal(null);
10771a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu                getInstrumentation().sendStatus(2, getBandwidthStats(entry));
10871a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu            } catch (IllegalStateException isx){
10971a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu                Log.w(TAG, "Failed to collect bandwidth stats");
11071a0d06fd8f0cae4d3f38f1f34ceebbfd6d61db6David Hu            }
111ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        } else {
112ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            runMethod(method, runCount, isRepetitive);
113ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        }
114ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu    }
115ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu
116ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu    private void runMethod(Method runMethod, int tolerance, boolean isRepetitive) throws Throwable {
117ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        //This is a copy of {@link InstrumentationTestCase#runMethod}
118ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        Throwable exception = null;
119ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu
120ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        int runCount = 0;
121ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        do {
122ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            try {
123ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                runMethod.invoke(this, (Object[]) null);
124ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                exception = null;
125ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            } catch (InvocationTargetException e) {
126ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                e.fillInStackTrace();
127ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                exception = e.getTargetException();
128ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            } catch (IllegalAccessException e) {
129ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                e.fillInStackTrace();
130ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                exception = e;
131ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            } finally {
132ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                runCount++;
133ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                // Report current iteration number, if test is repetitive
134ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                if (isRepetitive) {
135ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                    Bundle iterations = new Bundle();
136ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                    iterations.putInt("currentiterations", runCount);
137ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                    getInstrumentation().sendStatus(2, iterations);
138ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu                }
139ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            }
140ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        } while ((runCount < tolerance) && (isRepetitive || exception != null));
141ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu
142ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        if (exception != null) {
143ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu            throw exception;
144ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        }
145ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu    }
146ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu
147ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu    private Bundle getBandwidthStats(NetworkStats.Entry entry){
148ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        Bundle bundle = new Bundle();
149ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        bundle.putLong(REPORT_KEY_BYTES_RECEIVED, entry.rxBytes);
150ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        bundle.putLong(REPORT_KEY_BYTES_SENT, entry.txBytes);
151ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        bundle.putLong(REPORT_KEY_PACKETS_RECEIVED, entry.rxPackets);
152ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        bundle.putLong(REPORT_KEY_PACKETS_SENT, entry.txPackets);
153ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        bundle.putLong(REPORT_KEY_OPERATIONS, entry.operations);
154ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu        return bundle;
155ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu    }
156ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu}
157ca4aab9cd724708af30abb4bfcb2f9b45087f449David Hu
158