am 08e5a8ae: Merge "Coverage and unbundling changes for runtest." into jb-mr1-dev
* commit '08e5a8ae69a8d6f9d50cc84768c85a73ddfa748f': Coverage and unbundling changes for runtest.
This commit is contained in:
1
testrunner/.gitignore
vendored
1
testrunner/.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
*.pyc
|
*.pyc
|
||||||
|
.*
|
||||||
|
|||||||
@@ -131,6 +131,17 @@ class AdbInterface:
|
|||||||
logger.Log("ADB Pull Failed: Source file %s does not exist." % src)
|
logger.Log("ADB Pull Failed: Source file %s does not exist." % src)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def Install(self, apk_path):
|
||||||
|
"""Installs apk on device.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
apk_path: file path to apk file on host
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
output of install command
|
||||||
|
"""
|
||||||
|
return self.SendCommand("install -r %s" % apk_path)
|
||||||
|
|
||||||
def DoesFileExist(self, src):
|
def DoesFileExist(self, src):
|
||||||
"""Checks if the given path exists on device target.
|
"""Checks if the given path exists on device target.
|
||||||
|
|
||||||
|
|||||||
@@ -289,25 +289,6 @@ def EnableCoverageBuild():
|
|||||||
os.environ["EMMA_INSTRUMENT"] = "true"
|
os.environ["EMMA_INSTRUMENT"] = "true"
|
||||||
|
|
||||||
|
|
||||||
def TestDeviceCoverageSupport(adb):
|
|
||||||
"""Check if device has support for generating code coverage metrics.
|
|
||||||
|
|
||||||
This tries to dump emma help information on device, a response containing
|
|
||||||
help information will indicate that emma is already on system class path.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
True if device can support code coverage. False otherwise.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
output = adb.SendShellCommand("exec app_process / emma -h")
|
|
||||||
|
|
||||||
if output.find('emma usage:') == 0:
|
|
||||||
return True
|
|
||||||
except errors.AbortError:
|
|
||||||
pass
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def Run():
|
def Run():
|
||||||
"""Does coverage operations based on command line args."""
|
"""Does coverage operations based on command line args."""
|
||||||
# TODO: do we want to support combining coverage for a single target
|
# TODO: do we want to support combining coverage for a single target
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ Do runtest --help to see full list of options.
|
|||||||
import glob
|
import glob
|
||||||
import optparse
|
import optparse
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
from sets import Set
|
from sets import Set
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
@@ -73,6 +74,13 @@ class TestRunner(object):
|
|||||||
|
|
||||||
_DALVIK_VERIFIER_OFF_PROP = "dalvik.vm.dexopt-flags = v=n"
|
_DALVIK_VERIFIER_OFF_PROP = "dalvik.vm.dexopt-flags = v=n"
|
||||||
|
|
||||||
|
# regular expression to match install: statements in make output
|
||||||
|
_RE_MAKE_INSTALL = re.compile(r'Install:\s(.+)')
|
||||||
|
|
||||||
|
# regular expression to find remote device path from a file path relative
|
||||||
|
# to build root
|
||||||
|
_RE_MAKE_INSTALL_PATH = re.compile(r'out\/target\/product\/\w+\/(.+)$')
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# disable logging of timestamp
|
# disable logging of timestamp
|
||||||
self._root_path = android_build.GetTop()
|
self._root_path = android_build.GetTop()
|
||||||
@@ -243,23 +251,11 @@ class TestRunner(object):
|
|||||||
self._adb.EnableAdbRoot()
|
self._adb.EnableAdbRoot()
|
||||||
else:
|
else:
|
||||||
logger.Log("adb root")
|
logger.Log("adb root")
|
||||||
rebuild_libcore = False
|
|
||||||
if target_set:
|
if target_set:
|
||||||
if self._options.coverage:
|
if self._options.coverage:
|
||||||
coverage.EnableCoverageBuild()
|
coverage.EnableCoverageBuild()
|
||||||
# hack to remove core library intermediates
|
target_set.append("external/emma/Android.mk")
|
||||||
# hack is needed because:
|
# TODO: detect if external/emma exists
|
||||||
# 1. EMMA_INSTRUMENT changes what source files to include in libcore
|
|
||||||
# but it does not trigger a rebuild
|
|
||||||
# 2. there's no target (like "clear-intermediates") to remove the files
|
|
||||||
# decently
|
|
||||||
rebuild_libcore = not coverage.TestDeviceCoverageSupport(self._adb)
|
|
||||||
if rebuild_libcore:
|
|
||||||
cmd = "rm -rf %s" % os.path.join(
|
|
||||||
self._root_path,
|
|
||||||
"out/target/common/obj/JAVA_LIBRARIES/core_intermediates/")
|
|
||||||
logger.Log(cmd)
|
|
||||||
run_command.RunCommand(cmd, return_output=False)
|
|
||||||
|
|
||||||
target_build_string = " ".join(target_set)
|
target_build_string = " ".join(target_set)
|
||||||
extra_args_string = " ".join(extra_args_set)
|
extra_args_string = " ".join(extra_args_set)
|
||||||
@@ -270,17 +266,38 @@ class TestRunner(object):
|
|||||||
target_build_string, self._options.make_jobs, self._root_path,
|
target_build_string, self._options.make_jobs, self._root_path,
|
||||||
extra_args_string)
|
extra_args_string)
|
||||||
logger.Log(cmd)
|
logger.Log(cmd)
|
||||||
|
if not self._options.preview:
|
||||||
|
output = run_command.RunCommand(cmd, return_output=True, timeout_time=600)
|
||||||
|
self._DoInstall(output)
|
||||||
|
|
||||||
if self._options.preview:
|
def _DoInstall(self, make_output):
|
||||||
# in preview mode, just display to the user what command would have been
|
"""Install artifacts from build onto device.
|
||||||
# run
|
|
||||||
logger.Log("adb sync")
|
Looks for 'install:' text from make output to find artifacts to install.
|
||||||
else:
|
|
||||||
# set timeout for build to 10 minutes, since libcore may need to
|
Args:
|
||||||
# be rebuilt
|
make_output: stdout from make command
|
||||||
run_command.RunCommand(cmd, return_output=False, timeout_time=600)
|
"""
|
||||||
logger.Log("Syncing to device...")
|
for line in make_output.split("\n"):
|
||||||
self._adb.Sync(runtime_restart=rebuild_libcore)
|
m = self._RE_MAKE_INSTALL.match(line)
|
||||||
|
if m:
|
||||||
|
install_path = m.group(1)
|
||||||
|
if install_path.endswith(".apk"):
|
||||||
|
abs_install_path = os.path.join(self._root_path, install_path)
|
||||||
|
logger.Log("adb install -r %s" % abs_install_path)
|
||||||
|
logger.Log(self._adb.Install(abs_install_path))
|
||||||
|
else:
|
||||||
|
self._PushInstallFileToDevice(install_path)
|
||||||
|
|
||||||
|
def _PushInstallFileToDevice(self, install_path):
|
||||||
|
m = self._RE_MAKE_INSTALL_PATH.match(install_path)
|
||||||
|
if m:
|
||||||
|
remote_path = m.group(1)
|
||||||
|
abs_install_path = os.path.join(self._root_path, install_path)
|
||||||
|
logger.Log("adb push %s %s", abs_install_path, remote_path)
|
||||||
|
self._adb.Push(abs_install_path, remote_path)
|
||||||
|
else:
|
||||||
|
logger.Log("Error: Failed to recognize path of file to install %s" % install_path)
|
||||||
|
|
||||||
def _DoFullBuild(self, tests):
|
def _DoFullBuild(self, tests):
|
||||||
"""If necessary, run a full 'make' command for the tests that need it."""
|
"""If necessary, run a full 'make' command for the tests that need it."""
|
||||||
@@ -309,8 +326,9 @@ class TestRunner(object):
|
|||||||
if not self._options.preview:
|
if not self._options.preview:
|
||||||
old_dir = os.getcwd()
|
old_dir = os.getcwd()
|
||||||
os.chdir(self._root_path)
|
os.chdir(self._root_path)
|
||||||
run_command.RunCommand(cmd, return_output=False)
|
output = run_command.RunCommand(cmd, return_output=False)
|
||||||
os.chdir(old_dir)
|
os.chdir(old_dir)
|
||||||
|
self._DoInstall(output)
|
||||||
|
|
||||||
def _AddBuildTarget(self, test_suite, target_set, extra_args_set):
|
def _AddBuildTarget(self, test_suite, target_set, extra_args_set):
|
||||||
if not test_suite.IsFullMake():
|
if not test_suite.IsFullMake():
|
||||||
@@ -369,7 +387,7 @@ class TestRunner(object):
|
|||||||
If one or more tests needs dalvik verifier off, and it is not already off,
|
If one or more tests needs dalvik verifier off, and it is not already off,
|
||||||
turns off verifier and reboots device to allow change to take effect.
|
turns off verifier and reboots device to allow change to take effect.
|
||||||
"""
|
"""
|
||||||
# hack to check if these are framework/base tests. If so, turn off verifier
|
# hack to check if these are frameworks/base tests. If so, turn off verifier
|
||||||
# to allow framework tests to access package-private framework api
|
# to allow framework tests to access package-private framework api
|
||||||
framework_test = False
|
framework_test = False
|
||||||
for test in test_list:
|
for test in test_list:
|
||||||
|
|||||||
@@ -33,9 +33,6 @@ class InstrumentationTestSuite(test_suite.AbstractTestSuite):
|
|||||||
|
|
||||||
DEFAULT_RUNNER = "android.test.InstrumentationTestRunner"
|
DEFAULT_RUNNER = "android.test.InstrumentationTestRunner"
|
||||||
|
|
||||||
# dependency on libcore (used for Emma)
|
|
||||||
_LIBCORE_BUILD_PATH = "libcore"
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
test_suite.AbstractTestSuite.__init__(self)
|
test_suite.AbstractTestSuite.__init__(self)
|
||||||
self._package_name = None
|
self._package_name = None
|
||||||
@@ -87,8 +84,6 @@ class InstrumentationTestSuite(test_suite.AbstractTestSuite):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
def GetBuildDependencies(self, options):
|
def GetBuildDependencies(self, options):
|
||||||
if options.coverage:
|
|
||||||
return [self._LIBCORE_BUILD_PATH]
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def Run(self, options, adb):
|
def Run(self, options, adb):
|
||||||
@@ -145,8 +140,6 @@ class InstrumentationTestSuite(test_suite.AbstractTestSuite):
|
|||||||
logger.Log(adb_cmd)
|
logger.Log(adb_cmd)
|
||||||
elif options.coverage:
|
elif options.coverage:
|
||||||
coverage_gen = coverage.CoverageGenerator(adb)
|
coverage_gen = coverage.CoverageGenerator(adb)
|
||||||
adb.WaitForInstrumentation(self.GetPackageName(),
|
|
||||||
self.GetRunnerName())
|
|
||||||
# need to parse test output to determine path to coverage file
|
# need to parse test output to determine path to coverage file
|
||||||
logger.Log("Running in coverage mode, suppressing test output")
|
logger.Log("Running in coverage mode, suppressing test output")
|
||||||
try:
|
try:
|
||||||
@@ -168,8 +161,6 @@ class InstrumentationTestSuite(test_suite.AbstractTestSuite):
|
|||||||
if coverage_file is not None:
|
if coverage_file is not None:
|
||||||
logger.Log("Coverage report generated at %s" % coverage_file)
|
logger.Log("Coverage report generated at %s" % coverage_file)
|
||||||
else:
|
else:
|
||||||
adb.WaitForInstrumentation(self.GetPackageName(),
|
|
||||||
self.GetRunnerName())
|
|
||||||
adb.StartInstrumentationNoResults(
|
adb.StartInstrumentationNoResults(
|
||||||
package_name=self.GetPackageName(),
|
package_name=self.GetPackageName(),
|
||||||
runner_name=self.GetRunnerName(),
|
runner_name=self.GetRunnerName(),
|
||||||
|
|||||||
Reference in New Issue
Block a user