| Index: appengine/findit/handlers/test/triage_analysis_test.py
|
| diff --git a/appengine/findit/handlers/test/triage_analysis_test.py b/appengine/findit/handlers/test/triage_analysis_test.py
|
| index 7bf6bdaffa72019d7bfe0bfe1baa384a9c72ef05..cfb0ccbe8633dbfac65d2a865101af940be57930 100644
|
| --- a/appengine/findit/handlers/test/triage_analysis_test.py
|
| +++ b/appengine/findit/handlers/test/triage_analysis_test.py
|
| @@ -2,15 +2,18 @@
|
| # Use of this source code is governed by a BSD-style license that can be
|
| # found in the LICENSE file.
|
|
|
| +from datetime import datetime
|
| +from datetime import timedelta
|
| +
|
| from google.appengine.ext import ndb
|
| import webapp2
|
|
|
| from testing_utils import testing
|
|
|
| from handlers import triage_analysis
|
| -from model.wf_analysis import WfAnalysis
|
| -from model import result_status
|
| from model import analysis_status
|
| +from model import result_status
|
| +from model.wf_analysis import WfAnalysis
|
| from waterfall import buildbot
|
|
|
|
|
| @@ -33,6 +36,9 @@ class TriageAnalysisTest(testing.AppengineTestCase):
|
| 'url': 'https://codereview.chromium.org/123',
|
| }]
|
|
|
| + self.build_start_time = (datetime.utcnow() - timedelta(2)).replace(
|
| + hour=12, minute=0, second=0, microsecond=0) # Two days ago, UTC Noon.
|
| +
|
| analysis = WfAnalysis.Create(
|
| self.master_name, self.builder_name, self.build_number_incomplete)
|
| analysis.status = analysis_status.RUNNING
|
| @@ -42,6 +48,7 @@ class TriageAnalysisTest(testing.AppengineTestCase):
|
| self.master_name, self.builder_name, self.build_number_found)
|
| analysis.status = analysis_status.COMPLETED
|
| analysis.suspected_cls = self.suspected_cls
|
| + analysis.build_start_time = self.build_start_time
|
| analysis.put()
|
|
|
| analysis = WfAnalysis.Create(
|
| @@ -52,7 +59,7 @@ class TriageAnalysisTest(testing.AppengineTestCase):
|
| self.mock_current_user(user_email='test@chromium.org', is_admin=True)
|
|
|
| def testUpdateAnalysisResultStatusWhenAnalysisIsIncomplete(self):
|
| - success = triage_analysis._UpdateAnalysisResultStatus(
|
| + success, _ = triage_analysis._UpdateAnalysisResultStatus(
|
| self.master_name, self.builder_name, self.build_number_incomplete, True)
|
| self.assertFalse(success)
|
| analysis = WfAnalysis.Get(
|
| @@ -130,3 +137,329 @@ class TriageAnalysisTest(testing.AppengineTestCase):
|
| params={'url': build_url, 'correct': True, 'format': 'json'})
|
| self.assertEquals(200, response.status_int)
|
| self.assertEquals({'success': True}, response.json_body)
|
| +
|
| + def testIncompleteTriage(self):
|
| + build_url = buildbot.CreateBuildUrl(
|
| + self.master_name, self.builder_name, self.build_number_incomplete)
|
| + response = self.test_app.get(
|
| + '/triage-analysis',
|
| + params={'url': build_url, 'correct': True, 'format': 'json'})
|
| + self.assertEquals(200, response.status_int)
|
| + self.assertEquals({'success': False}, response.json_body)
|
| +
|
| + def testAnalysesMatch(self):
|
| + analysis_with_empty_failures = WfAnalysis.Create(
|
| + self.master_name, self.builder_name, 200)
|
| + analysis_with_empty_failures.result = {
|
| + 'failures': []
|
| + }
|
| + analysis_with_empty_failures.put()
|
| +
|
| + analysis_with_no_suspected_cls = WfAnalysis.Create(
|
| + self.master_name, self.builder_name, 201)
|
| + analysis_with_no_suspected_cls.result = {
|
| + 'failures': [
|
| + {
|
| + 'suspected_cls': []
|
| + },
|
| + {
|
| + 'suspected_cls': []
|
| + },
|
| + ]
|
| + }
|
| + analysis_with_no_suspected_cls.put()
|
| +
|
| + analysis_with_suspected_cls_1 = WfAnalysis.Create(
|
| + self.master_name, self.builder_name, 202)
|
| + analysis_with_suspected_cls_1.result = {
|
| + 'failures': [
|
| + {
|
| + 'step_name': 'step1',
|
| + 'suspected_cls': [
|
| + {
|
| + 'revision': 'rev1',
|
| + }
|
| + ],
|
| + }
|
| + ]
|
| + }
|
| + analysis_with_suspected_cls_1.put()
|
| +
|
| + analysis_with_suspected_cls_2 = WfAnalysis.Create(
|
| + self.master_name, self.builder_name, 203)
|
| + analysis_with_suspected_cls_2.result = {
|
| + 'failures': [
|
| + {
|
| + 'suspected_cls': [],
|
| + 'step_name': 'step2'
|
| + },
|
| + {
|
| + 'suspected_cls': [
|
| + {
|
| + 'revision': 'rev2',
|
| + }
|
| + ],
|
| + 'step_name': 'step3'
|
| + }
|
| + ]
|
| + }
|
| + analysis_with_suspected_cls_2.put()
|
| +
|
| + analysis_with_suspected_cls_3 = WfAnalysis.Create(
|
| + self.master_name, self.builder_name, 204)
|
| + analysis_with_suspected_cls_3.result = {
|
| + 'failures': [
|
| + {
|
| + 'suspected_cls': [],
|
| + 'step_name': 'step2',
|
| + },
|
| + {
|
| + 'suspected_cls': [
|
| + {
|
| + 'revision': 'rev2',
|
| + },
|
| + {
|
| + 'revision': 'rev3',
|
| + },
|
| + {
|
| + 'revision': 'rev4',
|
| + }
|
| + ],
|
| + 'step_name': 'step3',
|
| + }
|
| + ]
|
| + }
|
| + analysis_with_suspected_cls_3.result_status = result_status.FOUND_UNTRIAGED
|
| + analysis_with_suspected_cls_3.build_start_time = self.build_start_time
|
| + analysis_with_suspected_cls_3.put()
|
| +
|
| + analysis_with_suspected_cls_4 = WfAnalysis.Create(
|
| + self.master_name, self.builder_name, 205)
|
| + analysis_with_suspected_cls_4.result = {
|
| + 'failures': [
|
| + {
|
| + 'suspected_cls': [],
|
| + 'step_name': 'step2',
|
| + },
|
| + {
|
| + 'suspected_cls': [
|
| + {
|
| + 'revision': 'rev2',
|
| + },
|
| + {
|
| + 'revision': 'rev3',
|
| + },
|
| + {
|
| + 'revision': 'rev4',
|
| + }
|
| + ],
|
| + 'step_name': 'step3',
|
| + }
|
| + ]
|
| + }
|
| + analysis_with_suspected_cls_4.result_status = result_status.FOUND_UNTRIAGED
|
| + analysis_with_suspected_cls_4.build_start_time = self.build_start_time
|
| + analysis_with_suspected_cls_4.put()
|
| +
|
| + analysis_with_tests_1 = WfAnalysis.Create(
|
| + self.master_name, self.builder_name, 206)
|
| + analysis_with_tests_1.result = {
|
| + 'failures': [
|
| + {
|
| + 'tests': [
|
| + {
|
| + 'test_name': 'super_test_1',
|
| + 'suspected_cls': [
|
| + {
|
| + 'revision': 'abc'
|
| + }
|
| + ]
|
| + }, {
|
| + 'test_name': 'super_test_2',
|
| + 'suspected_cls': [
|
| + {
|
| + 'revision': 'def'
|
| + },
|
| + {
|
| + 'revision': 'ghi'
|
| + }
|
| + ]
|
| + }
|
| + ],
|
| + 'step_name': 'step1',
|
| + 'suspected_cls': [
|
| + {
|
| + 'revision': 'rev1',
|
| + }
|
| + ],
|
| + }
|
| + ]
|
| + }
|
| + analysis_with_tests_1.put()
|
| +
|
| + analysis_with_tests_2 = WfAnalysis.Create(
|
| + self.master_name, self.builder_name, 207)
|
| + analysis_with_tests_2.result = {
|
| + 'failures': [
|
| + {
|
| + 'tests': [
|
| + {
|
| + 'test_name': 'super_test_3',
|
| + 'suspected_cls': [
|
| + {
|
| + 'revision': 'ab'
|
| + },
|
| + {
|
| + 'revision': 'cd'
|
| + },
|
| + {
|
| + 'revision': 'ef'
|
| + }
|
| + ]
|
| + }
|
| + ],
|
| + 'step_name': 'step1',
|
| + 'suspected_cls': [
|
| + {
|
| + 'revision': 'rev1',
|
| + }
|
| + ],
|
| + }
|
| + ]
|
| + }
|
| + analysis_with_tests_2.put()
|
| +
|
| + # Empty failures list.
|
| + self.assertFalse(triage_analysis._DoAnalysesMatch(
|
| + analysis_with_empty_failures,
|
| + analysis_with_empty_failures))
|
| + # Zero culprit-tuples.
|
| + self.assertFalse(triage_analysis._DoAnalysesMatch(
|
| + analysis_with_no_suspected_cls,
|
| + analysis_with_no_suspected_cls))
|
| + # Zero culprit-tuples and some culprit-tuples.
|
| + self.assertFalse(triage_analysis._DoAnalysesMatch(
|
| + analysis_with_no_suspected_cls,
|
| + analysis_with_suspected_cls_1))
|
| + # Has step-level culprit-tuples, and should detect match.
|
| + self.assertTrue(triage_analysis._DoAnalysesMatch(
|
| + analysis_with_suspected_cls_2,
|
| + analysis_with_suspected_cls_2))
|
| + # Two different step-level culprit-tuples, and should fail to match.
|
| + self.assertFalse(triage_analysis._DoAnalysesMatch(
|
| + analysis_with_suspected_cls_2,
|
| + analysis_with_suspected_cls_3))
|
| + # Has test-level culprit-tuples, and should detect match.
|
| + self.assertTrue(triage_analysis._DoAnalysesMatch(
|
| + analysis_with_tests_1,
|
| + analysis_with_tests_1))
|
| + # Two different test-level culprit-tuples, and should fail to match.
|
| + self.assertFalse(triage_analysis._DoAnalysesMatch(
|
| + analysis_with_tests_1,
|
| + analysis_with_tests_2))
|
| +
|
| + def _createAnalysis(self, build_number, build_start_time):
|
| + analysis = WfAnalysis.Create(
|
| + self.master_name, self.builder_name, build_number)
|
| + analysis.result = {
|
| + 'failures': [
|
| + {
|
| + 'suspected_cls': [
|
| + {
|
| + 'revision': 'abc',
|
| + }
|
| + ],
|
| + 'step_name': 'step_4',
|
| + }
|
| + ]
|
| + }
|
| + analysis.result_status = result_status.FOUND_UNTRIAGED
|
| + analysis.build_start_time = build_start_time
|
| + analysis.status = analysis_status.COMPLETED
|
| + analysis.put()
|
| + return analysis
|
| +
|
| + def testGetDuplicateAnalysesTooEarly(self):
|
| + # Two days ago, UTC Noon.
|
| + original_time = (datetime.utcnow() - timedelta(days=2)).replace(
|
| + hour=12, minute=0, second=0, microsecond=0)
|
| + analysis_original = self._createAnalysis(300, original_time)
|
| +
|
| + # An earlier time, outside bounds.
|
| + too_early_time = (original_time - timedelta(
|
| + hours=triage_analysis.MATCHING_ANALYSIS_HOURS_AGO_START*2))
|
| + self._createAnalysis(301, too_early_time)
|
| +
|
| + self.assertEquals(
|
| + len(triage_analysis._GetDuplicateAnalyses(analysis_original)), 0)
|
| +
|
| + def testGetDuplicateAnalysesEarlier(self):
|
| + # Two days ago, UTC Noon.
|
| + original_time = (datetime.utcnow() - timedelta(days=2)).replace(
|
| + hour=12, minute=0, second=0, microsecond=0)
|
| + analysis_original = self._createAnalysis(302, original_time)
|
| +
|
| + # An earlier time, within bounds.
|
| + earlier_time = (original_time - timedelta(
|
| + hours=triage_analysis.MATCHING_ANALYSIS_HOURS_AGO_START/2))
|
| + self._createAnalysis(303, earlier_time)
|
| +
|
| + self.assertEquals(
|
| + len(triage_analysis._GetDuplicateAnalyses(analysis_original)), 1)
|
| +
|
| + def testGetDuplicateAnalysesLater(self):
|
| + # Two days ago, UTC Noon.
|
| + original_time = (datetime.utcnow() - timedelta(days=2)).replace(
|
| + hour=12, minute=0, second=0, microsecond=0)
|
| + analysis_original = self._createAnalysis(304, original_time)
|
| +
|
| + # A later time, within bounds.
|
| + later_time = (original_time + timedelta(
|
| + hours=triage_analysis.MATCHING_ANALYSIS_HOURS_AGO_START/2))
|
| + self._createAnalysis(305, later_time)
|
| +
|
| + self.assertEquals(
|
| + len(triage_analysis._GetDuplicateAnalyses(analysis_original)), 1)
|
| +
|
| + def testGetDuplicateAnalysesTooLate(self):
|
| + # Two days ago, UTC Noon.
|
| + original_time = (datetime.utcnow() - timedelta(days=2)).replace(
|
| + hour=12, minute=0, second=0, microsecond=0)
|
| + analysis_original = self._createAnalysis(306, original_time)
|
| +
|
| + # A later time, outside bounds.
|
| + too_late_time = (original_time + timedelta(
|
| + hours=triage_analysis.MATCHING_ANALYSIS_HOURS_AGO_START*2))
|
| + self._createAnalysis(307, too_late_time)
|
| +
|
| + self.assertEquals(
|
| + len(triage_analysis._GetDuplicateAnalyses(analysis_original)), 0)
|
| +
|
| + def testGetDuplicateAnalysesNotToday(self):
|
| + # Tomorrow, UTC Noon.
|
| + original_time = (datetime.utcnow() + timedelta(days=1)).replace(
|
| + hour=12, minute=0, second=0, microsecond=0)
|
| + analysis_original = self._createAnalysis(308, original_time)
|
| +
|
| + # Create another analysis at the same time (also tomorrow).
|
| + self._createAnalysis(309, original_time)
|
| +
|
| + self.assertEquals(
|
| + len(triage_analysis._GetDuplicateAnalyses(analysis_original)), 0)
|
| +
|
| + def testTriageDuplicateResults(self):
|
| + # Two days ago, UTC Noon.
|
| + original_time = (datetime.utcnow() - timedelta(days=2)).replace(
|
| + hour=12, minute=0, second=0, microsecond=0)
|
| + analysis_original = self._createAnalysis(310, original_time)
|
| +
|
| + # Create another analysis at the same time (also two days ago).
|
| + self._createAnalysis(311, original_time)
|
| +
|
| + triage_analysis._TriageDuplicateResults(analysis_original, True)
|
| +
|
| + second_analysis = WfAnalysis.Get(self.master_name, self.builder_name, 311)
|
| +
|
| + self.assertEquals(result_status.NOT_FOUND_CORRECT,
|
| + second_analysis.result_status)
|
| +
|
|
|