Merge "Add include-filter option support to ICU4CTest"
am: 8591213960
Change-Id: I1e7ae43b2b700897101782ca38ea0a66f443e9a8
diff --git a/icu4c/source/test/cintltst/AndroidTest.xml b/icu4c/source/test/cintltst/AndroidTest.xml
index 293235b..b7fd3ff 100644
--- a/icu4c/source/test/cintltst/AndroidTest.xml
+++ b/icu4c/source/test/cintltst/AndroidTest.xml
@@ -38,5 +38,8 @@
<option name="set-option" value="runtime-hint:20s" />
<option name="set-option" value="no-fail-data-errors:true" />
<option name="set-option" value="native-test-timeout:300000" />
+ <option name="set-option" value="command-filter-prefix:/" />
+ <!-- Sample include-filter to run a subset of tests in putiltst-->
+ <!-- <option name="set-option" value="include-filter:cintltst.putiltst" /> -->
</test>
</configuration>
diff --git a/icu4c/source/test/intltest/AndroidTest.xml b/icu4c/source/test/intltest/AndroidTest.xml
index 7d90146..327c5b8 100644
--- a/icu4c/source/test/intltest/AndroidTest.xml
+++ b/icu4c/source/test/intltest/AndroidTest.xml
@@ -39,6 +39,8 @@
<option name="set-option" value="no-fail-data-errors:true" />
<!-- test-timeout unit is ms, value = 10 minutes -->
<option name="set-option" value="native-test-timeout:600000" />
+ <!-- Sample include-filter to run a subset of tests in utility-->
+ <!-- <option name="set-option" value="include-filter:intltest.utility" /> -->
</test>
</configuration>
diff --git a/tools/testing/test_harness/src/com/android/icu/tradefed/testtype/ICU4CTest.java b/tools/testing/test_harness/src/com/android/icu/tradefed/testtype/ICU4CTest.java
index 670843c..5b2c302 100644
--- a/tools/testing/test_harness/src/com/android/icu/tradefed/testtype/ICU4CTest.java
+++ b/tools/testing/test_harness/src/com/android/icu/tradefed/testtype/ICU4CTest.java
@@ -29,6 +29,7 @@
import com.android.tradefed.testtype.IDeviceTest;
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.testtype.IRuntimeHintProvider;
+import com.android.tradefed.testtype.ITestFilterReceiver;
import com.android.tradefed.util.CommandResult;
import com.android.tradefed.util.CommandStatus;
import com.android.tradefed.util.FileUtil;
@@ -37,8 +38,11 @@
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.LinkedList;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
@@ -46,6 +50,7 @@
@OptionClass(alias = "icu4c")
public class ICU4CTest
implements IDeviceTest,
+ ITestFilterReceiver,
IRemoteTest,
IAbiReceiver,
IRuntimeHintProvider {
@@ -58,6 +63,10 @@
@Option(name = "module-name", description = "The name of the native test module to run.")
private String mTestModule = null;
+ @Option(name = "command-filter-prefix",
+ description = "The prefix required for each test filter when running the shell command")
+ private String mCommandFilterPrefix = "";
+
@Option(
name = "native-test-timeout",
description =
@@ -82,6 +91,19 @@
)
private boolean mNoFailDataErrors = false;
+ @Option(
+ name = "include-filter",
+ description = "The ICU-specific positive filter of the test names to run."
+ )
+ private Set<String> mIncludeFilters = new LinkedHashSet<>();
+
+
+ @Option(
+ name = "exclude-filter",
+ description = "The ICU-specific negative filter of the test names to run."
+ )
+ private Set<String> mExcludeFilters = new LinkedHashSet<>();
+
private static final String TEST_FLAG_NO_FAIL_DATA_ERRORS = "-w";
private static final String TEST_FLAG_XML_OUTPUT = "-x";
@@ -139,6 +161,62 @@
return mRuntimeHint;
}
+ /** {@inheritDoc} */
+ @Override
+ public void addIncludeFilter(String filter) {
+ mIncludeFilters.add(filter);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void addAllIncludeFilters(Set<String> filters) {
+ mIncludeFilters.addAll(filters);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void addExcludeFilter(String filter) {
+ mExcludeFilters.add(filter);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void addAllExcludeFilters(Set<String> filters) {
+ mExcludeFilters.addAll(filters);
+ }
+
+ @Override
+ public Set<String> getIncludeFilters() {
+ return mIncludeFilters;
+ }
+
+ @Override
+ public Set<String> getExcludeFilters() {
+ return mExcludeFilters;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void clearExcludeFilters() {
+ mExcludeFilters.clear();
+ }
+
+ @Override
+ public void clearIncludeFilters() {
+ mIncludeFilters.clear();
+ }
+
+ public void setCommandFilterPrefix(String s) {
+ if (s == null) {
+ throw new NullPointerException("CommandFilterPrefix can't be null");
+ }
+ mCommandFilterPrefix = s;
+ }
+
+ public String getCommandFilterPrefix() {
+ return mCommandFilterPrefix;
+ }
+
/**
* Gets the path where native tests live on the device.
*
@@ -226,7 +304,8 @@
File tmpOutput = FileUtil.createTempFile(testRunName, ".xml");
testDevice.pullFile(xmlFullPath, tmpOutput);
- ICU4CXmlResultParser parser = new ICU4CXmlResultParser(testRunName, listener);
+ ICU4CXmlResultParser parser = new ICU4CXmlResultParser(mTestModule,
+ testRunName, listener);
parser.parseResult(tmpOutput, commandResult);
} catch (IOException e) {
@@ -263,9 +342,41 @@
String cmd = String.join(" ", args);
+ List<String> includeFilters = preprocessIncludeFilters();
+ if (!includeFilters.isEmpty()) {
+ cmd += " " + String.join(" ", includeFilters);
+ }
+
return cmd;
}
+ private List<String> preprocessIncludeFilters() {
+ Set<String> includeFilters = mIncludeFilters;
+ List<String> results = new ArrayList<>();
+ for (String filter : includeFilters) {
+ if (!filter.startsWith(mTestModule)) {
+ CLog.i("Ignore positive filter which does not contain module prefix \"%s\":%s",
+ mTestModule, filter);
+ continue;
+ }
+ String modifiedFilter = filter.substring(mTestModule.length());
+ if (filter.length() == 0) {
+ // Ignore because it intends to run all tests when the filter is the module name.
+ continue;
+ }
+ // Android / tradefed uses '.' as package separator, but ICU4C tests use '/'.
+ modifiedFilter = modifiedFilter.replace('.', '/');
+
+ if (modifiedFilter.charAt(0) != '/' || modifiedFilter.length() == 1) {
+ CLog.i("Ignore invalid filter:%s", filter);
+ continue;
+ }
+ modifiedFilter = mCommandFilterPrefix + modifiedFilter.substring(1);
+ results.add(modifiedFilter);
+ }
+ return results;
+ }
+
/** {@inheritDoc} */
@Override
public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
@@ -286,6 +397,9 @@
"%s exists but is not executable in %s.",
testPath, mDevice.getSerialNumber()));
}
+ if (!mExcludeFilters.isEmpty()) {
+ throw new IllegalStateException("ICU4C test suites do not support exclude filters");
+ }
runTest(mDevice, testPath, listener);
}
}
diff --git a/tools/testing/test_harness/src/com/android/icu/tradefed/testtype/ICU4CXmlResultParser.java b/tools/testing/test_harness/src/com/android/icu/tradefed/testtype/ICU4CXmlResultParser.java
index f9a2007..bed19fd 100644
--- a/tools/testing/test_harness/src/com/android/icu/tradefed/testtype/ICU4CXmlResultParser.java
+++ b/tools/testing/test_harness/src/com/android/icu/tradefed/testtype/ICU4CXmlResultParser.java
@@ -43,6 +43,7 @@
private static final String TEST_CASE_TAG = "testcase";
private final String mTestRunName;
+ private final String mModuleName;
private int mNumTestsRun = 0;
private int mNumTestsExpected = 0;
private long mTotalRunTime = 0;
@@ -51,11 +52,14 @@
/**
* Creates the ICU4CXmlResultParser.
*
+ * @param moduleName module name
* @param testRunName the test run name to provide to {@link
* ITestInvocationListener#testRunStarted(String, int)}
* @param listeners informed of test results as the tests are executing
*/
- public ICU4CXmlResultParser(String testRunName, Collection<ITestInvocationListener> listeners) {
+ public ICU4CXmlResultParser(String moduleName, String testRunName,
+ Collection<ITestInvocationListener> listeners) {
+ mModuleName = moduleName;
mTestRunName = testRunName;
mTestListeners = new ArrayList<>(listeners);
}
@@ -63,11 +67,14 @@
/**
* Creates the ICU4CXmlResultParser for a single listener.
*
+ * @param moduleName module name
* @param testRunName the test run name to provide to {@link
* ITestInvocationListener#testRunStarted(String, int)}
* @param listener informed of test results as the tests are executing
*/
- public ICU4CXmlResultParser(String testRunName, ITestInvocationListener listener) {
+ public ICU4CXmlResultParser(String moduleName, String testRunName,
+ ITestInvocationListener listener) {
+ mModuleName = moduleName;
mTestRunName = testRunName;
mTestListeners = new ArrayList<>();
if (listener != null) {
@@ -162,6 +169,10 @@
classname = classname.substring(1);
}
+ // For test reporting on Android, prefix module name to the class name
+ // and replace '/' with '.'
+ classname = mModuleName + '.' + classname.replace('/', '.');
+
// TODO: Fix the duplicate test name in the testId
// Currently, testId is like spoof#spoof or spoof/testBug8654#testBug8654
// in order to avoid empty test name in the case of spoof#spoof. We should remove