OLD | NEW |
| (Empty) |
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 # pylint: disable=W0212 | |
7 | |
8 import logging | |
9 import os | |
10 import sys | |
11 import time | |
12 | |
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 | |
21 | |
22 | |
23 class TestPackageApk(TestPackage): | |
24 """A helper class for running APK-based native tests.""" | |
25 | |
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'] | |
41 | |
42 if suite_name == 'net_unittests': | |
43 self._extras = { | |
44 'org.chromium.native_test.NativeTestActivity.RunInSubThread': None | |
45 } | |
46 else: | |
47 self._extras = [] | |
48 | |
49 def _CreateCommandLineFileOnDevice(self, device, options): | |
50 device.WriteFile(self._package_info.cmdline_file, | |
51 self.suite_name + ' ' + options) | |
52 | |
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' | |
59 | |
60 def _ClearFifo(self, device): | |
61 device.RunShellCommand('rm -f ' + self._GetFifo()) | |
62 | |
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) | |
74 | |
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) | |
84 | |
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 | |
108 | |
109 #override | |
110 def CreateCommandLineFileOnDevice(self, device, test_filter, test_arguments): | |
111 self._CreateCommandLineFileOnDevice( | |
112 device, '--gtest_filter=%s %s' % (test_filter, test_arguments)) | |
113 | |
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) | |
131 | |
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) | |
145 | |
146 class _NewLineNormalizer(object): | |
147 def __init__(self, output): | |
148 self._output = output | |
149 | |
150 def write(self, data): | |
151 data = data.replace('\r\r\n', '\n') | |
152 self._output.write(data) | |
153 | |
154 def flush(self): | |
155 self._output.flush() | |
156 | |
157 #override | |
158 def Install(self, device): | |
159 self.tool.CopyFiles(device) | |
160 device.Install(self.suite_path) | |
161 | |
162 #override | |
163 def PullAppFiles(self, device, files, directory): | |
164 local_device_gtest_run.PullAppFilesImpl( | |
165 device, self._package_info.package, files, directory) | |
166 | |
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) | |
OLD | NEW |