Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 # Copyright 2015 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 json | |
| 6 | |
| 7 DEPS = [ | |
| 8 'auto_bisect', | |
| 9 'path', | |
| 10 'properties', | |
| 11 'raw_io', | |
| 12 'step', | |
| 13 ] | |
| 14 | |
| 15 | |
| 16 # This file is just a recipe showing how one would use this module. | |
| 17 # | |
| 18 # The GenSteps and GenTests functions define the required interface for a | |
| 19 # recipe. | |
| 20 # | |
| 21 # GenSteps is run by the recipe infrastructure and it defines the actual steps | |
| 22 # required to execute the recipe. | |
| 23 # | |
| 24 # GenTests yields test cases to test the recipe using the recipe infrastructure | |
| 25 # and it is run when executing recipe_simulation_test.py and by presubmit checks | |
| 26 # by git cl. Note that coverage of a 100% of the statements in the recipe and | |
| 27 # the recipe_modules themselves is required. | |
| 28 # | |
| 29 # More information is available in scripts/slave/README.recipes.md | |
|
qyearsley
2015/03/13 23:38:59
Thanks for adding this :-)
robertocn1
2015/03/19 21:48:23
Acknowledged.
| |
| 30 def GenSteps(api): | |
| 31 # Setting `api.path['checkout']` would ordinarily be done by | |
| 32 # `api.chromium_tests.sync_and_configure_build` | |
| 33 fake_checkout_path = api.path.mkdtemp('fake_checkout') | |
| 34 api.path['checkout'] = fake_checkout_path | |
| 35 bisector = api.auto_bisect.create_bisector(api.properties['bisect_config']) | |
| 36 | |
| 37 # Request builds/tests for initial range and wait | |
| 38 bisector.good_rev.start_job() | |
| 39 bisector.bad_rev.start_job() | |
|
iannucci
2015/03/18 23:43:28
potentially combine 'good_rev' and 'last_known_goo
robertocn1
2015/03/19 21:48:24
Acknowledged.
| |
| 40 bisector.wait_for_all([bisector.good_rev, bisector.bad_rev]) | |
| 41 | |
| 42 assert bisector.check_improvement_direction() | |
|
iannucci
2015/03/18 23:43:28
lets maybe do assert_improvement_direction, which
robertocn1
2015/03/19 21:48:23
Acknowledged.
| |
| 43 assert bisector.check_regression_confidence() | |
| 44 revisions_to_check = bisector.get_revisions_to_eval(1) | |
| 45 assert len(revisions_to_check) == 1 | |
| 46 revisions_to_check[0].start_job() | |
| 47 bisector.wait_for_any(revisions_to_check) | |
|
iannucci
2015/03/18 23:43:28
idea: have wait_for_any() set step text for which
robertocn1
2015/03/19 21:48:23
Acknowledged.
| |
| 48 bisector.check_bisect_finished(revisions_to_check[0]) | |
|
iannucci
2015/03/18 23:43:28
let's rephrase this example as a loop which is clo
robertocn1
2015/03/19 21:48:23
Done.
| |
| 49 | |
| 50 # Evaluate inserted DEPS-modified revisions | |
| 51 revisions_to_check = bisector.get_revisions_to_eval(2) | |
|
iannucci
2015/03/18 23:43:28
let's comment on the `2` here, since we did `1` ea
robertocn1
2015/03/19 21:48:23
Acknowledged.
| |
| 52 if revisions_to_check: | |
| 53 revisions_to_check[0].start_job() | |
|
iannucci
2015/03/18 23:43:28
could have revisions_to_check be a RevisionList ob
robertocn1
2015/03/19 21:48:23
Acknowledged.
| |
| 54 revisions_to_check[0].read_deps() # Only added for coverage. | |
|
iannucci
2015/03/18 23:43:28
Later TODO: make gclient have an API to do this pa
robertocn1
2015/03/19 21:48:23
Acknowledged.
| |
| 55 else: | |
| 56 raise api.step.StepFailure('Expected revisions to check.') | |
| 57 # TODO(robertocn): Add examples for the following operations | |
| 58 # Abort unnecesary jobs # Print results | |
| 59 | |
| 60 | |
| 61 def GenTests(api): | |
| 62 basic_data = _get_basic_test_data() | |
| 63 yield _make_test(api, basic_data, 'basic') | |
| 64 | |
| 65 reversed_basic_data = _get_reversed_basic_test_data() | |
| 66 yield _make_test(api, reversed_basic_data, 'reversed_basic') | |
| 67 | |
| 68 bad_git_hash_data = _get_basic_test_data() | |
| 69 bad_git_hash_data[1]['interned_hashes'] = {'003': '12345', '002': 'Bad Hash'} | |
| 70 yield _make_test(api, bad_git_hash_data, 'failed_git_hash_object') | |
| 71 | |
| 72 missing_dep_data = _get_basic_test_data() | |
| 73 tricked_DEPS_file = ("vars={'v8_' + 'revision': '001'};" | |
| 74 "deps = {'src/v8': 'v8.git@' + Var('v8_revision')," | |
| 75 "'src/third_party/WebKit': 'webkit.git@010'}") | |
| 76 missing_dep_data[0]['DEPS'] = tricked_DEPS_file | |
| 77 yield _make_test(api, missing_dep_data, 'missing_vars_entry') | |
| 78 | |
| 79 missing_dep_data = _get_basic_test_data() | |
| 80 tricked_DEPS_file = ("vars={'v8_revision': '001'};" | |
| 81 "deps = {'src/v8': 'v8.XXX@' + Var('v8_revision')," | |
| 82 "'src/third_party/WebKit': 'webkit.git@010'}") | |
| 83 missing_dep_data[0]['DEPS'] = tricked_DEPS_file | |
| 84 yield _make_test(api, missing_dep_data, 'missing_deps_entry') | |
| 85 | |
| 86 bad_deps_syntax_data = _get_basic_test_data() | |
| 87 bad_deps_syntax_data[1]['DEPS']='raise RuntimeError("")' | |
| 88 yield _make_test(api, bad_deps_syntax_data, 'bad_deps_syntax') | |
| 89 | |
| 90 | |
| 91 def _get_basic_test_data(): | |
| 92 return [ | |
| 93 { | |
| 94 'hash': 'a6298e4afedbf2cd461755ea6f45b0ad64222222', | |
| 95 'commit_pos': '314015', | |
| 96 'test_results': { | |
| 97 'results':{ | |
| 98 'mean': 20, | |
| 99 'std_err': 1, | |
| 100 'values': [19, 20, 21], | |
| 101 } | |
| 102 }, | |
| 103 "DEPS": ("vars={'v8_revision': '001'};" | |
| 104 "deps = {'src/v8': 'v8.git@' + Var('v8_revision')," | |
| 105 "'src/third_party/WebKit': 'webkit.git@010'}"), | |
| 106 'git_diff': { | |
| 107 '002': 'Dummy .diff contents 001 - 002', | |
| 108 '003': 'Dummy .diff contents 001 - 003', | |
| 109 }, | |
| 110 }, | |
| 111 { | |
| 112 'hash': 'dcdcdc0ff1122212323134879ddceeb1240b0988', | |
| 113 'commit_pos': '314016', | |
| 114 'test_results': { | |
| 115 'results':{ | |
| 116 'mean': 15, | |
| 117 'std_err': 1, | |
| 118 'values': [14, 15, 16], | |
| 119 } | |
| 120 }, | |
| 121 'DEPS_change': 'True', | |
| 122 "DEPS": ("vars={'v8_revision': '004'};" | |
| 123 "deps = {'src/v8': 'v8.git@' + Var('v8_revision')," | |
| 124 "'src/third_party/WebKit': 'webkit.git@010'}"), | |
| 125 'DEPS_interval': {'v8': '004 003 002'.split()}, | |
| 126 }, | |
| 127 { | |
| 128 'hash': '00316c9ddfb9d7b4e1ed2fff9fe6d964d2111111', | |
| 129 'commit_pos': '314017', | |
| 130 'test_results': { | |
| 131 'results':{ | |
| 132 'mean': 15, | |
| 133 'std_err': 1, | |
| 134 'values': [14, 15, 16], | |
| 135 } | |
| 136 } | |
| 137 }, | |
| 138 ] | |
| 139 | |
| 140 | |
| 141 def _get_reversed_basic_test_data(): | |
| 142 return [ | |
| 143 { | |
| 144 'hash': '00316c9ddfb9d7b4e1ed2fff9fe6d964d2111111', | |
| 145 'commit_pos': '314015', | |
| 146 'test_results': { | |
| 147 'results':{ | |
| 148 'mean': 20, | |
| 149 'std_err': 1, | |
| 150 'values': [19, 20, 21], | |
| 151 } | |
| 152 } | |
| 153 }, | |
| 154 { | |
| 155 'hash': 'a6298e4afedbf2cd461755ea6f45b0ad64222222', | |
| 156 'commit_pos': '314016', | |
| 157 'test_results': { | |
| 158 'results':{ | |
| 159 'mean': 20, | |
| 160 'std_err': 1, | |
| 161 'values': [19, 20, 21], | |
| 162 } | |
| 163 }, | |
| 164 "DEPS": ("vars={'v8_revision': '001'};" | |
| 165 "deps = {'src/v8': 'v8.git@' + Var('v8_revision')," | |
| 166 "'src/third_party/WebKit': 'webkit.git@010'}"), | |
| 167 'git_diff': { | |
| 168 '002': 'Dummy .diff contents 001 - 002', | |
| 169 '003': 'Dummy .diff contents 001 - 003', | |
| 170 }, | |
| 171 }, | |
| 172 { | |
| 173 'hash': 'dcdcdc0ff1122212323134879ddceeb1240b0988', | |
| 174 'commit_pos': '314017', | |
| 175 'test_results': { | |
| 176 'results':{ | |
| 177 'mean': 15, | |
| 178 'std_err': 1, | |
| 179 'values': [14, 15, 16], | |
| 180 } | |
| 181 }, | |
| 182 'DEPS_change': 'True', | |
| 183 "DEPS": ("vars={'v8_revision': '004'};" | |
| 184 "deps = {'src/v8': 'v8.git@' + Var('v8_revision')," | |
| 185 "'src/third_party/WebKit': 'webkit.git@010'}"), | |
| 186 'DEPS_interval': {'v8': '004 003 002'.split()}, | |
| 187 }, | |
| 188 ] | |
| 189 | |
| 190 | |
| 191 def _make_test(api, test_data, test_name): | |
| 192 basic_test = api.test(test_name) | |
| 193 for revision_data in test_data: | |
| 194 for step_data in _get_step_data_for_revision(api, revision_data): | |
| 195 basic_test += step_data | |
| 196 basic_test += api.properties(bisect_config=_get_default_config()) | |
| 197 return basic_test | |
| 198 | |
| 199 | |
| 200 def _get_default_config(): | |
| 201 example_config = { | |
| 202 'test_type':'perf', | |
| 203 'command': | |
| 204 ('src/tools/perf/run_benchmark -v --browser=release smoothness.' | |
| 205 'tough_scrolling_cases'), | |
| 206 'good_revision': '314015', | |
| 207 'bad_revision': '314017', | |
| 208 'metric': 'mean_input_event_latency/mean_input_event_latency', | |
| 209 'repeat_count': '2', | |
| 210 'max_time_minutes': '5', | |
| 211 'truncate_percent': '0', | |
| 212 'bug_id': '', | |
| 213 'gs_bucket': 'chrome-perf', | |
| 214 'builder_host': 'master4.golo.chromium.org', | |
| 215 'builder_port': '8341', | |
| 216 'dummy_builds': 'True', | |
| 217 } | |
| 218 return example_config | |
| 219 | |
| 220 | |
| 221 def _get_step_data_for_revision(api, revision_data, include_build_steps=True): | |
| 222 """Generator that produces step patches for fake results.""" | |
| 223 commit_pos = revision_data['commit_pos'] | |
| 224 commit_hash = revision_data['hash'] | |
| 225 test_results = revision_data['test_results'] | |
| 226 | |
| 227 step_name = 'resolving commit_pos ' + commit_pos | |
| 228 yield api.step_data(step_name, stdout=api.raw_io.output('hash:' + | |
| 229 commit_hash)) | |
| 230 | |
| 231 step_name = 'resolving hash ' + commit_hash | |
| 232 commit_pos_str = 'refs/heads/master@{#%s}' % commit_pos | |
| 233 yield api.step_data(step_name, stdout=api.raw_io.output(commit_pos_str)) | |
| 234 | |
| 235 if include_build_steps: | |
| 236 step_name = 'gsutil Get test results for build ' + commit_hash | |
| 237 yield api.step_data(step_name, stdout=api.raw_io.output(json.dumps( | |
| 238 test_results))) | |
| 239 | |
| 240 step_name = 'Get test status for build ' + commit_hash | |
| 241 yield api.step_data(step_name, stdout=api.raw_io.output('Complete')) | |
| 242 | |
| 243 step_name = 'gsutil Get test status url for build ' + commit_hash | |
| 244 yield api.step_data(step_name, stdout=api.raw_io.output('dummy/url')) | |
| 245 | |
| 246 if revision_data.get('DEPS', False): | |
| 247 step_name = 'git cat-file %s:DEPS' % commit_hash | |
| 248 yield api.step_data(step_name, stdout=api.raw_io.output( | |
| 249 revision_data['DEPS'])) | |
| 250 | |
| 251 if 'git_diff' in revision_data: | |
| 252 for deps_rev, diff_file in revision_data['git_diff'].iteritems(): | |
| 253 step_name = 'Generating patch for %s:DEPS to %s' | |
| 254 step_name %= (commit_hash, deps_rev) | |
| 255 yield api.step_data(step_name, stdout=api.raw_io.output(diff_file)) | |
| 256 | |
| 257 if 'DEPS_change' in revision_data: | |
| 258 step_name = 'Checking DEPS for ' + commit_hash | |
| 259 yield api.step_data(step_name, stdout=api.raw_io.output('DEPS')) | |
| 260 | |
| 261 if 'DEPS_interval' in revision_data: | |
| 262 for depot_name, interval in revision_data['DEPS_interval'].iteritems(): | |
| 263 for item in interval[1:]: | |
| 264 step_name = 'Hashing modified DEPS file with revision ' + item | |
| 265 file_hash = 'f412e8458' | |
| 266 if 'interned_hashes' in revision_data: | |
| 267 file_hash = revision_data['interned_hashes'][item] | |
| 268 yield api.step_data(step_name, stdout=api.raw_io.output(file_hash)) | |
| 269 step_name = 'Expanding revision range for revision %s on depot %s' | |
| 270 step_name %= (interval[0], depot_name) | |
| 271 stdout = api.raw_io.output('\n'.join(interval)) | |
| 272 yield api.step_data(step_name, stdout=stdout) | |
| 273 | |
| OLD | NEW |