Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: build/android/single_test_runner.py

Issue 8364020: Upstream: Test scripts for Android (phase 2) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: sync again Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « build/android/run_tests_helper.py ('k') | build/android/test_package.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import logging
7 import os
8 import sys
9
10 from base_test_runner import BaseTestRunner
11 import debug_info
12 import run_tests_helper
13 from test_package_executable import TestPackageExecutable
14 from test_result import TestResults
15
16
17 class SingleTestRunner(BaseTestRunner):
18 """Single test suite attached to a single device.
19
20 Args:
21 device: Device to run the tests.
22 test_suite: A specific test suite to run, empty to run all.
23 gtest_filter: A gtest_filter flag.
24 test_arguments: Additional arguments to pass to the test binary.
25 timeout: Timeout for each test.
26 rebaseline: Whether or not to run tests in isolation and update the filter.
27 performance_test: Whether or not performance test(s).
28 cleanup_test_files: Whether or not to cleanup test files on device.
29 tool: Name of the Valgrind tool.
30 dump_debug_info: Whether or not to dump debug information.
31 """
32
33 def __init__(self, device, test_suite, gtest_filter, test_arguments, timeout,
34 rebaseline, performance_test, cleanup_test_files, tool,
35 dump_debug_info=False):
36 BaseTestRunner.__init__(self, device)
37 self._running_on_emulator = self.device.startswith('emulator')
38 self._gtest_filter = gtest_filter
39 self._test_arguments = test_arguments
40 self.test_results = TestResults()
41 if dump_debug_info:
42 self.dump_debug_info = debug_info.GTestDebugInfo(self.adb, device,
43 os.path.basename(test_suite), gtest_filter)
44 else:
45 self.dump_debug_info = None
46
47 self.test_package = TestPackageExecutable(self.adb, device,
48 test_suite, timeout, rebaseline, performance_test, cleanup_test_files,
49 tool, self.dump_debug_info)
50
51 def _GetHttpServerDocumentRootForTestSuite(self):
52 """Returns the document root needed by the test suite."""
53 if self.test_package.test_suite_basename == 'page_cycler_tests':
54 return os.path.join(run_tests_helper.CHROME_DIR, 'data', 'page_cycler')
55 return None
56
57
58 def _TestSuiteRequiresMockTestServer(self):
59 """Returns True if the test suite requires mock test server."""
60 return False
61 # TODO(yfriedman): Disabled because of flakiness.
62 # (self.test_package.test_suite_basename == 'unit_tests' or
63 # self.test_package.test_suite_basename == 'net_unittests' or
64 # False)
65
66 def _GetFilterFileName(self):
67 """Returns the filename of gtest filter."""
68 filter_dir = os.path.join(sys.path[0], 'gtest_filter')
69 filter_name = self.test_package.test_suite_basename + '_disabled'
70 disabled_filter = os.path.join(filter_dir, filter_name)
71 return disabled_filter
72
73 def _GetAdditionalEmulatorFilterName(self):
74 """Returns the filename of additional gtest filter for emulator."""
75 filter_dir = os.path.join(sys.path[0], 'gtest_filter')
76 filter_name = '%s%s' % (self.test_package.test_suite_basename,
77 '_emulator_additional_disabled')
78 disabled_filter = os.path.join(filter_dir, filter_name)
79 return disabled_filter
80
81 def GetDisabledTests(self):
82 """Returns a list of disabled tests.
83
84 Returns:
85 A list of disabled tests obtained from gtest_filter/test_suite_disabled.
86 """
87 disabled_tests = run_tests_helper.GetExpectations(self._GetFilterFileName())
88 if self._running_on_emulator:
89 # Append emulator's filter file.
90 disabled_tests.extend(run_tests_helper.GetExpectations(
91 self._GetAdditionalEmulatorFilterName()))
92 return disabled_tests
93
94 def UpdateFilter(self, failed_tests):
95 """Updates test_suite_disabled file with the new filter (deletes if empty).
96
97 If running in Emulator, only the failed tests which are not in the normal
98 filter returned by _GetFilterFileName() are written to emulator's
99 additional filter file.
100
101 Args:
102 failed_tests: A sorted list of failed tests.
103 """
104 disabled_tests = []
105 if not self._running_on_emulator:
106 filter_file_name = self._GetFilterFileName()
107 else:
108 filter_file_name = self._GetAdditionalEmulatorFilterName()
109 disabled_tests.extend(
110 run_tests_helper.GetExpectations(self._GetFilterFileName()))
111 logging.info('About to update emulator\'s addtional filter (%s).'
112 % filter_file_name)
113
114 new_failed_tests = []
115 if failed_tests:
116 for test in failed_tests:
117 if test.name not in disabled_tests:
118 new_failed_tests.append(test.name)
119
120 if not new_failed_tests:
121 if os.path.exists(filter_file_name):
122 os.unlink(filter_file_name)
123 return
124
125 filter_file = file(filter_file_name, 'w')
126 if self._running_on_emulator:
127 filter_file.write('# Addtional list of suppressions from emulator\n')
128 else:
129 filter_file.write('# List of suppressions\n')
130 filter_file.write("""This file was automatically generated by run_tests.py
131 """)
132 filter_file.write('\n'.join(sorted(new_failed_tests)))
133 filter_file.write('\n')
134 filter_file.close()
135
136 def GetDataFilesForTestSuite(self):
137 """Returns a list of data files/dirs needed by the test suite."""
138 # Ideally, we'd just push all test data. However, it has >100MB, and a lot
139 # of the files are not relevant (some are used for browser_tests, others for
140 # features not supported, etc..).
141 if self.test_package.test_suite_basename in ['base_unittests',
142 'sql_unittests',
143 'unit_tests']:
144 return [
145 'net/data/cache_tests/insert_load1',
146 'net/data/cache_tests/dirty_entry5',
147 'ui/base/test/data/data_pack_unittest',
148 'chrome/test/data/bookmarks/History_with_empty_starred',
149 'chrome/test/data/bookmarks/History_with_starred',
150 'chrome/test/data/extensions/json_schema_test.js',
151 'chrome/test/data/History/',
152 'chrome/test/data/json_schema_validator/',
153 'chrome/test/data/serializer_nested_test.js',
154 'chrome/test/data/serializer_test.js',
155 'chrome/test/data/serializer_test_nowhitespace.js',
156 'chrome/test/data/top_sites/',
157 'chrome/test/data/web_database',
158 'chrome/test/data/zip',
159 ]
160 elif self.test_package.test_suite_basename == 'net_unittests':
161 return [
162 'net/data/cache_tests',
163 'net/data/filter_unittests',
164 'net/data/ftp',
165 'net/data/proxy_resolver_v8_unittest',
166 'net/data/ssl/certificates',
167 ]
168 elif self.test_package.test_suite_basename == 'ui_tests':
169 return [
170 'chrome/test/data/dromaeo',
171 'chrome/test/data/json2.js',
172 'chrome/test/data/sunspider',
173 'chrome/test/data/v8_benchmark',
174 'chrome/test/ui/sunspider_uitest.js',
175 'chrome/test/ui/v8_benchmark_uitest.js',
176 ]
177 elif self.test_package.test_suite_basename == 'page_cycler_tests':
178 data = [
179 'tools/page_cycler',
180 'data/page_cycler',
181 ]
182 for d in data:
183 if not os.path.exists(d):
184 raise Exception('Page cycler data not found.')
185 return data
186 elif self.test_package.test_suite_basename == 'webkit_unit_tests':
187 return [
188 'third_party/WebKit/Source/WebKit/chromium/tests/data',
189 ]
190 return []
191
192 def LaunchHelperToolsForTestSuite(self):
193 """Launches helper tools for the test suite.
194
195 Sometimes one test may need to run some helper tools first in order to
196 successfully complete the test.
197 """
198 document_root = self._GetHttpServerDocumentRootForTestSuite()
199 if document_root:
200 self.LaunchTestHttpServer(document_root)
201 if self._TestSuiteRequiresMockTestServer():
202 self.LaunchChromeTestServerSpawner()
203
204 def StripAndCopyFiles(self):
205 """Strips and copies the required data files for the test suite."""
206 self.test_package.StripAndCopyExecutable()
207 self.test_package.tool.CopyFiles()
208 test_data = self.GetDataFilesForTestSuite()
209 if test_data:
210 if self.test_package.test_suite_basename == 'page_cycler_tests':
211 # Since the test data for page cycler are huge (around 200M), we use
212 # sdcard to store the data and create symbol links to map them to
213 # data/local/tmp/ later.
214 self.CopyTestData(test_data, '/sdcard/')
215 for p in [os.path.dirname(d) for d in test_data if os.path.isdir(d)]:
216 mapped_device_path = '/data/local/tmp/' + p
217 # Unlink the mapped_device_path at first in case it was mapped to
218 # a wrong path. Add option '-r' becuase the old path could be a dir.
219 self.adb.RunShellCommand('rm -r %s' % mapped_device_path)
220 self.adb.RunShellCommand(
221 'ln -s /sdcard/%s %s' % (p, mapped_device_path))
222 else:
223 self.CopyTestData(test_data, '/data/local/tmp/')
224
225 def RunTestsWithFilter(self):
226 """Runs a tests via a small, temporary shell script."""
227 self.test_package.CreateTestRunnerScript(self._gtest_filter,
228 self._test_arguments)
229 self.test_results = self.test_package.RunTestsAndListResults()
230
231 def RebaselineTests(self):
232 """Runs all available tests, restarting in case of failures."""
233 if self._gtest_filter:
234 all_tests = set(self._gtest_filter.split(':'))
235 else:
236 all_tests = set(self.test_package.GetAllTests())
237 failed_results = set()
238 executed_results = set()
239 while True:
240 executed_names = set([f.name for f in executed_results])
241 self._gtest_filter = ':'.join(all_tests - executed_names)
242 self.RunTestsWithFilter()
243 failed_results.update(self.test_results.crashed,
244 self.test_results.failed)
245 executed_results.update(self.test_results.crashed,
246 self.test_results.failed,
247 self.test_results.ok)
248 executed_names = set([f.name for f in executed_results])
249 logging.info('*' * 80)
250 logging.info(self.device)
251 logging.info('Executed: ' + str(len(executed_names)) + ' of ' +
252 str(len(all_tests)))
253 logging.info('Failed so far: ' + str(len(failed_results)) + ' ' +
254 str([f.name for f in failed_results]))
255 logging.info('Remaining: ' + str(len(all_tests - executed_names)) + ' ' +
256 str(all_tests - executed_names))
257 logging.info('*' * 80)
258 if executed_names == all_tests:
259 break
260 self.test_results = TestResults.FromOkAndFailed(list(executed_results -
261 failed_results),
262 list(failed_results))
263
264 def _RunTestsForSuiteInternal(self):
265 """Runs all tests (in rebaseline mode, run each test in isolation).
266
267 Returns:
268 A TestResults object.
269 """
270 if self.test_package.rebaseline:
271 self.RebaselineTests()
272 else:
273 if not self._gtest_filter:
274 self._gtest_filter = ('-' + ':'.join(self.GetDisabledTests()) + ':' +
275 ':'.join(['*.' + x + '*' for x in
276 self.test_package.GetDisabledPrefixes()]))
277 self.RunTestsWithFilter()
278
279 def SetUp(self):
280 """Sets up necessary test enviroment for the test suite."""
281 super(SingleTestRunner, self).SetUp()
282 if self.test_package.performance_test:
283 if run_tests_helper.IsRunningAsBuildbot():
284 self.adb.SetJavaAssertsEnabled(enable=False)
285 self.adb.Reboot(full_reboot=False)
286 self.adb.SetupPerformanceTest()
287 if self.dump_debug_info:
288 self.dump_debug_info.StartRecordingLog(True)
289 self.StripAndCopyFiles()
290 self.LaunchHelperToolsForTestSuite()
291 self.test_package.tool.SetupEnvironment()
292
293 def TearDown(self):
294 """Cleans up the test enviroment for the test suite."""
295 super(SingleTestRunner, self).TearDown()
296 self.test_package.tool.CleanUpEnvironment()
297 if self.test_package.cleanup_test_files:
298 self.adb.RemovePushedFiles()
299 if self.dump_debug_info:
300 self.dump_debug_info.StopRecordingLog()
301 if self.test_package.performance_test:
302 self.adb.TearDownPerformanceTest()
303
304 def RunTests(self):
305 """Runs the tests and cleans up the files once finished.
306
307 Returns:
308 A TestResults object.
309 """
310 self.SetUp()
311 try:
312 self._RunTestsForSuiteInternal()
313 finally:
314 self.TearDown()
315 return self.test_results
OLDNEW
« no previous file with comments | « build/android/run_tests_helper.py ('k') | build/android/test_package.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698