Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / build / android / pylib / gtest / test_package_apk.py
blobc7fa54f6622a5b0d742d1e80f7bd44118458bc1b
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.
5 """Defines TestPackageApk to help run APK-based native tests."""
6 # pylint: disable=W0212
8 import logging
9 import os
10 import sys
11 import time
13 from devil.android import apk_helper
14 from devil.android import device_errors
15 from devil.android.sdk import intent
16 from pylib import constants
17 from pylib import pexpect
18 from pylib.gtest import gtest_test_instance
19 from pylib.gtest.test_package import TestPackage
20 from pylib.local.device import local_device_gtest_run
23 class TestPackageApk(TestPackage):
24 """A helper class for running APK-based native tests."""
26 def __init__(self, suite_name):
27 """
28 Args:
29 suite_name: Name of the test suite (e.g. base_unittests).
30 """
31 TestPackage.__init__(self, suite_name)
32 self.suite_path = os.path.join(
33 constants.GetOutDirectory(), '%s_apk' % suite_name,
34 '%s-debug.apk' % suite_name)
35 if suite_name == 'content_browsertests':
36 self._package_info = constants.PACKAGE_INFO['content_browsertests']
37 elif suite_name == 'components_browsertests':
38 self._package_info = constants.PACKAGE_INFO['components_browsertests']
39 else:
40 self._package_info = constants.PACKAGE_INFO['gtest']
42 if suite_name == 'net_unittests':
43 self._extras = {
44 'org.chromium.native_test.NativeTestActivity.RunInSubThread': None
46 else:
47 self._extras = []
49 def _CreateCommandLineFileOnDevice(self, device, options):
50 device.WriteFile(self._package_info.cmdline_file,
51 self.suite_name + ' ' + options)
53 def _GetFifo(self):
54 # The test.fifo path is determined by:
55 # testing/android/native_test/java/src/org/chromium/native_test/
56 # NativeTestActivity.java and
57 # testing/android/native_test_launcher.cc
58 return '/data/data/' + self._package_info.package + '/files/test.fifo'
60 def _ClearFifo(self, device):
61 device.RunShellCommand('rm -f ' + self._GetFifo())
63 def _WatchFifo(self, device, timeout, logfile=None):
64 for i in range(100):
65 if device.FileExists(self._GetFifo()):
66 logging.info('Fifo created. Slept for %f secs', i * 0.5)
67 break
68 time.sleep(0.5)
69 else:
70 raise device_errors.DeviceUnreachableError(
71 'Unable to find fifo on device %s ' % self._GetFifo())
72 args = ['-s', device.adb.GetDeviceSerial(), 'shell', 'cat', self._GetFifo()]
73 return pexpect.spawn('adb', args, timeout=timeout, logfile=logfile)
75 def _StartActivity(self, device, force_stop=True):
76 device.StartActivity(
77 intent.Intent(package=self._package_info.package,
78 activity=self._package_info.activity,
79 action='android.intent.action.MAIN',
80 extras=self._extras),
81 # No wait since the runner waits for FIFO creation anyway.
82 blocking=False,
83 force_stop=force_stop)
85 #override
86 def ClearApplicationState(self, device):
87 device.ClearApplicationState(self._package_info.package)
88 # Content shell creates a profile on the sdscard which accumulates cache
89 # files over time.
90 if self.suite_name == 'content_browsertests':
91 try:
92 device.RunShellCommand(
93 'rm -r %s/content_shell' % device.GetExternalStoragePath(),
94 timeout=60 * 2)
95 except device_errors.CommandFailedError:
96 # TODO(jbudorick) Handle this exception appropriately once the
97 # conversions are done.
98 pass
99 elif self.suite_name == 'components_browsertests':
100 try:
101 device.RunShellCommand(
102 'rm -r %s/components_shell' % device.GetExternalStoragePath(),
103 timeout=60 * 2)
104 except device_errors.CommandFailedError:
105 # TODO(jbudorick) Handle this exception appropriately once the
106 # conversions are done.
107 pass
109 #override
110 def CreateCommandLineFileOnDevice(self, device, test_filter, test_arguments):
111 self._CreateCommandLineFileOnDevice(
112 device, '--gtest_filter=%s %s' % (test_filter, test_arguments))
114 #override
115 def GetAllTests(self, device):
116 self._CreateCommandLineFileOnDevice(device, '--gtest_list_tests')
117 try:
118 self.tool.SetupEnvironment()
119 # Clear and start monitoring logcat.
120 self._ClearFifo(device)
121 self._StartActivity(device)
122 # Wait for native test to complete.
123 p = self._WatchFifo(device, timeout=30 * self.tool.GetTimeoutScale())
124 p.expect('<<ScopedMainEntryLogger')
125 p.close()
126 finally:
127 self.tool.CleanUpEnvironment()
128 # We need to strip the trailing newline.
129 content = [line.rstrip() for line in p.before.splitlines()]
130 return gtest_test_instance.ParseGTestListTests(content)
132 #override
133 def SpawnTestProcess(self, device):
134 try:
135 self.tool.SetupEnvironment()
136 self._ClearFifo(device)
137 # Doesn't need to stop an Activity because ClearApplicationState() is
138 # always called before this call and so it is already stopped at this
139 # point.
140 self._StartActivity(device, force_stop=False)
141 finally:
142 self.tool.CleanUpEnvironment()
143 logfile = self._NewLineNormalizer(sys.stdout)
144 return self._WatchFifo(device, timeout=10, logfile=logfile)
146 class _NewLineNormalizer(object):
147 def __init__(self, output):
148 self._output = output
150 def write(self, data):
151 data = data.replace('\r\r\n', '\n')
152 self._output.write(data)
154 def flush(self):
155 self._output.flush()
157 #override
158 def Install(self, device):
159 self.tool.CopyFiles(device)
160 device.Install(self.suite_path)
162 #override
163 def PullAppFiles(self, device, files, directory):
164 local_device_gtest_run.PullAppFilesImpl(
165 device, self._package_info.package, files, directory)
167 #override
168 def SetPermissions(self, device):
169 permissions = apk_helper.ApkHelper(self.suite_path).GetPermissions()
170 device.GrantPermissions(
171 apk_helper.GetPackageName(self.suite_path), permissions)