1 /* 2 * Copyright (C) 2018 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.device.collectors; 17 18 import android.os.Bundle; 19 import android.util.Log; 20 21 import androidx.annotation.VisibleForTesting; 22 23 import com.android.helpers.ICollectorHelper; 24 25 import org.junit.runner.Description; 26 import org.junit.runner.Result; 27 import org.junit.runner.notification.Failure; 28 29 import java.util.Map; 30 import java.util.function.Function; 31 32 /** 33 * A {@link BaseCollectionListener} that captures metrics collected during the testing. 34 * 35 * Metrics can be collected at the test run level or per test method using per_run option. 36 * 37 * If there are any failure in the metric collection, tests will still proceed to run and 38 * not posting the metrics at the end of the test. 39 * 40 * Do NOT throw exception anywhere in this class. We don't want to halt the test when metrics 41 * collection fails. 42 */ 43 public class BaseCollectionListener<T> extends BaseMetricListener { 44 45 protected ICollectorHelper mHelper; 46 // Collect per run if it is set to true otherwise collect per test. 47 public static final String COLLECT_PER_RUN = "per_run"; 48 // Skip failure metrics collection if this flag is set to true. 49 public static final String SKIP_TEST_FAILURE_METRICS = "skip_test_failure_metrics"; 50 protected boolean mIsCollectPerRun; 51 protected boolean mSkipTestFailureMetrics; 52 private boolean mIsTestFailed = false; 53 BaseCollectionListener()54 public BaseCollectionListener() { 55 super(); 56 } 57 58 @VisibleForTesting BaseCollectionListener(Bundle args, ICollectorHelper helper)59 public BaseCollectionListener(Bundle args, ICollectorHelper helper) { 60 super(args); 61 mHelper = helper; 62 } 63 64 @Override onTestRunStart(DataRecord runData, Description description)65 public void onTestRunStart(DataRecord runData, Description description) { 66 67 if (mIsCollectPerRun) { 68 Function<String, Boolean> filter = getFilter(description); 69 testStart(filter, description); 70 } 71 } 72 73 @Override parseArguments()74 protected void parseArguments() { 75 super.parseArguments(); 76 Bundle args = getArgsBundle(); 77 mIsCollectPerRun = "true".equals(args.getString(COLLECT_PER_RUN)); 78 // By default this flag is set to false to collect the metrics on test failure. 79 mSkipTestFailureMetrics = "true".equals(args.getString(SKIP_TEST_FAILURE_METRICS)); 80 } 81 getFilter(Description description)82 protected Function<String, Boolean> getFilter(Description description) { 83 return null; 84 } 85 86 @Override onTestStart(DataRecord testData, Description description)87 public final void onTestStart(DataRecord testData, Description description) { 88 mIsTestFailed = false; 89 if (!mIsCollectPerRun) { 90 Function<String, Boolean> filter = getFilter(description); 91 testStart(filter, description); 92 } 93 } 94 95 @Override onTestFail(DataRecord testData, Description description, Failure failure)96 public void onTestFail(DataRecord testData, Description description, Failure failure) { 97 mIsTestFailed = true; 98 } 99 100 @Override onTestEnd(DataRecord testData, Description description)101 public void onTestEnd(DataRecord testData, Description description) { 102 if (!mIsCollectPerRun) { 103 try { 104 // Skip adding the metrics collected during the test failure 105 // if the skip metrics on test failure flag is enabled and the 106 // current test is failed. 107 if (shouldSkipFailureTestMetrics()) { 108 Log.i(getTag(), "Skipping the metric collection."); 109 } else { 110 // Collect the metrics. 111 collectMetrics(testData); 112 } 113 } finally { 114 mHelper.stopCollecting(); 115 } 116 } 117 } 118 119 @Override onTestRunEnd(DataRecord runData, Result result)120 public void onTestRunEnd(DataRecord runData, Result result) { 121 if (mIsCollectPerRun) { 122 try { 123 collectMetrics(runData); 124 } finally { 125 mHelper.stopCollecting(); 126 } 127 } 128 } 129 testStart(Function<String, Boolean> filter, Description description)130 public void testStart(Function<String, Boolean> filter, Description description) { 131 if (filter == null) { 132 mHelper.startCollecting(); 133 } else { 134 mHelper.startCollecting(filter); 135 } 136 } 137 createHelperInstance(ICollectorHelper helper)138 protected void createHelperInstance(ICollectorHelper helper) { 139 mHelper = helper; 140 } 141 collectMetrics(DataRecord data)142 protected void collectMetrics(DataRecord data) { 143 Map<String, T> metrics = mHelper.getMetrics(); 144 for (Map.Entry<String, T> entry : metrics.entrySet()) { 145 data.addStringMetric(entry.getKey(), entry.getValue().toString()); 146 } 147 } 148 shouldSkipFailureTestMetrics()149 protected boolean shouldSkipFailureTestMetrics() { 150 return mSkipTestFailureMetrics && mIsTestFailed; 151 } 152 } 153