blob: 40bf6337b57e6a00c157e7ed8c7ca1e088da1940 [file] [log] [blame]
/*
* Copyright (C) 2017 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.compatibility.common.tradefed.testtype.retry;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
import com.android.compatibility.common.tradefed.testtype.suite.CompatibilityTestSuite;
import com.android.compatibility.common.tradefed.util.RetryFilterHelper;
import com.android.compatibility.common.tradefed.util.RetryType;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.ConfigurationException;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.Option.Importance;
import com.android.tradefed.config.OptionClass;
import com.android.tradefed.config.OptionSetter;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.suite.checker.ISystemStatusChecker;
import com.android.tradefed.suite.checker.ISystemStatusCheckerReceiver;
import com.android.tradefed.testtype.IBuildReceiver;
import com.android.tradefed.testtype.IDeviceTest;
import com.android.tradefed.testtype.IInvocationContextReceiver;
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.testtype.IShardableTest;
import com.google.common.annotations.VisibleForTesting;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Runner that creates a {@link CompatibilityTest} to re-run some previous results.
* Only the 'cts' plan is supported.
* TODO: explore other new way to build the retry (instead of relying on one massive pair of
* include/exclude filters)
*/
@OptionClass(alias = "compatibility")
public class RetryFactoryTest implements IRemoteTest, IDeviceTest, IBuildReceiver,
ISystemStatusCheckerReceiver, IInvocationContextReceiver, IShardableTest {
/**
* Mirror the {@link CompatibilityTest} options in order to create it.
*/
public static final String RETRY_OPTION = "retry";
@Option(name = RETRY_OPTION,
shortName = 'r',
description = "retry a previous session's failed and not executed tests.",
mandatory = true)
private Integer mRetrySessionId = null;
@Option(name = CompatibilityTest.SUBPLAN_OPTION,
description = "the subplan to run",
importance = Importance.IF_UNSET)
protected String mSubPlan;
@Option(name = CompatibilityTest.INCLUDE_FILTER_OPTION,
description = "the include module filters to apply.",
importance = Importance.ALWAYS)
protected Set<String> mIncludeFilters = new HashSet<>();
@Option(name = CompatibilityTest.EXCLUDE_FILTER_OPTION,
description = "the exclude module filters to apply.",
importance = Importance.ALWAYS)
protected Set<String> mExcludeFilters = new HashSet<>();
@Option(name = CompatibilityTest.ABI_OPTION,
shortName = 'a',
description = "the abi to test.",
importance = Importance.IF_UNSET)
protected String mAbiName = null;
@Option(name = CompatibilityTest.MODULE_OPTION,
shortName = 'm',
description = "the test module to run.",
importance = Importance.IF_UNSET)
protected String mModuleName = null;
@Option(name = CompatibilityTest.TEST_OPTION,
shortName = CompatibilityTest.TEST_OPTION_SHORT_NAME,
description = "the test run.",
importance = Importance.IF_UNSET)
protected String mTestName = null;
@Option(name = CompatibilityTest.RETRY_TYPE_OPTION,
description = "used with " + CompatibilityTest.RETRY_OPTION + ", retry tests"
+ " of a certain status. Possible values include \"failed\" and \"not_executed\".",
importance = Importance.IF_UNSET)
protected RetryType mRetryType = null;
private List<ISystemStatusChecker> mStatusCheckers;
private IBuildInfo mBuildInfo;
private ITestDevice mDevice;
private IInvocationContext mContext;
@Override
public void setSystemStatusChecker(List<ISystemStatusChecker> systemCheckers) {
mStatusCheckers = systemCheckers;
}
@Override
public void setBuild(IBuildInfo buildInfo) {
mBuildInfo = buildInfo;
}
@Override
public void setDevice(ITestDevice device) {
mDevice = device;
}
@Override
public ITestDevice getDevice() {
return mDevice;
}
@Override
public void setInvocationContext(IInvocationContext invocationContext) {
mContext = invocationContext;
}
/**
* Build a CompatibilityTest with appropriate filters to run only the tests of interests.
*/
@Override
public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
CompatibilityTestSuite test = loadSuite();
// run the retry run.
test.run(listener);
}
@Override
public Collection<IRemoteTest> split(int shardCountHint) {
try {
CompatibilityTestSuite test = loadSuite();
return test.split(shardCountHint);
} catch (DeviceNotAvailableException e) {
CLog.e("Failed to shard the retry run.");
CLog.e(e);
}
return null;
}
/**
* Helper to create a {@link CompatibilityTestSuite} from previous results.
*/
private CompatibilityTestSuite loadSuite() throws DeviceNotAvailableException {
// Create a compatibility test and set it to run only what we want.
CompatibilityTestSuite test = createTest();
CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuildInfo);
// Create the helper with all the options needed.
RetryFilterHelper helper = createFilterHelper(buildHelper);
// TODO: we have access to the original command line, we should accommodate more re-run
// scenario like when the original cts.xml config was not used.
helper.validateBuildFingerprint(mDevice);
helper.setCommandLineOptionsFor(test);
helper.setCommandLineOptionsFor(this);
helper.populateRetryFilters();
try {
OptionSetter setter = new OptionSetter(test);
setter.setOptionValue("compatibility:test-arg",
"com.android.tradefed.testtype.AndroidJUnitTest:rerun-from-file:true");
setter.setOptionValue("compatibility:test-arg",
"com.android.tradefed.testtype.AndroidJUnitTest:fallback-to-serial-rerun:"
+ "false");
} catch (ConfigurationException e) {
throw new RuntimeException(e);
}
test.setIncludeFilter(helper.getIncludeFilters());
test.setExcludeFilter(helper.getExcludeFilters());
test.setDevice(mDevice);
test.setBuild(mBuildInfo);
test.setSystemStatusChecker(mStatusCheckers);
test.setInvocationContext(mContext);
// clean the helper
helper.tearDown();
return test;
}
@VisibleForTesting
RetryFilterHelper createFilterHelper(CompatibilityBuildHelper buildHelper) {
return new RetryFilterHelper(buildHelper, mRetrySessionId, mSubPlan, mIncludeFilters,
mExcludeFilters, mAbiName, mModuleName, mTestName, mRetryType);
}
@VisibleForTesting
CompatibilityTestSuite createTest() {
return new CompatibilityTestSuite();
}
}