test_package_apk.py revision 558790d6acca3451cf3a6b497803a5f07d0bec58
1# Copyright (c) 2012 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Defines TestPackageApk to help run APK-based native tests."""
6
7import logging
8import os
9import shlex
10import sys
11import tempfile
12import time
13
14from pylib import android_commands
15from pylib import constants
16from pylib import pexpect
17from pylib.android_commands import errors
18
19from test_package import TestPackage
20
21
22class TestPackageApk(TestPackage):
23  """A helper class for running APK-based native tests."""
24
25  def __init__(self, adb, device, suite_path_full, tool, test_apk_package_name,
26               test_activity_name, command_line_file):
27    """
28    Args:
29      adb: ADB interface the tests are using.
30      device: Device to run the tests.
31      suite_path_full: Absolute path to a specific test suite to run,
32          empty to run all.
33          Ex: '/foo/bar/base_unittests-debug.apk', for which
34            self.suite_path_full = '/foo/bar/base_unittests-debug.apk'
35            self.suite_path = '/foo/bar/base_unittests-debug'
36            self.suite_basename = 'base_unittests'
37            self.suite_dirname = '/foo/bar'
38      tool: Name of the Valgrind tool.
39      test_apk_package_name: Apk package name for tests running in APKs.
40      test_activity_name: Test activity to invoke for APK tests.
41      command_line_file: Filename to use to pass arguments to tests.
42    """
43    TestPackage.__init__(self, adb, device, suite_path_full, tool)
44    self._test_apk_package_name = test_apk_package_name
45    self._test_activity_name = test_activity_name
46    self._command_line_file = command_line_file
47
48  def _CreateCommandLineFileOnDevice(self, options):
49    command_line_file = tempfile.NamedTemporaryFile()
50    # GTest expects argv[0] to be the executable path.
51    command_line_file.write(self.suite_basename + ' ' + options)
52    command_line_file.flush()
53    self.adb.PushIfNeeded(command_line_file.name,
54                          constants.TEST_EXECUTABLE_DIR + '/' +
55                          self._command_line_file)
56
57  def _GetGTestReturnCode(self):
58    return None
59
60  def _GetFifo(self):
61    # The test.fifo path is determined by:
62    # testing/android/java/src/org/chromium/native_test/
63    #     ChromeNativeTestActivity.java and
64    # testing/android/native_test_launcher.cc
65    return '/data/data/' + self._test_apk_package_name + '/files/test.fifo'
66
67  def _ClearFifo(self):
68    self.adb.RunShellCommand('rm -f ' + self._GetFifo())
69
70  def _WatchFifo(self, timeout, logfile=None):
71    for i in range(10):
72      if self.adb.FileExistsOnDevice(self._GetFifo()):
73        logging.info('Fifo created.')
74        break
75      time.sleep(i)
76    else:
77      raise errors.DeviceUnresponsiveError(
78          'Unable to find fifo on device %s ' % self._GetFifo())
79    args = shlex.split(self.adb.Adb()._target_arg)
80    args += ['shell', 'cat', self._GetFifo()]
81    return pexpect.spawn('adb', args, timeout=timeout, logfile=logfile)
82
83  def _StartActivity(self):
84    self.adb.StartActivity(
85        self._test_apk_package_name,
86        self._test_activity_name,
87        wait_for_completion=True,
88        action='android.intent.action.MAIN',
89        force_stop=True)
90
91  def _GetTestSuiteBaseName(self):
92    """Returns the  base name of the test suite."""
93    # APK test suite names end with '-debug.apk'
94    return os.path.basename(self.suite_path).rsplit('-debug', 1)[0]
95
96  #override
97  def ClearApplicationState(self):
98    self.adb.ClearApplicationState(self._test_apk_package_name)
99
100  #override
101  def CreateCommandLineFileOnDevice(self, test_filter, test_arguments):
102    self._CreateCommandLineFileOnDevice(
103        '--gtest_filter=%s %s' % (test_filter, test_arguments))
104
105  #override
106  def GetAllTests(self):
107    self._CreateCommandLineFileOnDevice('--gtest_list_tests')
108    try:
109      self.tool.SetupEnvironment()
110      # Clear and start monitoring logcat.
111      self._ClearFifo()
112      self._StartActivity()
113      # Wait for native test to complete.
114      p = self._WatchFifo(timeout=30 * self.tool.GetTimeoutScale())
115      p.expect('<<ScopedMainEntryLogger')
116      p.close()
117    finally:
118      self.tool.CleanUpEnvironment()
119    # We need to strip the trailing newline.
120    content = [line.rstrip() for line in p.before.splitlines()]
121    return self._ParseGTestListTests(content)
122
123  #override
124  def SpawnTestProcess(self):
125    try:
126      self.tool.SetupEnvironment()
127      self._ClearFifo()
128      self._StartActivity()
129    finally:
130      self.tool.CleanUpEnvironment()
131    logfile = android_commands.NewLineNormalizer(sys.stdout)
132    return self._WatchFifo(timeout=10, logfile=logfile)
133
134  #override
135  def Install(self):
136    self.tool.CopyFiles()
137    self.adb.ManagedInstall(self.suite_path_full, False,
138                            package_name=self._test_apk_package_name)
139
140