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:
Brett Chabot
2012-09-10 07:59:59 -07:00
committed by Android Git Automerger
5 changed files with 56 additions and 54 deletions

View File

@@ -1 +1,2 @@
*.pyc *.pyc
.*

View File

@@ -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.

View File

@@ -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

View File

@@ -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:

View File

@@ -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(),