1 | package com.example.instrumentation; |
2 | |
3 | import java.lang.reflect.InvocationTargetException; |
4 | import java.lang.reflect.Method; |
5 | |
6 | import com.example.i2at.tc.TemperatureConverterActivity; |
7 | //import com.vladium.emma.rt.RT; |
8 | |
9 | import android.app.Activity; |
10 | import android.app.Instrumentation; |
11 | import android.content.Intent; |
12 | import android.os.Bundle; |
13 | import android.os.Looper; |
14 | import android.util.Log; |
15 | |
16 | public class EmmaInstrumentation extends Instrumentation implements FinishListener { |
17 | |
18 | private static final String TAG = "EmmaInstrumentation"; |
19 | |
20 | private static final boolean LOGD = true; |
21 | |
22 | private static final String DEFAULT_COVERAGE_FILE_PATH = "/mnt/sdcard/coverage.ec"; |
23 | |
24 | private final Bundle mResults = new Bundle(); |
25 | |
26 | private Intent mIntent; |
27 | |
28 | private boolean mCoverage = true; |
29 | |
30 | private String mCoverageFilePath; |
31 | |
32 | /** |
33 | * Extends the AUT to provide the necessary behavior to invoke the |
34 | * {@link FinishListener} that may have been provided using |
35 | * {@link #setFinishListener(FinishListener)}. |
36 | * |
37 | * It's important to note that the original Activity has not been modified. |
38 | * Also, the Activity must be declared in the |
39 | * <code>AndroidManifest.xml</code> because it is started by an intent in |
40 | * {@link EmmaInstrumentation#onStart()}. This turns more difficult to use |
41 | * other methods like using template classes. This latter method could be |
42 | * viable, but all Activity methods should be re-written to invoke the |
43 | * template parameter class corresponding methods. |
44 | * |
45 | * @author diego |
46 | * |
47 | */ |
48 | public static class InstrumentedActivity extends |
49 | TemperatureConverterActivity { |
50 | private FinishListener mListener; |
51 | |
52 | public void setFinishListener(FinishListener listener) { |
53 | mListener = listener; |
54 | } |
55 | |
56 | @Override |
57 | public void finish() { |
58 | if (LOGD) |
59 | Log.d(TAG + ".InstrumentedActivity", "finish()"); |
60 | super.finish(); |
61 | if (mListener != null) { |
62 | mListener.onActivityFinished(); |
63 | } |
64 | } |
65 | |
66 | } |
67 | |
68 | /** |
69 | * Constructor |
70 | */ |
71 | public EmmaInstrumentation() { |
72 | |
73 | } |
74 | |
75 | @Override |
76 | public void onCreate(Bundle arguments) { |
77 | if (LOGD) |
78 | Log.d(TAG, "onCreate(" + arguments + ")"); |
79 | super.onCreate(arguments); |
80 | |
81 | if (arguments != null) { |
82 | mCoverage = getBooleanArgument(arguments, "coverage"); |
83 | mCoverageFilePath = arguments.getString("coverageFile"); |
84 | } |
85 | |
86 | mIntent = new Intent(getTargetContext(), InstrumentedActivity.class); |
87 | mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
88 | start(); |
89 | } |
90 | |
91 | @Override |
92 | public void onStart() { |
93 | if (LOGD) |
94 | Log.d(TAG, "onStart()"); |
95 | super.onStart(); |
96 | |
97 | Looper.prepare(); |
98 | InstrumentedActivity activity = (InstrumentedActivity) startActivitySync(mIntent); |
99 | activity.setFinishListener(this); |
100 | } |
101 | |
102 | private boolean getBooleanArgument(Bundle arguments, String tag) { |
103 | String tagString = arguments.getString(tag); |
104 | return tagString != null && Boolean.parseBoolean(tagString); |
105 | } |
106 | |
107 | private void generateCoverageReport() { |
108 | if (LOGD) |
109 | Log.d(TAG, "generateCoverageReport()"); |
110 | |
111 | java.io.File coverageFile = new java.io.File(getCoverageFilePath()); |
112 | |
113 | // We may use this if we want to avoid reflection and we include |
114 | // emma.jar |
115 | // RT.dumpCoverageData(coverageFile, false, false); |
116 | |
117 | // Use reflection to call emma dump coverage method, to avoid |
118 | // always statically compiling against emma jar |
119 | try { |
120 | Class<?> emmaRTClass = Class.forName("com.vladium.emma.rt.RT"); |
121 | Method dumpCoverageMethod = emmaRTClass.getMethod( |
122 | "dumpCoverageData", coverageFile.getClass(), boolean.class, |
123 | boolean.class); |
124 | dumpCoverageMethod.invoke(null, coverageFile, false, false); |
125 | } catch (ClassNotFoundException e) { |
126 | reportEmmaError("Is emma jar on classpath?", e); |
127 | } catch (SecurityException e) { |
128 | reportEmmaError(e); |
129 | } catch (NoSuchMethodException e) { |
130 | reportEmmaError(e); |
131 | } catch (IllegalArgumentException e) { |
132 | reportEmmaError(e); |
133 | } catch (IllegalAccessException e) { |
134 | reportEmmaError(e); |
135 | } catch (InvocationTargetException e) { |
136 | reportEmmaError(e); |
137 | } |
138 | } |
139 | |
140 | private String getCoverageFilePath() { |
141 | if (mCoverageFilePath == null) { |
142 | return DEFAULT_COVERAGE_FILE_PATH; |
143 | } else { |
144 | return mCoverageFilePath; |
145 | } |
146 | } |
147 | |
148 | private void reportEmmaError(Exception e) { |
149 | reportEmmaError("", e); |
150 | } |
151 | |
152 | private void reportEmmaError(String hint, Exception e) { |
153 | String msg = "Failed to generate emma coverage. " + hint; |
154 | Log.e(TAG, msg, e); |
155 | mResults.putString(Instrumentation.REPORT_KEY_STREAMRESULT, "\nError: " |
156 | + msg); |
157 | } |
158 | |
159 | /* (non-Javadoc) |
160 | * @see com.example.instrumentation.FinishListener#onActivityFinished() |
161 | */ |
162 | @Override |
163 | public void onActivityFinished() { |
164 | if (LOGD) |
165 | Log.d(TAG, "onActivityFinished()"); |
166 | if (mCoverage) { |
167 | generateCoverageReport(); |
168 | } |
169 | finish(Activity.RESULT_OK, mResults); |
170 | } |
171 | |
172 | } |