Chromium Code Reviews| 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..acc0a0fc8ade8d85ba82ad7ed1caef4795ae0072 100644 |
| --- a/appengine/findit/handlers/test/triage_analysis_test.py |
| +++ b/appengine/findit/handlers/test/triage_analysis_test.py |
| @@ -2,6 +2,9 @@ |
| # 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 |
| @@ -33,6 +36,9 @@ class TriageAnalysisTest(testing.AppengineTestCase): |
| 'url': 'https://codereview.chromium.org/123', |
| }] |
| + self.build_start_time = (datetime.utcnow() - timedelta(1)).replace( |
| + hour=12, minute=0, second=0, microsecond=0) # Yesterday, 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': 'interactive_ui_tests', |
| + 'suspected_cls': [ |
| + { |
| + 'revision': '3cf9343f4602d4ec11717cb6ff56a793c1d5f84b', |
|
lijeffrey
2016/06/24 01:30:06
nit: for consistency with the rest of the changes
josiahk
2016/06/24 18:12:38
Done.
|
| + } |
| + ], |
| + } |
| + ] |
| + } |
| + 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': 'browser_tests' |
| + }, |
| + { |
| + 'suspected_cls': [ |
| + { |
| + 'revision': '0e8dc209f5e4a6140e43551de0e036324c68a383', |
| + } |
| + ], |
| + 'step_name': 'content_browsertests' |
| + } |
| + ] |
| + } |
| + 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': 'browser_tests', |
| + }, |
| + { |
| + 'suspected_cls': [ |
| + { |
| + 'revision': '0e8dc209f5e4a6140e43551de0e036324c68a383', |
| + }, |
| + { |
| + 'revision': '292b41bbd603ae2f11d239f457a8a5f04387fa85', |
| + }, |
| + { |
| + 'revision': 'f6c9ef029e28a6bef28e727cd70751d782963e21', |
| + } |
| + ], |
| + 'step_name': 'content_browsertests', |
| + } |
| + ] |
| + } |
| + 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': 'browser_tests', |
| + }, |
| + { |
| + 'suspected_cls': [ |
| + { |
| + 'revision': '0e8dc209f5e4a6140e43551de0e036324c68a383', |
| + }, |
| + { |
| + 'revision': '292b41bbd603ae2f11d239f457a8a5f04387fa85', |
| + }, |
| + { |
| + 'revision': 'f6c9ef029e28a6bef28e727cd70751d782963e21', |
| + } |
| + ], |
| + 'step_name': 'content_browsertests', |
| + } |
| + ] |
| + } |
| + 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': 'interactive_ui_tests', |
|
lijeffrey
2016/06/24 01:30:06
nit: use general test names, i.e. 'step_name': 'st
josiahk
2016/06/24 18:12:38
Done.
|
| + 'suspected_cls': [ |
| + { |
| + 'revision': '3cf9343f4602d4ec11717cb6ff56a793c1d5f84b', |
| + } |
| + ], |
| + } |
| + ] |
| + } |
| + 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': 'interactive_ui_tests', |
| + 'suspected_cls': [ |
| + { |
| + 'revision': '3cf9343f4602d4ec11717cb6ff56a793c1d5f84b', |
| + } |
| + ], |
| + } |
| + ] |
| + } |
| + 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': 'turing_test', |
| + } |
| + ] |
| + } |
| + 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): |
| + # Yesterday, UTC Noon. |
| + original_time = (datetime.utcnow() - timedelta(days=1)).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): |
| + # Yesterday, UTC Noon. |
| + original_time = (datetime.utcnow() - timedelta(days=1)).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): |
| + # Yesterday, UTC Noon. |
| + original_time = (datetime.utcnow() - timedelta(days=1)).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): |
| + # Yesterday, UTC Noon. |
| + original_time = (datetime.utcnow() - timedelta(days=1)).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): |
| + # Today, UTC Noon. |
| + original_time = datetime.utcnow().replace( |
| + hour=12, minute=0, second=0, microsecond=0) |
| + analysis_original = self.createAnalysis(308, original_time) |
| + |
| + # Create another analysis at the same time (also today). |
| + self.createAnalysis(309, original_time) |
| + |
| + self.assertEquals( |
| + len(triage_analysis._GetDuplicateAnalyses(analysis_original)), 0) |
| + |
| + def testTriageDuplicateResults(self): |
| + # Yesterday, UTC Noon. |
| + original_time = (datetime.utcnow() - timedelta(days=1)).replace( |
| + hour=12, minute=0, second=0, microsecond=0) |
| + analysis_original = self.createAnalysis(310, original_time) |
| + |
| + # Create another analysis at the same time (also yesterday). |
| + 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) |
| + |