1 /* 2 * Copyright (C) 2020 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 com.android.tradefed.testtype.suite; 17 18 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric; 19 import com.android.tradefed.result.FailureDescription; 20 import com.android.tradefed.result.ITestInvocationListener; 21 import com.android.tradefed.result.proto.TestRecordProto.FailureStatus; 22 import com.android.tradefed.testtype.IRemoteTest; 23 24 import java.time.Duration; 25 import java.util.HashMap; 26 import java.util.concurrent.TimeUnit; 27 28 /** 29 * Listeners that allows to check the execution time of a given test config and fail it if it goes 30 * over a given timeout. 31 * 32 * <p>Note that this enforcer doesn't interrupt the tests, but will make them fail. 33 */ 34 public class RemoteTestTimeOutEnforcer implements ITestInvocationListener { 35 36 // The option name & description we want to share across class that uses the enforcer. 37 public static final String REMOTE_TEST_TIMEOUT_OPTION = "remote-test-timeout"; 38 public static final String REMOTE_TEST_TIMEOUT_DESCRIPTION = 39 "The timeout that will be applied to each remote test object of the run."; 40 41 private IRemoteTest mIRemoteTest; 42 private Duration mTimeOut; 43 private ModuleDefinition mModuleDefinition; 44 private ModuleListener mListener; 45 46 /** 47 * Create the {@link RemoteTestTimeOutEnforcer} with the given timeout to enforce. 48 * 49 * @param listener The {@link ModuleListener} for each test run. 50 * @param moduleDefinition The {@link ModuleDefinition} of the test module to be executed. 51 * @param test The {@link IRemoteTest} to be executed. 52 * @param timeOut The {@link Duration} of the time out per test run. 53 */ RemoteTestTimeOutEnforcer( ModuleListener listener, ModuleDefinition moduleDefinition, IRemoteTest test, Duration timeOut)54 public RemoteTestTimeOutEnforcer( 55 ModuleListener listener, 56 ModuleDefinition moduleDefinition, 57 IRemoteTest test, 58 Duration timeOut) { 59 mListener = listener; 60 mIRemoteTest = test; 61 mModuleDefinition = moduleDefinition; 62 mTimeOut = timeOut; 63 } 64 65 @Override testRunEnded(long elapsedTime, HashMap<String, Metric> runMetrics)66 public void testRunEnded(long elapsedTime, HashMap<String, Metric> runMetrics) { 67 if (elapsedTime >= mTimeOut.toMillis()) { 68 String failureString = String.format( 69 "%s defined in %s took %s seconds while timeout is %s seconds", 70 mModuleDefinition.getId(), 71 mModuleDefinition.getModuleInvocationContext().getConfigurationDescriptor(). 72 getMetaData(Integer.toString(mIRemoteTest.hashCode())), 73 TimeUnit.MILLISECONDS.toSeconds(elapsedTime), 74 mTimeOut.toSeconds()); 75 if (!mListener.hasLastAttemptFailed()) { 76 FailureDescription failure = FailureDescription.create( 77 failureString, FailureStatus.TIMED_OUT).setRetriable(false); 78 mListener.testRunFailed(failure); 79 } 80 } 81 } 82 } 83