1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
/*
* 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 android.util.Log;
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 TAG = "BandwidthTestCase";
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)) {
/**
* If bandwidth profiling fails for whatever reason the test
* should be allow to execute to its completion.
* Typically bandwidth profiling would fail when a lower level
* component is missing, such as the kernel module, for a newly
* introduced hardware.
*/
try{
TrafficStats.startDataProfiling(null);
} catch(IllegalStateException isx){
Log.w(TAG, "Failed to start bandwidth profiling");
}
runMethod(method, 1, false);
try{
NetworkStats stats = TrafficStats.stopDataProfiling(null);
NetworkStats.Entry entry = stats.getTotal(null);
getInstrumentation().sendStatus(2, getBandwidthStats(entry));
} catch (IllegalStateException isx){
Log.w(TAG, "Failed to collect bandwidth stats");
}
} 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;
}
}
|