| 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 datetime import datetime | 5 from datetime import datetime |
| 6 from datetime import timedelta | 6 from datetime import timedelta |
| 7 | 7 |
| 8 from google.appengine.ext import ndb | 8 from testing_utils import testing |
| 9 import webapp2 | 9 import webapp2 |
| 10 | 10 |
| 11 from testing_utils import testing | |
| 12 | |
| 13 from handlers import triage_analysis | 11 from handlers import triage_analysis |
| 14 from model import analysis_status | 12 from model import analysis_status |
| 15 from model import result_status | 13 from model import result_status |
| 16 from model.wf_analysis import WfAnalysis | 14 from model.wf_analysis import WfAnalysis |
| 17 from waterfall import buildbot | 15 from waterfall import buildbot |
| 18 | 16 |
| 19 | 17 |
| 20 class TriageAnalysisTest(testing.AppengineTestCase): | 18 class TriageAnalysisTest(testing.AppengineTestCase): |
| 21 app_module = webapp2.WSGIApplication([ | 19 app_module = webapp2.WSGIApplication([ |
| 22 ('/triage-analysis', triage_analysis.TriageAnalysis), | 20 ('/triage-analysis', triage_analysis.TriageAnalysis), |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 self.assertEquals(2, len(analysis.triage_history)) | 116 self.assertEquals(2, len(analysis.triage_history)) |
| 119 self.assertEquals(result_status.FOUND_CORRECT, | 117 self.assertEquals(result_status.FOUND_CORRECT, |
| 120 analysis.triage_history[0]['result_status']) | 118 analysis.triage_history[0]['result_status']) |
| 121 self.assertEquals(result_status.FOUND_INCORRECT, | 119 self.assertEquals(result_status.FOUND_INCORRECT, |
| 122 analysis.triage_history[1]['result_status']) | 120 analysis.triage_history[1]['result_status']) |
| 123 | 121 |
| 124 def testInvalidBuildUrl(self): | 122 def testInvalidBuildUrl(self): |
| 125 build_url = 'http://invalid/build/url' | 123 build_url = 'http://invalid/build/url' |
| 126 response = self.test_app.get( | 124 response = self.test_app.get( |
| 127 '/triage-analysis', | 125 '/triage-analysis', |
| 128 params={'url': build_url, 'correct': True, 'format': 'json'}) | 126 params={ |
| 127 'url': build_url, |
| 128 'correct': True, |
| 129 'format': 'json' |
| 130 }) |
| 129 self.assertEquals(200, response.status_int) | 131 self.assertEquals(200, response.status_int) |
| 130 self.assertEquals({'success': False}, response.json_body) | 132 self.assertEquals({'success': False}, response.json_body) |
| 131 | 133 |
| 132 def testSuccessfulTriage(self): | 134 def testSuccessfulTriage(self): |
| 133 build_url = buildbot.CreateBuildUrl( | 135 build_url = buildbot.CreateBuildUrl( |
| 134 self.master_name, self.builder_name, self.build_number_found) | 136 self.master_name, self.builder_name, self.build_number_found) |
| 135 response = self.test_app.get( | 137 response = self.test_app.get( |
| 136 '/triage-analysis', | 138 '/triage-analysis', |
| 137 params={'url': build_url, 'correct': True, 'format': 'json'}) | 139 params={ |
| 140 'url': build_url, |
| 141 'correct': True, |
| 142 'format': 'json' |
| 143 }) |
| 138 self.assertEquals(200, response.status_int) | 144 self.assertEquals(200, response.status_int) |
| 139 self.assertEquals({'success': True}, response.json_body) | 145 self.assertEquals( |
| 146 { |
| 147 'success': True, |
| 148 'num_duplicate_analyses': 0 |
| 149 }, |
| 150 response.json_body) |
| 140 | 151 |
| 141 def testIncompleteTriage(self): | 152 def testIncompleteTriage(self): |
| 142 build_url = buildbot.CreateBuildUrl( | 153 build_url = buildbot.CreateBuildUrl( |
| 143 self.master_name, self.builder_name, self.build_number_incomplete) | 154 self.master_name, self.builder_name, self.build_number_incomplete) |
| 144 response = self.test_app.get( | 155 response = self.test_app.get( |
| 145 '/triage-analysis', | 156 '/triage-analysis', |
| 146 params={'url': build_url, 'correct': True, 'format': 'json'}) | 157 params={ |
| 158 'url': build_url, |
| 159 'correct': True, |
| 160 'format': 'json' |
| 161 }) |
| 147 self.assertEquals(200, response.status_int) | 162 self.assertEquals(200, response.status_int) |
| 148 self.assertEquals({'success': False}, response.json_body) | 163 self.assertEquals( |
| 164 { |
| 165 'success': False, |
| 166 'num_duplicate_analyses': 0 |
| 167 }, |
| 168 response.json_body) |
| 149 | 169 |
| 150 def testAnalysesMatch(self): | 170 def testAnalysesMatch(self): |
| 151 analysis_with_empty_failures = WfAnalysis.Create( | 171 analysis_with_empty_failures = WfAnalysis.Create( |
| 152 self.master_name, self.builder_name, 200) | 172 self.master_name, self.builder_name, 200) |
| 153 analysis_with_empty_failures.result = { | 173 analysis_with_empty_failures.result = { |
| 154 'failures': [] | 174 'failures': [] |
| 155 } | 175 } |
| 156 analysis_with_empty_failures.put() | 176 analysis_with_empty_failures.put() |
| 157 | 177 |
| 158 analysis_with_no_suspected_cls = WfAnalysis.Create( | 178 analysis_with_no_suspected_cls = WfAnalysis.Create( |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 self.assertFalse(triage_analysis._DoAnalysesMatch( | 377 self.assertFalse(triage_analysis._DoAnalysesMatch( |
| 358 analysis_with_tests_1, | 378 analysis_with_tests_1, |
| 359 analysis_with_tests_2)) | 379 analysis_with_tests_2)) |
| 360 | 380 |
| 361 def _createAnalysis(self, build_number, build_start_time): | 381 def _createAnalysis(self, build_number, build_start_time): |
| 362 analysis = WfAnalysis.Create( | 382 analysis = WfAnalysis.Create( |
| 363 self.master_name, self.builder_name, build_number) | 383 self.master_name, self.builder_name, build_number) |
| 364 analysis.result = { | 384 analysis.result = { |
| 365 'failures': [ | 385 'failures': [ |
| 366 { | 386 { |
| 367 'suspected_cls': [ | 387 'suspected_cls': self.suspected_cls, |
| 368 { | |
| 369 'revision': 'abc', | |
| 370 } | |
| 371 ], | |
| 372 'step_name': 'step_4', | 388 'step_name': 'step_4', |
| 373 } | 389 } |
| 374 ] | 390 ] |
| 375 } | 391 } |
| 376 analysis.result_status = result_status.FOUND_UNTRIAGED | 392 analysis.result_status = result_status.FOUND_UNTRIAGED |
| 377 analysis.build_start_time = build_start_time | 393 analysis.build_start_time = build_start_time |
| 378 analysis.status = analysis_status.COMPLETED | 394 analysis.status = analysis_status.COMPLETED |
| 395 analysis.suspected_cls = self.suspected_cls |
| 379 analysis.put() | 396 analysis.put() |
| 380 return analysis | 397 return analysis |
| 381 | 398 |
| 382 def testGetDuplicateAnalysesTooEarly(self): | 399 def testGetDuplicateAnalysesTooEarly(self): |
| 383 # Two days ago, UTC Noon. | 400 # Two days ago, UTC Noon. |
| 384 original_time = (datetime.utcnow() - timedelta(days=2)).replace( | 401 original_time = (datetime.utcnow() - timedelta(days=2)).replace( |
| 385 hour=12, minute=0, second=0, microsecond=0) | 402 hour=12, minute=0, second=0, microsecond=0) |
| 386 analysis_original = self._createAnalysis(300, original_time) | 403 analysis_original = self._createAnalysis(300, original_time) |
| 387 | 404 |
| 388 # An earlier time, outside bounds. | 405 # An earlier time, outside bounds. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 analysis_original = self._createAnalysis(306, original_time) | 445 analysis_original = self._createAnalysis(306, original_time) |
| 429 | 446 |
| 430 # A later time, outside bounds. | 447 # A later time, outside bounds. |
| 431 too_late_time = (original_time + timedelta( | 448 too_late_time = (original_time + timedelta( |
| 432 hours=triage_analysis.MATCHING_ANALYSIS_HOURS_AGO_START*2)) | 449 hours=triage_analysis.MATCHING_ANALYSIS_HOURS_AGO_START*2)) |
| 433 self._createAnalysis(307, too_late_time) | 450 self._createAnalysis(307, too_late_time) |
| 434 | 451 |
| 435 self.assertEquals( | 452 self.assertEquals( |
| 436 len(triage_analysis._GetDuplicateAnalyses(analysis_original)), 0) | 453 len(triage_analysis._GetDuplicateAnalyses(analysis_original)), 0) |
| 437 | 454 |
| 438 def testGetDuplicateAnalysesNotToday(self): | 455 def testGetDuplicateAnalysesPastEndBoundTime(self): |
| 439 # Tomorrow, UTC Noon. | 456 # Tomorrow, UTC Noon. |
| 440 original_time = (datetime.utcnow() + timedelta(days=1)).replace( | 457 original_time = (datetime.utcnow() + timedelta(days=1)).replace( |
| 441 hour=12, minute=0, second=0, microsecond=0) | 458 hour=12, minute=0, second=0, microsecond=0) |
| 442 analysis_original = self._createAnalysis(308, original_time) | 459 analysis_original = self._createAnalysis(308, original_time) |
| 443 | 460 |
| 444 # Create another analysis at the same time (also tomorrow). | 461 # Create another analysis at the same time (also tomorrow). |
| 445 self._createAnalysis(309, original_time) | 462 self._createAnalysis(309, original_time) |
| 446 | 463 |
| 447 self.assertEquals( | 464 self.assertEquals( |
| 448 len(triage_analysis._GetDuplicateAnalyses(analysis_original)), 0) | 465 len(triage_analysis._GetDuplicateAnalyses(analysis_original)), 0) |
| 449 | 466 |
| 450 def testTriageDuplicateResults(self): | 467 def testTriageDuplicateResultsFoundCorrectDuplicate(self): |
| 451 # Two days ago, UTC Noon. | 468 # Two days ago, UTC Noon. |
| 452 original_time = (datetime.utcnow() - timedelta(days=2)).replace( | 469 original_time = (datetime.utcnow() - timedelta(days=2)).replace( |
| 453 hour=12, minute=0, second=0, microsecond=0) | 470 hour=12, minute=0, second=0, microsecond=0) |
| 454 analysis_original = self._createAnalysis(310, original_time) | 471 analysis_original = self._createAnalysis(310, original_time) |
| 455 | 472 |
| 456 # Create another analysis at the same time (also two days ago). | 473 # Create another analysis a bit later (also two days ago). |
| 457 self._createAnalysis(311, original_time) | 474 self._createAnalysis(311, original_time + timedelta(minutes=1)) |
| 458 | 475 |
| 459 triage_analysis._TriageDuplicateResults(analysis_original, True) | 476 triage_analysis._TriageAndCountDuplicateResults(analysis_original, |
| 477 is_correct=True) |
| 460 | 478 |
| 461 second_analysis = WfAnalysis.Get(self.master_name, self.builder_name, 311) | 479 second_analysis = WfAnalysis.Get(self.master_name, self.builder_name, 311) |
| 462 | 480 |
| 463 self.assertEquals(result_status.NOT_FOUND_CORRECT, | 481 self.assertEquals(result_status.FOUND_CORRECT_DUPLICATE, |
| 464 second_analysis.result_status) | 482 second_analysis.result_status) |
| 465 | 483 |
| 484 def testTriageDuplicateResultsFoundIncorrectDuplicate(self): |
| 485 # Two days ago, UTC Noon. |
| 486 original_time = (datetime.utcnow() - timedelta(days=2)).replace( |
| 487 hour=12, minute=0, second=0, microsecond=0) |
| 488 analysis_original = self._createAnalysis(312, original_time) |
| 489 |
| 490 # Create another analysis a bit later (also two days ago). |
| 491 self._createAnalysis(313, original_time + timedelta(minutes=1)) |
| 492 |
| 493 triage_analysis._TriageAndCountDuplicateResults(analysis_original, |
| 494 is_correct=False) |
| 495 |
| 496 second_analysis = WfAnalysis.Get(self.master_name, self.builder_name, 313) |
| 497 |
| 498 self.assertEquals(result_status.FOUND_INCORRECT_DUPLICATE, |
| 499 second_analysis.result_status) |
| OLD | NEW |