| 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 analysis_status | 8 from model import analysis_status |
| 9 from model import result_status |
| 10 from model.wf_analysis import WfAnalysis |
| 9 from model.wf_try_job import WfTryJob | 11 from model.wf_try_job import WfTryJob |
| 10 from model.wf_try_job_data import WfTryJobData | 12 from model.wf_try_job_data import WfTryJobData |
| 13 from waterfall import identify_try_job_culprit_pipeline |
| 11 from waterfall.identify_try_job_culprit_pipeline import( | 14 from waterfall.identify_try_job_culprit_pipeline import( |
| 12 IdentifyTryJobCulpritPipeline) | 15 IdentifyTryJobCulpritPipeline) |
| 13 from waterfall.try_job_type import TryJobType | 16 from waterfall.try_job_type import TryJobType |
| 14 | 17 |
| 15 | 18 |
| 16 class IdentifyTryJobCulpritPipelineTest(testing.AppengineTestCase): | 19 class IdentifyTryJobCulpritPipelineTest(testing.AppengineTestCase): |
| 17 | 20 |
| 18 def _MockGetChangeLog(self, revision): | 21 def _MockGetChangeLog(self, revision): |
| 19 class MockedChangeLog(object): | 22 class MockedChangeLog(object): |
| 20 | 23 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 IdentifyTryJobCulpritPipeline._GetFailedRevisionFromCompileResult( | 72 IdentifyTryJobCulpritPipeline._GetFailedRevisionFromCompileResult( |
| 70 { | 73 { |
| 71 'report': { | 74 'report': { |
| 72 'result': { | 75 'result': { |
| 73 'rev1': 'passed', | 76 'rev1': 'passed', |
| 74 'rev2': 'failed' | 77 'rev2': 'failed' |
| 75 } | 78 } |
| 76 } | 79 } |
| 77 })) | 80 })) |
| 78 | 81 |
| 82 def testGetResultanalysisStatusWithTryJobCulpritNotFoundUntriaged(self): |
| 83 # Heuristic analysis provided no results, but the try job found a culprit. |
| 84 analysis = WfAnalysis.Create('m', 'b', 1) |
| 85 analysis.result_status = result_status.NOT_FOUND_UNTRIAGED |
| 86 analysis.put() |
| 87 |
| 88 result = { |
| 89 'culprit': { |
| 90 'compile': { |
| 91 'revision': 'rev1', |
| 92 'commit_position': '1', |
| 93 'review_url': 'url_1', |
| 94 'repo_name': 'chromium' |
| 95 } |
| 96 } |
| 97 } |
| 98 |
| 99 status = identify_try_job_culprit_pipeline._GetResultAnalysisStatus( |
| 100 analysis, result) |
| 101 |
| 102 self.assertEqual(status, result_status.FOUND_UNTRIAGED) |
| 103 |
| 104 def testGetResultanalysisStatusWithTryJobCulpritNotFoundCorrect(self): |
| 105 # Heuristic analysis found no results, which was correct. In this case, the |
| 106 # try job result is actually a false positive. |
| 107 analysis = WfAnalysis.Create('m', 'b', 1) |
| 108 analysis.result_status = result_status.NOT_FOUND_CORRECT |
| 109 analysis.put() |
| 110 |
| 111 result = { |
| 112 'culprit': { |
| 113 'compile': { |
| 114 'revision': 'rev1', |
| 115 'commit_position': '1', |
| 116 'review_url': 'url_1', |
| 117 'repo_name': 'chromium' |
| 118 } |
| 119 } |
| 120 } |
| 121 |
| 122 status = identify_try_job_culprit_pipeline._GetResultAnalysisStatus( |
| 123 analysis, result) |
| 124 |
| 125 self.assertEqual(status, result_status.FOUND_UNTRIAGED) |
| 126 |
| 127 def testGetResultanalysisStatusWithTryJobCulpritNotFoundIncorrect(self): |
| 128 # Heuristic analysis found no results and was triaged to incorrect before a |
| 129 # try job result was found. In this case the try job result should override |
| 130 # the heuristic result. |
| 131 analysis = WfAnalysis.Create('m', 'b', 1) |
| 132 analysis.result_status = result_status.NOT_FOUND_INCORRECT |
| 133 analysis.put() |
| 134 |
| 135 result = { |
| 136 'culprit': { |
| 137 'compile': { |
| 138 'revision': 'rev1', |
| 139 'commit_position': '1', |
| 140 'review_url': 'url_1', |
| 141 'repo_name': 'chromium' |
| 142 } |
| 143 } |
| 144 } |
| 145 |
| 146 status = identify_try_job_culprit_pipeline._GetResultAnalysisStatus( |
| 147 analysis, result) |
| 148 |
| 149 self.assertEqual(status, result_status.FOUND_UNTRIAGED) |
| 150 |
| 151 def testGetResultanalysisStatusWithTryJobCulpritNoHeuristicResult(self): |
| 152 # In this case, the try job found a result before the heuristic result is |
| 153 # available. This case should generally never happen, as heuristic analysis |
| 154 # is usually much faster than try jobs. |
| 155 analysis = WfAnalysis.Create('m', 'b', 1) |
| 156 analysis.put() |
| 157 |
| 158 result = { |
| 159 'culprit': { |
| 160 'compile': { |
| 161 'revision': 'rev1', |
| 162 'commit_position': '1', |
| 163 'review_url': 'url_1', |
| 164 'repo_name': 'chromium' |
| 165 } |
| 166 } |
| 167 } |
| 168 |
| 169 status = identify_try_job_culprit_pipeline._GetResultAnalysisStatus( |
| 170 analysis, result) |
| 171 |
| 172 self.assertEqual(status, result_status.FOUND_UNTRIAGED) |
| 173 |
| 174 def testGetResultanalysisStatusWithNoTryJobCulpritNoHeuristicResult(self): |
| 175 # In this case, the try job completed faster than heuristic analysis |
| 176 # (which should never happen) but no results were found. |
| 177 analysis = WfAnalysis.Create('m', 'b', 1) |
| 178 analysis.put() |
| 179 |
| 180 result = {} |
| 181 |
| 182 status = identify_try_job_culprit_pipeline._GetResultAnalysisStatus( |
| 183 analysis, result) |
| 184 self.assertEqual(status, result_status.NOT_FOUND_UNTRIAGED) |
| 185 |
| 186 def testGetResultanalysisStatusWithTryJobCulpritAndHeuristicResult(self): |
| 187 # In this case, heuristic analysis found the correct culprit. The try job |
| 188 # result should not overwrite it. |
| 189 analysis = WfAnalysis.Create('m', 'b', 1) |
| 190 analysis.result_status = result_status.FOUND_CORRECT |
| 191 analysis.put() |
| 192 |
| 193 result = { |
| 194 'culprit': { |
| 195 'compile': { |
| 196 'revision': 'rev1', |
| 197 'commit_position': '1', |
| 198 'review_url': 'url_1', |
| 199 'repo_name': 'chromium' |
| 200 } |
| 201 } |
| 202 } |
| 203 |
| 204 status = identify_try_job_culprit_pipeline._GetResultAnalysisStatus( |
| 205 analysis, result) |
| 206 self.assertEqual(status, result_status.FOUND_CORRECT) |
| 207 |
| 208 def testGetResultanalysisStatusWithNoCulpritTriagedCorrect(self): |
| 209 # In this case, heuristic analysis correctly found no culprit and was |
| 210 # triaged, and the try job came back with nothing. The try job result should |
| 211 # not overwrite the heuristic result. |
| 212 analysis = WfAnalysis.Create('m', 'b', 1) |
| 213 analysis.result_status = result_status.NOT_FOUND_CORRECT |
| 214 analysis.put() |
| 215 |
| 216 result = {} |
| 217 |
| 218 status = identify_try_job_culprit_pipeline._GetResultAnalysisStatus( |
| 219 analysis, result) |
| 220 self.assertEqual(status, result_status.NOT_FOUND_CORRECT) |
| 221 |
| 222 def testGetResultanalysisStatusWithNoCulpritTriagedIncorrect(self): |
| 223 # In this case, heuristic analysis correctly found no culprit and was |
| 224 # triaged, and the try job came back with nothing. The try job result should |
| 225 # not overwrite the heuristic result. |
| 226 analysis = WfAnalysis.Create('m', 'b', 1) |
| 227 analysis.result_status = result_status.NOT_FOUND_INCORRECT |
| 228 analysis.put() |
| 229 |
| 230 result = {} |
| 231 |
| 232 status = identify_try_job_culprit_pipeline._GetResultAnalysisStatus( |
| 233 analysis, result) |
| 234 self.assertEqual(status, result_status.NOT_FOUND_INCORRECT) |
| 235 |
| 236 def testGetSuspectedCLsForCompileTryJob(self): |
| 237 heuristic_suspected_cl = { |
| 238 'revision': 'rev1', |
| 239 'commit_position': '1', |
| 240 'review_url': 'url_1', |
| 241 'repo_name': 'chromium' |
| 242 } |
| 243 |
| 244 compile_suspected_cl = { |
| 245 'revision': 'rev2', |
| 246 'commit_position': '2', |
| 247 'review_url': 'url_2', |
| 248 'repo_name': 'chromium' |
| 249 } |
| 250 |
| 251 analysis = WfAnalysis.Create('m', 'b', 1) |
| 252 analysis.suspected_cls = [heuristic_suspected_cl] |
| 253 analysis.put() |
| 254 |
| 255 result = { |
| 256 'culprit': { |
| 257 'compile': compile_suspected_cl |
| 258 } |
| 259 } |
| 260 |
| 261 self.assertEqual( |
| 262 identify_try_job_culprit_pipeline._GetSuspectedCLs(analysis, result), |
| 263 [heuristic_suspected_cl, compile_suspected_cl]) |
| 264 |
| 265 def testGetSuspectedCLsForTestTryJobAndHeuristicResultsSame(self): |
| 266 suspected_cl = { |
| 267 'revision': 'rev1', |
| 268 'commit_position': '1', |
| 269 'review_url': 'url_1', |
| 270 'repo_name': 'chromium' |
| 271 } |
| 272 |
| 273 analysis = WfAnalysis.Create('m', 'b', 1) |
| 274 analysis.suspected_cls = [suspected_cl] |
| 275 analysis.put() |
| 276 |
| 277 result = { |
| 278 'culprit': { |
| 279 'compile': suspected_cl |
| 280 } |
| 281 } |
| 282 |
| 283 self.assertEqual( |
| 284 identify_try_job_culprit_pipeline._GetSuspectedCLs(analysis, result), |
| 285 [suspected_cl]) |
| 286 |
| 287 def testGetSuspectedCLsForTestTryJob(self): |
| 288 suspected_cl1 = { |
| 289 'revision': 'rev1', |
| 290 'commit_position': '1', |
| 291 'review_url': 'url_1', |
| 292 'repo_name': 'chromium' |
| 293 } |
| 294 suspected_cl2 = { |
| 295 'revision': 'rev2', |
| 296 'commit_position': '2', |
| 297 'review_url': 'url_2', |
| 298 'repo_name': 'chromium' |
| 299 } |
| 300 suspected_cl3 = { |
| 301 'revision': 'rev3', |
| 302 'commit_position': '3', |
| 303 'review_url': 'url_3', |
| 304 'repo_name': 'chromium' |
| 305 } |
| 306 |
| 307 analysis = WfAnalysis.Create('m', 'b', 1) |
| 308 analysis.suspected_cls = [] |
| 309 analysis.put() |
| 310 |
| 311 result = { |
| 312 'culprit': { |
| 313 'a_test': { |
| 314 'tests': { |
| 315 'a_test1': suspected_cl1, |
| 316 'a_test2': suspected_cl1 |
| 317 } |
| 318 }, |
| 319 'b_test': { |
| 320 'tests': { |
| 321 'b_test1': suspected_cl2 |
| 322 } |
| 323 }, |
| 324 'c_test': { |
| 325 'revision': 'rev3', |
| 326 'commit_position': '3', |
| 327 'review_url': 'url_3', |
| 328 'repo_name': 'chromium', |
| 329 'tests': {} |
| 330 } |
| 331 } |
| 332 } |
| 333 |
| 334 self.assertEqual( |
| 335 identify_try_job_culprit_pipeline._GetSuspectedCLs(analysis, result), |
| 336 [suspected_cl3, suspected_cl2, suspected_cl1]) |
| 337 |
| 338 def testGetSuspectedCLsForTestTryJobWithHeuristicResult(self): |
| 339 suspected_cl = { |
| 340 'revision': 'rev1', |
| 341 'commit_position': '1', |
| 342 'review_url': 'url_1', |
| 343 'repo_name': 'chromium' |
| 344 } |
| 345 |
| 346 analysis = WfAnalysis.Create('m', 'b', 1) |
| 347 analysis.suspected_cls = [suspected_cl] |
| 348 analysis.put() |
| 349 |
| 350 result = { |
| 351 'culprit': { |
| 352 'a_test': { |
| 353 'revision': 'rev1', |
| 354 'commit_position': '1', |
| 355 'review_url': 'url_1', |
| 356 'repo_name': 'chromium', |
| 357 'tests': {} |
| 358 } |
| 359 } |
| 360 } |
| 361 |
| 362 self.assertEqual( |
| 363 identify_try_job_culprit_pipeline._GetSuspectedCLs(analysis, result), |
| 364 [suspected_cl]) |
| 365 |
| 79 def testIdentifyCulpritForCompileTryJobNoCulprit(self): | 366 def testIdentifyCulpritForCompileTryJobNoCulprit(self): |
| 80 master_name = 'm' | 367 master_name = 'm' |
| 81 builder_name = 'b' | 368 builder_name = 'b' |
| 82 build_number = 1 | 369 build_number = 1 |
| 83 try_job_id = '1' | 370 try_job_id = '1' |
| 84 | 371 |
| 85 try_job = WfTryJob.Create(master_name, builder_name, build_number) | 372 try_job = WfTryJob.Create(master_name, builder_name, build_number) |
| 86 try_job.put() | 373 try_job.put() |
| 87 try_job_data = WfTryJobData.Create(try_job_id) | 374 try_job_data = WfTryJobData.Create(try_job_id) |
| 88 try_job_data.put() | 375 try_job_data.put() |
| 89 | 376 |
| 377 analysis = WfAnalysis.Create(master_name, builder_name, build_number) |
| 378 analysis.put() |
| 379 |
| 90 pipeline = IdentifyTryJobCulpritPipeline() | 380 pipeline = IdentifyTryJobCulpritPipeline() |
| 91 culprit = pipeline.run( | 381 culprit = pipeline.run( |
| 92 master_name, builder_name, build_number, ['rev1'], | 382 master_name, builder_name, build_number, ['rev1'], |
| 93 TryJobType.COMPILE, '1', None) | 383 TryJobType.COMPILE, '1', None) |
| 94 try_job = WfTryJob.Get(master_name, builder_name, build_number) | 384 try_job = WfTryJob.Get(master_name, builder_name, build_number) |
| 95 | 385 |
| 96 self.assertEqual(analysis_status.COMPLETED, try_job.status) | 386 self.assertEqual(analysis_status.COMPLETED, try_job.status) |
| 97 self.assertEqual([], try_job.compile_results) | 387 self.assertEqual([], try_job.compile_results) |
| 98 self.assertIsNone(culprit) | 388 self.assertIsNone(culprit) |
| 99 self.assertIsNone(try_job_data.culprits) | 389 self.assertIsNone(try_job_data.culprits) |
| 390 self.assertEqual(analysis.result_status, |
| 391 result_status.NOT_FOUND_UNTRIAGED) |
| 392 self.assertEqual(analysis.suspected_cls, []) |
| 100 | 393 |
| 101 def testIdentifyCulpritForCompileTryJobSuccess(self): | 394 def testIdentifyCulpritForCompileTryJobSuccess(self): |
| 102 master_name = 'm' | 395 master_name = 'm' |
| 103 builder_name = 'b' | 396 builder_name = 'b' |
| 104 build_number = 1 | 397 build_number = 1 |
| 105 try_job_id = '1' | 398 try_job_id = '1' |
| 106 | 399 |
| 107 compile_result = { | 400 compile_result = { |
| 108 'report': { | 401 'report': { |
| 109 'result': { | 402 'result': { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 121 try_job.compile_results = [{ | 414 try_job.compile_results = [{ |
| 122 'report': { | 415 'report': { |
| 123 'result': { | 416 'result': { |
| 124 'rev1': 'passed', | 417 'rev1': 'passed', |
| 125 'rev2': 'failed' | 418 'rev2': 'failed' |
| 126 }, | 419 }, |
| 127 }, | 420 }, |
| 128 'try_job_id': try_job_id, | 421 'try_job_id': try_job_id, |
| 129 }] | 422 }] |
| 130 try_job.put() | 423 try_job.put() |
| 424 analysis = WfAnalysis.Create(master_name, builder_name, build_number) |
| 425 analysis.put() |
| 131 | 426 |
| 132 pipeline = IdentifyTryJobCulpritPipeline() | 427 pipeline = IdentifyTryJobCulpritPipeline() |
| 133 culprit = pipeline.run( | 428 culprit = pipeline.run( |
| 134 master_name, builder_name, build_number, ['rev1'], | 429 master_name, builder_name, build_number, ['rev1'], |
| 135 TryJobType.COMPILE, '1', compile_result) | 430 TryJobType.COMPILE, '1', compile_result) |
| 136 | 431 |
| 137 expected_culprit = 'rev2' | 432 expected_culprit = 'rev2' |
| 433 expected_suspected_cl = { |
| 434 'revision': 'rev2', |
| 435 'commit_position': '2', |
| 436 'review_url': 'url_2', |
| 437 'repo_name': 'chromium' |
| 438 } |
| 138 expected_compile_result = { | 439 expected_compile_result = { |
| 139 'report': { | 440 'report': { |
| 140 'result': { | 441 'result': { |
| 141 'rev1': 'passed', | 442 'rev1': 'passed', |
| 142 'rev2': 'failed' | 443 'rev2': 'failed' |
| 143 } | 444 } |
| 144 }, | 445 }, |
| 145 'try_job_id': try_job_id, | 446 'try_job_id': try_job_id, |
| 146 'culprit': { | 447 'culprit': { |
| 147 'compile': { | 448 'compile': expected_suspected_cl |
| 148 'revision': 'rev2', | |
| 149 'commit_position': '2', | |
| 150 'review_url': 'url_2' | |
| 151 } | |
| 152 } | 449 } |
| 153 } | 450 } |
| 154 | 451 |
| 155 self.assertEqual(expected_compile_result['culprit'], culprit) | 452 self.assertEqual(expected_compile_result['culprit'], culprit) |
| 156 | 453 |
| 157 try_job = WfTryJob.Get(master_name, builder_name, build_number) | 454 try_job = WfTryJob.Get(master_name, builder_name, build_number) |
| 158 self.assertEqual(expected_compile_result, try_job.compile_results[-1]) | 455 self.assertEqual(expected_compile_result, try_job.compile_results[-1]) |
| 159 self.assertEqual(analysis_status.COMPLETED, try_job.status) | 456 self.assertEqual(analysis_status.COMPLETED, try_job.status) |
| 160 | 457 |
| 161 try_job_data = WfTryJobData.Get(try_job_id) | 458 try_job_data = WfTryJobData.Get(try_job_id) |
| 162 self.assertEqual({'compile': expected_culprit}, try_job_data.culprits) | 459 self.assertEqual({'compile': expected_culprit}, try_job_data.culprits) |
| 460 self.assertEqual(analysis.result_status, |
| 461 result_status.FOUND_UNTRIAGED) |
| 462 self.assertEqual(analysis.suspected_cls, |
| 463 [expected_suspected_cl]) |
| 163 | 464 |
| 164 def testIdentifyCulpritForCompileReturnNoneIfAllPassed(self): | 465 def testIdentifyCulpritForCompileReturnNoneIfAllPassed(self): |
| 165 master_name = 'm' | 466 master_name = 'm' |
| 166 builder_name = 'b' | 467 builder_name = 'b' |
| 167 build_number = 1 | 468 build_number = 1 |
| 168 try_job_id = '1' | 469 try_job_id = '1' |
| 169 | 470 |
| 170 compile_result = { | 471 compile_result = { |
| 171 'report': { | 472 'report': { |
| 172 'result': { | 473 'result': { |
| 173 'rev1': 'passed', | 474 'rev1': 'passed', |
| 174 'rev2': 'passed' | 475 'rev2': 'passed' |
| 175 } | 476 } |
| 176 }, | 477 }, |
| 177 'url': 'url', | 478 'url': 'url', |
| 178 'try_job_id': try_job_id, | 479 'try_job_id': try_job_id, |
| 179 } | 480 } |
| 180 | 481 |
| 181 WfTryJobData.Create(try_job_id).put() | 482 WfTryJobData.Create(try_job_id).put() |
| 182 WfTryJob.Create(master_name, builder_name, build_number).put() | 483 WfTryJob.Create(master_name, builder_name, build_number).put() |
| 484 analysis = WfAnalysis.Create(master_name, builder_name, build_number) |
| 485 analysis.put() |
| 183 | 486 |
| 184 pipeline = IdentifyTryJobCulpritPipeline() | 487 pipeline = IdentifyTryJobCulpritPipeline() |
| 185 culprit = pipeline.run( | 488 culprit = pipeline.run( |
| 186 master_name, builder_name, build_number, ['rev1'], | 489 master_name, builder_name, build_number, ['rev1'], |
| 187 TryJobType.COMPILE, '1', compile_result) | 490 TryJobType.COMPILE, '1', compile_result) |
| 188 try_job = WfTryJob.Get(master_name, builder_name, build_number) | 491 try_job = WfTryJob.Get(master_name, builder_name, build_number) |
| 189 | 492 |
| 190 self.assertIsNone(culprit) | 493 self.assertIsNone(culprit) |
| 191 self.assertEqual(analysis_status.COMPLETED, try_job.status) | 494 self.assertEqual(analysis_status.COMPLETED, try_job.status) |
| 192 | 495 |
| 193 try_job_data = WfTryJobData.Get(try_job_id) | 496 try_job_data = WfTryJobData.Get(try_job_id) |
| 194 self.assertIsNone(try_job_data.culprits) | 497 self.assertIsNone(try_job_data.culprits) |
| 195 | 498 |
| 499 self.assertEqual(analysis.result_status, |
| 500 result_status.NOT_FOUND_UNTRIAGED) |
| 501 self.assertEqual(analysis.suspected_cls, []) |
| 502 |
| 196 def testIdentifyCulpritForTestTryJobReturnNoneIfNoTryJobResult(self): | 503 def testIdentifyCulpritForTestTryJobReturnNoneIfNoTryJobResult(self): |
| 197 master_name = 'm' | 504 master_name = 'm' |
| 198 builder_name = 'b' | 505 builder_name = 'b' |
| 199 build_number = 1 | 506 build_number = 1 |
| 200 try_job_id = '1' | 507 try_job_id = '1' |
| 201 | 508 |
| 202 WfTryJobData.Create(try_job_id).put() | 509 WfTryJobData.Create(try_job_id).put() |
| 203 try_job = WfTryJob.Create(master_name, builder_name, build_number) | 510 try_job = WfTryJob.Create(master_name, builder_name, build_number) |
| 204 try_job.status = analysis_status.RUNNING | 511 try_job.status = analysis_status.RUNNING |
| 205 try_job.put() | 512 try_job.put() |
| 513 analysis = WfAnalysis.Create(master_name, builder_name, build_number) |
| 514 analysis.put() |
| 206 | 515 |
| 207 pipeline = IdentifyTryJobCulpritPipeline() | 516 pipeline = IdentifyTryJobCulpritPipeline() |
| 208 culprit = pipeline.run( | 517 culprit = pipeline.run( |
| 209 master_name, builder_name, build_number, ['rev1', 'rev2'], | 518 master_name, builder_name, build_number, ['rev1', 'rev2'], |
| 210 TryJobType.TEST, '1', None) | 519 TryJobType.TEST, '1', None) |
| 211 | 520 |
| 212 self.assertIsNone(culprit) | 521 self.assertIsNone(culprit) |
| 213 | 522 |
| 214 try_job_data = WfTryJobData.Get(try_job_id) | 523 try_job_data = WfTryJobData.Get(try_job_id) |
| 215 self.assertIsNone(try_job_data.culprits) | 524 self.assertIsNone(try_job_data.culprits) |
| 525 self.assertEqual(analysis.result_status, |
| 526 result_status.NOT_FOUND_UNTRIAGED) |
| 527 self.assertEqual(analysis.suspected_cls, []) |
| 216 | 528 |
| 217 def testIdentifyCulpritForTestTryJobReturnNoneIfNoRevisionToCheck(self): | 529 def testIdentifyCulpritForTestTryJobReturnNoneIfNoRevisionToCheck(self): |
| 218 master_name = 'm' | 530 master_name = 'm' |
| 219 builder_name = 'b' | 531 builder_name = 'b' |
| 220 build_number = 1 | 532 build_number = 1 |
| 221 try_job_id = '1' | 533 try_job_id = '1' |
| 222 | 534 |
| 223 test_result = { | 535 test_result = { |
| 224 'report': { | 536 'report': { |
| 225 'result': { | 537 'result': { |
| 226 'rev1': { | 538 'rev1': { |
| 227 'a_test': { | 539 'a_test': { |
| 228 'status': 'failed', | 540 'status': 'failed', |
| 229 'valid': True, | 541 'valid': True, |
| 230 'failures': ['a_test1'] | 542 'failures': ['a_test1'] |
| 231 } | 543 } |
| 232 } | 544 } |
| 233 } | 545 } |
| 234 }, | 546 }, |
| 235 'url': 'url', | 547 'url': 'url', |
| 236 'try_job_id': try_job_id | 548 'try_job_id': try_job_id |
| 237 } | 549 } |
| 238 | 550 |
| 239 WfTryJobData.Create(try_job_id).put() | 551 WfTryJobData.Create(try_job_id).put() |
| 240 try_job = WfTryJob.Create(master_name, builder_name, build_number) | 552 try_job = WfTryJob.Create(master_name, builder_name, build_number) |
| 241 try_job.status = analysis_status.RUNNING | 553 try_job.status = analysis_status.RUNNING |
| 242 try_job.put() | 554 try_job.put() |
| 555 analysis = WfAnalysis.Create(master_name, builder_name, build_number) |
| 556 analysis.put() |
| 243 | 557 |
| 244 pipeline = IdentifyTryJobCulpritPipeline() | 558 pipeline = IdentifyTryJobCulpritPipeline() |
| 245 culprit = pipeline.run( | 559 culprit = pipeline.run( |
| 246 master_name, builder_name, build_number, [], TryJobType.TEST, '1', | 560 master_name, builder_name, build_number, [], TryJobType.TEST, '1', |
| 247 test_result) | 561 test_result) |
| 248 | 562 |
| 249 self.assertIsNone(culprit) | 563 self.assertIsNone(culprit) |
| 250 | 564 |
| 251 try_job_data = WfTryJobData.Get(try_job_id) | 565 try_job_data = WfTryJobData.Get(try_job_id) |
| 252 self.assertIsNone(try_job_data.culprits) | 566 self.assertIsNone(try_job_data.culprits) |
| 253 | 567 |
| 568 self.assertEqual(analysis.result_status, |
| 569 result_status.NOT_FOUND_UNTRIAGED) |
| 570 self.assertEqual(analysis.suspected_cls, []) |
| 571 |
| 254 def testIdentifyCulpritForTestTryJobReturnRevisionIfNoCulpritInfo(self): | 572 def testIdentifyCulpritForTestTryJobReturnRevisionIfNoCulpritInfo(self): |
| 255 master_name = 'm' | 573 master_name = 'm' |
| 256 builder_name = 'b' | 574 builder_name = 'b' |
| 257 build_number = 1 | 575 build_number = 1 |
| 258 try_job_id = '1' | 576 try_job_id = '1' |
| 259 | 577 |
| 260 test_result = { | 578 test_result = { |
| 261 'report': { | 579 'report': { |
| 262 'result': { | 580 'result': { |
| 263 'rev3': { | 581 'rev3': { |
| 264 'a_test': { | 582 'a_test': { |
| 265 'status': 'failed', | 583 'status': 'failed', |
| 266 'valid': True, | 584 'valid': True, |
| 267 'failures': ['a_test1'] | 585 'failures': ['a_test1'] |
| 268 } | 586 } |
| 269 } | 587 } |
| 270 } | 588 } |
| 271 }, | 589 }, |
| 272 'url': 'url', | 590 'url': 'url', |
| 273 'try_job_id': try_job_id | 591 'try_job_id': try_job_id |
| 274 } | 592 } |
| 275 | 593 |
| 276 WfTryJobData.Create(try_job_id).put() | 594 WfTryJobData.Create(try_job_id).put() |
| 277 try_job = WfTryJob.Create(master_name, builder_name, build_number) | 595 try_job = WfTryJob.Create(master_name, builder_name, build_number) |
| 278 try_job.status = analysis_status.RUNNING | 596 try_job.status = analysis_status.RUNNING |
| 279 try_job.put() | 597 try_job.put() |
| 598 analysis = WfAnalysis.Create(master_name, builder_name, build_number) |
| 599 analysis.put() |
| 280 | 600 |
| 281 pipeline = IdentifyTryJobCulpritPipeline() | 601 pipeline = IdentifyTryJobCulpritPipeline() |
| 282 culprit = pipeline.run( | 602 culprit = pipeline.run( |
| 283 master_name, builder_name, build_number, ['rev3'], TryJobType.TEST, | 603 master_name, builder_name, build_number, ['rev3'], TryJobType.TEST, |
| 284 '1', test_result) | 604 '1', test_result) |
| 285 | 605 |
| 606 expected_suspected_cl = { |
| 607 'revision': 'rev3', |
| 608 'repo_name': 'chromium' |
| 609 } |
| 610 |
| 286 expected_culprit = { | 611 expected_culprit = { |
| 287 'a_test': { | 612 'a_test': { |
| 288 'tests': { | 613 'tests': { |
| 289 'a_test1': { | 614 'a_test1': expected_suspected_cl |
| 290 'revision': 'rev3' | |
| 291 } | |
| 292 } | 615 } |
| 293 } | 616 } |
| 294 } | 617 } |
| 295 self.assertEqual(expected_culprit, culprit) | 618 self.assertEqual(expected_culprit, culprit) |
| 296 | 619 |
| 297 try_job_data = WfTryJobData.Get(try_job_id) | 620 try_job_data = WfTryJobData.Get(try_job_id) |
| 298 expected_culprit_data = { | 621 expected_culprit_data = { |
| 299 'a_test': { | 622 'a_test': { |
| 300 'a_test1': 'rev3' | 623 'a_test1': 'rev3' |
| 301 } | 624 } |
| 302 } | 625 } |
| 303 self.assertEqual(expected_culprit_data, try_job_data.culprits) | 626 self.assertEqual(expected_culprit_data, try_job_data.culprits) |
| 627 self.assertEqual(analysis.result_status, |
| 628 result_status.FOUND_UNTRIAGED) |
| 629 self.assertEqual(analysis.suspected_cls, [expected_suspected_cl]) |
| 304 | 630 |
| 305 def testIdentifyCulpritForTestTryJobSuccess(self): | 631 def testIdentifyCulpritForTestTryJobSuccess(self): |
| 306 master_name = 'm' | 632 master_name = 'm' |
| 307 builder_name = 'b' | 633 builder_name = 'b' |
| 308 build_number = 1 | 634 build_number = 1 |
| 309 try_job_id = '1' | 635 try_job_id = '1' |
| 310 | 636 |
| 311 test_result = { | 637 test_result = { |
| 312 'report': { | 638 'report': { |
| 313 'result': { | 639 'result': { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 }, | 673 }, |
| 348 'url': 'url', | 674 'url': 'url', |
| 349 'try_job_id': try_job_id | 675 'try_job_id': try_job_id |
| 350 } | 676 } |
| 351 | 677 |
| 352 WfTryJobData.Create(try_job_id).put() | 678 WfTryJobData.Create(try_job_id).put() |
| 353 try_job = WfTryJob.Create(master_name, builder_name, build_number) | 679 try_job = WfTryJob.Create(master_name, builder_name, build_number) |
| 354 try_job.status = analysis_status.RUNNING | 680 try_job.status = analysis_status.RUNNING |
| 355 try_job.test_results = [test_result] | 681 try_job.test_results = [test_result] |
| 356 try_job.put() | 682 try_job.put() |
| 683 analysis = WfAnalysis.Create(master_name, builder_name, build_number) |
| 684 analysis.put() |
| 357 | 685 |
| 358 pipeline = IdentifyTryJobCulpritPipeline() | 686 pipeline = IdentifyTryJobCulpritPipeline() |
| 359 culprit = pipeline.run( | 687 culprit = pipeline.run( |
| 360 master_name, builder_name, build_number, ['rev1', 'rev2'], | 688 master_name, builder_name, build_number, ['rev1', 'rev2'], |
| 361 TryJobType.TEST, '1', test_result) | 689 TryJobType.TEST, '1', test_result) |
| 362 | 690 |
| 691 a_test1_suspected_cl = { |
| 692 'revision': 'rev1', |
| 693 'commit_position': '1', |
| 694 'review_url': 'url_1', |
| 695 'repo_name': 'chromium' |
| 696 } |
| 697 a_test2_suspected_cl = { |
| 698 'revision': 'rev2', |
| 699 'commit_position': '2', |
| 700 'review_url': 'url_2', |
| 701 'repo_name': 'chromium' |
| 702 } |
| 703 |
| 704 b_test1_suspected_cl = a_test1_suspected_cl |
| 705 |
| 363 expected_test_result = { | 706 expected_test_result = { |
| 364 'report': { | 707 'report': { |
| 365 'result': { | 708 'result': { |
| 366 'rev1': { | 709 'rev1': { |
| 367 'a_test': { | 710 'a_test': { |
| 368 'status': 'failed', | 711 'status': 'failed', |
| 369 'valid': True, | 712 'valid': True, |
| 370 'failures': ['a_test1'] | 713 'failures': ['a_test1'] |
| 371 }, | 714 }, |
| 372 'b_test': { | 715 'b_test': { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 395 'failures': [] | 738 'failures': [] |
| 396 } | 739 } |
| 397 } | 740 } |
| 398 } | 741 } |
| 399 }, | 742 }, |
| 400 'url': 'url', | 743 'url': 'url', |
| 401 'try_job_id': try_job_id, | 744 'try_job_id': try_job_id, |
| 402 'culprit': { | 745 'culprit': { |
| 403 'a_test': { | 746 'a_test': { |
| 404 'tests': { | 747 'tests': { |
| 405 'a_test1': { | 748 'a_test1': a_test1_suspected_cl, |
| 406 'revision': 'rev1', | 749 'a_test2': a_test2_suspected_cl |
| 407 'commit_position': '1', | |
| 408 'review_url': 'url_1' | |
| 409 }, | |
| 410 'a_test2': { | |
| 411 'revision': 'rev2', | |
| 412 'commit_position': '2', | |
| 413 'review_url': 'url_2' | |
| 414 } | |
| 415 } | 750 } |
| 416 }, | 751 }, |
| 417 'b_test': { | 752 'b_test': { |
| 418 'tests': { | 753 'tests': { |
| 419 'b_test1': { | 754 'b_test1': b_test1_suspected_cl |
| 420 'revision': 'rev1', | |
| 421 'commit_position': '1', | |
| 422 'review_url': 'url_1' | |
| 423 } | |
| 424 } | 755 } |
| 425 }, | 756 }, |
| 426 'c_test': { | 757 'c_test': { |
| 427 'revision': 'rev2', | 758 'revision': 'rev2', |
| 428 'commit_position': '2', | 759 'commit_position': '2', |
| 429 'review_url': 'url_2', | 760 'review_url': 'url_2', |
| 761 'repo_name': 'chromium', |
| 430 'tests': {} | 762 'tests': {} |
| 431 } | 763 } |
| 432 } | 764 } |
| 433 } | 765 } |
| 434 | 766 |
| 435 self.assertEqual(expected_test_result['culprit'], culprit) | 767 self.assertEqual(expected_test_result['culprit'], culprit) |
| 436 | 768 |
| 437 try_job = WfTryJob.Get(master_name, builder_name, build_number) | 769 try_job = WfTryJob.Get(master_name, builder_name, build_number) |
| 438 self.assertEqual(expected_test_result, try_job.test_results[-1]) | 770 self.assertEqual(expected_test_result, try_job.test_results[-1]) |
| 439 self.assertEqual(analysis_status.COMPLETED, try_job.status) | 771 self.assertEqual(analysis_status.COMPLETED, try_job.status) |
| 440 | 772 |
| 441 try_job_data = WfTryJobData.Get(try_job_id) | 773 try_job_data = WfTryJobData.Get(try_job_id) |
| 442 expected_culprit_data = { | 774 expected_culprit_data = { |
| 443 'a_test': { | 775 'a_test': { |
| 444 'a_test1': 'rev1', | 776 'a_test1': 'rev1', |
| 445 'a_test2': 'rev2', | 777 'a_test2': 'rev2', |
| 446 }, | 778 }, |
| 447 'b_test': { | 779 'b_test': { |
| 448 'b_test1': 'rev1', | 780 'b_test1': 'rev1', |
| 449 }, | 781 }, |
| 450 'c_test': 'rev2' | 782 'c_test': 'rev2' |
| 451 } | 783 } |
| 452 self.assertEqual(expected_culprit_data, try_job_data.culprits) | 784 self.assertEqual(expected_culprit_data, try_job_data.culprits) |
| 785 self.assertEqual(analysis.result_status, |
| 786 result_status.FOUND_UNTRIAGED) |
| 787 self.assertEqual(analysis.suspected_cls, |
| 788 [a_test2_suspected_cl, a_test1_suspected_cl]) |
| 789 |
| 790 def testAnalysisIsUpdatedOnlyIfStatusOrSuspectedCLsChanged(self): |
| 791 master_name = 'm' |
| 792 builder_name = 'b' |
| 793 build_number = 1 |
| 794 try_job_id = '1' |
| 795 |
| 796 suspected_cl = { |
| 797 'revision': 'rev1', |
| 798 'commit_position': '1', |
| 799 'review_url': 'url_1', |
| 800 'repo_name': 'chromium' |
| 801 } |
| 802 |
| 803 analysis = WfAnalysis.Create(master_name, builder_name, build_number) |
| 804 analysis.suspected_cls = [suspected_cl] |
| 805 analysis.result_status = result_status.FOUND_UNTRIAGED |
| 806 analysis.put() |
| 807 version = analysis.version |
| 808 compile_result = { |
| 809 'report': { |
| 810 'result': { |
| 811 'rev1': 'failed', |
| 812 }, |
| 813 }, |
| 814 } |
| 815 |
| 816 try_job_data = WfTryJobData.Create(try_job_id) |
| 817 try_job_data.put() |
| 818 |
| 819 try_job = WfTryJob.Create(master_name, builder_name, build_number) |
| 820 try_job.status = analysis_status.RUNNING |
| 821 try_job.compile_results = [{ |
| 822 'report': { |
| 823 'result': { |
| 824 'rev1': 'failed', |
| 825 }, |
| 826 }, |
| 827 'try_job_id': try_job_id, |
| 828 }] |
| 829 |
| 830 try_job.put() |
| 831 |
| 832 pipeline = IdentifyTryJobCulpritPipeline() |
| 833 pipeline.run(master_name, builder_name, build_number, ['rev1'], |
| 834 TryJobType.COMPILE, '1', compile_result) |
| 835 |
| 836 self.assertEqual(analysis.result_status, |
| 837 result_status.FOUND_UNTRIAGED) |
| 838 self.assertEqual(analysis.suspected_cls, [suspected_cl]) |
| 839 self.assertEqual(version, analysis.version) # No update to analysis. |
| OLD | NEW |