Merge "Move LocationListenerActivity to managedprovisioning/"
diff --git a/hostsidetests/appsecurity/OWNERS b/hostsidetests/appsecurity/OWNERS
index cbfad62..927344a 100644
--- a/hostsidetests/appsecurity/OWNERS
+++ b/hostsidetests/appsecurity/OWNERS
@@ -21,7 +21,7 @@
per-file ExternalStorageHostTest.java = jsharkey@google.com
per-file InstantAppUserTest.java = toddke@google.com
per-file InstantCookieHostTest.java = toddke@google.com
-per-file IsolatedSplitsTests.java = toddke@google.com
+per-file IsolatedSplitsTests.java = patb@google.com,toddke@google.com
per-file KeySetHostTest.java = cbrubaker@google.com
per-file ListeningPortsTest.java = cbrubaker@google.com
per-file MajorVersionTest.java = toddke@google.com
@@ -35,7 +35,7 @@
per-file RequestsOnlyCalendarApp22.java = moltmann@google.com
per-file ScopedDirectoryAccessTest.java = jsharkey@google.com
per-file SharedUserIdTest.java = toddke@google.com
-per-file SplitTests.java = toddke@google.com
+per-file SplitTests.java = patb@google.com,toddke@google.com
per-file StorageHostTest.java = jsharkey@google.com
per-file UseEmbeddedDexTest.java = victorhsieh@google.com
# test apps
diff --git a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/OWNERS b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/OWNERS
index 87e75ec..f17768d 100644
--- a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/OWNERS
@@ -1,2 +1,3 @@
# Bug component: 533114
+patb@google.com
toddke@google.com
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/OWNERS b/hostsidetests/appsecurity/test-apps/SplitApp/OWNERS
new file mode 100644
index 0000000..f17768d
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 533114
+patb@google.com
+toddke@google.com
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
index 9bba49c..3584353 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
@@ -150,7 +150,7 @@
// Launch a resizeable activity on new secondary display.
separateTestJournal();
- launchActivityOnDisplay(RESIZEABLE_ACTIVITY, newDisplay.mId);
+ launchActivityOnDisplay(RESIZEABLE_ACTIVITY, WINDOWING_MODE_FULLSCREEN, newDisplay.mId);
waitAndAssertActivityStateOnDisplay(RESIZEABLE_ACTIVITY, STATE_RESUMED, newDisplay.mId,
"Launched activity must be resumed");
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/itest_impl.h b/tests/tests/binder_ndk/libbinder_ndk_test/itest_impl.h
index 8b1a1c3..413e190 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/itest_impl.h
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/itest_impl.h
@@ -459,7 +459,7 @@
MyExt ext2;
ext2.a = ext->a;
ext2.b = ext->b;
- out_output->ext.setParcelable(&ext2);
+ out_output->ext.setParcelable(ext2);
return ::ndk::ScopedAStatus(AStatus_newOk());
}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp b/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp
index c81f1d4..10d6b65 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp
@@ -939,7 +939,7 @@
MyExt myext1;
myext1.a = 42;
myext1.b = "mystr";
- ep.ext.setParcelable(&myext1);
+ ep.ext.setParcelable(myext1);
std::unique_ptr<MyExt> myext2 = ep.ext.getParcelable<MyExt>();
EXPECT_TRUE(myext2);
EXPECT_EQ(42, myext2->a);
@@ -962,7 +962,7 @@
MyExt myext1;
myext1.a = 42;
myext1.b = "mystr";
- ep.ext.setParcelable(&myext1);
+ ep.ext.setParcelable(myext1);
ExtendableParcelable ep2;
EXPECT_OK(iface->RepeatExtendableParcelable(ep, &ep2));
diff --git a/tools/cts-tradefed/OWNERS b/tools/cts-tradefed/OWNERS
new file mode 100644
index 0000000..5f93ef3
--- /dev/null
+++ b/tools/cts-tradefed/OWNERS
@@ -0,0 +1,17 @@
+# Android EngProd Approvers
+guangzhu@google.com
+fdeng@google.com
+moonk@google.com
+jdesprez@google.com
+
+# Android Partner Eng Approvers
+aaronholden@google.com
+yuji@google.com
+nickrose@google.com
+
+# File Specific Approvers
+per-file Backup* = aabhinav@google.com, jstemmer@google.com, nathch@google.com, niagra@google.com, niamhfw@google.com, philippov@google.com, rthakohov@google.com, tobiast@google.com
+per-file cts-meerkat.xml = alanstokes@google.com, brufino@google.com, lus@google.com, rickywai@google.com
+per-file cts-on-csi*.xml = ycchen@google.com, hsinyichen@google.com, tyanh@google.com
+per-file csi-*.xml = ycchen@google.com, hsinyichen@google.com, tyanh@google.com
+
diff --git a/tools/cts-tradefed/tests/.classpath b/tools/cts-tradefed/tests/.classpath
new file mode 100644
index 0000000..1c238bc
--- /dev/null
+++ b/tools/cts-tradefed/tests/.classpath
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-9">
+ <attributes>
+ <attribute name="module" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry combineaccessrules="false" kind="src" path="/tradefederation">
+ <attributes>
+ <attribute name="module" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry combineaccessrules="false" kind="src" path="/cts-tradefed">
+ <attributes>
+ <attribute name="module" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/tools/cts-tradefed/tests/.project b/tools/cts-tradefed/tests/.project
new file mode 100644
index 0000000..2f00b36
--- /dev/null
+++ b/tools/cts-tradefed/tests/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>cts-tradefed-tests</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ApkPackageNameCheck.java b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ApkPackageNameCheck.java
new file mode 100644
index 0000000..b50c906
--- /dev/null
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ApkPackageNameCheck.java
@@ -0,0 +1,165 @@
+/*
+ * 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.presubmit;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.android.compatibility.common.tradefed.targetprep.FilePusher;
+import com.android.tradefed.config.ConfigurationException;
+import com.android.tradefed.config.ConfigurationFactory;
+import com.android.tradefed.config.IConfiguration;
+import com.android.tradefed.targetprep.ITargetPreparer;
+import com.android.tradefed.targetprep.PushFilePreparer;
+import com.android.tradefed.targetprep.TestAppInstallSetup;
+import com.android.tradefed.testtype.IRemoteTest;
+import com.android.tradefed.testtype.InstrumentationTest;
+import com.android.tradefed.util.AaptParser;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Class to validate tests Apks in testcases/
+ */
+@RunWith(JUnit4.class)
+public class ApkPackageNameCheck {
+
+ private static final Set<String> EXCEPTION_LIST = new HashSet<>();
+ static {
+ // TODO: Remove exception when their package have been fixed.
+ EXCEPTION_LIST.add("android.app.cts");
+ EXCEPTION_LIST.add("android.systemui.cts");
+ }
+
+ /**
+ * We ensure that no apk with same package names may be installed. Otherwise it may results in
+ * conflicts.
+ */
+ @Test
+ public void testApkPackageNames() throws Exception {
+ String ctsRoot = System.getProperty("CTS_ROOT");
+ File testcases = new File(ctsRoot, "/android-cts/testcases/");
+ if (!testcases.exists()) {
+ fail(String.format("%s does not exists", testcases));
+ return;
+ }
+ File[] listConfig = testcases.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ if (name.endsWith(".config")) {
+ return true;
+ }
+ return false;
+ }
+ });
+ assertTrue(listConfig.length > 0);
+ // We check all apk installed by all modules
+ Map<String, String> packageNames = new HashMap<>();
+
+ for (File config : listConfig) {
+ IConfiguration c = ConfigurationFactory.getInstance()
+ .createConfigurationFromArgs(new String[] {config.getAbsolutePath()});
+ // For each config, we check all the apk it's going to install
+ List<File> apkNames = new ArrayList<>();
+ List<String> packageListNames = new ArrayList<>();
+ for (ITargetPreparer prep : c.getTargetPreparers()) {
+ if (prep instanceof TestAppInstallSetup) {
+ apkNames.addAll(((TestAppInstallSetup) prep).getTestsFileName());
+ }
+ // Ensure the files requested to be pushed exist.
+ if (prep instanceof FilePusher && ((FilePusher) prep).shouldAppendBitness()) {
+ for (File f : ((PushFilePreparer) prep).getPushSpecs(null).values()) {
+ String path = f.getPath();
+ if (!new File(testcases, path + "32").exists()
+ || !new File(testcases, path + "64").exists()) {
+ // TODO: Enforce should abort on failure is True in CTS
+ if (((FilePusher) prep).shouldAbortOnFailure()) {
+ fail(
+ String.format(
+ "File %s[32/64] wasn't found in testcases/ while "
+ + "it's expected to be pushed as part of "
+ + "%s",
+ path, config.getName()));
+ }
+ }
+ }
+ } else if (prep instanceof PushFilePreparer) {
+ for (File f : ((PushFilePreparer) prep).getPushSpecs(null).values()) {
+ String path = f.getPath();
+ if (!new File(testcases, path).exists()) {
+ // TODO: Enforce should abort on failure is True in CTS
+ if (((PushFilePreparer) prep).shouldAbortOnFailure()) {
+ fail(
+ String.format(
+ "File %s wasn't found in testcases/ while it's "
+ + "expected to be pushed as part of %s",
+ path, config.getName()));
+ }
+ }
+ }
+ }
+ }
+
+ for (File apk : apkNames) {
+ String apkName = apk.getName();
+ File apkFile = new File(testcases, apkName);
+ if (!apkFile.exists()) {
+ fail(String.format("Module %s is trying to install %s which does not "
+ + "exists in testcases/", config.getName(), apkFile));
+ }
+ AaptParser res = AaptParser.parse(apkFile);
+ assertNotNull(res);
+ String packageName = res.getPackageName();
+ String put = packageNames.put(packageName, apkName);
+ packageListNames.add(packageName);
+ // The package already exists and it's a different apk
+ if (put != null && !apkName.equals(put) && !EXCEPTION_LIST.contains(packageName)) {
+ fail(String.format("Module %s: Package name '%s' from apk '%s' was already "
+ + "added by previous apk '%s'.",
+ config.getName(), packageName, apkName, put));
+ }
+ }
+
+ // Catch a test trying to run something it doesn't install.
+ List<IRemoteTest> tests = c.getTests();
+ for (IRemoteTest test : tests) {
+ if (test instanceof InstrumentationTest) {
+ InstrumentationTest instrumentationTest = (InstrumentationTest) test;
+ if (instrumentationTest.getPackageName() != null) {
+ if (!packageListNames.contains(instrumentationTest.getPackageName())) {
+ throw new ConfigurationException(
+ String.format("Module %s requests to run '%s' but it's not "
+ + "part of any apks.",
+ config.getName(), instrumentationTest.getPackageName()));
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java
new file mode 100644
index 0000000..625da2f
--- /dev/null
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java
@@ -0,0 +1,404 @@
+/*
+ * 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.presubmit;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.tradefed.targetprep.ApkInstaller;
+import com.android.compatibility.common.tradefed.targetprep.PreconditionPreparer;
+import com.android.compatibility.common.tradefed.testtype.JarHostTest;
+import com.android.tradefed.build.FolderBuildInfo;
+import com.android.tradefed.config.ConfigurationDescriptor;
+import com.android.tradefed.config.ConfigurationException;
+import com.android.tradefed.config.ConfigurationFactory;
+import com.android.tradefed.config.IConfiguration;
+import com.android.tradefed.invoker.ExecutionFiles.FilesKey;
+import com.android.tradefed.invoker.TestInformation;
+import com.android.tradefed.invoker.shard.token.TokenProperty;
+import com.android.tradefed.targetprep.ITargetPreparer;
+import com.android.tradefed.testtype.AndroidJUnitTest;
+import com.android.tradefed.testtype.HostTest;
+import com.android.tradefed.testtype.IRemoteTest;
+import com.android.tradefed.testtype.ITestFilterReceiver;
+import com.android.tradefed.testtype.suite.ITestSuite;
+import com.android.tradefed.testtype.suite.params.ModuleParameters;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Test that configuration in CTS can load and have expected properties.
+ */
+@RunWith(JUnit4.class)
+public class CtsConfigLoadingTest {
+
+ private static final String METADATA_COMPONENT = "component";
+ private static final Set<String> KNOWN_COMPONENTS =
+ new HashSet<>(
+ Arrays.asList(
+ // modifications to the list below must be reviewed
+ "abuse",
+ "art",
+ "auth",
+ "auto",
+ "autofill",
+ "backup",
+ "bionic",
+ "bluetooth",
+ "camera",
+ "contentcapture",
+ "deviceinfo",
+ "deqp",
+ "devtools",
+ "framework",
+ "graphics",
+ "hdmi",
+ "inputmethod",
+ "libcore",
+ "location",
+ "media",
+ "metrics",
+ "misc",
+ "mocking",
+ "networking",
+ "neuralnetworks",
+ "print",
+ "renderscript",
+ "security",
+ "statsd",
+ "systems",
+ "sysui",
+ "telecom",
+ "tv",
+ "uitoolkit",
+ "vr",
+ "webview",
+ "wifi"));
+ private static final Set<String> KNOWN_MISC_MODULES =
+ new HashSet<>(
+ Arrays.asList(
+ // Modifications to the list below must be approved by someone in
+ // test/suite_harness/OWNERS.
+ "CtsSliceTestCases.config",
+ "CtsSampleDeviceTestCases.config",
+ "CtsUsbTests.config",
+ "CtsGpuToolsHostTestCases.config",
+ "CtsEdiHostTestCases.config",
+ "CtsClassLoaderFactoryPathClassLoaderTestCases.config",
+ "CtsSampleHostTestCases.config",
+ "CtsHardwareTestCases.config",
+ "CtsMonkeyTestCases.config",
+ "CtsAndroidAppTestCases.config",
+ "CtsClassLoaderFactoryInMemoryDexClassLoaderTestCases.config",
+ "CtsAppComponentFactoryTestCases.config",
+ "CtsSeccompHostTestCases.config"));
+
+ /**
+ * List of the officially supported runners in CTS, they meet all the interfaces criteria as
+ * well as support sharding very well. Any new addition should go through a review.
+ */
+ private static final Set<String> SUPPORTED_CTS_TEST_TYPE = new HashSet<>(Arrays.asList(
+ // Cts runners
+ "com.android.compatibility.common.tradefed.testtype.JarHostTest",
+ "com.android.compatibility.testtype.DalvikTest",
+ "com.android.compatibility.testtype.LibcoreTest",
+ "com.drawelements.deqp.runner.DeqpTestRunner",
+ // Tradefed runners
+ "com.android.tradefed.testtype.AndroidJUnitTest",
+ "com.android.tradefed.testtype.HostTest",
+ "com.android.tradefed.testtype.GTest"
+ ));
+
+ /**
+ * In Most cases we impose the usage of the AndroidJUnitRunner because it supports all the
+ * features required (filtering, sharding, etc.). We do not typically expect people to need a
+ * different runner.
+ */
+ private static final Set<String> ALLOWED_INSTRUMENTATION_RUNNER_NAME = new HashSet<>();
+ static {
+ ALLOWED_INSTRUMENTATION_RUNNER_NAME.add("android.support.test.runner.AndroidJUnitRunner");
+ ALLOWED_INSTRUMENTATION_RUNNER_NAME.add("androidx.test.runner.AndroidJUnitRunner");
+ }
+ private static final Set<String> RUNNER_EXCEPTION = new HashSet<>();
+ static {
+ // Used for a bunch of system-api cts tests
+ RUNNER_EXCEPTION.add("repackaged.android.test.InstrumentationTestRunner");
+ // Used by a UiRendering scenario where an activity is persisted between tests
+ RUNNER_EXCEPTION.add("android.uirendering.cts.runner.UiRenderingRunner");
+ }
+
+ /**
+ * Families of module parameterization that MUST be specified explicitly in the module
+ * AndroidTest.xml.
+ */
+ private static final Set<String> MANDATORY_PARAMETERS_FAMILY = new HashSet<>();
+
+ static {
+ MANDATORY_PARAMETERS_FAMILY.add(ModuleParameters.INSTANT_APP_FAMILY);
+ MANDATORY_PARAMETERS_FAMILY.add(ModuleParameters.MULTI_ABI_FAMILY);
+ MANDATORY_PARAMETERS_FAMILY.add(ModuleParameters.SECONDARY_USER_FAMILY);
+ }
+
+ /**
+ * AllowList to start enforcing metadata on modules. No additional entry will be allowed! This
+ * is meant to burn down the remaining modules definition.
+ */
+ private static final Set<String> ALLOWLIST_MODULE_PARAMETERS = new HashSet<>();
+
+ static {
+ ALLOWLIST_MODULE_PARAMETERS.add("CtsAccessibilityServiceTestCases.config");
+ ALLOWLIST_MODULE_PARAMETERS.add("CtsCarrierApiTestCases.config");
+ ALLOWLIST_MODULE_PARAMETERS.add("CtsMediaTestCases.config");
+ ALLOWLIST_MODULE_PARAMETERS.add("CtsMediaV2TestCases.config");
+ ALLOWLIST_MODULE_PARAMETERS.add("CtsOpenGlPerfTestCases.config");
+ ALLOWLIST_MODULE_PARAMETERS.add("CtsOsTestCases.config");
+ ALLOWLIST_MODULE_PARAMETERS.add("CtsPermission2TestCases.config");
+ ALLOWLIST_MODULE_PARAMETERS.add("CtsPermissionTestCases.config");
+ ALLOWLIST_MODULE_PARAMETERS.add("CtsProviderUiTestCases.config");
+ }
+
+ /**
+ * Test that configuration shipped in Tradefed can be parsed.
+ * -> Exclude deprecated ApkInstaller.
+ * -> Check if host-side tests are non empty.
+ */
+ @Test
+ public void testConfigurationLoad() throws Exception {
+ String ctsRoot = System.getProperty("CTS_ROOT");
+ File testcases = new File(ctsRoot, "/android-cts/testcases/");
+ if (!testcases.exists()) {
+ fail(String.format("%s does not exists", testcases));
+ return;
+ }
+ File[] listConfig = testcases.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ if (name.endsWith(".config")) {
+ return true;
+ }
+ return false;
+ }
+ });
+ assertTrue(listConfig.length > 0);
+ // Create a FolderBuildInfo to similate the CompatibilityBuildProvider
+ FolderBuildInfo stubFolder = new FolderBuildInfo("-1", "-1");
+ stubFolder.setRootDir(new File(ctsRoot));
+ stubFolder.addBuildAttribute(CompatibilityBuildHelper.SUITE_NAME, "CTS");
+ stubFolder.addBuildAttribute("ROOT_DIR", ctsRoot);
+ TestInformation stubTestInfo = TestInformation.newBuilder().build();
+ stubTestInfo.executionFiles().put(FilesKey.TESTS_DIRECTORY, new File(ctsRoot));
+
+ List<String> missingMandatoryParameters = new ArrayList<>();
+ // We expect to be able to load every single config in testcases/
+ for (File config : listConfig) {
+ IConfiguration c = ConfigurationFactory.getInstance()
+ .createConfigurationFromArgs(new String[] {config.getAbsolutePath()});
+ // Ensure the deprecated ApkInstaller is not used anymore.
+ for (ITargetPreparer prep : c.getTargetPreparers()) {
+ if (prep.getClass().isAssignableFrom(ApkInstaller.class)) {
+ throw new ConfigurationException(
+ String.format("%s: Use com.android.tradefed.targetprep.suite."
+ + "SuiteApkInstaller instead of com.android.compatibility."
+ + "common.tradefed.targetprep.ApkInstaller, options will be "
+ + "the same.", config));
+ }
+ if (prep.getClass().isAssignableFrom(PreconditionPreparer.class)) {
+ throw new ConfigurationException(
+ String.format(
+ "%s: includes a PreconditionPreparer (%s) which is not allowed"
+ + " in modules.",
+ config.getName(), prep.getClass()));
+ }
+ }
+ // We can ensure that Host side tests are not empty.
+ for (IRemoteTest test : c.getTests()) {
+ // Check that all the tests runners are well supported.
+ if (!SUPPORTED_CTS_TEST_TYPE.contains(test.getClass().getCanonicalName())) {
+ throw new ConfigurationException(
+ String.format(
+ "testtype %s is not officially supported by CTS. "
+ + "The supported ones are: %s",
+ test.getClass().getCanonicalName(), SUPPORTED_CTS_TEST_TYPE));
+ }
+ if (test instanceof HostTest) {
+ HostTest hostTest = (HostTest) test;
+ // We inject a made up folder so that it can find the tests.
+ hostTest.setBuild(stubFolder);
+ hostTest.setTestInformation(stubTestInfo);
+ int testCount = hostTest.countTestCases();
+ if (testCount == 0) {
+ throw new ConfigurationException(
+ String.format("%s: %s reports 0 test cases.",
+ config.getName(), test));
+ }
+ }
+ // Tests are expected to implement that interface.
+ if (!(test instanceof ITestFilterReceiver)) {
+ throw new IllegalArgumentException(String.format(
+ "Test in module %s must implement ITestFilterReceiver.",
+ config.getName()));
+ }
+ // Ensure that the device runner is the AJUR one if explicitly specified.
+ if (test instanceof AndroidJUnitTest) {
+ AndroidJUnitTest instru = (AndroidJUnitTest) test;
+ if (instru.getRunnerName() != null &&
+ !ALLOWED_INSTRUMENTATION_RUNNER_NAME.contains(instru.getRunnerName())) {
+ // Some runner are exempt
+ if (!RUNNER_EXCEPTION.contains(instru.getRunnerName())) {
+ throw new ConfigurationException(
+ String.format("%s: uses '%s' instead of on of '%s' that are "
+ + "expected", config.getName(), instru.getRunnerName(),
+ ALLOWED_INSTRUMENTATION_RUNNER_NAME));
+ }
+ }
+ }
+ }
+ ConfigurationDescriptor cd = c.getConfigurationDescription();
+ Assert.assertNotNull(config + ": configuration descriptor is null", cd);
+ List<String> component = cd.getMetaData(METADATA_COMPONENT);
+ Assert.assertNotNull(String.format("Missing module metadata field \"component\", "
+ + "please add the following line to your AndroidTest.xml:\n"
+ + "<option name=\"config-descriptor:metadata\" key=\"component\" "
+ + "value=\"...\" />\nwhere \"value\" must be one of: %s\n"
+ + "config: %s", KNOWN_COMPONENTS, config),
+ component);
+ Assert.assertEquals(String.format("Module config contains more than one \"component\" "
+ + "metadata field: %s\nconfig: %s", component, config),
+ 1, component.size());
+ String cmp = component.get(0);
+ Assert.assertTrue(String.format("Module config contains unknown \"component\" metadata "
+ + "field \"%s\", supported ones are: %s\nconfig: %s",
+ cmp, KNOWN_COMPONENTS, config), KNOWN_COMPONENTS.contains(cmp));
+
+ if ("misc".equals(cmp)) {
+ String configFileName = config.getName();
+ Assert.assertTrue(
+ String.format(
+ "Adding new module %s to \"misc\" component is restricted, "
+ + "please pick a component that your module fits in",
+ configFileName),
+ KNOWN_MISC_MODULES.contains(configFileName));
+ }
+
+ // Check that specified parameters are expected
+ boolean res =
+ checkModuleParameters(
+ config.getName(), cd.getMetaData(ITestSuite.PARAMETER_KEY));
+ if (!res) {
+ missingMandatoryParameters.add(config.getName());
+ }
+ // Check that specified tokens are expected
+ checkTokens(config.getName(), cd.getMetaData(ITestSuite.TOKEN_KEY));
+
+ // Ensure each CTS module is tagged with <option name="test-suite-tag" value="cts" />
+ Assert.assertTrue(String.format(
+ "Module config %s does not contains "
+ + "'<option name=\"test-suite-tag\" value=\"cts\" />'", config.getName()),
+ cd.getSuiteTags().contains("cts"));
+
+ // Check not-shardable: JarHostTest cannot create empty shards so it should never need
+ // to be not-shardable.
+ if (cd.isNotShardable()) {
+ for (IRemoteTest test : c.getTests()) {
+ if (test.getClass().isAssignableFrom(JarHostTest.class)) {
+ throw new ConfigurationException(
+ String.format("config: %s. JarHostTest does not need the "
+ + "not-shardable option.", config.getName()));
+ }
+ }
+ }
+ // Ensure options have been set
+ c.validateOptions();
+ }
+
+ // Exempt the allow list
+ missingMandatoryParameters.removeAll(ALLOWLIST_MODULE_PARAMETERS);
+ // Ensure the mandatory fields are filled
+ if (!missingMandatoryParameters.isEmpty()) {
+ String msg =
+ String.format(
+ "The following %s modules are missing some of the mandatory "
+ + "parameters [instant_app, not_instant_app, "
+ + "multi_abi, not_multi_abi, "
+ + "secondary_user, not_secondary_user]: '%s'",
+ missingMandatoryParameters.size(), missingMandatoryParameters);
+ throw new ConfigurationException(msg);
+ }
+ }
+
+ /** Test that all parameter metadata can be resolved. */
+ private boolean checkModuleParameters(String configName, List<String> parameters)
+ throws ConfigurationException {
+ if (parameters == null) {
+ return false;
+ }
+ Map<String, Boolean> families = createFamilyCheckMap();
+ for (String param : parameters) {
+ try {
+ ModuleParameters p = ModuleParameters.valueOf(param.toUpperCase());
+ if (families.containsKey(p.getFamily())) {
+ families.put(p.getFamily(), true);
+ }
+ } catch (IllegalArgumentException e) {
+ throw new ConfigurationException(
+ String.format("Config: %s includes an unknown parameter '%s'.",
+ configName, param));
+ }
+ }
+ if (families.containsValue(false)) {
+ return false;
+ }
+ return true;
+ }
+
+ /** Test that all tokens can be resolved. */
+ private void checkTokens(String configName, List<String> tokens) throws ConfigurationException {
+ if (tokens == null) {
+ return;
+ }
+ for (String token : tokens) {
+ try {
+ TokenProperty.valueOf(token.toUpperCase());
+ } catch (IllegalArgumentException e) {
+ throw new ConfigurationException(
+ String.format(
+ "Config: %s includes an unknown token '%s'.", configName, token));
+ }
+ }
+ }
+
+ private Map<String, Boolean> createFamilyCheckMap() {
+ Map<String, Boolean> families = new HashMap<>();
+ for (String family : MANDATORY_PARAMETERS_FAMILY) {
+ families.put(family, false);
+ }
+ return families;
+ }
+}
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/DupFileTest.java b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/DupFileTest.java
new file mode 100644
index 0000000..7701279
--- /dev/null
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/DupFileTest.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2018 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.presubmit;
+
+import static org.junit.Assert.fail;
+
+import com.android.tradefed.config.ConfigurationException;
+
+import com.google.common.collect.ImmutableSet;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * Test to check for duplicate files in different jars and prevent the same dependencies of being
+ * included several time (which might result in version conflicts).
+ */
+@RunWith(JUnit4.class)
+public class DupFileTest {
+
+ // We ignore directories part of the common java and google packages.
+ private static final String[] IGNORE_DIRS =
+ new String[] {
+ "android/",
+ "javax/annotation/",
+ "com/google/protobuf/",
+ "kotlin/",
+ "perfetto/protos/"
+ };
+ // Temporarily exclude some Tradefed jar while we work on unbundling them.
+ private static final Set<String> IGNORE_JARS =
+ ImmutableSet.of("tradefed-no-fwk.jar", "tradefed-test-framework.jar",
+ "compatibility-tradefed-tests.jar",
+ "compatibility-common-util-tests.jar", "compatibility-host-util-tests.jar");
+
+ /** test if there are duplicate files in different jars. */
+ @Test
+ public void testDupFilesExist() throws Exception {
+ // Get list of jars.
+ List<File> jars = getListOfBuiltJars();
+
+ // Create map of files to jars.
+ Map<String, List<String>> filesToJars = getMapOfFilesAndJars(jars);
+
+ // Check if there are any files with the same name in diff jars.
+ int dupedFiles = 0;
+ StringBuilder dupedFilesSummary = new StringBuilder();
+ for (Map.Entry<String, List<String>> entry : filesToJars.entrySet()) {
+ String file = entry.getKey();
+ List<String> jarFiles = entry.getValue();
+
+ if (jarFiles.size() != 1) {
+ dupedFiles++;
+ dupedFilesSummary.append(file + ": " + jarFiles.toString() + "\n");
+ }
+ }
+
+ if (dupedFiles != 0) {
+ fail(
+ String.format(
+ "%d files are duplicated in different jars:\n%s",
+ dupedFiles, dupedFilesSummary.toString()));
+ }
+ }
+
+ /** Create map of file to jars */
+ private Map<String, List<String>> getMapOfFilesAndJars(List<File> jars) throws IOException {
+ Map<String, List<String>> map = new LinkedHashMap<String, List<String>>();
+ JarFile jarFile;
+ List<String> jarFileList;
+ // Map all the files from all the jars.
+ for (File jar : jars) {
+ if (IGNORE_JARS.contains(jar.getName())) {
+ continue;
+ }
+ jarFile = new JarFile(jar);
+ jarFileList = getListOfFiles(jarFile);
+ jarFile.close();
+
+ // Add in the jar file to the map.
+ for (String file : jarFileList) {
+ if (!map.containsKey(file)) {
+ map.put(file, new LinkedList<String>());
+ }
+
+ map.get(file).add(jar.getName());
+ }
+ }
+ return map;
+ }
+
+ /** Get the list of jars specified in the path. */
+ private List<File> getListOfBuiltJars() throws ConfigurationException {
+ String classpathStr = System.getProperty("java.class.path");
+ if (classpathStr == null) {
+ throw new ConfigurationException(
+ "Could not find the classpath property: java.class.path");
+ }
+ List<File> listOfJars = new ArrayList<File>();
+ for (String jar : classpathStr.split(":")) {
+ File jarFile = new File(jar);
+ if (jarFile.exists()) {
+ listOfJars.add(jarFile);
+ }
+ }
+ return listOfJars;
+ }
+
+ /** Return the list of files in the jar. */
+ private List<String> getListOfFiles(JarFile jar) {
+ List<String> files = new ArrayList<String>();
+ Enumeration<JarEntry> e = jar.entries();
+ while (e.hasMoreElements()) {
+ JarEntry entry = e.nextElement();
+ String filename = entry.getName();
+ if (checkThisFile(filename)) {
+ files.add(filename);
+ }
+ }
+ return files;
+ }
+
+ /** Check if we should add this file to list of files. We only want to check for classes. */
+ private Boolean checkThisFile(String filename) {
+ if (!filename.endsWith(".class")) {
+ return false;
+ }
+
+ for (String skipDir : IGNORE_DIRS) {
+ if (filename.startsWith(skipDir)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/PresubmitSetupValidation.java b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/PresubmitSetupValidation.java
new file mode 100644
index 0000000..4eb48fc
--- /dev/null
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/PresubmitSetupValidation.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 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.presubmit;
+
+import com.android.tradefed.config.ConfigurationException;
+import com.android.tradefed.config.ConfigurationFactory;
+import com.android.tradefed.config.IConfigurationFactory;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests that validate the CTS presubmit setup to ensure no CL will break the presubmit setup
+ * itself.
+ */
+public class PresubmitSetupValidation extends TestCase {
+ private static final String PRESUBMIT_CTS_UNIT_TESTS = "cts-unit-tests";
+
+ /**
+ * Test that the base cts unit tests configuration is still working, and has a reporter
+ * template placeholder.
+ */
+ public void testCtsPresubmit_unit_tests() {
+ IConfigurationFactory factory = ConfigurationFactory.getInstance();
+ String[] presubmitCommand = {PRESUBMIT_CTS_UNIT_TESTS, "--template:map", "reporters=empty"};
+ try {
+ factory.createConfigurationFromArgs(presubmitCommand);
+ } catch (ConfigurationException e) {
+ CLog.e(e);
+ fail(String.format("ConfigException '%s': One of your change is breaking the presubmit "
+ + "CTS unit tests configuration.", e.getMessage()));
+ }
+ }
+
+ /**
+ * Test to ensure that Zip dependency on the Apache Commons Compress coming from TradeFed is
+ * properly setup. This dependency is required for some utilities of TradeFed to work.
+ */
+ public void testDependencyCommonsCompress() throws Exception {
+ ClassLoader loader = ClassLoader.getSystemClassLoader();
+ // This will throw an exception if dependency isn't met.
+ loader.loadClass("org.apache.commons.compress.archivers.zip.ZipFile");
+ }
+}
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
new file mode 100644
index 0000000..9fd38ad
--- /dev/null
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
@@ -0,0 +1,217 @@
+/*
+ * 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.presubmit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.android.tradefed.testtype.suite.TestSuiteInfo;
+import com.android.tradefed.util.AaptParser;
+import com.android.tradefed.util.AbiUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * Tests to validate that the build is containing usable test artifact.
+ */
+@RunWith(JUnit4.class)
+public class ValidateTestsAbi {
+
+ private static final Set<String> MODULE_EXCEPTIONS = new HashSet<>();
+ static {
+ /**
+ * This particular module is shipping all its dependencies in all abis with prebuilt stuff.
+ * Excluding it for now to have the test setup.
+ */
+ MODULE_EXCEPTIONS.add("CtsSplitApp");
+
+ /**
+ * This module tests for security vulnerabilities when installing attacker-devised APKs.
+ */
+ MODULE_EXCEPTIONS.add("CtsCorruptApkTests");
+
+ /**
+ * This module tests for installations of packages that have only 32-bit native libraries
+ * and extract native libraries.
+ */
+ MODULE_EXCEPTIONS.add("CtsExtractNativeLibsAppTrue32");
+
+ /**
+ * This module tests for installations of packages that have only 64-bit native libraries
+ * and extract native libraries.
+ */
+ MODULE_EXCEPTIONS.add("CtsExtractNativeLibsAppTrue64");
+ /**
+ * This module tests for installations of packages that have only 32-bit native libraries
+ * and embed native libraries.
+ */
+ MODULE_EXCEPTIONS.add("CtsExtractNativeLibsAppFalse32");
+
+ /**
+ * This module tests for installations of packages that have only 64-bit native libraries
+ * and embed native libraries.
+ */
+ MODULE_EXCEPTIONS.add("CtsExtractNativeLibsAppFalse64");
+ }
+
+ private static final Set<String> BINARY_EXCEPTIONS = new HashSet<>();
+ static {
+ /**
+ * This binary is a host side helper, so we do not need to check it.
+ */
+ BINARY_EXCEPTIONS.add("sepolicy-analyze");
+ }
+
+ /**
+ * Test that all apks have the same supported abis.
+ * Sometimes, if a module is missing LOCAL_MULTILIB := both, we will end up with only one of
+ * the two abis required and the second one will fail.
+ */
+ @Test
+ public void testApksAbis() {
+ String ctsRoot = System.getProperty("CTS_ROOT");
+ File testcases = new File(ctsRoot, "/android-cts/testcases/");
+ if (!testcases.exists()) {
+ fail(String.format("%s does not exists", testcases));
+ return;
+ }
+ File[] listApks = testcases.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ for (String module : MODULE_EXCEPTIONS) {
+ if (name.startsWith(module)) {
+ return false;
+ }
+ }
+
+ return name.endsWith(".apk");
+ }
+ });
+ assertTrue(listApks.length > 0);
+ int maxAbi = 0;
+ Map<String, Integer> apkToAbi = new HashMap<>();
+
+ for (File testApk : listApks) {
+ AaptParser result = AaptParser.parse(testApk);
+ // Retry as we have seen flake with aapt sometimes.
+ if (result == null) {
+ for (int i = 0; i < 2; i++) {
+ result = AaptParser.parse(testApk);
+ if (result != null) {
+ break;
+ }
+ }
+ // If still couldn't parse the apk
+ if (result == null) {
+ fail(String.format("Fail to run 'aapt dump badging %s'",
+ testApk.getAbsolutePath()));
+ }
+ }
+ // We only check the apk that have native code
+ if (!result.getNativeCode().isEmpty()) {
+ List<String> supportedAbiApk = result.getNativeCode();
+ Set<String> buildTarget = AbiUtils.getAbisForArch(
+ TestSuiteInfo.getInstance().getTargetArchs().get(0));
+ // first check, all the abis are supported
+ for (String abi : supportedAbiApk) {
+ if (!buildTarget.contains(abi)) {
+ fail(String.format("apk %s %s does not support our abis [%s]",
+ testApk.getName(), supportedAbiApk, buildTarget));
+ }
+ }
+ apkToAbi.put(testApk.getName(), supportedAbiApk.size());
+ maxAbi = Math.max(maxAbi, supportedAbiApk.size());
+ }
+ }
+
+ // We do a second pass to make sure nobody is short on abi
+ for (Entry<String, Integer> apk : apkToAbi.entrySet()) {
+ if (apk.getValue() < maxAbi) {
+ fail(String.format("apk %s only has %s abi when it should have %s", apk.getKey(),
+ apk.getValue(), maxAbi));
+ }
+ }
+ }
+
+ /**
+ * Test that when CTS has multiple abis, we have binary for each ABI. In this case the abi will
+ * be the same with different bitness (only case supported by build system).
+ * <p/>
+ * If there is only one bitness, then we check that it's the right one.
+ */
+ @Test
+ public void testBinariesAbis() {
+ String ctsRoot = System.getProperty("CTS_ROOT");
+ File testcases = new File(ctsRoot, "/android-cts/testcases/");
+ if (!testcases.exists()) {
+ fail(String.format("%s does not exist", testcases));
+ return;
+ }
+ String[] listBinaries = testcases.list(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ if (name.contains(".")) {
+ return false;
+ }
+ if (BINARY_EXCEPTIONS.contains(name)) {
+ return false;
+ }
+ File file = new File(dir, name);
+ if (file.isDirectory()) {
+ return false;
+ }
+ if (!file.canExecute()) {
+ return false;
+ }
+ return true;
+ }
+ });
+ assertTrue(listBinaries.length > 0);
+ List<String> orderedList = Arrays.asList(listBinaries);
+ // we sort to have binary starting with same name, next to each other. The last two
+ // characters of their name with be the bitness (32 or 64).
+ Collections.sort(orderedList);
+ Set<String> buildTarget = AbiUtils.getAbisForArch(
+ TestSuiteInfo.getInstance().getTargetArchs().get(0));
+ // We expect one binary per abi of CTS, they should be appended with 32 or 64
+ for (int i = 0; i < orderedList.size(); i=i + buildTarget.size()) {
+ List<String> subSet = orderedList.subList(i, i + buildTarget.size());
+ if (subSet.size() > 1) {
+ String base = subSet.get(0).substring(0, subSet.get(0).length() - 2);
+ for (int j = 0; j < subSet.size(); j++) {
+ assertEquals(base, subSet.get(j).substring(0, subSet.get(j).length() - 2));
+ }
+ } else {
+ String bitness = AbiUtils.getBitness(buildTarget.iterator().next());
+ assertTrue(subSet.get(i).endsWith(bitness));
+ }
+ }
+ }
+}
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/tradefed/CtsTradefedTest.java b/tools/cts-tradefed/tests/src/com/android/compatibility/tradefed/CtsTradefedTest.java
index 5d5df59..8bab842 100644
--- a/tools/cts-tradefed/tests/src/com/android/compatibility/tradefed/CtsTradefedTest.java
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/tradefed/CtsTradefedTest.java
@@ -15,20 +15,27 @@
*/
package com.android.compatibility.tradefed;
+import static org.junit.Assert.assertEquals;
+
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildProvider;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.OptionSetter;
import com.android.tradefed.util.FileUtil;
-import junit.framework.TestCase;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
import java.io.File;
/**
* Tests for cts-tradefed.
*/
-public class CtsTradefedTest extends TestCase {
+@RunWith(JUnit4.class)
+public class CtsTradefedTest {
private static final String PROPERTY_NAME = "CTS_ROOT";
private static final String SUITE_FULL_NAME = "Compatibility Test Suite";
@@ -38,20 +45,19 @@
private String mOriginalProperty = null;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
mOriginalProperty = System.getProperty(PROPERTY_NAME);
}
- @Override
- protected void tearDown() throws Exception {
+ @After
+ public void tearDown() throws Exception {
if (mOriginalProperty != null) {
System.setProperty(PROPERTY_NAME, mOriginalProperty);
}
- super.tearDown();
}
+ @Test
public void testSuiteInfoLoad() throws Exception {
// Test the values in the manifest can be loaded
File root = FileUtil.createTempDir("root");
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/tradefed/CtsUnitTests.java b/tools/cts-tradefed/tests/src/com/android/compatibility/tradefed/CtsUnitTests.java
new file mode 100644
index 0000000..d989014
--- /dev/null
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/tradefed/CtsUnitTests.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 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.tradefed;
+
+import com.android.compatibility.common.tradefed.presubmit.ApkPackageNameCheck;
+import com.android.compatibility.common.tradefed.presubmit.CtsConfigLoadingTest;
+import com.android.compatibility.common.tradefed.presubmit.DupFileTest;
+import com.android.compatibility.common.tradefed.presubmit.PresubmitSetupValidation;
+import com.android.compatibility.common.tradefed.presubmit.ValidateTestsAbi;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+/**
+ * A test suite for all compatibility tradefed unit tests.
+ *
+ * <p>All tests listed here should be self-contained, and do not require any external dependencies.
+ */
+@RunWith(Suite.class)
+@SuiteClasses({
+ // base
+ CtsTradefedTest.class,
+
+ // presubmit
+ ApkPackageNameCheck.class,
+ CtsConfigLoadingTest.class,
+ DupFileTest.class,
+ PresubmitSetupValidation.class,
+ ValidateTestsAbi.class,
+})
+public class CtsUnitTests {
+ // Empty on purpose
+}