| /* |
| * 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 com.android.test.runner.listener; |
| |
| import android.app.Instrumentation; |
| import android.os.Bundle; |
| import android.util.Log; |
| |
| import java.io.File; |
| import java.io.PrintStream; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| |
| /** |
| * A test {@link RunListener} that generates EMMA code coverage. |
| */ |
| public class CoverageListener extends InstrumentationRunListener { |
| |
| private String mCoverageFilePath; |
| |
| /** |
| * If included in the status or final bundle sent to an IInstrumentationWatcher, this key |
| * identifies the path to the generated code coverage file. |
| */ |
| private static final String REPORT_KEY_COVERAGE_PATH = "coverageFilePath"; |
| // Default file name for code coverage |
| private static final String DEFAULT_COVERAGE_FILE_NAME = "coverage.ec"; |
| |
| private static final String LOG_TAG = null; |
| |
| /** |
| * Creates a {@link CoverageListener). |
| * |
| * @param instr the {@link Instrumentation} that the test is running under |
| * @param customCoverageFilePath an optional user specified path for the coverage file |
| * If null, file will be generated in test app's file directory. |
| */ |
| public CoverageListener(Instrumentation instr, String customCoverageFilePath) { |
| super(instr); |
| mCoverageFilePath = customCoverageFilePath; |
| if (mCoverageFilePath == null) { |
| mCoverageFilePath = instr.getTargetContext().getFilesDir().getAbsolutePath() + |
| File.separator + DEFAULT_COVERAGE_FILE_NAME; |
| } |
| } |
| |
| @Override |
| public void instrumentationRunFinished(PrintStream writer, Bundle results) { |
| generateCoverageReport(writer, results); |
| } |
| |
| private void generateCoverageReport(PrintStream writer, Bundle results) { |
| // use reflection to call emma dump coverage method, to avoid |
| // always statically compiling against emma jar |
| java.io.File coverageFile = new java.io.File(mCoverageFilePath); |
| try { |
| Class<?> emmaRTClass = Class.forName("com.vladium.emma.rt.RT"); |
| Method dumpCoverageMethod = emmaRTClass.getMethod("dumpCoverageData", |
| coverageFile.getClass(), boolean.class, boolean.class); |
| |
| dumpCoverageMethod.invoke(null, coverageFile, false, false); |
| |
| // output path to generated coverage file so it can be parsed by a test harness if |
| // needed |
| results.putString(REPORT_KEY_COVERAGE_PATH, mCoverageFilePath); |
| // also output a more user friendly msg |
| writer.format("\nGenerated code coverage data to %s",mCoverageFilePath); |
| } catch (ClassNotFoundException e) { |
| reportEmmaError(writer, "Is emma jar on classpath?", e); |
| } catch (SecurityException e) { |
| reportEmmaError(writer, e); |
| } catch (NoSuchMethodException e) { |
| reportEmmaError(writer, e); |
| } catch (IllegalArgumentException e) { |
| reportEmmaError(writer, e); |
| } catch (IllegalAccessException e) { |
| reportEmmaError(writer, e); |
| } catch (InvocationTargetException e) { |
| reportEmmaError(writer, e); |
| } |
| } |
| |
| private void reportEmmaError(PrintStream writer, Exception e) { |
| reportEmmaError(writer, "", e); |
| } |
| |
| private void reportEmmaError(PrintStream writer, String hint, Exception e) { |
| String msg = "Failed to generate emma coverage. " + hint; |
| Log.e(LOG_TAG, msg, e); |
| writer.format("\nError: %s", msg); |
| } |
| } |