AI 144412: am: CL 144340 Added support to run native tests on the device.
The tests name must start with 'test_'.
Tests should return 0 on success, 1 on failure.
* development/testrunner/test_defs.xml:
Added new element to represent native tests.
* development/testrunner/test_defs.py:
Added handling of the new <test-native> element.
The testsuite has new IsNative method.
TestDefinition's iterator is ordered by test names.
Added GetDescription() method to access the optional description.
* development/testrunner/runtest.py:
Print the description next to the test name if applicable
(runtest_py -l)
Added a _RunNativeTest method to run a test on the target, report
the status and clean up the test after the run.
Added
Original author: niko
Automated import of CL 144412
diff --git a/testrunner/runtest.py b/testrunner/runtest.py
index 243da77..b727270 100755
--- a/testrunner/runtest.py
+++ b/testrunner/runtest.py
@@ -23,6 +23,7 @@
import glob
import optparse
import os
+import re
from sets import Set
import sys
@@ -58,6 +59,7 @@
def __init__(self):
# disable logging of timestamp
+ self._root_path = android_build.GetTop()
logger.SetTimestampLogging(False)
def _ProcessOptions(self):
@@ -137,8 +139,6 @@
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 @@
"""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 @@
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 @@
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 949ad6e..f7a435e 100644
--- a/testrunner/test_defs.py
+++ b/testrunner/test_defs.py
@@ -38,7 +38,14 @@
[class=""]
[coverage_target=""]
[build_path=""]
- [continuous]
+ [continuous=false]
+ [description=""]
+ />
+ <test-native
+ name=""
+ build_path=""
+ [continuous=false]
+ [description=""]
/>
<test ...
</test-definitions>
@@ -48,13 +55,17 @@
# 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 @@
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 @@
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 @@
_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 @@
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 @@
"""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 d186af4..9007a11 100644
--- a/testrunner/test_defs.xml
+++ b/testrunner/test_defs.xml
@@ -17,32 +17,65 @@
<!--
This file contains standard test definitions for the Android platform
-Tests are defined by <test> tags with the following attributes
+Java tests are defined by <test> tags and native ones (C/C++) are defined by
+<test-native> tags.
-name package [class runner build_path coverage_target continuous]
+JAVA/application tests:
+=======================
+ The java <test> element has the following attributes
-Where:
-name: Self-descriptive name used to uniquely identify the test
-build_path: File system path, relative to Android build root, to this package's
- Android.mk file. If omitted, build/sync step for this test will be skipped
-package: Android application package that contains the tests
-class: Optional. Fully qualified Java test class to run.
-runner: Fully qualified InstrumentationTestRunner to execute. If omitted,
- will default to android.test.InstrumentationTestRunner
-coverage_target: Build name of Android package this test targets - these targets
- are defined in the coverage_targets.xml file. Used as basis for code
- coverage metrics. If omitted, code coverage will not be supported for this
- test
-continuous: Optional boolean. Default is false. Set to true if tests are known
- to be reliable, and should be included in a continuous test system. false if
- they are under development.
+ name package [class runner build_path coverage_target continuous description]
-These attributes map to the following commands:
-(if class is defined)
- adb shell am instrument -w <package>/<runner>
-(else)
- adb shell am instrument -w -e class <class> <package>/<runner>
+ Where:
+ name: Self-descriptive name used to uniquely identify the test
+ build_path: File system path, relative to Android build root, to this
+ package's Android.mk file. If omitted, build/sync step for this test will
+ be skipped.
+ package: Android application package that contains the tests
+ class: Optional. Fully qualified Java test class to run.
+ runner: Fully qualified InstrumentationTestRunner to execute. If omitted,
+ will default to android.test.InstrumentationTestRunner.
+ coverage_target: Build name of Android package this test targets - these
+ targets are defined in the coverage_targets.xml file. Used as basis for
+ code coverage metrics. If omitted, code coverage will not be supported for
+ this test.
+ continuous: Optional boolean. Default is false. Set to true if tests are known
+ to be reliable, and should be included in a continuous test system. false if
+ they are under development.
+ description: Optional string. Default is empty. Short description (typically
+ less than 60 characters) about this test.
+
+ These attributes map to the following commands:
+ (if class is defined)
+ adb shell am instrument -w <package>/<runner>
+ (else)
+ adb shell am instrument -w -e class <class> <package>/<runner>
+
+Native tests:
+=============
+ The <test-native> element has the following attributes
+
+ name build_path [continuous description]
+
+ Where:
+ name: Self-descriptive name used to uniquely identify the test
+ build_path: File system path, relative to Android build root, to this
+ package's Android.mk file. By convention the name of a test starts with
+ 'test_'.
+ continuous: Optional boolean. Default is false. Set to true if tests are known
+ to be reliable, and should be included in a continuous test system.
+ false if they are under development.
+ description: Optional string. Default is empty. Short description (typically
+ less than 60 characters) about this test.
+
+ These attributes map to the following commands:
+ make <build_path>/Android.mk
+ adb sync
+ for test_prog in <tests built>; do
+ adb shell "/system/bin/${test_prog} >/dev/null 2>&1;echo \$?"
+ adb shell "rm /system/bin/${test_prog}"
+ done
-->
<test-definitions version="1">
@@ -223,4 +256,10 @@
coverage_target="Settings" />
-->
+<!-- native tests -->
+<test-native name="libstdcpp"
+ build_path="system/extras/tests/bionic/libstdc++"
+ description="Bionic libstdc++." />
+
+
</test-definitions>