OLD | NEW |
---|---|
1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import os | 5 import os |
6 import re | 6 import re |
7 import shutil | 7 import shutil |
8 import sys | 8 import sys |
9 import unittest | 9 import unittest |
10 | 10 |
11 SRC = os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir) | 11 SRC = os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir) |
12 sys.path.append(os.path.join(SRC, 'third_party', 'pymock')) | 12 sys.path.append(os.path.join(SRC, 'third_party', 'pymock')) |
13 | 13 |
14 import bisect_perf_regression | 14 import bisect_perf_regression |
15 import bisect_results | 15 import bisect_results |
16 import mock | 16 import mock |
17 import source_control as source_control_module | 17 import source_control as source_control_module |
18 | 18 |
19 | 19 |
20 def _GetBisectPerformanceMetricsInstance(): | 20 # Default options for the dry run |
21 """Returns an instance of the BisectPerformanceMetrics class.""" | 21 DEFAULT_OPTIONS = { |
22 options_dict = { | |
23 'debug_ignore_build': True, | 22 'debug_ignore_build': True, |
24 'debug_ignore_sync': True, | 23 'debug_ignore_sync': True, |
25 'debug_ignore_perf_test': True, | 24 'debug_ignore_perf_test': True, |
26 'command': 'fake_command', | 25 'command': 'fake_command', |
27 'metric': 'fake/metric', | 26 'metric': 'fake/metric', |
28 'good_revision': 280000, | 27 'good_revision': 280000, |
29 'bad_revision': 280005, | 28 'bad_revision': 280005, |
30 } | 29 } |
30 | |
31 | |
32 def _GetBisectPerformanceMetricsInstance(options_dict): | |
33 """Returns an instance of the BisectPerformanceMetrics class.""" | |
31 bisect_options = bisect_perf_regression.BisectOptions.FromDict(options_dict) | 34 bisect_options = bisect_perf_regression.BisectOptions.FromDict(options_dict) |
32 source_control = source_control_module.DetermineAndCreateSourceControl( | 35 source_control = source_control_module.DetermineAndCreateSourceControl( |
33 bisect_options) | 36 bisect_options) |
34 bisect_instance = bisect_perf_regression.BisectPerformanceMetrics( | 37 bisect_instance = bisect_perf_regression.BisectPerformanceMetrics( |
35 source_control, bisect_options) | 38 source_control, bisect_options) |
36 return bisect_instance | 39 return bisect_instance |
37 | 40 |
38 | 41 |
42 def _GetExtendedOptions(d, f): | |
43 """Returns the a copy of the default options dict plus some options.""" | |
44 result = dict(DEFAULT_OPTIONS) | |
45 result.update({ | |
46 'direction_of_improvement': d, | |
47 'debug_fake_first_test_mean': f}) | |
48 return result | |
49 | |
50 | |
51 def _GenericDryRun(options, print_results=False): | |
52 """Performs a dry run of the bisector. | |
53 | |
54 Args: | |
55 options: Dictionary containing the options for the bisect instance. | |
56 print_results: Boolean telling whether to call FormatAndPrintResults. | |
57 | |
58 Returns: | |
59 The results dictionary as returned by the bisect Run method. | |
60 """ | |
61 # Disable rmtree to avoid deleting local trees. | |
62 old_rmtree = shutil.rmtree | |
63 try: | |
64 shutil.rmtree = lambda path, onerror: None | |
65 bisect_instance = _GetBisectPerformanceMetricsInstance(options) | |
66 results = bisect_instance.Run(bisect_instance.opts.command, | |
67 bisect_instance.opts.bad_revision, | |
68 bisect_instance.opts.good_revision, | |
69 bisect_instance.opts.metric) | |
70 | |
71 if print_results: | |
72 bisect_instance.FormatAndPrintResults(results) | |
73 | |
74 return results | |
75 finally: | |
76 shutil.rmtree = old_rmtree | |
77 | |
78 | |
39 class BisectPerfRegressionTest(unittest.TestCase): | 79 class BisectPerfRegressionTest(unittest.TestCase): |
40 """Test case for other functions and classes in bisect-perf-regression.py.""" | 80 """Test case for other functions and classes in bisect-perf-regression.py.""" |
41 | 81 |
42 def setUp(self): | 82 def setUp(self): |
43 self.cwd = os.getcwd() | 83 self.cwd = os.getcwd() |
44 os.chdir(os.path.abspath(os.path.join(os.path.dirname(__file__), | 84 os.chdir(os.path.abspath(os.path.join(os.path.dirname(__file__), |
45 os.path.pardir, os.path.pardir))) | 85 os.path.pardir, os.path.pardir))) |
46 | 86 |
47 def tearDown(self): | 87 def tearDown(self): |
48 os.chdir(self.cwd) | 88 os.chdir(self.cwd) |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
254 276628, 'chromium') | 294 276628, 'chromium') |
255 | 295 |
256 # This method doesn't reference self; it fails if an error is thrown. | 296 # This method doesn't reference self; it fails if an error is thrown. |
257 # pylint: disable=R0201 | 297 # pylint: disable=R0201 |
258 def testDryRun(self): | 298 def testDryRun(self): |
259 """Does a dry run of the bisect script. | 299 """Does a dry run of the bisect script. |
260 | 300 |
261 This serves as a smoke test to catch errors in the basic execution of the | 301 This serves as a smoke test to catch errors in the basic execution of the |
262 script. | 302 script. |
263 """ | 303 """ |
264 # Disable rmtree to avoid deleting local trees. | 304 _GenericDryRun(DEFAULT_OPTIONS, True) |
265 old_rmtree = shutil.rmtree | 305 |
266 try: | 306 def testBisectImprovementDirectionFails(self): |
267 shutil.rmtree = lambda path, onerror: None | 307 """Dry run of a bisect with an improvement instead of regression. |
268 bisect_instance = _GetBisectPerformanceMetricsInstance() | 308 """ |
qyearsley
2014/10/12 03:37:11
Style nit: In general we've been putting the closi
RobertoCN
2014/10/15 18:44:44
Done.
| |
269 results = bisect_instance.Run(bisect_instance.opts.command, | 309 |
270 bisect_instance.opts.bad_revision, | 310 # Test result goes from 0 to 100 where higher is better |
271 bisect_instance.opts.good_revision, | 311 results = _GenericDryRun(_GetExtendedOptions(1, 100)) |
272 bisect_instance.opts.metric) | 312 self.assertIsNotNone(results.error) |
273 bisect_instance.FormatAndPrintResults(results) | 313 self.assertIn('does not represent a regression', results.error) |
274 finally: | 314 # Test result goes from 0 to -100 where lower is better |
275 shutil.rmtree = old_rmtree | 315 results = _GenericDryRun(_GetExtendedOptions(-1, -100)) |
316 self.assertIsNotNone(results.error) | |
317 self.assertIn('does not represent a regression', results.error) | |
318 | |
319 def testBisectImprovementDirectionSucceeds(self): | |
320 """Bisects with improvement direction matching regression range. | |
321 """ | |
322 # Test result goes from 0 to 100 where lower is better | |
323 results = _GenericDryRun(_GetExtendedOptions(-1, 100)) | |
324 self.assertIsNone(results.error) | |
325 # Test result goes from 0 to -100 where higher is better | |
326 results = _GenericDryRun(_GetExtendedOptions(1, -100)) | |
327 self.assertIsNone(results.error) | |
328 | |
276 | 329 |
277 def testGetCommitPosition(self): | 330 def testGetCommitPosition(self): |
278 bisect_instance = _GetBisectPerformanceMetricsInstance() | 331 bisect_instance = _GetBisectPerformanceMetricsInstance(DEFAULT_OPTIONS) |
279 cp_git_rev = '7017a81991de983e12ab50dfc071c70e06979531' | 332 cp_git_rev = '7017a81991de983e12ab50dfc071c70e06979531' |
280 self.assertEqual( | 333 self.assertEqual( |
281 291765, bisect_instance.source_control.GetCommitPosition(cp_git_rev)) | 334 291765, bisect_instance.source_control.GetCommitPosition(cp_git_rev)) |
282 | 335 |
283 svn_git_rev = 'e6db23a037cad47299a94b155b95eebd1ee61a58' | 336 svn_git_rev = 'e6db23a037cad47299a94b155b95eebd1ee61a58' |
284 self.assertEqual( | 337 self.assertEqual( |
285 291467, bisect_instance.source_control.GetCommitPosition(svn_git_rev)) | 338 291467, bisect_instance.source_control.GetCommitPosition(svn_git_rev)) |
286 | 339 |
287 def testGetCommitPositionForV8(self): | 340 def testGetCommitPositionForV8(self): |
288 bisect_instance = _GetBisectPerformanceMetricsInstance() | 341 bisect_instance = _GetBisectPerformanceMetricsInstance(DEFAULT_OPTIONS) |
289 v8_rev = '21d700eedcdd6570eff22ece724b63a5eefe78cb' | 342 v8_rev = '21d700eedcdd6570eff22ece724b63a5eefe78cb' |
290 depot_path = os.path.join(bisect_instance.src_cwd, 'v8') | 343 depot_path = os.path.join(bisect_instance.src_cwd, 'v8') |
291 self.assertEqual( | 344 self.assertEqual( |
292 23634, | 345 23634, |
293 bisect_instance.source_control.GetCommitPosition(v8_rev, depot_path)) | 346 bisect_instance.source_control.GetCommitPosition(v8_rev, depot_path)) |
294 | 347 |
295 def testGetCommitPositionForWebKit(self): | 348 def testGetCommitPositionForWebKit(self): |
296 bisect_instance = _GetBisectPerformanceMetricsInstance() | 349 bisect_instance = _GetBisectPerformanceMetricsInstance(DEFAULT_OPTIONS) |
297 wk_rev = 'a94d028e0f2c77f159b3dac95eb90c3b4cf48c61' | 350 wk_rev = 'a94d028e0f2c77f159b3dac95eb90c3b4cf48c61' |
298 depot_path = os.path.join(bisect_instance.src_cwd, 'third_party', 'WebKit') | 351 depot_path = os.path.join(bisect_instance.src_cwd, 'third_party', 'WebKit') |
299 self.assertEqual( | 352 self.assertEqual( |
300 181660, | 353 181660, |
301 bisect_instance.source_control.GetCommitPosition(wk_rev, depot_path)) | 354 bisect_instance.source_control.GetCommitPosition(wk_rev, depot_path)) |
302 | 355 |
303 def testUpdateDepsContent(self): | 356 def testUpdateDepsContent(self): |
304 bisect_instance = _GetBisectPerformanceMetricsInstance() | 357 bisect_instance = _GetBisectPerformanceMetricsInstance(DEFAULT_OPTIONS) |
305 deps_file = 'DEPS' | 358 deps_file = 'DEPS' |
306 # We are intentionally reading DEPS file contents instead of string literal | 359 # We are intentionally reading DEPS file contents instead of string literal |
307 # with few lines from DEPS because to check if the format we are expecting | 360 # with few lines from DEPS because to check if the format we are expecting |
308 # to search is not changed in DEPS content. | 361 # to search is not changed in DEPS content. |
309 # TODO (prasadv): Add a separate test to validate the DEPS contents with the | 362 # TODO (prasadv): Add a separate test to validate the DEPS contents with the |
310 # format that bisect script expects. | 363 # format that bisect script expects. |
311 deps_contents = bisect_perf_regression.ReadStringFromFile(deps_file) | 364 deps_contents = bisect_perf_regression.ReadStringFromFile(deps_file) |
312 deps_key = 'v8_revision' | 365 deps_key = 'v8_revision' |
313 depot = 'v8' | 366 depot = 'v8' |
314 git_revision = 'a12345789a23456789a123456789a123456789' | 367 git_revision = 'a12345789a23456789a123456789a123456789' |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
500 '--diff=%s' % patch_content | 553 '--diff=%s' % patch_content |
501 ], (None, 0)) | 554 ], (None, 0)) |
502 ] | 555 ] |
503 self._SetupRunGitMock(try_cmd) | 556 self._SetupRunGitMock(try_cmd) |
504 bisect_perf_regression._BuilderTryjob( | 557 bisect_perf_regression._BuilderTryjob( |
505 git_revision, bot_name, bisect_job_name, patch) | 558 git_revision, bot_name, bisect_job_name, patch) |
506 | 559 |
507 | 560 |
508 if __name__ == '__main__': | 561 if __name__ == '__main__': |
509 unittest.main() | 562 unittest.main() |
OLD | NEW |