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 | 17 import source_control |
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 bisect_instance = bisect_perf_regression.BisectPerformanceMetrics( | 35 bisect_instance = bisect_perf_regression.BisectPerformanceMetrics( |
33 bisect_options) | 36 bisect_options) |
34 return bisect_instance | 37 return bisect_instance |
35 | 38 |
36 | 39 |
| 40 def _GetExtendedOptions(d, f): |
| 41 """Returns the a copy of the default options dict plus some options.""" |
| 42 result = dict(DEFAULT_OPTIONS) |
| 43 result.update({ |
| 44 'improvement_direction': d, |
| 45 'debug_fake_first_test_mean': f}) |
| 46 return result |
| 47 |
| 48 |
| 49 def _GenericDryRun(options, print_results=False): |
| 50 """Performs a dry run of the bisector. |
| 51 |
| 52 Args: |
| 53 options: Dictionary containing the options for the bisect instance. |
| 54 print_results: Boolean telling whether to call FormatAndPrintResults. |
| 55 |
| 56 Returns: |
| 57 The results dictionary as returned by the bisect Run method. |
| 58 """ |
| 59 # Disable rmtree to avoid deleting local trees. |
| 60 old_rmtree = shutil.rmtree |
| 61 try: |
| 62 shutil.rmtree = lambda path, onerror: None |
| 63 bisect_instance = _GetBisectPerformanceMetricsInstance(options) |
| 64 results = bisect_instance.Run(bisect_instance.opts.command, |
| 65 bisect_instance.opts.bad_revision, |
| 66 bisect_instance.opts.good_revision, |
| 67 bisect_instance.opts.metric) |
| 68 |
| 69 if print_results: |
| 70 bisect_instance.FormatAndPrintResults(results) |
| 71 |
| 72 return results |
| 73 finally: |
| 74 shutil.rmtree = old_rmtree |
| 75 |
| 76 |
37 class BisectPerfRegressionTest(unittest.TestCase): | 77 class BisectPerfRegressionTest(unittest.TestCase): |
38 """Test case for other functions and classes in bisect-perf-regression.py.""" | 78 """Test case for other functions and classes in bisect-perf-regression.py.""" |
39 | 79 |
40 def setUp(self): | 80 def setUp(self): |
41 self.cwd = os.getcwd() | 81 self.cwd = os.getcwd() |
42 os.chdir(os.path.abspath(os.path.join(os.path.dirname(__file__), | 82 os.chdir(os.path.abspath(os.path.join(os.path.dirname(__file__), |
43 os.path.pardir, os.path.pardir))) | 83 os.path.pardir, os.path.pardir))) |
44 | 84 |
45 def tearDown(self): | 85 def tearDown(self): |
46 os.chdir(self.cwd) | 86 os.chdir(self.cwd) |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 276628, 'chromium') | 290 276628, 'chromium') |
251 | 291 |
252 # This method doesn't reference self; it fails if an error is thrown. | 292 # This method doesn't reference self; it fails if an error is thrown. |
253 # pylint: disable=R0201 | 293 # pylint: disable=R0201 |
254 def testDryRun(self): | 294 def testDryRun(self): |
255 """Does a dry run of the bisect script. | 295 """Does a dry run of the bisect script. |
256 | 296 |
257 This serves as a smoke test to catch errors in the basic execution of the | 297 This serves as a smoke test to catch errors in the basic execution of the |
258 script. | 298 script. |
259 """ | 299 """ |
260 # Disable rmtree to avoid deleting local trees. | 300 _GenericDryRun(DEFAULT_OPTIONS, True) |
261 old_rmtree = shutil.rmtree | 301 |
262 try: | 302 def testBisectImprovementDirectionFails(self): |
263 shutil.rmtree = lambda path, onerror: None | 303 """Dry run of a bisect with an improvement instead of regression.""" |
264 bisect_instance = _GetBisectPerformanceMetricsInstance() | 304 |
265 results = bisect_instance.Run(bisect_instance.opts.command, | 305 # Test result goes from 0 to 100 where higher is better |
266 bisect_instance.opts.bad_revision, | 306 results = _GenericDryRun(_GetExtendedOptions(1, 100)) |
267 bisect_instance.opts.good_revision, | 307 self.assertIsNotNone(results.error) |
268 bisect_instance.opts.metric) | 308 self.assertIn('not a regression', results.error) |
269 bisect_instance.FormatAndPrintResults(results) | 309 # Test result goes from 0 to -100 where lower is better |
270 finally: | 310 results = _GenericDryRun(_GetExtendedOptions(-1, -100)) |
271 shutil.rmtree = old_rmtree | 311 self.assertIsNotNone(results.error) |
| 312 self.assertIn('not a regression', results.error) |
| 313 |
| 314 def testBisectImprovementDirectionSucceeds(self): |
| 315 """Bisects with improvement direction matching regression range.""" |
| 316 # Test result goes from 0 to 100 where lower is better |
| 317 results = _GenericDryRun(_GetExtendedOptions(-1, 100)) |
| 318 self.assertIsNone(results.error) |
| 319 # Test result goes from 0 to -100 where higher is better |
| 320 results = _GenericDryRun(_GetExtendedOptions(1, -100)) |
| 321 self.assertIsNone(results.error) |
| 322 |
272 | 323 |
273 def testGetCommitPosition(self): | 324 def testGetCommitPosition(self): |
274 cp_git_rev = '7017a81991de983e12ab50dfc071c70e06979531' | 325 cp_git_rev = '7017a81991de983e12ab50dfc071c70e06979531' |
275 self.assertEqual(291765, source_control.GetCommitPosition(cp_git_rev)) | 326 self.assertEqual(291765, source_control.GetCommitPosition(cp_git_rev)) |
276 | 327 |
277 svn_git_rev = 'e6db23a037cad47299a94b155b95eebd1ee61a58' | 328 svn_git_rev = 'e6db23a037cad47299a94b155b95eebd1ee61a58' |
278 self.assertEqual(291467, source_control.GetCommitPosition(svn_git_rev)) | 329 self.assertEqual(291467, source_control.GetCommitPosition(svn_git_rev)) |
279 | 330 |
280 def testGetCommitPositionForV8(self): | 331 def testGetCommitPositionForV8(self): |
281 bisect_instance = _GetBisectPerformanceMetricsInstance() | 332 bisect_instance = _GetBisectPerformanceMetricsInstance(DEFAULT_OPTIONS) |
282 v8_rev = '21d700eedcdd6570eff22ece724b63a5eefe78cb' | 333 v8_rev = '21d700eedcdd6570eff22ece724b63a5eefe78cb' |
283 depot_path = os.path.join(bisect_instance.src_cwd, 'v8') | 334 depot_path = os.path.join(bisect_instance.src_cwd, 'v8') |
284 self.assertEqual( | 335 self.assertEqual( |
285 23634, source_control.GetCommitPosition(v8_rev, depot_path)) | 336 23634, source_control.GetCommitPosition(v8_rev, depot_path)) |
286 | 337 |
287 def testGetCommitPositionForWebKit(self): | 338 def testGetCommitPositionForWebKit(self): |
288 bisect_instance = _GetBisectPerformanceMetricsInstance() | 339 bisect_instance = _GetBisectPerformanceMetricsInstance(DEFAULT_OPTIONS) |
289 wk_rev = 'a94d028e0f2c77f159b3dac95eb90c3b4cf48c61' | 340 wk_rev = 'a94d028e0f2c77f159b3dac95eb90c3b4cf48c61' |
290 depot_path = os.path.join(bisect_instance.src_cwd, 'third_party', 'WebKit') | 341 depot_path = os.path.join(bisect_instance.src_cwd, 'third_party', 'WebKit') |
291 self.assertEqual( | 342 self.assertEqual( |
292 181660, source_control.GetCommitPosition(wk_rev, depot_path)) | 343 181660, source_control.GetCommitPosition(wk_rev, depot_path)) |
293 | 344 |
294 def testUpdateDepsContent(self): | 345 def testUpdateDepsContent(self): |
295 bisect_instance = _GetBisectPerformanceMetricsInstance() | 346 bisect_instance = _GetBisectPerformanceMetricsInstance(DEFAULT_OPTIONS) |
296 deps_file = 'DEPS' | 347 deps_file = 'DEPS' |
297 # We are intentionally reading DEPS file contents instead of string literal | 348 # We are intentionally reading DEPS file contents instead of string literal |
298 # with few lines from DEPS because to check if the format we are expecting | 349 # with few lines from DEPS because to check if the format we are expecting |
299 # to search is not changed in DEPS content. | 350 # to search is not changed in DEPS content. |
300 # TODO (prasadv): Add a separate test to validate the DEPS contents with the | 351 # TODO (prasadv): Add a separate test to validate the DEPS contents with the |
301 # format that bisect script expects. | 352 # format that bisect script expects. |
302 deps_contents = bisect_perf_regression.ReadStringFromFile(deps_file) | 353 deps_contents = bisect_perf_regression.ReadStringFromFile(deps_file) |
303 deps_key = 'v8_revision' | 354 deps_key = 'v8_revision' |
304 depot = 'v8' | 355 depot = 'v8' |
305 git_revision = 'a12345789a23456789a123456789a123456789' | 356 git_revision = 'a12345789a23456789a123456789a123456789' |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
491 '--diff=%s' % patch_content | 542 '--diff=%s' % patch_content |
492 ], (None, 0)) | 543 ], (None, 0)) |
493 ] | 544 ] |
494 self._SetupRunGitMock(try_cmd) | 545 self._SetupRunGitMock(try_cmd) |
495 bisect_perf_regression._BuilderTryjob( | 546 bisect_perf_regression._BuilderTryjob( |
496 git_revision, bot_name, bisect_job_name, patch) | 547 git_revision, bot_name, bisect_job_name, patch) |
497 | 548 |
498 | 549 |
499 if __name__ == '__main__': | 550 if __name__ == '__main__': |
500 unittest.main() | 551 unittest.main() |
OLD | NEW |