OSDN Git Service

code coverage improvement (DO NOT MERGE)
authorGuang Zhu <guangzhu@google.com>
Thu, 15 Apr 2010 17:48:26 +0000 (10:48 -0700)
committerGuang Zhu <guangzhu@google.com>
Tue, 18 May 2010 17:54:47 +0000 (10:54 -0700)
* automatically detect if emma is on device
* build emma into libcore if necessary
* stop runtime before adb sync and restart afterwards

Change-Id: Id5087fdd6c0345f2b9b76658a5083b9260af061e

testrunner/adb_interface.py
testrunner/coverage.py
testrunner/runtest.py
testrunner/test_defs/instrumentation_test.py

index 698ea8b..ea9188c 100755 (executable)
@@ -355,13 +355,44 @@ class AdbInterface:
           "in test_defs.xml?" % instrumentation_path)
       raise errors.WaitForResponseTimedOutError()
 
-  def Sync(self, retry_count=3):
+  def WaitForBootComplete(self, wait_time=120):
+    """Waits for targeted device's bootcomplete flag to be set.
+
+    Args:
+      wait_time: time in seconds to wait
+
+    Raises:
+      WaitForResponseTimedOutError if wait_time elapses and pm still does not
+      respond.
+    """
+    logger.Log("Waiting for boot complete...")
+    self.SendCommand("wait-for-device")
+    # Now the device is there, but may not be running.
+    # Query the package manager with a basic command
+    boot_complete = False
+    attempts = 0
+    wait_period = 5
+    while not boot_complete and (attempts*wait_period) < wait_time:
+      output = self.SendShellCommand("getprop dev.bootcomplete", retry_count=1)
+      output = output.strip()
+      if output == "1":
+        boot_complete = True
+      else:
+        time.sleep(wait_period)
+        attempts += 1
+    if not boot_complete:
+      raise errors.WaitForResponseTimedOutError(
+          "dev.bootcomplete flag was not set after %s seconds" % wait_time)
+
+  def Sync(self, retry_count=3, runtime_restart=False):
     """Perform a adb sync.
 
     Blocks until device package manager is responding.
 
     Args:
       retry_count: number of times to retry sync before failing
+      runtime_restart: stop runtime during sync and restart afterwards, useful
+        for syncing system libraries (core, framework etc)
 
     Raises:
       WaitForResponseTimedOutError if package manager does not respond
@@ -369,6 +400,13 @@ class AdbInterface:
     """
     output = ""
     error = None
+    if runtime_restart:
+      self.SendShellCommand("setprop ro.monkey 1", retry_count=retry_count)
+      # manual rest bootcomplete flag
+      self.SendShellCommand("setprop dev.bootcomplete 0",
+                            retry_count=retry_count)
+      self.SendShellCommand("stop", retry_count=retry_count)
+
     try:
       output = self.SendCommand("sync", retry_count=retry_count)
     except errors.AbortError, e:
@@ -389,10 +427,17 @@ class AdbInterface:
       # exception occurred that cannot be recovered from
       raise error
     logger.SilentLog(output)
-    self.WaitForDevicePm()
+    if runtime_restart:
+      # start runtime and wait till boot complete flag is set
+      self.SendShellCommand("start", retry_count=retry_count)
+      self.WaitForBootComplete()
+      # press the MENU key, this will disable key guard if runtime is started
+      # with ro.monkey set to 1
+      self.SendShellCommand("input keyevent 82", retry_count=retry_count)
+    else:
+      self.WaitForDevicePm()
     return output
 
   def GetSerialNumber(self):
     """Returns the serial number of the targeted device."""
     return self.SendCommand("get-serialno").strip()
-
index 52e8a8c..4322e26 100755 (executable)
@@ -62,28 +62,6 @@ class CoverageGenerator(object):
     self._adb = adb_interface
     self._targets_manifest = self._ReadTargets()
 
-  def TestDeviceCoverageSupport(self):
-    """Check if device has support for generating code coverage metrics.
-
-    Currently this will check if the emma.jar file is on the device's boot
-    classpath.
-
-    Returns:
-      True if device can support code coverage. False otherwise.
-    """
-    try:
-      output = self._adb.SendShellCommand("cat init.rc | grep BOOTCLASSPATH | "
-                                          "grep emma.jar")
-      if len(output) > 0:
-        return True
-    except errors.AbortError:
-      pass
-    logger.Log("Error: Targeted device does not have emma.jar on its "
-               "BOOTCLASSPATH.")
-    logger.Log("Modify the BOOTCLASSPATH entry in system/core/rootdir/init.rc"
-               " to add emma.jar")
-    return False
-
   def ExtractReport(self, test_suite,
                     device_coverage_path,
                     output_path=None,
@@ -311,6 +289,25 @@ def EnableCoverageBuild():
   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():
   """Does coverage operations based on command line args."""
   # TODO: do we want to support combining coverage for a single target
index d53312f..5bea81a 100755 (executable)
@@ -157,7 +157,6 @@ class TestRunner(object):
     group.add_option("-s", "--serial", dest="serial",
                      help="use specific serial")
     parser.add_option_group(group)
-
     self._options, self._test_args = parser.parse_args()
 
     if (not self._options.only_list_tests
@@ -228,9 +227,23 @@ class TestRunner(object):
     for test_suite in tests:
       self._AddBuildTarget(test_suite, target_set, extra_args_set)
 
+    rebuild_libcore = False
     if target_set:
       if self._options.coverage:
         coverage.EnableCoverageBuild()
+        # hack to remove core library intermediates
+        # hack is needed because:
+        # 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)
 
       # hack to build cts dependencies
       # TODO: remove this when build dependency support added to runtest or
@@ -259,9 +272,11 @@ class TestRunner(object):
         # run
         logger.Log("adb sync")
       else:
-        run_command.RunCommand(cmd, return_output=False)
+        # set timeout for build to 10 minutes, since libcore may need to
+        # be rebuilt
+        run_command.RunCommand(cmd, return_output=False, timeout_time=600)
         logger.Log("Syncing to device...")
-        self._adb.Sync()
+        self._adb.Sync(runtime_restart=rebuild_libcore)
 
   def _AddBuildTarget(self, test_suite, target_set, extra_args_set):
     build_dir = test_suite.GetBuildPath()
index f0a8656..8782615 100644 (file)
@@ -32,8 +32,8 @@ class InstrumentationTestSuite(test_suite.AbstractTestSuite):
 
   DEFAULT_RUNNER = "android.test.InstrumentationTestRunner"
 
-    # build path to Emma target Makefile
-  _EMMA_BUILD_PATH = os.path.join("external", "emma")
+  # dependency on libcore (used for Emma)
+  _LIBCORE_BUILD_PATH = "libcore"
 
   def __init__(self):
     test_suite.AbstractTestSuite.__init__(self)
@@ -87,7 +87,7 @@ class InstrumentationTestSuite(test_suite.AbstractTestSuite):
 
   def GetBuildDependencies(self, options):
     if options.coverage:
-      return [self._EMMA_BUILD_PATH]
+      return [self._LIBCORE_BUILD_PATH]
     return []
 
   def Run(self, options, adb):
@@ -144,8 +144,6 @@ class InstrumentationTestSuite(test_suite.AbstractTestSuite):
       logger.Log(adb_cmd)
     elif options.coverage:
       coverage_gen = coverage.CoverageGenerator(adb)
-      if not coverage_gen.TestDeviceCoverageSupport():
-        raise errors.AbortError
       adb.WaitForInstrumentation(self.GetPackageName(),
                                  self.GetRunnerName())
       # need to parse test output to determine path to coverage file