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