| 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 from testing_utils import testing | 5 from testing_utils import testing |
| 6 | 6 |
| 7 from common.git_repository import GitRepository | 7 from common.git_repository import GitRepository |
| 8 from model import wf_analysis_status | 8 from model import wf_analysis_status |
| 9 from model.wf_try_job import WfTryJob | 9 from model.wf_try_job import WfTryJob |
| 10 from model.wf_try_job_data import WfTryJobData | 10 from model.wf_try_job_data import WfTryJobData |
| 11 from waterfall.identify_try_job_culprit_pipeline import( | 11 from waterfall.identify_try_job_culprit_pipeline import( |
| 12 IdentifyTryJobCulpritPipeline) | 12 IdentifyTryJobCulpritPipeline) |
| 13 from waterfall.try_job_type import TryJobType |
| 13 | 14 |
| 14 | 15 |
| 15 class IdentifyTryJobCulpritPipelineTest(testing.AppengineTestCase): | 16 class IdentifyTryJobCulpritPipelineTest(testing.AppengineTestCase): |
| 16 | 17 |
| 17 def _MockGetChangeLog(self, revision): | 18 def _MockGetChangeLog(self, revision): |
| 18 class MockedChangeLog(object): | 19 class MockedChangeLog(object): |
| 19 | 20 |
| 20 def __init__(self, commit_position, code_review_url): | 21 def __init__(self, commit_position, code_review_url): |
| 21 self.commit_position = commit_position | 22 self.commit_position = commit_position |
| 22 self.code_review_url = code_review_url | 23 self.code_review_url = code_review_url |
| 23 | 24 |
| 24 mock_change_logs = {} | 25 mock_change_logs = {} |
| 26 mock_change_logs['rev1'] = MockedChangeLog('1', 'url_1') |
| 25 mock_change_logs['rev2'] = MockedChangeLog('2', 'url_2') | 27 mock_change_logs['rev2'] = MockedChangeLog('2', 'url_2') |
| 26 return mock_change_logs.get(revision) | 28 return mock_change_logs.get(revision) |
| 27 | 29 |
| 28 def testGetFailedRevisionFromResultsDict(self): | 30 def testGetFailedRevisionFromResultsDict(self): |
| 29 self.assertIsNone( | 31 self.assertIsNone( |
| 30 IdentifyTryJobCulpritPipeline._GetFailedRevisionFromResultsDict({})) | 32 IdentifyTryJobCulpritPipeline._GetFailedRevisionFromResultsDict({})) |
| 31 self.assertEqual( | 33 self.assertEqual( |
| 32 None, | 34 None, |
| 33 IdentifyTryJobCulpritPipeline._GetFailedRevisionFromResultsDict( | 35 IdentifyTryJobCulpritPipeline._GetFailedRevisionFromResultsDict( |
| 34 {'rev1': 'passed'})) | 36 {'rev1': 'passed'})) |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 self.assertEqual( | 73 self.assertEqual( |
| 72 'rev2', | 74 'rev2', |
| 73 IdentifyTryJobCulpritPipeline._GetFailedRevisionFromCompileResult( | 75 IdentifyTryJobCulpritPipeline._GetFailedRevisionFromCompileResult( |
| 74 { | 76 { |
| 75 'report': [ | 77 'report': [ |
| 76 ['rev1', 'passed'], | 78 ['rev1', 'passed'], |
| 77 ['rev2', 'failed'] | 79 ['rev2', 'failed'] |
| 78 ] | 80 ] |
| 79 })) | 81 })) |
| 80 | 82 |
| 81 def testGetCulpritFromFailedRevision(self): | |
| 82 self.mock(GitRepository, 'GetChangeLog', self._MockGetChangeLog) | |
| 83 self.assertIsNone( | |
| 84 IdentifyTryJobCulpritPipeline._GetCulpritFromFailedRevision(None)) | |
| 85 self.assertIsNone( | |
| 86 IdentifyTryJobCulpritPipeline._GetCulpritFromFailedRevision( | |
| 87 'revision_with_no_change_log')) | |
| 88 self.assertEqual( | |
| 89 { | |
| 90 'revision': 'rev2', | |
| 91 'commit_position': '2', | |
| 92 'review_url': 'url_2' | |
| 93 }, | |
| 94 IdentifyTryJobCulpritPipeline._GetCulpritFromFailedRevision('rev2')) | |
| 95 | |
| 96 def testIdentifyCulpritForCompileTryJobNoCulprit(self): | 83 def testIdentifyCulpritForCompileTryJobNoCulprit(self): |
| 97 master_name = 'm' | 84 master_name = 'm' |
| 98 builder_name = 'b' | 85 builder_name = 'b' |
| 99 build_number = 1 | 86 build_number = 1 |
| 100 try_job_id = '1' | 87 try_job_id = '1' |
| 101 | 88 |
| 102 try_job = WfTryJob.Create(master_name, builder_name, build_number) | 89 try_job = WfTryJob.Create(master_name, builder_name, build_number) |
| 103 try_job.put() | 90 try_job.put() |
| 104 try_job_data = WfTryJobData.Create(try_job_id) | 91 try_job_data = WfTryJobData.Create(try_job_id) |
| 105 try_job_data.put() | 92 try_job_data.put() |
| 106 | 93 |
| 107 pipeline = IdentifyTryJobCulpritPipeline() | 94 pipeline = IdentifyTryJobCulpritPipeline() |
| 108 culprit = pipeline.run( | 95 culprit = pipeline.run( |
| 109 master_name, builder_name, build_number, try_job_id, None) | 96 master_name, builder_name, build_number, ['rev1'], |
| 97 TryJobType.COMPILE, '1', None) |
| 98 try_job = WfTryJob.Get(master_name, builder_name, build_number) |
| 110 | 99 |
| 111 self.assertEqual(wf_analysis_status.ANALYZED, try_job.status) | 100 self.assertEqual(wf_analysis_status.ANALYZED, try_job.status) |
| 112 self.assertEqual([], try_job.compile_results) | 101 self.assertEqual([], try_job.compile_results) |
| 113 self.assertIsNone(culprit) | 102 self.assertIsNone(culprit) |
| 114 self.assertIsNone(try_job_data.culprits) | 103 self.assertIsNone(try_job_data.culprits) |
| 115 | 104 |
| 116 def testIdentifyCulpritForCompileTryJobSuccess(self): | 105 def testIdentifyCulpritForCompileTryJobSuccess(self): |
| 117 master_name = 'm' | 106 master_name = 'm' |
| 118 builder_name = 'b' | 107 builder_name = 'b' |
| 119 build_number = 1 | 108 build_number = 1 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 133 | 122 |
| 134 try_job = WfTryJob.Create(master_name, builder_name, build_number) | 123 try_job = WfTryJob.Create(master_name, builder_name, build_number) |
| 135 try_job.status = wf_analysis_status.ANALYZING | 124 try_job.status = wf_analysis_status.ANALYZING |
| 136 try_job.compile_results = [{ | 125 try_job.compile_results = [{ |
| 137 'report': { | 126 'report': { |
| 138 'result': { | 127 'result': { |
| 139 'rev1': 'passed', | 128 'rev1': 'passed', |
| 140 'rev2': 'failed' | 129 'rev2': 'failed' |
| 141 }, | 130 }, |
| 142 }, | 131 }, |
| 143 'try_job_id': '1', | 132 'try_job_id': try_job_id, |
| 144 }] | 133 }] |
| 145 try_job.put() | 134 try_job.put() |
| 146 | 135 |
| 147 self.mock(GitRepository, 'GetChangeLog', self._MockGetChangeLog) | 136 self.mock(GitRepository, 'GetChangeLog', self._MockGetChangeLog) |
| 148 | 137 |
| 149 pipeline = IdentifyTryJobCulpritPipeline() | 138 pipeline = IdentifyTryJobCulpritPipeline() |
| 150 culprit = pipeline.run( | 139 culprit = pipeline.run( |
| 151 master_name, builder_name, build_number, try_job_id, compile_result) | 140 master_name, builder_name, build_number, ['rev1'], |
| 141 TryJobType.COMPILE, '1', compile_result) |
| 152 | 142 |
| 153 expected_culprit = 'rev2' | 143 expected_culprit = 'rev2' |
| 154 expected_compile_result = { | 144 expected_compile_result = { |
| 155 'report': { | 145 'report': { |
| 156 'result': { | 146 'result': { |
| 157 'rev1': 'passed', | 147 'rev1': 'passed', |
| 158 'rev2': 'failed' | 148 'rev2': 'failed' |
| 159 } | 149 } |
| 160 }, | 150 }, |
| 161 'try_job_id': '1', | 151 'try_job_id': try_job_id, |
| 162 'culprit': { | 152 'culprit': { |
| 163 'revision': expected_culprit, | 153 'revision': expected_culprit, |
| 164 'commit_position': '2', | 154 'commit_position': '2', |
| 165 'review_url': 'url_2' | 155 'review_url': 'url_2' |
| 166 } | 156 } |
| 167 } | 157 } |
| 168 | 158 |
| 169 self.assertEqual(expected_compile_result['culprit'], culprit) | 159 self.assertEqual(expected_compile_result['culprit'], culprit) |
| 170 | 160 |
| 171 try_job = WfTryJob.Get(master_name, builder_name, build_number) | 161 try_job = WfTryJob.Get(master_name, builder_name, build_number) |
| 172 self.assertEqual(expected_compile_result, try_job.compile_results[-1]) | 162 self.assertEqual(expected_compile_result, try_job.compile_results[-1]) |
| 173 self.assertEqual(wf_analysis_status.ANALYZED, try_job.status) | 163 self.assertEqual(wf_analysis_status.ANALYZED, try_job.status) |
| 174 | 164 |
| 175 try_job_data = WfTryJobData.Get(try_job_id) | 165 try_job_data = WfTryJobData.Get(try_job_id) |
| 176 self.assertEqual({'compile': expected_culprit}, try_job_data.culprits) | 166 self.assertEqual({'compile': expected_culprit}, try_job_data.culprits) |
| 167 |
| 168 def testIdentifyCulpritForCompileReturnNoneIfAllPassed(self): |
| 169 master_name = 'm' |
| 170 builder_name = 'b' |
| 171 build_number = 1 |
| 172 try_job_id = '1' |
| 173 |
| 174 compile_result = { |
| 175 'report': { |
| 176 'result': { |
| 177 'rev1': 'passed', |
| 178 'rev2': 'passed' |
| 179 } |
| 180 }, |
| 181 'url': 'url', |
| 182 'try_job_id': try_job_id, |
| 183 } |
| 184 |
| 185 WfTryJobData.Create(try_job_id).put() |
| 186 WfTryJob.Create(master_name, builder_name, build_number).put() |
| 187 |
| 188 pipeline = IdentifyTryJobCulpritPipeline() |
| 189 culprit = pipeline.run( |
| 190 master_name, builder_name, build_number, ['rev1'], |
| 191 TryJobType.COMPILE, '1', compile_result) |
| 192 try_job = WfTryJob.Get(master_name, builder_name, build_number) |
| 193 |
| 194 self.assertIsNone(culprit) |
| 195 self.assertEqual(wf_analysis_status.ANALYZED, try_job.status) |
| 196 |
| 197 try_job_data = WfTryJobData.Get(try_job_id) |
| 198 self.assertIsNone(try_job_data.culprits) |
| 199 |
| 200 def testIdentifyCulpritForTestTryJobReturnNoneIfNoTryJobResult(self): |
| 201 master_name = 'm' |
| 202 builder_name = 'b' |
| 203 build_number = 1 |
| 204 try_job_id = '1' |
| 205 |
| 206 WfTryJobData.Create(try_job_id).put() |
| 207 try_job = WfTryJob.Create(master_name, builder_name, build_number) |
| 208 try_job.status = wf_analysis_status.ANALYZING |
| 209 try_job.put() |
| 210 |
| 211 pipeline = IdentifyTryJobCulpritPipeline() |
| 212 culprit = pipeline.run( |
| 213 master_name, builder_name, build_number, ['rev1', 'rev2'], |
| 214 TryJobType.TEST, '1', None) |
| 215 |
| 216 self.assertIsNone(culprit) |
| 217 |
| 218 try_job_data = WfTryJobData.Get(try_job_id) |
| 219 self.assertIsNone(try_job_data.culprits) |
| 220 |
| 221 def testIdentifyCulpritForTestTryJobReturnNoneIfNoRevisionToCheck(self): |
| 222 master_name = 'm' |
| 223 builder_name = 'b' |
| 224 build_number = 1 |
| 225 try_job_id = '1' |
| 226 |
| 227 test_result = { |
| 228 'report': { |
| 229 'rev1': { |
| 230 'a_test': { |
| 231 'status': 'failed', |
| 232 'valid': True, |
| 233 'failures': ['a_test1'] |
| 234 } |
| 235 } |
| 236 }, |
| 237 'url': 'url', |
| 238 'try_job_id': try_job_id |
| 239 } |
| 240 |
| 241 WfTryJobData.Create(try_job_id).put() |
| 242 try_job = WfTryJob.Create(master_name, builder_name, build_number) |
| 243 try_job.status = wf_analysis_status.ANALYZING |
| 244 try_job.put() |
| 245 |
| 246 pipeline = IdentifyTryJobCulpritPipeline() |
| 247 culprit = pipeline.run( |
| 248 master_name, builder_name, build_number, [], TryJobType.TEST, '1', |
| 249 test_result) |
| 250 |
| 251 self.assertIsNone(culprit) |
| 252 |
| 253 try_job_data = WfTryJobData.Get(try_job_id) |
| 254 self.assertIsNone(try_job_data.culprits) |
| 255 |
| 256 def testIdentifyCulpritForTestTryJobReturnRevisionIfNoCulpritInfo(self): |
| 257 master_name = 'm' |
| 258 builder_name = 'b' |
| 259 build_number = 1 |
| 260 try_job_id = '1' |
| 261 |
| 262 test_result = { |
| 263 'report': { |
| 264 'rev3': { |
| 265 'a_test': { |
| 266 'status': 'failed', |
| 267 'valid': True, |
| 268 'failures': ['a_test1'] |
| 269 } |
| 270 } |
| 271 }, |
| 272 'url': 'url', |
| 273 'try_job_id': try_job_id |
| 274 } |
| 275 |
| 276 WfTryJobData.Create(try_job_id).put() |
| 277 try_job = WfTryJob.Create(master_name, builder_name, build_number) |
| 278 try_job.status = wf_analysis_status.ANALYZING |
| 279 try_job.put() |
| 280 |
| 281 pipeline = IdentifyTryJobCulpritPipeline() |
| 282 culprit = pipeline.run( |
| 283 master_name, builder_name, build_number, ['rev3'], TryJobType.TEST, |
| 284 '1', test_result) |
| 285 |
| 286 expected_culprit = { |
| 287 'a_test': { |
| 288 'tests': { |
| 289 'a_test1': { |
| 290 'revision': 'rev3' |
| 291 } |
| 292 } |
| 293 } |
| 294 } |
| 295 self.assertEqual(expected_culprit, culprit) |
| 296 |
| 297 try_job_data = WfTryJobData.Get(try_job_id) |
| 298 expected_culprit_data = { |
| 299 'a_test': { |
| 300 'a_test1': 'rev3' |
| 301 } |
| 302 } |
| 303 self.assertEqual(expected_culprit_data, try_job_data.culprits) |
| 304 |
| 305 def testIdentifyCulpritForTestTryJobSuccess(self): |
| 306 master_name = 'm' |
| 307 builder_name = 'b' |
| 308 build_number = 1 |
| 309 try_job_id = '1' |
| 310 |
| 311 test_result = { |
| 312 'report': { |
| 313 'rev1': { |
| 314 'a_test': { |
| 315 'status': 'failed', |
| 316 'valid': True, |
| 317 'failures': ['a_test1'] |
| 318 }, |
| 319 'b_test': { |
| 320 'status': 'failed', |
| 321 'valid': True, |
| 322 'failures': ['b_test1'] |
| 323 }, |
| 324 'c_test': { |
| 325 'status': 'passed', |
| 326 'valid': True |
| 327 } |
| 328 }, |
| 329 'rev2': { |
| 330 'a_test': { |
| 331 'status': 'failed', |
| 332 'valid': True, |
| 333 'failures': ['a_test1', 'a_test2'] |
| 334 }, |
| 335 'b_test': { |
| 336 'status': 'passed', |
| 337 'valid': True |
| 338 }, |
| 339 'c_test': { |
| 340 'status': 'failed', |
| 341 'valid': True, |
| 342 'failures': [] |
| 343 } |
| 344 } |
| 345 }, |
| 346 'url': 'url', |
| 347 'try_job_id': try_job_id |
| 348 } |
| 349 |
| 350 WfTryJobData.Create(try_job_id).put() |
| 351 try_job = WfTryJob.Create(master_name, builder_name, build_number) |
| 352 try_job.status = wf_analysis_status.ANALYZING |
| 353 try_job.test_results = [test_result] |
| 354 try_job.put() |
| 355 |
| 356 self.mock(GitRepository, 'GetChangeLog', self._MockGetChangeLog) |
| 357 |
| 358 pipeline = IdentifyTryJobCulpritPipeline() |
| 359 culprit = pipeline.run( |
| 360 master_name, builder_name, build_number, ['rev1', 'rev2'], |
| 361 TryJobType.TEST, '1', test_result) |
| 362 |
| 363 expected_test_result = { |
| 364 'report': { |
| 365 'rev1': { |
| 366 'a_test': { |
| 367 'status': 'failed', |
| 368 'valid': True, |
| 369 'failures': ['a_test1'] |
| 370 }, |
| 371 'b_test': { |
| 372 'status': 'failed', |
| 373 'valid': True, |
| 374 'failures': ['b_test1'] |
| 375 }, |
| 376 'c_test': { |
| 377 'status': 'passed', |
| 378 'valid': True |
| 379 } |
| 380 }, |
| 381 'rev2': { |
| 382 'a_test': { |
| 383 'status': 'failed', |
| 384 'valid': True, |
| 385 'failures': ['a_test1', 'a_test2'] |
| 386 }, |
| 387 'b_test': { |
| 388 'status': 'passed', |
| 389 'valid': True |
| 390 }, |
| 391 'c_test': { |
| 392 'status': 'failed', |
| 393 'valid': True, |
| 394 'failures': [] |
| 395 } |
| 396 } |
| 397 }, |
| 398 'url': 'url', |
| 399 'try_job_id': try_job_id, |
| 400 'culprit': { |
| 401 'a_test': { |
| 402 'tests': { |
| 403 'a_test1': { |
| 404 'revision': 'rev1', |
| 405 'commit_position': '1', |
| 406 'review_url': 'url_1' |
| 407 }, |
| 408 'a_test2': { |
| 409 'revision': 'rev2', |
| 410 'commit_position': '2', |
| 411 'review_url': 'url_2' |
| 412 } |
| 413 } |
| 414 }, |
| 415 'b_test': { |
| 416 'tests': { |
| 417 'b_test1': { |
| 418 'revision': 'rev1', |
| 419 'commit_position': '1', |
| 420 'review_url': 'url_1' |
| 421 } |
| 422 } |
| 423 }, |
| 424 'c_test': { |
| 425 'revision': 'rev2', |
| 426 'commit_position': '2', |
| 427 'review_url': 'url_2', |
| 428 'tests': {} |
| 429 } |
| 430 } |
| 431 } |
| 432 |
| 433 self.assertEqual(expected_test_result['culprit'], culprit) |
| 434 |
| 435 try_job = WfTryJob.Get(master_name, builder_name, build_number) |
| 436 self.assertEqual(expected_test_result, try_job.test_results[-1]) |
| 437 self.assertEqual(wf_analysis_status.ANALYZED, try_job.status) |
| 438 |
| 439 try_job_data = WfTryJobData.Get(try_job_id) |
| 440 expected_culprit_data = { |
| 441 'a_test': { |
| 442 'a_test1': 'rev1', |
| 443 'a_test2': 'rev2', |
| 444 }, |
| 445 'b_test': { |
| 446 'b_test1': 'rev1', |
| 447 }, |
| 448 'c_test': 'rev2' |
| 449 } |
| 450 self.assertEqual(expected_culprit_data, try_job_data.culprits) |
| OLD | NEW |