diff --git a/testrunner/runtest.py b/testrunner/runtest.py index 243da77b5..b72727064 100755 --- a/testrunner/runtest.py +++ b/testrunner/runtest.py @@ -23,6 +23,7 @@ Based on previous /development/tools/runtest shell script. import glob import optparse import os +import re from sets import Set import sys @@ -58,6 +59,7 @@ class TestRunner(object): def __init__(self): # disable logging of timestamp + self._root_path = android_build.GetTop() logger.SetTimestampLogging(False) def _ProcessOptions(self): @@ -137,8 +139,6 @@ class TestRunner(object): if self._options.verbose: logger.SetVerbose(True) - self._root_path = android_build.GetTop() - self._known_tests = self._ReadTests() self._coverage_gen = coverage.CoverageGenerator( @@ -172,7 +172,7 @@ class TestRunner(object): """Prints out set of defined tests.""" print "The following tests are currently defined:" for test in self._known_tests: - print test.GetName() + print "%-15s %s" % (test.GetName(), test.GetDescription()) def _DoBuild(self): logger.SilentLog("Building tests...") @@ -261,6 +261,37 @@ class TestRunner(object): if coverage_file is not None: logger.Log("Coverage report generated at %s" % coverage_file) + def _RunNativeTest(self, test_suite): + """Run the provided *native* test suite. + + The test_suite must contain a build path where the native test files are. + Each test's name must start with 'test_' and have a .cc or .cpp extension. + A successful test must return 0. Any other value will be considered + as an error. + + Args: + test_suite: TestSuite to run + """ + # find all test files, convert unicode names to ascii, take the basename + # and drop the .cc/.cpp extension. + file_pattern = os.path.join(test_suite.GetBuildPath(), "test_*") + file_list = [] + for f in map(str, glob.glob(file_pattern)): + f = os.path.basename(f) + f = re.split(".[cp]+$", f)[0] + file_list.append(f) + + for f in file_list: + full_path = "/system/bin/%s" % f + + # Run + status = self._adb.SendShellCommand("%s >/dev/null 2>&1;echo -n $?" % + full_path) + logger.Log("%s... %s" % (f, status == "0" and "ok" or "failed")) + + # Cleanup + self._adb.SendShellCommand("rm %s" % full_path) + def RunTests(self): """Main entry method - executes the tests according to command line args.""" try: @@ -278,7 +309,10 @@ class TestRunner(object): self._DoBuild() for test_suite in self._GetTestsToRun(): - self._RunTest(test_suite) + if test_suite.IsNative(): + self._RunNativeTest(test_suite) + else: + self._RunTest(test_suite) except KeyboardInterrupt: logger.Log("Exiting...") except errors.AbortError: diff --git a/testrunner/test_defs.py b/testrunner/test_defs.py index 949ad6ef8..f7a435e95 100644 --- a/testrunner/test_defs.py +++ b/testrunner/test_defs.py @@ -38,7 +38,14 @@ class TestDefinitions(object): [class=""] [coverage_target=""] [build_path=""] - [continuous] + [continuous=false] + [description=""] + /> + @@ -48,13 +55,17 @@ class TestDefinitions(object): # tag/attribute constants _TEST_TAG_NAME = "test" + _TEST_NATIVE_TAG_NAME = "test-native" def __init__(self): # dictionary of test name to tests self._testname_map = {} def __iter__(self): - return iter(self._testname_map.values()) + ordered_list = [] + for k in sorted(self._testname_map): + ordered_list.append(self._testname_map[k]) + return iter(ordered_list) def Parse(self, file_path): """Parse the test suite data from from given file path. @@ -87,6 +98,12 @@ class TestDefinitions(object): test = self._ParseTestSuite(suite_element) self._AddTest(test) + suite_elements = doc.getElementsByTagName(self._TEST_NATIVE_TAG_NAME) + + for suite_element in suite_elements: + test = self._ParseNativeTestSuite(suite_element) + self._AddTest(test) + def _ParseTestSuite(self, suite_element): """Parse the suite element. @@ -96,6 +113,17 @@ class TestDefinitions(object): test = TestSuite(suite_element) return test + def _ParseNativeTestSuite(self, suite_element): + """Parse the native test element. + + Returns: + a TestSuite object, populated with parsed data + Raises: + ParseError if some required attribute is missing. + """ + test = TestSuite(suite_element, native=True) + return test + def _AddTest(self, test): """Adds a test to this TestManifest. @@ -129,13 +157,27 @@ class TestSuite(object): _TARGET_ATTR = "coverage_target" _BUILD_ATTR = "build_path" _CONTINUOUS_ATTR = "continuous" + _DESCRIPTION_ATTR = "description" _DEFAULT_RUNNER = "android.test.InstrumentationTestRunner" - def __init__(self, suite_element): - """Populates this instance's data from given suite xml element.""" + def __init__(self, suite_element, native=False): + """Populates this instance's data from given suite xml element. + Raises: + ParseError if some required attribute is missing. + """ + self._native = native self._name = suite_element.getAttribute(self._NAME_ATTR) - self._package = suite_element.getAttribute(self._PKG_ATTR) + + if self._native: + # For native runs, _BUILD_ATTR is required + if not suite_element.hasAttribute(self._BUILD_ATTR): + logger.Log("Error: %s is missing required build_path attribute" % + self._name) + raise errors.ParseError + else: + self._package = suite_element.getAttribute(self._PKG_ATTR) + if suite_element.hasAttribute(self._RUNNER_ATTR): self._runner = suite_element.getAttribute(self._RUNNER_ATTR) else: @@ -156,6 +198,10 @@ class TestSuite(object): self._continuous = suite_element.getAttribute(self._CONTINUOUS_ATTR) else: self._continuous = False + if suite_element.hasAttribute(self._DESCRIPTION_ATTR): + self._description = suite_element.getAttribute(self._DESCRIPTION_ATTR) + else: + self._description = "" def GetName(self): return self._name @@ -184,6 +230,13 @@ class TestSuite(object): """Returns true if test is flagged as being part of the continuous tests""" return self._continuous + def IsNative(self): + """Returns true if test is a native one.""" + return self._native + + def GetDescription(self): + return self._description + def Parse(file_path): """Parses out a TestDefinitions from given path to xml file. diff --git a/testrunner/test_defs.xml b/testrunner/test_defs.xml index d186af4c7..9007a11bf 100644 --- a/testrunner/test_defs.xml +++ b/testrunner/test_defs.xml @@ -17,32 +17,65 @@ @@ -223,4 +256,10 @@ These attributes map to the following commands: coverage_target="Settings" /> --> + + + +