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 math | 5 import math |
6 import unittest | 6 import unittest |
7 | 7 |
| 8 from auto_bisect import source_control as source_control_module |
| 9 |
8 # Special import necessary because filename contains dash characters. | 10 # Special import necessary because filename contains dash characters. |
9 bisect_perf_module = __import__('bisect-perf-regression') | 11 bisect_perf_module = __import__('bisect-perf-regression') |
10 | 12 |
11 | 13 # Sample output for a performance test used in the results parsing tests below. |
12 RESULTS_OUTPUT = """RESULT write_operations: write_operations= 23089 count | 14 RESULTS_OUTPUT = """RESULT write_operations: write_operations= 23089 count |
13 RESULT read_bytes_gpu: read_bytes_gpu= 35201 kb | 15 RESULT read_bytes_gpu: read_bytes_gpu= 35201 kb |
14 RESULT write_bytes_gpu: write_bytes_gpu= 542 kb | 16 RESULT write_bytes_gpu: write_bytes_gpu= 542 kb |
15 RESULT telemetry_page_measurement_results: num_failed= 0 count | 17 RESULT telemetry_page_measurement_results: num_failed= 0 count |
16 RESULT telemetry_page_measurement_results: num_errored= 0 count | 18 RESULT telemetry_page_measurement_results: num_errored= 0 count |
17 *RESULT Total: Total_ref= %(value)s | 19 *RESULT Total: Total_ref= %(value)s |
18 """ | 20 """ |
19 | 21 |
20 | 22 |
21 class BisectPerfRegressionTest(unittest.TestCase): | 23 class BisectPerfRegressionTest(unittest.TestCase): |
22 """Test case for top-level functions in the bisect-perf-regrssion module.""" | 24 """Test case for top-level functions in the bisect-perf-regrssion module.""" |
23 | 25 |
24 def setUp(self): | 26 def setUp(self): |
25 """Sets up the test environment before each test method.""" | 27 """Sets up the test environment before each test method.""" |
26 pass | 28 pass |
27 | 29 |
28 def tearDown(self): | 30 def tearDown(self): |
29 """Cleans up the test environment after each test method.""" | 31 """Cleans up the test environment after each test method.""" |
30 pass | 32 pass |
31 | 33 |
| 34 def testConfidenceScore(self): |
| 35 """Tests the confidence calculation.""" |
| 36 bad_values = [[0, 1], [1, 2]] |
| 37 good_values = [[6, 7], [7, 8]] |
| 38 # Closest means are mean(1, 2) and mean(6, 7). |
| 39 distance = 6.5 - 1.5 |
| 40 # Standard deviation of [n-1, n, n, n+1] is 0.8165. |
| 41 stddev_sum = 0.8165 + 0.8165 |
| 42 # Expected confidence is an int in the range [0, 100]. |
| 43 expected_confidence = min(100, int(100 * distance / float(stddev_sum))) |
| 44 self.assertEqual( |
| 45 expected_confidence, |
| 46 bisect_perf_module.ConfidenceScore(bad_values, good_values)) |
| 47 |
| 48 def testConfidenceScoreZeroConfidence(self): |
| 49 """Tests the confidence calculation when it's expected to be 0.""" |
| 50 bad_values = [[0, 1], [1, 2], [4, 5], [0, 2]] |
| 51 good_values = [[4, 5], [6, 7], [7, 8]] |
| 52 # Both groups have value lists with means of 4.5, which means distance |
| 53 # between groups is zero, and thus confidence is zero. |
| 54 self.assertEqual( |
| 55 0, bisect_perf_module.ConfidenceScore(bad_values, good_values)) |
| 56 |
| 57 def testConfidenceScoreMaxConfidence(self): |
| 58 """Tests the confidence calculation when it's expected to be 100.""" |
| 59 bad_values = [[1, 1], [1, 1]] |
| 60 good_values = [[1.2, 1.2], [1.2, 1.2]] |
| 61 # Standard deviation in both groups is zero, so confidence is 100. |
| 62 self.assertEqual( |
| 63 100, bisect_perf_module.ConfidenceScore(bad_values, good_values)) |
| 64 |
32 def testParseDEPSStringManually(self): | 65 def testParseDEPSStringManually(self): |
33 """Tests DEPS parsing.""" | 66 """Tests DEPS parsing.""" |
34 bisect_options = bisect_perf_module.BisectOptions() | 67 bisect_options = bisect_perf_module.BisectOptions() |
35 bisect_instance = bisect_perf_module.BisectPerformanceMetrics( | 68 bisect_instance = bisect_perf_module.BisectPerformanceMetrics( |
36 None, bisect_options) | 69 None, bisect_options) |
37 | 70 |
38 deps_file_contents = """ | 71 deps_file_contents = """ |
39 vars = { | 72 vars = { |
40 'ffmpeg_hash': | 73 'ffmpeg_hash': |
41 '@ac4a9f31fe2610bd146857bbd55d7a260003a888', | 74 '@ac4a9f31fe2610bd146857bbd55d7a260003a888', |
(...skipping 11 matching lines...) Expand all Loading... |
53 # filtered out. | 86 # filtered out. |
54 expected_vars_dict = { | 87 expected_vars_dict = { |
55 'ffmpeg_hash': '@ac4a9f31fe2610bd146857bbd55d7a260003a888', | 88 'ffmpeg_hash': '@ac4a9f31fe2610bd146857bbd55d7a260003a888', |
56 'webkit_rev': '@e01ac0a267d1017288bc67fa3c366b10469d8a24', | 89 'webkit_rev': '@e01ac0a267d1017288bc67fa3c366b10469d8a24', |
57 'angle_revision': '74697cf2064c0a2c0d7e1b1b28db439286766a05' | 90 'angle_revision': '74697cf2064c0a2c0d7e1b1b28db439286766a05' |
58 } | 91 } |
59 vars_dict = bisect_instance._ParseRevisionsFromDEPSFileManually( | 92 vars_dict = bisect_instance._ParseRevisionsFromDEPSFileManually( |
60 deps_file_contents) | 93 deps_file_contents) |
61 self.assertEqual(vars_dict, expected_vars_dict) | 94 self.assertEqual(vars_dict, expected_vars_dict) |
62 | 95 |
63 def testCalculateTruncatedMeanRaisesError(self): | |
64 """CalculateTrunctedMean raises an error when passed an empty list.""" | |
65 with self.assertRaises(TypeError): | |
66 bisect_perf_module.CalculateTruncatedMean([], 0) | |
67 | |
68 def testCalculateMeanSingleNum(self): | |
69 """Tests the CalculateMean function with a single number.""" | |
70 self.assertEqual(3.0, bisect_perf_module.CalculateMean([3])) | |
71 | |
72 def testCalculateMeanShortList(self): | |
73 """Tests the CalculateMean function with a short list.""" | |
74 self.assertEqual(0.5, bisect_perf_module.CalculateMean([-3, 0, 1, 4])) | |
75 | |
76 def testCalculateMeanCompareAlternateImplementation(self): | |
77 """Tests CalculateMean by comparing against an alternate implementation.""" | |
78 def AlternateMeanFunction(values): | |
79 """Simple arithmetic mean function.""" | |
80 return sum(values) / float(len(values)) | |
81 test_values_lists = [[1], [5, 6.5, 1.2, 3], [-3, 0, 1, 4], | |
82 [-3, -1, 0.12, 0.752, 3.33, 8, 16, 32, 439]] | |
83 for values in test_values_lists: | |
84 self.assertEqual( | |
85 AlternateMeanFunction(values), | |
86 bisect_perf_module.CalculateMean(values)) | |
87 | |
88 def testCalculateConfidence(self): | |
89 """Tests the confidence calculation.""" | |
90 bad_values = [[0, 1], [1, 2]] | |
91 good_values = [[6, 7], [7, 8]] | |
92 # Closest means are mean(1, 2) and mean(6, 7). | |
93 distance = 6.5 - 1.5 | |
94 # Standard deviation of [n-1, n, n, n+1] is 0.8165. | |
95 stddev_sum = 0.8165 + 0.8165 | |
96 # Expected confidence is an int in the range [0, 100]. | |
97 expected_confidence = min(100, int(100 * distance / float(stddev_sum))) | |
98 self.assertEqual( | |
99 expected_confidence, | |
100 bisect_perf_module.CalculateConfidence(bad_values, good_values)) | |
101 | |
102 def testCalculateConfidence0(self): | |
103 """Tests the confidence calculation when it's expected to be 0.""" | |
104 bad_values = [[0, 1], [1, 2], [4, 5], [0, 2]] | |
105 good_values = [[4, 5], [6, 7], [7, 8]] | |
106 # Both groups have value lists with means of 4.5, which means distance | |
107 # between groups is zero, and thus confidence is zero. | |
108 self.assertEqual( | |
109 0, bisect_perf_module.CalculateConfidence(bad_values, good_values)) | |
110 | |
111 def testCalculateConfidence100(self): | |
112 """Tests the confidence calculation when it's expected to be 100.""" | |
113 bad_values = [[1, 1], [1, 1]] | |
114 good_values = [[1.2, 1.2], [1.2, 1.2]] | |
115 # Standard deviation in both groups is zero, so confidence is 100. | |
116 self.assertEqual( | |
117 100, bisect_perf_module.CalculateConfidence(bad_values, good_values)) | |
118 | |
119 def testCalculateRelativeChange(self): | |
120 """Tests the common cases for calculating relative change.""" | |
121 # The change is relative to the first value, regardless of which is bigger. | |
122 self.assertEqual(0.5, bisect_perf_module.CalculateRelativeChange(1.0, 1.5)) | |
123 self.assertEqual(0.5, bisect_perf_module.CalculateRelativeChange(2.0, 1.0)) | |
124 | |
125 def testCalculateRelativeChangeFromZero(self): | |
126 """Tests what happens when relative change from zero is calculated.""" | |
127 # If the first number is zero, then the result is not a number. | |
128 self.assertEqual(0, bisect_perf_module.CalculateRelativeChange(0, 0)) | |
129 self.assertTrue( | |
130 math.isnan(bisect_perf_module.CalculateRelativeChange(0, 1))) | |
131 self.assertTrue( | |
132 math.isnan(bisect_perf_module.CalculateRelativeChange(0, -1))) | |
133 | |
134 def testCalculateRelativeChangeWithNegatives(self): | |
135 """Tests that relative change given is always positive.""" | |
136 self.assertEqual(3.0, bisect_perf_module.CalculateRelativeChange(-1, 2)) | |
137 self.assertEqual(3.0, bisect_perf_module.CalculateRelativeChange(1, -2)) | |
138 self.assertEqual(1.0, bisect_perf_module.CalculateRelativeChange(-1, -2)) | |
139 | |
140 def testTryParseResultValuesFromOutputWithSingleValue(self): | 96 def testTryParseResultValuesFromOutputWithSingleValue(self): |
141 """Tests result pattern <*>RESULT <graph>: <trace>= <value>""" | 97 """Tests result pattern <*>RESULT <graph>: <trace>= <value>""" |
142 bisect_options = bisect_perf_module.BisectOptions() | 98 bisect_options = bisect_perf_module.BisectOptions() |
143 bisect_instance = bisect_perf_module.BisectPerformanceMetrics( | 99 bisect_instance = bisect_perf_module.BisectPerformanceMetrics( |
144 None, bisect_options) | 100 None, bisect_options) |
145 metrics = ['Total', 'Total_ref'] | 101 metrics = ['Total', 'Total_ref'] |
146 self.assertEqual( | 102 self.assertEqual( |
147 [66.88], bisect_instance.TryParseResultValuesFromOutput( | 103 [66.88], bisect_instance.TryParseResultValuesFromOutput( |
148 metrics, RESULTS_OUTPUT % {'value': '66.88 kb'})) | 104 metrics, RESULTS_OUTPUT % {'value': '66.88 kb'})) |
149 self.assertEqual( | 105 self.assertEqual( |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 self.assertEqual( | 191 self.assertEqual( |
236 [], bisect_instance.TryParseResultValuesFromOutput( | 192 [], bisect_instance.TryParseResultValuesFromOutput( |
237 metrics, RESULTS_OUTPUT % {'value': '{}kb'})) | 193 metrics, RESULTS_OUTPUT % {'value': '{}kb'})) |
238 self.assertEqual( | 194 self.assertEqual( |
239 [], bisect_instance.TryParseResultValuesFromOutput( | 195 [], bisect_instance.TryParseResultValuesFromOutput( |
240 metrics, RESULTS_OUTPUT % {'value': '{XYZ}kb'})) | 196 metrics, RESULTS_OUTPUT % {'value': '{XYZ}kb'})) |
241 | 197 |
242 def testGetCompatibleCommand(self): | 198 def testGetCompatibleCommand(self): |
243 bisect_options = bisect_perf_module.BisectOptions() | 199 bisect_options = bisect_perf_module.BisectOptions() |
244 bisect_options.output_buildbot_annotations = None | 200 bisect_options.output_buildbot_annotations = None |
245 source_control = bisect_perf_module.DetermineAndCreateSourceControl( | 201 source_control = source_control_module.DetermineAndCreateSourceControl( |
246 bisect_options) | 202 bisect_options) |
247 bisect_instance = bisect_perf_module.BisectPerformanceMetrics( | 203 bisect_instance = bisect_perf_module.BisectPerformanceMetrics( |
248 source_control, bisect_options) | 204 source_control, bisect_options) |
249 bisect_instance.opts.target_platform = 'android' | 205 bisect_instance.opts.target_platform = 'android' |
250 depot = 'chromium' | 206 depot = 'chromium' |
251 # android-chrome-shell -> android-chromium-testshell | 207 # android-chrome-shell -> android-chromium-testshell |
252 revision = 274857 | 208 revision = 274857 |
253 git_revision = bisect_instance.source_control.ResolveToRevision( | 209 git_revision = bisect_instance.source_control.ResolveToRevision( |
254 revision, 'chromium', 100) | 210 revision, 'chromium', bisect_perf_module.DEPOT_DEPS_NAME, 100) |
255 command = ('tools/perf/run_benchmark -v ' | 211 command = ('tools/perf/run_benchmark -v ' |
256 '--browser=android-chrome-shell page_cycler.intl_ja_zh') | 212 '--browser=android-chrome-shell page_cycler.intl_ja_zh') |
257 expected_command = ('tools/perf/run_benchmark -v --browser=' | 213 expected_command = ('tools/perf/run_benchmark -v --browser=' |
258 'android-chromium-testshell page_cycler.intl_ja_zh') | 214 'android-chromium-testshell page_cycler.intl_ja_zh') |
259 self.assertEqual( | 215 self.assertEqual( |
260 bisect_instance.GetCompatibleCommand(command, git_revision, depot), | 216 bisect_instance.GetCompatibleCommand(command, git_revision, depot), |
261 expected_command) | 217 expected_command) |
262 | 218 |
263 # android-chromium-testshell -> android-chromium-testshell | 219 # android-chromium-testshell -> android-chromium-testshell |
264 revision = 274858 | 220 revision = 274858 |
265 git_revision = bisect_instance.source_control.ResolveToRevision( | 221 git_revision = bisect_instance.source_control.ResolveToRevision( |
266 revision, 'chromium', 100) | 222 revision, 'chromium', bisect_perf_module.DEPOT_DEPS_NAME, 100) |
267 command = ('tools/perf/run_benchmark -v ' | 223 command = ('tools/perf/run_benchmark -v ' |
268 '--browser=android-chromium-testshell page_cycler.intl_ja_zh') | 224 '--browser=android-chromium-testshell page_cycler.intl_ja_zh') |
269 expected_command = ('tools/perf/run_benchmark -v --browser=' | 225 expected_command = ('tools/perf/run_benchmark -v --browser=' |
270 'android-chromium-testshell page_cycler.intl_ja_zh') | 226 'android-chromium-testshell page_cycler.intl_ja_zh') |
271 self.assertEqual( | 227 self.assertEqual( |
272 bisect_instance.GetCompatibleCommand(command, git_revision, depot), | 228 bisect_instance.GetCompatibleCommand(command, git_revision, depot), |
273 expected_command) | 229 expected_command) |
274 | 230 |
275 # android-chromium-testshell -> android-chrome-shell | 231 # android-chromium-testshell -> android-chrome-shell |
276 revision = 276628 | 232 revision = 276628 |
277 git_revision = bisect_instance.source_control.ResolveToRevision( | 233 git_revision = bisect_instance.source_control.ResolveToRevision( |
278 revision, 'chromium', 100) | 234 revision, 'chromium', bisect_perf_module.DEPOT_DEPS_NAME, 100) |
279 command = ('tools/perf/run_benchmark -v ' | 235 command = ('tools/perf/run_benchmark -v ' |
280 '--browser=android-chromium-testshell page_cycler.intl_ja_zh') | 236 '--browser=android-chromium-testshell page_cycler.intl_ja_zh') |
281 expected_command = ('tools/perf/run_benchmark -v --browser=' | 237 expected_command = ('tools/perf/run_benchmark -v --browser=' |
282 'android-chrome-shell page_cycler.intl_ja_zh') | 238 'android-chrome-shell page_cycler.intl_ja_zh') |
283 self.assertEqual( | 239 self.assertEqual( |
284 bisect_instance.GetCompatibleCommand(command, git_revision, depot), | 240 bisect_instance.GetCompatibleCommand(command, git_revision, depot), |
285 expected_command) | 241 expected_command) |
286 # android-chrome-shell -> android-chrome-shell | 242 # android-chrome-shell -> android-chrome-shell |
287 command = ('tools/perf/run_benchmark -v ' | 243 command = ('tools/perf/run_benchmark -v ' |
288 '--browser=android-chrome-shell page_cycler.intl_ja_zh') | 244 '--browser=android-chrome-shell page_cycler.intl_ja_zh') |
289 expected_command = ('tools/perf/run_benchmark -v --browser=' | 245 expected_command = ('tools/perf/run_benchmark -v --browser=' |
290 'android-chrome-shell page_cycler.intl_ja_zh') | 246 'android-chrome-shell page_cycler.intl_ja_zh') |
291 self.assertEqual( | 247 self.assertEqual( |
292 bisect_instance.GetCompatibleCommand(command, git_revision, depot), | 248 bisect_instance.GetCompatibleCommand(command, git_revision, depot), |
293 expected_command) | 249 expected_command) |
294 # Not android platform | 250 # Not android platform |
295 bisect_instance.opts.target_platform = 'chromium' | 251 bisect_instance.opts.target_platform = 'chromium' |
296 command = ('tools/perf/run_benchmark -v ' | 252 command = ('tools/perf/run_benchmark -v ' |
297 '--browser=release page_cycler.intl_ja_zh') | 253 '--browser=release page_cycler.intl_ja_zh') |
298 expected_command = ('tools/perf/run_benchmark -v --browser=' | 254 expected_command = ('tools/perf/run_benchmark -v --browser=' |
299 'release page_cycler.intl_ja_zh') | 255 'release page_cycler.intl_ja_zh') |
300 self.assertEqual( | 256 self.assertEqual( |
301 bisect_instance.GetCompatibleCommand(command, git_revision, depot), | 257 bisect_instance.GetCompatibleCommand(command, git_revision, depot), |
302 expected_command) | 258 expected_command) |
303 | 259 |
| 260 |
304 if __name__ == '__main__': | 261 if __name__ == '__main__': |
305 unittest.main() | 262 unittest.main() |
OLD | NEW |