def testGetWfSuspectedClKeysFromCLInfo(self): cl_info = { 'rev1': { 'revision': 'rev1', 'repo_name': 'chromium', 'commit_position': 100 }, 'rev2': { 'revision': 'rev2', 'repo_name': 'chromium', 'commit_position': 123, 'url': 'url' } } expected_cl_keys = {} for _, v in cl_info.iteritems(): cl = WfSuspectedCL.Create(v['repo_name'], v['revision'], v['commit_position']) cl.put() expected_cl_keys[v['revision']] = cl.key.urlsafe() self.assertEqual(expected_cl_keys, consistent_failure_culprits.GetWfSuspectedClKeysFromCLInfo( cl_info).ToSerializable())
def testGetHeuristicSuspectedCLs(self): repo_name = 'chromium' revision = 'r123_2' culprit = WfSuspectedCL.Create(repo_name, revision, None) culprit.put() analysis = WfAnalysis.Create('m', 'b', 123) analysis.suspected_cls = [{ 'repo_name': repo_name, 'revision': revision, 'commit_position': None, 'url': None, 'failures': { 'b': ['Unittest2.Subtest1', 'Unittest3.Subtest2'] }, 'top_score': 4 }] analysis.put() suspected_cls = [culprit.key.urlsafe()] self.assertEqual( suspected_cls, build_failure_analysis.GetHeuristicSuspectedCLs( 'm', 'b', 123).ToSerializable())
def testRevertCulprit(self, mock_revert, *_): repo_name = 'chromium' revision = 'rev1' build_key = 'm/b/123' revert_cl = RevertCL() revert_cl.revert_cl_url = 'url' revert_cl.created_time = datetime.datetime(2018, 6, 20, 0, 0, 0) mock_revert.return_value = (constants.CREATED_BY_FINDIT, revert_cl, None) culprit = WfSuspectedCL.Create(repo_name, revision, 1) culprit.put() pipeline_input = CreateRevertCLParameters( cl_key=culprit.key.urlsafe(), build_key=build_key, failure_type=failure_type.COMPILE) self.assertEqual( constants.CREATED_BY_FINDIT, culprit_action.RevertCulprit(pipeline_input, 'pipeline_id')) culprit = WfSuspectedCL.Get(repo_name, revision) self.assertEqual(revert_cl, culprit.revert_cl) self.assertEqual(analysis_status.COMPLETED, culprit.revert_status)
def testSubmitRevertSucceed(self, mock_fn, mock_commit, *_): repo_name = 'chromium' revision = 'rev1' commit_position = 123 cl_info = ClInfo(self.review_server_host, self.review_change_id) cl_info.commits.append( Commit('20001', 'rev1', [], datetime(2017, 2, 1, 0, 0, 0))) mock_fn.return_value = cl_info mock_commit.return_value = True culprit = WfSuspectedCL.Create(repo_name, revision, commit_position) revert = RevertCL() revert_change_id = '54321' revert.revert_cl_url = 'https://%s/q/%s' % (self.review_server_host, revert_change_id) culprit.revert_cl = revert culprit.revert_status = status.COMPLETED culprit.put() revert_status = constants.CREATED_BY_FINDIT pipeline_input = SubmitRevertCLParameters( cl_key=culprit.key.urlsafe(), revert_status=revert_status, failure_type=failure_type.COMPILE) pipeline = SubmitRevertCLPipeline(pipeline_input) self.assertEqual(constants.COMMITTED, pipeline.run(pipeline_input)) culprit = WfSuspectedCL.Get(repo_name, revision) self.assertEqual(culprit.revert_submission_status, status.COMPLETED) mock_commit.assert_called_with(revert_change_id)
def testUpdateSuspectedCLNonFirstTimeFailure(self): suspected_cl = WfSuspectedCL.Create(self.repo_name, self.revision_1, self.commit_position) suspected_cl.builds = { self.build_key_1: { 'failure_type': 'test', 'failures': { 's1': ['t1', 't2'] }, 'status': None, 'approaches': [ analysis_approach_type.HEURISTIC, analysis_approach_type.TRY_JOB ], 'top_score': None, 'Confidence': 80.0 } } suspected_cl.put() self.assertTrue( triage_suspected_cl._UpdateSuspectedCL(self.repo_name, self.revision_1, self.build_key_2, None))
def setUp(self): super(TestCulpritActionTest, self).setUp() repo_name = 'chromium' revision = 'rev1' self.culprit = WfSuspectedCL.Create(repo_name, revision, 100).put().urlsafe() culprit_dict = DictOfBasestring() culprit_dict[revision] = self.culprit heuristic_cls = ListOfBasestring() heuristic_cls.append(self.culprit) parameters_dict = { 'build_key': { 'master_name': 'm', 'builder_name': 'b', 'build_number': 123 }, 'culprits': { 'rev1': self.culprit }, 'heuristic_cls': heuristic_cls } self.parameters = CulpritActionParameters.FromSerializable( parameters_dict)
def UpdateSuspectedCL(repo_name, revision, commit_position, approach, master_name, builder_name, build_number, cl_failure_type, failures, top_score): suspected_cl = ( WfSuspectedCL.Get(repo_name, revision) or WfSuspectedCL.Create(repo_name, revision, commit_position)) if not suspected_cl.identified_time: # pragma: no cover. suspected_cl.identified_time = time_util.GetUTCNow() suspected_cl.updated_time = time_util.GetUTCNow() if approach not in suspected_cl.approaches: suspected_cl.approaches.append(approach) if cl_failure_type not in suspected_cl.failure_type: suspected_cl.failure_type.append(cl_failure_type) build_key = BaseBuildModel.CreateBuildKey(master_name, builder_name, build_number) if build_key not in suspected_cl.builds: suspected_cl.builds[build_key] = { 'approaches': [approach], 'failure_type': cl_failure_type, 'failures': failures, 'status': _GetsStatusFromSameFailure(suspected_cl.builds, failures), 'top_score': top_score } else: build = suspected_cl.builds[build_key] if approach not in build['approaches']: build['approaches'].append(approach) suspected_cl.put()
def testCanAutoCreateRevert(self, _): repo_name = 'chromium' revision = 'rev1' culprit = WfSuspectedCL.Create(repo_name, revision, 123) culprit.failure_type.append(failure_type.TEST) culprit.revert_created_time = datetime(2018, 2, 14, 12, 0, 0) culprit.put() culprit_dict = DictOfBasestring() culprit_dict[revision] = culprit.key.urlsafe() heuristic_cls = ListOfBasestring() heuristic_cls.append(culprit.key.urlsafe()) parameters_dict = { 'build_key': { 'master_name': 'm', 'builder_name': 'b', 'build_number': 123 }, 'culprits': { 'rev1': culprit.key.urlsafe() }, 'heuristic_cls': heuristic_cls } parameters = CulpritActionParameters.FromSerializable(parameters_dict) self.assertTrue( test_culprit_action.CanAutoCreateRevert(culprit.key.urlsafe(), parameters))
def _AddDummyCLs(self): suspected_cls = [] for i in xrange(0, 10): cl = self._AddCL(i) suspected_cls.append(cl) # Adds a cl with no builds. cl10 = WfSuspectedCL.Create('chromium', '10', None) cl10.approaches = APPROACH_MAP[2] cl10.status = suspected_cl_status.CORRECT cl10.updated_time = self.start_date + datetime.timedelta(hours=10) cl10.put() suspected_cls.append(cl10) # Adds a build with the same failure for a heuristic result. new_value = copy.deepcopy(suspected_cls[3].builds['m/b/3']) suspected_cls[3].builds['new_key'] = new_value suspected_cls[3].put() # Adds a build with the same failure for a try job result. new_value = copy.deepcopy(suspected_cls[4].builds['m/b/4']) suspected_cls[4].builds['new_key'] = new_value suspected_cls[4].put() return suspected_cls
def testUpdateSuspectedCLCorrect(self): suspected_cl = WfSuspectedCL.Create( self.repo_name, self.revision_1, self.commit_position) suspected_cl.builds = { self.build_key_1: { 'failure_type': 'test', 'failures': { 's1': ['t1', 't2'] }, 'status': None, 'approaches': [analysis_approach_type.HEURISTIC, analysis_approach_type.TRY_JOB], 'top_score': None, 'Confidence': 80.0 } } suspected_cl.put() cl_status = suspected_cl_status.CORRECT triage_suspected_cl._UpdateSuspectedCL( self.repo_name, self.revision_1, self.build_key_1, cl_status) suspected_cl = WfSuspectedCL.Get(self.repo_name, self.revision_1) self.assertEqual( suspected_cl.builds[self.build_key_1]['status'], cl_status) self.assertEqual(suspected_cl.status, cl_status)
def testAddedReviewerFailedBefore(self, mock_fn, mock_send, *_): repo_name = 'chromium' revision = 'rev1' cl_info = ClInfo(self.review_server_host, self.review_change_id) cl_info.commits.append( Commit('20001', 'rev1', [], datetime(2017, 2, 1, 0, 0, 0))) cl_info.owner_email = '*****@*****.**' revert_cl = ClInfo('revert_review_host', '123V3127') revert_cl.url = 'https://chromium-review.googlesource.com/54321' cl_info.reverts.append( Revert('20001', revert_cl, constants.DEFAULT_SERVICE_ACCOUNT, datetime(2017, 2, 1, 1, 0, 0))) mock_fn.return_value = cl_info culprit = WfSuspectedCL.Create(repo_name, revision, 123) culprit.revert_cl = RevertCL() culprit.revert_status = status.RUNNING culprit.cr_notification_status = status.COMPLETED culprit.put() revert_status, _, _ = gerrit.RevertCulprit(culprit.key.urlsafe(), 'm/b/1', failure_type.COMPILE, 'compile', self.codereview_info) self.assertEquals(revert_status, services_constants.CREATED_BY_FINDIT)
def testLatestBuildSucceeded(self, mock_fn, *_): repo_name = 'chromium' revision = 'rev1' cl_info = ClInfo(self.review_server_host, self.review_change_id) cl_info.owner_email = '*****@*****.**' cl_info.commits.append( Commit('20001', 'rev1', datetime(2017, 2, 1, 0, 0, 0))) revert_cl = ClInfo('revert_review_host', '123V3127') revert_cl.url = 'https://codereview.chromium.org/54321' cl_info.reverts.append( Revert('20001', revert_cl, constants.DEFAULT_SERVICE_ACCOUNT, datetime(2017, 2, 1, 1, 0, 0))) mock_fn.return_value = cl_info culprit = WfSuspectedCL.Create(repo_name, revision, 123) culprit.revert_cl = RevertCL() culprit.revert_status = status.RUNNING culprit.put() pipeline = CreateRevertCLPipeline('m', 'b', 123, repo_name, revision) revert_status = pipeline.run('m', 'b', 123, repo_name, revision) self.assertEquals(revert_status, create_revert_cl_pipeline.SKIPPED) culprit = WfSuspectedCL.Get(repo_name, revision) self.assertEqual(culprit.revert_status, status.SKIPPED) self.assertIsNotNone(culprit.revert_cl) self.assertEqual(culprit.skip_revert_reason, create_revert_cl_pipeline.NEWEST_BUILD_GREEN)
def testRevertCLNotSaved(self, mock_fn, *_): repo_name = 'chromium' revision = 'rev1' cl_info = ClInfo(self.review_server_host, self.review_change_id) cl_info.commits.append( Commit('20001', 'rev1', datetime(2017, 2, 1, 0, 0, 0))) cl_info.owner_email = '*****@*****.**' revert_cl = ClInfo('revert_review_host', '123V3127') revert_cl.url = 'https://codereview.chromium.org/54321' cl_info.reverts.append( Revert('20001', revert_cl, constants.DEFAULT_SERVICE_ACCOUNT, datetime(2017, 2, 1, 1, 0, 0))) mock_fn.return_value = cl_info WfSuspectedCL.Create(repo_name, revision, 123).put() pipeline = CreateRevertCLPipeline('m', 'b', 123, repo_name, revision) revert_status = pipeline.run('m', 'b', 123, repo_name, revision) self.assertEquals(revert_status, create_revert_cl_pipeline.CREATED_BY_FINDIT) culprit = WfSuspectedCL.Get(repo_name, revision) self.assertEqual(culprit.revert_status, status.COMPLETED) self.assertIsNotNone(culprit.revert_cl)
def testCanAutoCommitRevertByFindit(self): repo_name = 'chromium' revision = 'rev1' culprit = WfSuspectedCL.Create(repo_name, revision, 123) culprit.put() self.assertTrue(compile_culprit_action.CanAutoCommitRevertByFindit())
def testUpdateSuspectedCLBailOut(self): suspected_cl = WfSuspectedCL.Create('chromium', 'a1b2c3d4', 1) suspected_cl.sheriff_action_time = datetime(2017, 4, 6, 0, 0) check_reverted_cls._UpdateSuspectedCL(suspected_cl, datetime(2017, 4, 6, 0, 1)) self.assertEqual(datetime(2017, 4, 6, 0, 0), suspected_cl.sheriff_action_time)
def testSendNotificationForCulprit(self, mock_post, _): repo_name = 'chromium' revision = 'rev1' revert_status = None culprit = WfSuspectedCL.Create(repo_name, revision, 123) culprit.put() culprit_link = culprit.GetCulpritLink() false_positive_bug_link = gerrit.CreateFinditWrongBugLink( gerrit.FINDIT_BUILD_FAILURE_COMPONENT, culprit_link, revision) parameters = SendNotificationForCulpritParameters( cl_key=culprit.key.urlsafe(), force_notify=False, revert_status=revert_status, failure_type=failure_type.COMPILE) self.assertTrue( gerrit.SendNotificationForCulprit(parameters, self.codereview_info)) message = textwrap.dedent(""" Findit (https://goo.gl/kROfz5) %s this CL at revision %s as the culprit for failures in the build cycles as shown on: https://analysis.chromium.org/waterfall/culprit?key=%s If it is a false positive, please report it at %s.""") % ( 'identified', self.culprit_commit_position, culprit.key.urlsafe(), false_positive_bug_link) mock_post.assert_called_once_with(self.review_change_id, message, True)
def testCrNotificationProcessed(self): culprit = WfSuspectedCL.Create('chromium', 'r1', 123) for s in (status.COMPLETED, status.RUNNING): culprit.cr_notification_status = s self.assertTrue(culprit.cr_notification_processed) for s in (status.ERROR, None): culprit.cr_notification_status = s self.assertFalse(culprit.cr_notification_processed)
def testAutoRevertExceedsLimit(self, _): repo_name = 'chromium' revision = 'rev1' culprit = WfSuspectedCL.Create(repo_name, revision, 123) culprit.put() self.assertFalse(compile_culprit_action.CanAutoCreateRevert())
def testGetBuildInfo(self): repo_name = 'chromium' revision = 'rev1' commit_position = 1 build = {'status': None} suspected_cl = WfSuspectedCL.Create(repo_name, revision, commit_position) suspected_cl.builds = {'m/b/123': build} self.assertEqual(build, suspected_cl.GetBuildInfo('m', 'b', 123))
def testShouldNotSendNotificationForSingleFailedBuild(self): culprit = WfSuspectedCL.Create('chromium', 'r1', 1) culprit.builds['m/b1/1'] = {} culprit.put() self.assertFalse( send_notification_for_culprit_pipeline._ShouldSendNotification( 'chromium', 'r1', 2, False)) self.assertFalse(culprit.cr_notification_processed)
def testIdentifyCulpritForCompileTryJobSuccess(self, mock_fn): master_name = 'm' builder_name = 'b' build_number = 1 try_job_id = '1' compile_result = { 'report': { 'result': { 'rev1': 'passed', 'rev2': 'failed' }, 'culprit': 'rev2' }, 'try_job_id': try_job_id, } repo_name = 'chromium' revision = 'rev2' culprit = WfSuspectedCL.Create(repo_name, revision, 100) culprit.put() culprits_result = { 'rev2': { 'revision': revision, 'commit_position': 2, 'url': 'url_2', 'repo_name': repo_name } } mock_fn.return_value = culprits_result, ListOfBasestring() culprits = DictOfBasestring() culprits['rev2'] = culprit.key.urlsafe() self.MockGeneratorPipeline(pipeline_class=revert_pipeline. RevertAndNotifyCompileCulpritPipeline, expected_input=CulpritActionParameters( build_key=BuildKey( master_name=master_name, builder_name=builder_name, build_number=build_number), culprits=culprits, heuristic_cls=ListOfBasestring(), failure_to_culprit_map=None), mocked_output=False) pipeline_input = IdentifyCompileTryJobCulpritParameters( build_key=BuildKey(master_name=master_name, builder_name=builder_name, build_number=build_number), result=CompileTryJobResult.FromSerializable(compile_result)) pipeline = culprit_pipeline.IdentifyCompileTryJobCulpritPipeline( pipeline_input) pipeline.start() self.execute_queued_tasks()
def testShouldNotSendNotificationIfRevertedByFindit(self): culprit = WfSuspectedCL.Create('chromium', 'r1', 1) culprit.builds['m/b1/1'] = {} culprit.put() self.assertFalse( culprit_action._ShouldSendNotification('chromium', 'r1', True, constants.CREATED_BY_FINDIT, 2)) self.assertFalse(culprit.cr_notification_processed)
def testLogUnexpectedAbortingNoChange(self): repo_name = 'chromium' revision = 'rev1' culprit = WfSuspectedCL.Create(repo_name, revision, 123) culprit.put() CreateRevertCLPipeline('m', 'b', 123, repo_name, revision)._LogUnexpectedAborting(True) culprit = WfSuspectedCL.Get(repo_name, revision) self.assertIsNone(culprit.revert_status)
def testGetAnalysesWithinDateRange(self): start_date = datetime(2017, 4, 8, 0, 0) end_date = datetime(2017, 4, 9, 0, 0) suspected_cl_1 = WfSuspectedCL.Create('chromium', 'r1', 1) suspected_cl_1.identified_time = datetime(2017, 4, 8, 0, 1) suspected_cl_1.put() suspected_cl_2 = WfSuspectedCL.Create('chromium', 'r2', 2) suspected_cl_2.identified_time = datetime(2017, 4, 8, 0, 2) suspected_cl_2.put() suspected_cl_3 = WfSuspectedCL.Create('chromium', 'r3', 3) suspected_cl_3.identified_time = datetime(2017, 4, 9, 0, 2) suspected_cl_3.put() self.assertEqual([suspected_cl_1, suspected_cl_2], auto_revert_metrics._GetAnalysesWithinDateRange( start_date, end_date, 1))
def testCanAutoCommitRevertByFindit(self, _): repo_name = 'chromium' revision = 'rev1' culprit = WfSuspectedCL.Create(repo_name, revision, 123) culprit.failure_type.append(failure_type.TEST) culprit.revert_committed_time = datetime(2018, 2, 14, 12, 0, 0) culprit.put() self.assertTrue(test_culprit_action.CanAutoCommitRevertByFindit())
def testIdentifyCulpritForTestTryJobSuccess(self, mock_fn, mock_fn2): master_name = 'm' builder_name = 'b' build_number = 1 repo_name = 'chromium' revision = 'rev2' culprit = WfSuspectedCL.Create(repo_name, revision, 100) culprit.put() culprits_result = { 'rev1': { 'revision': 'rev1', 'repo_name': 'chromium', 'commit_position': 1, 'url': 'url_1' }, 'rev2': { 'revision': revision, 'commit_position': 2, 'url': 'url_2', 'repo_name': repo_name } } culprit_map = {'step': {'test1': 'rev1', 'test2': 'rev2'}} mock_fn.return_value = culprits_result, ListOfBasestring.FromSerializable( []), FailureToCulpritMap.FromSerializable(culprit_map) culprits = DictOfBasestring() culprits['rev2'] = culprit.key.urlsafe() mock_fn2.return_value = culprits self.MockGeneratorPipeline( pipeline_class=RevertAndNotifyTestCulpritPipeline, expected_input=CulpritActionParameters( build_key=BuildKey(master_name=master_name, builder_name=builder_name, build_number=build_number), culprits=culprits, heuristic_cls=ListOfBasestring(), failure_to_culprit_map=FailureToCulpritMap.FromSerializable( culprit_map)), mocked_output=False) parameters = IdentifyTestTryJobCulpritParameters( build_key=BuildKey(master_name=master_name, builder_name=builder_name, build_number=build_number), result=TestTryJobResult.FromSerializable({})) pipeline = IdentifyTestTryJobCulpritPipeline(parameters) pipeline.start() self.execute_queued_tasks() mock_fn.assert_called_once_with(parameters)
def testLogUnexpectedAborting(self): repo_name = 'chromium' revision = 'rev1' culprit = WfSuspectedCL.Create(repo_name, revision, 123) culprit.revert_status = status.RUNNING culprit.put() CreateRevertCLPipeline('m', 'b', 123, repo_name, revision)._LogUnexpectedAborting(True) culprit = WfSuspectedCL.Get(repo_name, revision) self.assertEquals(culprit.revert_status, status.ERROR)
def testUpdateWfSuspectedCLAddSameBuild(self): approach = analysis_approach_type.HEURISTIC master_name = 'm' builder_name = 'b' build_number = 122 test_failure_type = failure_type.TEST repo_name = 'chromium' revision = 'r2' commit_position = 2 failures = {'step_1': ['test1', 'test2']} top_score = 4 suspected_cl = WfSuspectedCL.Create(repo_name, revision, commit_position) suspected_cl.approaches = [analysis_approach_type.HEURISTIC] suspected_cl.builds = { build_util.CreateBuildId(master_name, builder_name, build_number): { 'approaches': [analysis_approach_type.HEURISTIC], 'failure_type': test_failure_type, 'failures': failures, 'status': None, 'top_score': 4 } } suspected_cl.failure_type = [test_failure_type] suspected_cl.put() suspected_cl_util.UpdateSuspectedCL(repo_name, revision, commit_position, approach, master_name, builder_name, build_number, test_failure_type, failures, top_score) expected_builds = { build_util.CreateBuildId(master_name, builder_name, build_number): { 'approaches': [analysis_approach_type.HEURISTIC], 'failure_type': test_failure_type, 'failures': failures, 'status': None, 'top_score': 4 } } expected_approaches = [analysis_approach_type.HEURISTIC] suspected_cl = WfSuspectedCL.Get(repo_name, revision) self.assertIsNotNone(suspected_cl) self.assertEqual(expected_approaches, suspected_cl.approaches) self.assertEqual([test_failure_type], suspected_cl.failure_type) self.assertEqual(expected_builds, suspected_cl.builds)
def testDontSendNotificationIfShouldNot(self): rietveld_requests = [] self._MockRietveld(rietveld_requests) self._MockGitRepository('https://codeReview.chromium.org/123') self.MockUTCNow(_MOCKED_DATETIME_UTCNOW) culprit = WfSuspectedCL.Create('chromium', 'r7', 123) culprit.builds['m/b71/71'] = {} culprit.put() pipeline = SendNotificationForCulpritPipeline() self.assertFalse(pipeline.run('m', 'b71', 71, 'chromium', 'r7', False)) self.assertEqual(0, len(rietveld_requests))
def testShouldNotSendNotificationForSameFailedBuild(self): culprit = WfSuspectedCL.Create('chromium', 'r2', 1) culprit.builds['m/b2/2'] = {} culprit.put() self.assertTrue( send_notification_for_culprit_pipeline._ShouldSendNotification( 'chromium', 'r2', 2, True)) self.assertFalse( send_notification_for_culprit_pipeline._ShouldSendNotification( 'chromium', 'r2', 2, True)) culprit = WfSuspectedCL.Get('chromium', 'r2') self.assertEqual(status.RUNNING, culprit.cr_notification_status)