Upstream version 10.38.222.0
[platform/framework/web/crosswalk.git] / src / tools / bisect-perf-regression_test.py
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
3 # found in the LICENSE file.
4
5 import unittest
6
7 from auto_bisect import source_control as source_control_module
8
9 # Special import necessary because filename contains dash characters.
10 bisect_perf_module = __import__('bisect-perf-regression')
11
12
13 class BisectPerfRegressionTest(unittest.TestCase):
14   """Test case for other functions and classes in bisect-perf-regression.py."""
15
16   def _AssertConfidence(self, score, bad_values, good_values):
17     """Checks whether the given sets of values have a given confidence score.
18
19     The score represents our confidence that the two sets of values wouldn't
20     be as different as they are just by chance; that is, that some real change
21     occurred between the two sets of values.
22
23     Args:
24       score: Expected confidence score.
25       bad_values: First list of numbers.
26       good_values: Second list of numbers.
27     """
28     # ConfidenceScore takes a list of lists but these lists are flattened
29     # inside the function.
30     confidence = bisect_perf_module.ConfidenceScore(
31         [[v] for v in bad_values],
32         [[v] for v in good_values])
33     self.assertEqual(score, confidence)
34
35   def testConfidenceScore_ZeroConfidence(self):
36     # The good and bad sets contain the same values, so the confidence that
37     # they're different should be zero.
38     self._AssertConfidence(0.0, [4, 5, 7, 6, 8, 7], [8, 7, 6, 7, 5, 4])
39
40   def testConfidenceScore_MediumConfidence(self):
41     self._AssertConfidence(80.0, [0, 1, 1, 1, 2, 2], [1, 1, 1, 3, 3, 4])
42
43   def testConfidenceScore_HighConfidence(self):
44     self._AssertConfidence(95.0, [0, 1, 1, 1, 2, 2], [1, 2, 2, 3, 3, 4])
45
46   def testConfidenceScore_VeryHighConfidence(self):
47     # Confidence is high if the two sets of values have no internal variance.
48     self._AssertConfidence(99.9, [1, 1, 1, 1], [1.2, 1.2, 1.2, 1.2])
49     self._AssertConfidence(99.9, [1, 1, 1, 1], [1.01, 1.01, 1.01, 1.01])
50
51   def testConfidenceScore_UnbalancedSampleSize(self):
52     # The second set of numbers only contains one number, so confidence is 0.
53     self._AssertConfidence(0.0, [1.1, 1.2, 1.1, 1.2, 1.0, 1.3, 1.2], [1.4])
54
55   def testConfidenceScore_EmptySample(self):
56     # Confidence is zero if either or both samples are empty.
57     self._AssertConfidence(0.0, [], [])
58     self._AssertConfidence(0.0, [], [1.1, 1.2, 1.1, 1.2, 1.0, 1.3, 1.2, 1.3])
59     self._AssertConfidence(0.0, [1.1, 1.2, 1.1, 1.2, 1.0, 1.3, 1.2, 1.3], [])
60
61   def testConfidenceScore_FunctionalTestResults(self):
62     self._AssertConfidence(80.0, [1, 1, 0, 1, 1, 1, 0, 1], [0, 0, 1, 0, 1, 0])
63     self._AssertConfidence(99.9, [1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0])
64
65   def testParseDEPSStringManually(self):
66     """Tests DEPS parsing."""
67     deps_file_contents = """
68     vars = {
69         'ffmpeg_hash':
70              '@ac4a9f31fe2610bd146857bbd55d7a260003a888',
71         'webkit_url':
72              'https://chromium.googlesource.com/chromium/blink.git',
73         'git_url':
74              'https://chromium.googlesource.com',
75         'webkit_rev':
76              '@e01ac0a267d1017288bc67fa3c366b10469d8a24',
77         'angle_revision':
78              '74697cf2064c0a2c0d7e1b1b28db439286766a05'
79     }"""
80
81     # Should only expect SVN/git revisions to come through, and URLs should be
82     # filtered out.
83     expected_vars_dict = {
84         'ffmpeg_hash': '@ac4a9f31fe2610bd146857bbd55d7a260003a888',
85         'webkit_rev': '@e01ac0a267d1017288bc67fa3c366b10469d8a24',
86         'angle_revision': '74697cf2064c0a2c0d7e1b1b28db439286766a05'
87     }
88     # Testing private function.
89     # pylint: disable=W0212
90     vars_dict = bisect_perf_module._ParseRevisionsFromDEPSFileManually(
91         deps_file_contents)
92     self.assertEqual(vars_dict, expected_vars_dict)
93
94   def _AssertParseResult(self, expected_values, result_string):
95     """Asserts some values are parsed from a RESULT line."""
96     results_template = ('RESULT other_chart: other_trace= 123 count\n'
97                         'RESULT my_chart: my_trace= %(value)s\n')
98     results = results_template % {'value': result_string}
99     metric = ['my_chart', 'my_trace']
100     # Testing private function.
101     # pylint: disable=W0212
102     values = bisect_perf_module._TryParseResultValuesFromOutput(metric, results)
103     self.assertEqual(expected_values, values)
104
105   def testTryParseResultValuesFromOutput_WithSingleValue(self):
106     """Tests result pattern <*>RESULT <graph>: <trace>= <value>"""
107     self._AssertParseResult([66.88], '66.88 kb')
108     self._AssertParseResult([66.88], '66.88 ')
109     self._AssertParseResult([-66.88], '-66.88 kb')
110     self._AssertParseResult([66], '66 kb')
111     self._AssertParseResult([0.66], '.66 kb')
112     self._AssertParseResult([], '. kb')
113     self._AssertParseResult([], 'aaa kb')
114
115   def testTryParseResultValuesFromOutput_WithMultiValue(self):
116     """Tests result pattern <*>RESULT <graph>: <trace>= [<value>,<value>, ..]"""
117     self._AssertParseResult([66.88], '[66.88] kb')
118     self._AssertParseResult([66.88, 99.44], '[66.88, 99.44]kb')
119     self._AssertParseResult([66.88, 99.44], '[ 66.88, 99.44 ]')
120     self._AssertParseResult([-66.88, 99.44], '[-66.88, 99.44] kb')
121     self._AssertParseResult([-66, 99], '[-66,99] kb')
122     self._AssertParseResult([-66, 99], '[-66,99,] kb')
123     self._AssertParseResult([-66, 0.99], '[-66,.99] kb')
124     self._AssertParseResult([], '[] kb')
125     self._AssertParseResult([], '[-66,abc] kb')
126
127   def testTryParseResultValuesFromOutputWithMeanStd(self):
128     """Tests result pattern <*>RESULT <graph>: <trace>= {<mean, std}"""
129     self._AssertParseResult([33.22], '{33.22, 3.6} kb')
130     self._AssertParseResult([33.22], '{33.22, 3.6} kb')
131     self._AssertParseResult([33.22], '{33.22,3.6}kb')
132     self._AssertParseResult([33.22], '{33.22,3.6} kb')
133     self._AssertParseResult([33.22], '{ 33.22,3.6 }kb')
134     self._AssertParseResult([-33.22], '{-33.22,3.6}kb')
135     self._AssertParseResult([22], '{22,6}kb')
136     self._AssertParseResult([.22], '{.22,6}kb')
137     self._AssertParseResult([], '{.22,6, 44}kb')
138     self._AssertParseResult([], '{}kb')
139     self._AssertParseResult([], '{XYZ}kb')
140
141   def _AssertCompatibleCommand(
142       self, expected_command, original_command, revision, target_platform):
143     """Tests the modification of the command that might be done.
144
145     This modification to the command is done in order to get a Telemetry
146     command that works; before some revisions, the browser name that Telemetry
147     expects is different in some cases, but we want it to work anyway.
148
149     Specifically, only for android:
150       After r276628, only android-chrome-shell works.
151       Prior to r274857, only android-chromium-testshell works.
152       In the range [274857, 276628], both work.
153     """
154     bisect_options = bisect_perf_module.BisectOptions()
155     bisect_options.output_buildbot_annotations = None
156     source_control = source_control_module.DetermineAndCreateSourceControl(
157         bisect_options)
158     bisect_instance = bisect_perf_module.BisectPerformanceMetrics(
159         source_control, bisect_options)
160     bisect_instance.opts.target_platform = target_platform
161     git_revision = bisect_instance.source_control.ResolveToRevision(
162         revision, 'chromium', bisect_perf_module.DEPOT_DEPS_NAME, 100)
163     depot = 'chromium'
164     command = bisect_instance.GetCompatibleCommand(
165         original_command, git_revision, depot)
166     self.assertEqual(expected_command, command)
167
168   def testGetCompatibleCommand_ChangeToTestShell(self):
169     # For revisions <= r274857, only android-chromium-testshell is used.
170     self._AssertCompatibleCommand(
171         'tools/perf/run_benchmark -v --browser=android-chromium-testshell foo',
172         'tools/perf/run_benchmark -v --browser=android-chrome-shell foo',
173         274857, 'android')
174
175   def testGetCompatibleCommand_ChangeToShell(self):
176     # For revisions >= r276728, only android-chrome-shell can be used.
177     self._AssertCompatibleCommand(
178         'tools/perf/run_benchmark -v --browser=android-chrome-shell foo',
179         'tools/perf/run_benchmark -v --browser=android-chromium-testshell foo',
180         276628, 'android')
181
182   def testGetCompatibleCommand_NoChange(self):
183     # For revisions < r276728, android-chromium-testshell can be used.
184     self._AssertCompatibleCommand(
185         'tools/perf/run_benchmark -v --browser=android-chromium-testshell foo',
186         'tools/perf/run_benchmark -v --browser=android-chromium-testshell foo',
187         274858, 'android')
188     # For revisions > r274857, android-chrome-shell can be used.
189     self._AssertCompatibleCommand(
190         'tools/perf/run_benchmark -v --browser=android-chrome-shell foo',
191         'tools/perf/run_benchmark -v --browser=android-chrome-shell foo',
192         274858, 'android')
193
194   def testGetCompatibleCommand_NonAndroidPlatform(self):
195     # In most cases, there's no need to change Telemetry command.
196     # For revisions >= r276728, only android-chrome-shell can be used.
197     self._AssertCompatibleCommand(
198         'tools/perf/run_benchmark -v --browser=release foo',
199         'tools/perf/run_benchmark -v --browser=release foo',
200         276628, 'chromium')
201
202   # This method doesn't reference self; it fails if an error is thrown.
203   # pylint: disable=R0201
204   def testDryRun(self):
205     """Does a dry run of the bisect script.
206
207     This serves as a smoke test to catch errors in the basic execution of the
208     script.
209     """
210     options_dict = {
211       'debug_ignore_build': True,
212       'debug_ignore_sync': True,
213       'debug_ignore_perf_test': True,
214       'command': 'fake_command',
215       'metric': 'fake/metric',
216       'good_revision': 280000,
217       'bad_revision': 280005,
218     }
219     bisect_options = bisect_perf_module.BisectOptions.FromDict(options_dict)
220     source_control = source_control_module.DetermineAndCreateSourceControl(
221         bisect_options)
222     bisect_instance = bisect_perf_module.BisectPerformanceMetrics(
223         source_control, bisect_options)
224     results = bisect_instance.Run(bisect_options.command,
225                                   bisect_options.bad_revision,
226                                   bisect_options.good_revision,
227                                   bisect_options.metric)
228     bisect_instance.FormatAndPrintResults(results)
229
230
231 if __name__ == '__main__':
232   unittest.main()