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