Merge "Handle timeout in test runner"
diff --git a/harnesses/tradefed/src/com/android/compatibility/common/tradefed/targetprep/HidlProfilerPreparer.java b/harnesses/tradefed/src/com/android/compatibility/common/tradefed/targetprep/HidlProfilerPreparer.java
index 46dc357..4ee9a0c 100644
--- a/harnesses/tradefed/src/com/android/compatibility/common/tradefed/targetprep/HidlProfilerPreparer.java
+++ b/harnesses/tradefed/src/com/android/compatibility/common/tradefed/targetprep/HidlProfilerPreparer.java
@@ -46,7 +46,7 @@
* This is used when one wants to do such setup and cleanup operations in Java instead of the
* VTS Python runner, Python test template, or Python test case.
*/
-@OptionClass(alias = "push-file")
+@OptionClass(alias = "hidl-profiler-preparer")
public class HidlProfilerPreparer implements ITargetCleaner, IAbiReceiver {
private static final String LOG_TAG = "HidlProfilerPreparer";
diff --git a/runners/target/vts_hal_hidl_target/Android.bp b/runners/target/vts_hal_hidl_target/Android.bp
index c570060..8fa0675 100644
--- a/runners/target/vts_hal_hidl_target/Android.bp
+++ b/runners/target/vts_hal_hidl_target/Android.bp
@@ -18,7 +18,8 @@
name: "VtsHalHidlTargetTestBase",
srcs : [
"VtsHalHidlTargetTestBase.cpp",
- "VtsHalHidlTargetCallbackBase.cpp"
+ "VtsHalHidlTargetCallbackBase.cpp",
+ "VtsHalHidlTargetTestEnvBase.cpp"
],
shared_libs: [
diff --git a/runners/target/vts_hal_hidl_target/VtsHalHidlTargetTestBase.cpp b/runners/target/vts_hal_hidl_target/VtsHalHidlTargetTestBase.cpp
index 6755719..f07026e 100644
--- a/runners/target/vts_hal_hidl_target/VtsHalHidlTargetTestBase.cpp
+++ b/runners/target/vts_hal_hidl_target/VtsHalHidlTargetTestBase.cpp
@@ -22,7 +22,7 @@
namespace testing {
-std::string VtsHalHidlTargetTestBase::PropertyGet(const char* name) {
+string VtsHalHidlTargetTestBase::PropertyGet(const char* name) {
char value[PROP_VALUE_MAX] = {0};
__system_property_get(name, value);
return value;
diff --git a/runners/target/vts_hal_hidl_target/VtsHalHidlTargetTestEnvBase.cpp b/runners/target/vts_hal_hidl_target/VtsHalHidlTargetTestEnvBase.cpp
new file mode 100644
index 0000000..b402f8f
--- /dev/null
+++ b/runners/target/vts_hal_hidl_target/VtsHalHidlTargetTestEnvBase.cpp
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+#include "VtsHalHidlTargetTestEnvBase.h"
+
+#include <string>
+
+#include <utils/Log.h>
+
+#define LOG_TAG "VtsHalHidlTargetTestEnvBase"
+
+static constexpr const char* kListFlag = "--list_registered_services";
+static constexpr const char* kServceInstanceFlag = "--hal_service_instance";
+
+using namespace std;
+
+namespace testing {
+
+void VtsHalHidlTargetTestEnvBase::SetUp() {
+ if (!inited_) {
+ ALOGE("Environment not inited, did you forget to call init()?");
+ abort();
+ }
+ // Register services used in the test.
+ registerTestServices();
+ // For a dummy run which just print the registered hal services.
+ if (listService_) {
+ listRegisteredServices();
+ exit(0);
+ }
+ // Call the customized setup process.
+ HidlSetUp();
+}
+
+void VtsHalHidlTargetTestEnvBase::TearDown() {
+ // Call the customized teardown process.
+ HidlTearDown();
+}
+
+void VtsHalHidlTargetTestEnvBase::init(int* argc, char** argv) {
+ if (inited_) return;
+ for (int i = 1; i < *argc; i++) {
+ if (parseVtsTestOption(argv[i])) {
+ // Shift the remainder of the argv list left by one.
+ for (int j = i; j != *argc; j++) {
+ argv[j] = argv[j + 1];
+ }
+
+ // Decrements the argument count.
+ (*argc)--;
+
+ // We also need to decrement the iterator as we just removed an element.
+ i--;
+ }
+ }
+ inited_ = true;
+}
+
+bool VtsHalHidlTargetTestEnvBase::parseVtsTestOption(const char* arg) {
+ // str and flag must not be NULL.
+ if (arg == NULL) return false;
+
+ if (strncmp(arg, kListFlag, strlen(kListFlag)) == 0) {
+ listService_ = true;
+ return true;
+ }
+
+ if (strncmp(arg, kServceInstanceFlag, strlen(kServceInstanceFlag)) == 0) {
+ // value is the past after "--hal_service_instance="
+ const char* value = arg + strlen(kServceInstanceFlag) + 1;
+ addHalServiceInstance(string(value));
+ return true;
+ }
+ return false;
+}
+
+void VtsHalHidlTargetTestEnvBase::addHalServiceInstance(
+ string halServiceInstance) {
+ // hal_service_instance follows the format:
+ // package@version::interface/service_name e.g.:
+ // android.hardware.vibrator@1.0::IVibrator/default
+ string instance_name =
+ halServiceInstance.substr(0, halServiceInstance.find('/'));
+ string service_name =
+ halServiceInstance.substr(halServiceInstance.find('/') + 1);
+ // Fail the process if trying to pass multiple service names for the same
+ // service instance.
+ if (halServiceInstances_.find(instance_name) != halServiceInstances_.end()) {
+ ALOGE("Exisitng instance %s with name %s", instance_name.c_str(),
+ halServiceInstances_[instance_name].c_str());
+ abort();
+ }
+ halServiceInstances_[instance_name] = service_name;
+}
+
+string VtsHalHidlTargetTestEnvBase::getServiceName(string instanceName) {
+ if (halServiceInstances_.find(instanceName) != halServiceInstances_.end()) {
+ return halServiceInstances_[instanceName];
+ }
+ // Could not find the instance.
+ return "";
+}
+
+void VtsHalHidlTargetTestEnvBase::registerTestService(string package,
+ string version,
+ string interfaceName) {
+ string FQName = package + '@' + version + "::" + interfaceName;
+ registeredHalServices_.insert(FQName);
+}
+
+void VtsHalHidlTargetTestEnvBase::listRegisteredServices() {
+ for (string service : registeredHalServices_) {
+ printf("hal_service: %s\n", service.c_str());
+ }
+}
+
+} // namespace testing
diff --git a/runners/target/vts_hal_hidl_target/VtsHalHidlTargetTestEnvBase.h b/runners/target/vts_hal_hidl_target/VtsHalHidlTargetTestEnvBase.h
new file mode 100644
index 0000000..2740ccd
--- /dev/null
+++ b/runners/target/vts_hal_hidl_target/VtsHalHidlTargetTestEnvBase.h
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+#ifndef __VTS_HAL_HIDL_TARGET_TEST_ENV_BASE_H
+#define __VTS_HAL_HIDL_TARGET_TEST_ENV_BASE_H
+
+#include <gtest/gtest.h>
+
+using namespace std;
+
+namespace testing {
+
+// A class for test environment setup
+class VtsHalHidlTargetTestEnvBase : public ::testing::Environment {
+ public:
+ VtsHalHidlTargetTestEnvBase() {}
+
+ /*
+ * SetUp process, should not be overridden by the test.
+ */
+ void SetUp() final;
+
+ /*
+ * TearDown process, should not be overridden by the test.
+ */
+ void TearDown() final;
+
+ /*
+ * Test should override this method for any custom setup process.
+ */
+ virtual void HidlSetUp() {}
+
+ /*
+ * Test should override this method for any custom teardown process.
+ */
+ virtual void HidlTearDown() {}
+
+ /*
+ * Test should override this method to register hal services used in the test.
+ */
+ virtual void registerTestServices() {}
+
+ /* Parses the command line argument, extracts the vts reserved flags and
+ * leaves other options untouched.
+ * Must be called when the test environment is created is registered.
+ */
+ void init(int* argc, char** argv);
+
+ /*
+ * Gets the service name for a hal instance. Returns empty string if the hal
+ * instance is unkonwn (not in hal_instances_).
+ */
+ string getServiceName(string instanceName);
+
+ /*
+ * Adds a hal sevice identified with the package_name, version and
+ * interface name into registeredHalServices_.
+ */
+ void registerTestService(string package, string version,
+ string interfaceName);
+
+ private:
+ /*
+ * Parses VTS specific flags, currently support two flags:
+ * --list_registered_services to print all registered service.
+ * --hal_service_instance to pass a running service instance. e.g.
+ * --hal_service_instance=android.hardware.vibrator@1.0::IVibrator/default
+ * It is possible to have mulitple --hal_service_instance options passed if
+ * mutliple hal service is used in the test.
+ * Returns true if successfully pased the given arg, false if arg is null or
+ * unknown flag.
+ */
+ bool parseVtsTestOption(const char* arg);
+
+ /*
+ * Prints all registered sercives.
+ */
+ void listRegisteredServices();
+
+ /*
+ * Internal method to add a hal service instance.
+ */
+ void addHalServiceInstance(string halServiceInstance);
+
+ // Map of hal instances with their correpoding service names.
+ map<string, string> halServiceInstances_;
+ // Set of all hal services used in the test.
+ set<string> registeredHalServices_;
+ // Flag to print registered hal services and exit the process.
+ bool listService_ = false;
+ // Flag whether init is called.
+ bool inited_ = false;
+};
+
+} // namespace testing
+
+#endif // __VTS_HAL_HIDL_TARGET_TEST_ENV_BASE_H
\ No newline at end of file
diff --git a/testcases/template/gtest_binary_test/gtest_binary_test.py b/testcases/template/gtest_binary_test/gtest_binary_test.py
index c919130..12bbef2 100644
--- a/testcases/template/gtest_binary_test/gtest_binary_test.py
+++ b/testcases/template/gtest_binary_test/gtest_binary_test.py
@@ -78,7 +78,7 @@
ld_library_path = self.ld_library_path[
tag] if tag in self.ld_library_path else None
profiling_library_path = self.profiling_library_path[
- tag] if tag in self.ld_library_path else None
+ tag] if tag in self.profiling_library_path else None
args += " --gtest_list_tests"
list_test_case = binary_test_case.BinaryTestCase(
diff --git a/testcases/template/hal_hidl_gtest/hal_hidl_gtest.py b/testcases/template/hal_hidl_gtest/hal_hidl_gtest.py
index 9236f42..554b919 100644
--- a/testcases/template/hal_hidl_gtest/hal_hidl_gtest.py
+++ b/testcases/template/hal_hidl_gtest/hal_hidl_gtest.py
@@ -14,13 +14,14 @@
# limitations under the License.
#
+import copy
import logging
from vts.runners.host import const
from vts.runners.host import keys
from vts.runners.host import test_runner
from vts.testcases.template.gtest_binary_test import gtest_binary_test
-
+from vts.testcases.template.gtest_binary_test import gtest_test_case
from vts.utils.python.cpu import cpu_frequency_scaling
@@ -72,6 +73,107 @@
if passthrough_opt or self.coverage.enabled:
self._EnablePassthroughMode()
+ # @Override
+ def CreateTestCase(self, path, tag=''):
+ '''Create a list of GtestTestCase objects from a binary path.
+
+ Support testing against different service names by first executing a
+ dummpy test case which lists all the registered hal services. Then
+ query the service name(s) for each registered service with lshal.
+ For each service name, create a new test case each with the service
+ name as an additional argument.
+
+ Args:
+ path: string, absolute path of a gtest binary on device
+ tag: string, a tag that will be appended to the end of test name
+
+ Returns:
+ A list of GtestTestCase objects.
+ '''
+ initial_test_cases = super(HidlHalGTest, self).CreateTestCase(path,
+ tag)
+ if not initial_test_cases:
+ return initial_test_cases
+ # first, run one test with --list_registered_services.
+ list_service_test_case = copy.copy(initial_test_cases[0])
+ list_service_test_case.args += " --list_registered_services"
+ results = self.shell.Execute(list_service_test_case.GetRunCommand())
+ if (results[const.EXIT_CODE][0]):
+ logging.error('Failed to list test cases from binary %s',
+ list_service_test_case.path)
+ # parse the results to get the registered service list.
+ registered_services = []
+ for line in results[const.STDOUT][0].split('\n'):
+ line = str(line)
+ if line.startswith('hal_service: '):
+ service = line[len('hal_service: '):]
+ registered_services.append(service)
+
+ # If no service registered, return the initial test cases directly.
+ if not registered_services:
+ return initial_test_cases
+
+ # find the correponding service name(s) for each registered service and
+ # store the mapping in dict service_instances.
+ service_instances = {}
+ for service in registered_services:
+ cmd = '"lshal -i | grep -o %s/.* | sort -u"' % service
+ out = str(self._dut.adb.shell(cmd)).split()
+ service_names = map(lambda x: x[x.find('/') + 1:], out)
+ logging.info("registered service: %s with name: %s" %
+ (service, ' '.join(service_names)))
+ service_instances[service] = service_names
+
+ # get all the combination of service instances.
+ service_instance_combinations = self._GetServiceInstancesCombinations(
+ registered_services, service_instances)
+
+ new_test_cases = []
+ for test_case in initial_test_cases:
+ for instance_combination in service_instance_combinations:
+ new_test_case = copy.copy(test_case)
+ for instance in instance_combination:
+ new_test_case.args += " --hal_service_instance=" + instance
+ new_test_case.tag = instance[instance.find(
+ '/'):] + new_test_case.tag
+ new_test_cases.append(new_test_case)
+ return new_test_cases
+
+ @classmethod
+ def _GetServiceInstancesCombinations(self, services, service_instances):
+ '''Create all combinations of instances for all services.
+
+ Args:
+ services: list, all services used in the test. e.g. [s1, s2]
+ service_instances: dictionary, mapping of each service and the
+ corresponding service name(s).
+ e.g. {"s1": ["n1"], "s2": ["n2", "n3"]}
+
+ Returns:
+ A list of all service instance combinations.
+ e.g. [[s1/n1, s2/n2], [s1/n1, s2/n3]]
+ '''
+
+ service_instance_combinations = []
+ if not services:
+ return service_instance_combinations
+ service = services.pop()
+ pre_instance_combs = self._GetServiceInstancesCombinations(
+ services, service_instances)
+ if service not in service_instances:
+ return pre_instance_combs
+ for name in service_instances[service]:
+ if not pre_instance_combs:
+ new_instance_comb = [service + '/' + name]
+ service_instance_combinations.append(new_instance_comb)
+ else:
+ for instance_comb in pre_instance_combs:
+ new_instance_comb = [service + '/' + name]
+ new_instance_comb.extend(instance_comb)
+ service_instance_combinations.append(new_instance_comb)
+
+ return service_instance_combinations
+
def _EnablePassthroughMode(self):
"""Enable passthrough mode by setting getStub to true.
@@ -94,21 +196,20 @@
super(HidlHalGTest, self).setUp()
if (self._skip_if_thermal_throttling and
- getattr(self, "_cpu_freq", None)):
+ getattr(self, "_cpu_freq", None)):
self._cpu_freq.SkipIfThermalThrottling(retry_delay_secs=30)
def tearDown(self):
"""Skips the test case if there is thermal throttling."""
if (self._skip_if_thermal_throttling and
- getattr(self, "_cpu_freq", None)):
+ getattr(self, "_cpu_freq", None)):
self._cpu_freq.SkipIfThermalThrottling()
super(HidlHalGTest, self).tearDown()
def tearDownClass(self):
"""Turns off CPU frequency scaling."""
- if (not self._skip_all_testcases and
- getattr(self, "_cpu_freq", None)):
+ if (not self._skip_all_testcases and getattr(self, "_cpu_freq", None)):
logging.info("Enable CPU frequency scaling")
self._cpu_freq.EnableCpuScaling()
diff --git a/testcases/template/hal_hidl_gtest/hal_hidl_gtest_unittest.py b/testcases/template/hal_hidl_gtest/hal_hidl_gtest_unittest.py
new file mode 100644
index 0000000..bde230e
--- /dev/null
+++ b/testcases/template/hal_hidl_gtest/hal_hidl_gtest_unittest.py
@@ -0,0 +1,54 @@
+#
+# 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.
+#
+
+import unittest
+
+from vts.testcases.template.hal_hidl_gtest import hal_hidl_gtest
+
+class HidlHalGTestUnitTest(unittest.TestCase):
+ """Tests for hal hidl gtest template"""
+
+ def testGetServiceInstancesCombinations(self):
+ """Test the function to get service instance combinations"""
+
+ comb1 = hal_hidl_gtest.HidlHalGTest._GetServiceInstancesCombinations(
+ [], {})
+ self.assertEquals(0, len(comb1))
+ comb2 = hal_hidl_gtest.HidlHalGTest._GetServiceInstancesCombinations(
+ ["s1"], {})
+ self.assertEquals(0, len(comb2))
+ comb3 = hal_hidl_gtest.HidlHalGTest._GetServiceInstancesCombinations(
+ ["s1"], {"s1": ["n1"]})
+ self.assertEqual([["s1/n1"]], comb3)
+ comb4 = hal_hidl_gtest.HidlHalGTest._GetServiceInstancesCombinations(
+ ["s1"], {"s1": ["n1", "n2"]})
+ self.assertEqual([["s1/n1"], ["s1/n2"]], comb4)
+ comb5 = hal_hidl_gtest.HidlHalGTest._GetServiceInstancesCombinations(
+ ["s1", "s2"], {"s1": ["n1", "n2"]})
+ self.assertEqual([["s1/n1"], ["s1/n2"]], comb5)
+ comb6 = hal_hidl_gtest.HidlHalGTest._GetServiceInstancesCombinations(
+ ["s1", "s2"], {"s1": ["n1", "n2"],
+ "s2": ["n3"]})
+ self.assertEqual([["s2/n3", "s1/n1"], ["s2/n3", "s1/n2"]], comb6)
+ comb7 = hal_hidl_gtest.HidlHalGTest._GetServiceInstancesCombinations(
+ ["s1", "s2"], {"s1": ["n1", "n2"],
+ "s2": ["n3", "n4"]})
+ self.assertEqual([["s2/n3", "s1/n1"], ["s2/n3", "s1/n2"],
+ ["s2/n4", "s1/n1"], ["s2/n4", "s1/n2"]], comb7)
+
+
+if __name__ == '__main__':
+ unittest.main()