 Chromium Code Reviews
 Chromium Code Reviews Issue 1154593005:
  [Findit] Add a sub-pipeline to analyze failures caused by DEPS rolls.  (Closed) 
  Base URL: https://chromium.googlesource.com/infra/infra.git@master
    
  
    Issue 1154593005:
  [Findit] Add a sub-pipeline to analyze failures caused by DEPS rolls.  (Closed) 
  Base URL: https://chromium.googlesource.com/infra/infra.git@master| OLD | NEW | 
|---|---|
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 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 unittest | 5 import unittest | 
| 6 | 6 | 
| 7 from common.diff import ChangeType | 7 from common.diff import ChangeType | 
| 8 from waterfall import build_failure_analysis | 8 from waterfall import build_failure_analysis | 
| 9 from waterfall.failure_signal import FailureSignal | 9 from waterfall.failure_signal import FailureSignal | 
| 10 | 10 | 
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 'files': { | 66 'files': { | 
| 67 'src/a/b/f1.cc': [], | 67 'src/a/b/f1.cc': [], | 
| 68 'd/e/a2_test.cc': [], | 68 'd/e/a2_test.cc': [], | 
| 69 'b/c/f2.cc': [10, 20], | 69 'b/c/f2.cc': [10, 20], | 
| 70 'd/e/f3.h': [], | 70 'd/e/f3.h': [], | 
| 71 'x/y/f4.py': [], | 71 'x/y/f4.py': [], | 
| 72 'f5_impl.cc': [] | 72 'f5_impl.cc': [] | 
| 73 } | 73 } | 
| 74 } | 74 } | 
| 75 change_log_json = { | 75 change_log_json = { | 
| 76 'revision': 'rev', | |
| 76 'touched_files': [ | 77 'touched_files': [ | 
| 77 { | 78 { | 
| 78 'change_type': ChangeType.ADD, | 79 'change_type': ChangeType.ADD, | 
| 79 'old_path': '/dev/null', | 80 'old_path': '/dev/null', | 
| 80 'new_path': 'a/b/f1.cc' | 81 'new_path': 'a/b/f1.cc' | 
| 81 }, | 82 }, | 
| 82 { | 83 { | 
| 83 'change_type': ChangeType.ADD, | 84 'change_type': ChangeType.ADD, | 
| 84 'old_path': '/dev/null', | 85 'old_path': '/dev/null', | 
| 85 'new_path': 'd/e/a2.cc' | 86 'new_path': 'd/e/a2.cc' | 
| (...skipping 18 matching lines...) Expand all Loading... | |
| 104 'old_path': 'h/f5.h', | 105 'old_path': 'h/f5.h', | 
| 105 'new_path': '/dev/null' | 106 'new_path': '/dev/null' | 
| 106 }, | 107 }, | 
| 107 { | 108 { | 
| 108 'change_type': ChangeType.RENAME, | 109 'change_type': ChangeType.RENAME, | 
| 109 'old_path': 't/y/x.cc', | 110 'old_path': 't/y/x.cc', | 
| 110 'new_path': 's/z/x.cc' | 111 'new_path': 's/z/x.cc' | 
| 111 }, | 112 }, | 
| 112 ] | 113 ] | 
| 113 } | 114 } | 
| 115 deps_info = {} | |
| 114 | 116 | 
| 115 justification = build_failure_analysis._CheckFiles( | 117 justification = build_failure_analysis._CheckFiles( | 
| 116 FailureSignal.FromDict(failure_signal_json), change_log_json) | 118 FailureSignal.FromDict(failure_signal_json), change_log_json, deps_info) | 
| 117 self.assertIsNotNone(justification) | 119 self.assertIsNotNone(justification) | 
| 118 # The score is 14 because: | 120 # The score is 15 because: | 
| 119 # +5 added a/b/f1.cc (same file src/a/b/f1.cc in failure_signal log) | 121 # +5 added a/b/f1.cc (same file src/a/b/f1.cc in failure_signal log) | 
| 120 # +1 added d/e/a2.cc (related file a2_test.cc in failure_signal log) | 122 # +1 added d/e/a2.cc (related file a2_test.cc in failure_signal log) | 
| 121 # +1 modified b/c/f2.h (related file a/b/c/f2.cc in failure_signal log) | 123 # +1 modified b/c/f2.h (related file a/b/c/f2.cc in failure_signal log) | 
| 122 # +2 modified d/e/f3.h (same file d/e/f3.h in failure_signal log) | 124 # +2 modified d/e/f3.h (same file d/e/f3.h in failure_signal log) | 
| 123 # +5 deleted x/y/f4.py (same file x/y/f4.py in failure_signal log) | 125 # +5 deleted x/y/f4.py (same file x/y/f4.py in failure_signal log) | 
| 124 # +1 deleted h/f5.h (related file f5_impl.cc in failure_signal log) | 126 # +1 deleted h/f5.h (related file f5_impl.cc in failure_signal log) | 
| 125 # +0 renamed t/y/x.cc -> s/z/x.cc (no related file in failure_signal log) | 127 # +0 renamed t/y/x.cc -> s/z/x.cc (no related file in failure_signal log) | 
| 126 self.assertEqual(15, justification['score']) | 128 self.assertEqual(15, justification['score']) | 
| 127 | 129 | 
| 128 def testCheckFilesAgainstUnrelatedCL(self): | 130 def testCheckFilesAgainstUnrelatedCL(self): | 
| 129 failure_signal_json = { | 131 failure_signal_json = { | 
| 130 'files': { | 132 'files': { | 
| 131 'src/a/b/f.cc': [], | 133 'src/a/b/f.cc': [], | 
| 132 } | 134 } | 
| 133 } | 135 } | 
| 134 change_log_json = { | 136 change_log_json = { | 
| 137 'revision': 'rev', | |
| 135 'touched_files': [ | 138 'touched_files': [ | 
| 136 { | 139 { | 
| 137 'change_type': ChangeType.ADD, | 140 'change_type': ChangeType.ADD, | 
| 138 'old_path': '/dev/null', | 141 'old_path': '/dev/null', | 
| 139 'new_path': 'a/d/f1.cc' | 142 'new_path': 'a/d/f1.cc' | 
| 140 }, | 143 }, | 
| 141 ] | 144 ] | 
| 142 } | 145 } | 
| 146 deps_info = {} | |
| 143 | 147 | 
| 144 justification = build_failure_analysis._CheckFiles( | 148 justification = build_failure_analysis._CheckFiles( | 
| 145 FailureSignal.FromDict(failure_signal_json), change_log_json) | 149 FailureSignal.FromDict(failure_signal_json), change_log_json, deps_info) | 
| 146 self.assertIsNone(justification) | 150 self.assertIsNone(justification) | 
| 147 | 151 | 
| 152 def testCheckFilesAgainstDEPSRoll(self): | |
| 153 failure_signal_json = { | |
| 154 'files': { | |
| 155 'src/third_party/dep1/f.cc': [123], | |
| 156 } | |
| 157 } | |
| 158 change_log_json = { | |
| 159 'revision': 'rev', | |
| 160 'touched_files': [ | |
| 161 { | |
| 162 'change_type': ChangeType.MODIFY, | |
| 163 'old_path': 'DEPS', | |
| 164 'new_path': 'DEPS' | |
| 165 }, | |
| 166 ] | |
| 167 } | |
| 168 deps_info = { | |
| 169 'deps_rolls': { | |
| 170 'rev': [ | |
| 171 { | |
| 172 'path': 'src/third_party/dep1/', | |
| 173 'repo_url': 'https://url_dep1', | |
| 174 'old_revision': '7', | |
| 175 'new_revision': '9', | |
| 176 }, | |
| 177 { | |
| 178 'path': 'third_party/dep2', | |
| 179 'repo_url': 'https://url_dep2', | |
| 180 'old_revision': None, | |
| 181 'new_revision': '1', | |
| 182 }, | |
| 183 ] | |
| 184 } | |
| 185 } | |
| 186 | |
| 187 justification = build_failure_analysis._CheckFiles( | |
| 188 FailureSignal.FromDict(failure_signal_json), change_log_json, deps_info) | |
| 189 self.assertIsNotNone(justification) | |
| 190 # The score is 2 because: | |
| 191 # +2 rolled third_party/dep1/ and src/third_party/dep1/f.cc was in log. | |
| 192 self.assertEqual(2, justification['score']) | |
| 193 | |
| 148 def testAnalyzeSuccessfulBuild(self): | 194 def testAnalyzeSuccessfulBuild(self): | 
| 149 failure_info = { | 195 failure_info = { | 
| 150 'failed': False, | 196 'failed': False, | 
| 151 } | 197 } | 
| 152 result = build_failure_analysis.AnalyzeBuildFailure( | 198 result = build_failure_analysis.AnalyzeBuildFailure( | 
| 153 failure_info, None, None) | 199 failure_info, None, None, None) | 
| 
qyearsley
2015/05/29 23:14:33
Optional: You can add argument names, even if they
 
stgao
2015/05/30 00:21:05
Done. That's a good idea for readability.
 | |
| 154 self.assertEqual(0, len(result['failures'])) | 200 self.assertEqual(0, len(result['failures'])) | 
| 155 | 201 | 
| 156 def testAnalyzeBuildFailure(self): | 202 def testAnalyzeBuildFailure(self): | 
| 157 failure_info = { | 203 failure_info = { | 
| 158 'failed': True, | 204 'failed': True, | 
| 159 'failed_steps': { | 205 'failed_steps': { | 
| 160 'a': { | 206 'a': { | 
| 161 'current_failure': 99, | 207 'current_failure': 99, | 
| 162 'first_failure': 98, | 208 'first_failure': 98, | 
| 163 }, | 209 }, | 
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 232 'revision': 'r96_1', | 278 'revision': 'r96_1', | 
| 233 'touched_files': [ | 279 'touched_files': [ | 
| 234 { | 280 { | 
| 235 'change_type': ChangeType.MODIFY, | 281 'change_type': ChangeType.MODIFY, | 
| 236 'old_path': 'a/b/f96_1.cc', | 282 'old_path': 'a/b/f96_1.cc', | 
| 237 'new_path': 'a/b/f96_1.cc' | 283 'new_path': 'a/b/f96_1.cc' | 
| 238 }, | 284 }, | 
| 239 ], | 285 ], | 
| 240 }, | 286 }, | 
| 241 } | 287 } | 
| 288 deps_info = {} | |
| 242 failure_signals_json = { | 289 failure_signals_json = { | 
| 243 'a': { | 290 'a': { | 
| 244 'files': { | 291 'files': { | 
| 245 'src/a/b/f99_2.cc': [], | 292 'src/a/b/f99_2.cc': [], | 
| 246 }, | 293 }, | 
| 247 }, | 294 }, | 
| 248 'b': { | 295 'b': { | 
| 249 'files': { | 296 'files': { | 
| 250 'x/y/f99_1.cc': [], | 297 'x/y/f99_1.cc': [], | 
| 251 }, | 298 }, | 
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 286 'hints': { | 333 'hints': { | 
| 287 'added x/y/f99_1.cc (and it was in log)': 5, | 334 'added x/y/f99_1.cc (and it was in log)': 5, | 
| 288 }, | 335 }, | 
| 289 } | 336 } | 
| 290 ], | 337 ], | 
| 291 } | 338 } | 
| 292 ] | 339 ] | 
| 293 } | 340 } | 
| 294 | 341 | 
| 295 analysis_result = build_failure_analysis.AnalyzeBuildFailure( | 342 analysis_result = build_failure_analysis.AnalyzeBuildFailure( | 
| 296 failure_info, change_logs, failure_signals_json) | 343 failure_info, change_logs, deps_info, failure_signals_json) | 
| 297 self.assertEqual(expected_analysis_result, analysis_result) | 344 self.assertEqual(expected_analysis_result, analysis_result) | 
| OLD | NEW |