def testDoNotGroupCompilesWithDifferentOutputNodes(self): master_name = 'm1' builder_name = 'b' build_number = 1 master_name_2 = 'm2' blame_list = ['a'] signals_1 = {'compile': {'failed_output_nodes': ['abc.obj']}} signals_2 = {'compile': {'failed_output_nodes': ['def.obj']}} WfAnalysis.Create(master_name, builder_name, build_number).put() # Run pipeline with signals that have certain failed output nodes. # Observe new group creation. self.assertTrue( try_job_util._IsBuildFailureUniqueAcrossPlatforms( master_name, builder_name, build_number, failure_type.COMPILE, blame_list, None, signals_1, None)) self.assertIsNotNone( WfFailureGroup.Get(master_name, builder_name, build_number)) WfAnalysis.Create(master_name_2, builder_name, build_number).put() # Run pipeline with signals that have different failed output nodes. # Observe new group creation. self.assertTrue( try_job_util._IsBuildFailureUniqueAcrossPlatforms( master_name_2, builder_name, build_number, failure_type.COMPILE, blame_list, None, signals_2, None)) self.assertTrue( WfFailureGroup.Get(master_name_2, builder_name, build_number))
def testGroupTestsWithRelatedStepsWithoutHeuristicResult(self): master_name = 'm1' builder_name = 'b' build_number = 1 master_name_2 = 'm2' blame_list = ['a'] failed_steps = { 'step_a': { 'current_failure': 3, 'first_failure': 2, 'last_pass': 1 } } WfAnalysis.Create(master_name, builder_name, build_number).put() # Run pipeline with signals that have certain failed steps. # Observe new group creation. self.assertTrue( try_job_util._IsBuildFailureUniqueAcrossPlatforms( master_name, builder_name, build_number, failure_type.TEST, blame_list, failed_steps, None, None)) self.assertIsNotNone( WfFailureGroup.Get(master_name, builder_name, build_number)) WfAnalysis.Create(master_name_2, builder_name, build_number).put() # Run pipeline with signals that have the same failed steps. # Observe no new group creation. self.assertFalse( try_job_util._IsBuildFailureUniqueAcrossPlatforms( master_name_2, builder_name, build_number, failure_type.TEST, blame_list, failed_steps, None, None)) self.assertIsNone( WfFailureGroup.Get(master_name_2, builder_name, build_number))
def testGroupCompilesWithRelatedFailuresWithoutHeuristicResult(self): master_name = 'm1' builder_name = 'b' build_number = 1 master_name_2 = 'm2' blame_list = ['a'] signals = {'compile': {'failed_output_nodes': ['abc.obj']}} WfAnalysis.Create(master_name, builder_name, build_number).put() # Run pipeline with signals that have certain failed output nodes. # Observe new group creation. self.assertTrue( try_job_util._IsBuildFailureUniqueAcrossPlatforms( master_name, builder_name, build_number, failure_type.COMPILE, blame_list, None, signals, None)) self.assertIsNotNone( WfFailureGroup.Get(master_name, builder_name, build_number)) WfAnalysis.Create(master_name_2, builder_name, build_number).put() # Run pipeline with signals that have the same failed output nodes. # Observe no new group creation. self.assertFalse( try_job_util._IsBuildFailureUniqueAcrossPlatforms( master_name_2, builder_name, build_number, failure_type.COMPILE, blame_list, None, signals, None)) self.assertIsNone( WfFailureGroup.Get(master_name_2, builder_name, build_number))
def testSecondAnalysisFailureGroupKeySet(self): master_name = 'm1' builder_name = 'b' build_number = 1 master_name_2 = 'm2' blame_list = ['a'] signals = {'compile': {'failed_output_nodes': ['abc.obj']}} WfAnalysis.Create(master_name, builder_name, build_number).put() # Run pipeline with signals that have certain failed output nodes. # Observe new group creation. self.assertTrue( try_job_util._IsBuildFailureUniqueAcrossPlatforms( master_name, builder_name, build_number, failure_type.COMPILE, blame_list, None, signals, None)) WfAnalysis.Create(master_name_2, builder_name, build_number).put() # Run pipeline with signals that have the same failed output nodes. # Observe no new group creation. self.assertFalse( try_job_util._IsBuildFailureUniqueAcrossPlatforms( master_name_2, builder_name, build_number, failure_type.COMPILE, blame_list, None, signals, None)) analysis_2 = WfAnalysis.Get(master_name_2, builder_name, build_number) self.assertEqual([master_name, builder_name, build_number], analysis_2.failure_group_key)
def testDoNotGroupTestsWithDisjointBlameLists(self): master_name = 'm1' builder_name = 'b' build_number = 1 master_name_2 = 'm2' blame_list_1 = ['a'] blame_list_2 = ['b'] failed_steps = { 'step_a': { 'current_failure': 3, 'first_failure': 2, 'last_pass': 1 } } WfAnalysis.Create(master_name, builder_name, build_number).put() # Run pipeline with signals that have certain failed steps. # Observe new group creation. self.assertTrue( try_job_util._IsBuildFailureUniqueAcrossPlatforms( master_name, builder_name, build_number, failure_type.TEST, blame_list_1, failed_steps, None, None)) self.assertIsNotNone( WfFailureGroup.Get(master_name, builder_name, build_number)) WfAnalysis.Create(master_name_2, builder_name, build_number).put() # Run pipeline with signals that have different failed steps. # Observe new group creation. self.assertTrue( try_job_util._IsBuildFailureUniqueAcrossPlatforms( master_name_2, builder_name, build_number, failure_type.TEST, blame_list_2, failed_steps, None, None)) self.assertTrue( WfFailureGroup.Get(master_name_2, builder_name, build_number))
def setUp(self): super(TriageAnalysisTest, self).setUp() self.master_name = 'm' self.builder_name = 'b' self.build_number_incomplete = 120 # Analysis is not completed yet. self.build_number_found = 122 # Suspected CLs are found for this build. self.build_number_not_found = 123 # No suspected CLs found. self.suspected_cls = [{ 'repo_name': 'chromium', 'revision': 'r1', 'commit_position': 123, 'url': 'https://codereview.chromium.org/123', }] analysis = WfAnalysis.Create(self.master_name, self.builder_name, self.build_number_incomplete) analysis.status = wf_analysis_status.ANALYZING analysis.put() analysis = WfAnalysis.Create(self.master_name, self.builder_name, self.build_number_found) analysis.status = wf_analysis_status.ANALYZED analysis.suspected_cls = self.suspected_cls analysis.put() analysis = WfAnalysis.Create(self.master_name, self.builder_name, self.build_number_not_found) analysis.status = wf_analysis_status.ANALYZED analysis.put() self.mock_current_user(user_email='*****@*****.**', is_admin=True)
def testDoNotGroupTestsWithDifferentHeuristicResults(self): master_name = 'm1' builder_name = 'b' build_number = 1 master_name_2 = 'm2' blame_list = ['a'] failed_steps = { 'step_a': { 'current_failure': 3, 'first_failure': 2, 'last_pass': 1 } } heuristic_result_1 = { 'failures': [{ 'step_name': 'step1', 'suspected_cls': [{ 'revision': 'rev1', }], }] } heuristic_result_2 = { 'failures': [{ 'step_name': 'step1', 'suspected_cls': [{ 'revision': 'rev2', }], }] } WfAnalysis.Create(master_name, builder_name, build_number).put() # Run pipeline with signals that have certain failed steps. # Observe new group creation. self.assertTrue( try_job_util._IsBuildFailureUniqueAcrossPlatforms( master_name, builder_name, build_number, failure_type.TEST, blame_list, failed_steps, None, heuristic_result_1)) self.assertIsNotNone( WfFailureGroup.Get(master_name, builder_name, build_number)) WfAnalysis.Create(master_name_2, builder_name, build_number).put() # Run pipeline with signals that have different failed steps. # Observe new group creation. self.assertTrue( try_job_util._IsBuildFailureUniqueAcrossPlatforms( master_name_2, builder_name, build_number, failure_type.TEST, blame_list, failed_steps, None, heuristic_result_2)) self.assertTrue( WfFailureGroup.Get(master_name_2, builder_name, build_number))
def testDoNotGroupCompilesWithDifferentHeuristicResults(self): master_name = 'm1' builder_name = 'b' build_number = 1 master_name_2 = 'm2' blame_list = ['a'] signals = {'compile': {'failed_output_nodes': ['abc.obj']}} heuristic_result_1 = { 'failures': [{ 'step_name': 'step1', 'suspected_cls': [{ 'revision': 'rev1', }], }] } heuristic_result_2 = { 'failures': [{ 'step_name': 'step1', 'suspected_cls': [{ 'revision': 'rev2', }], }] } WfAnalysis.Create(master_name, builder_name, build_number).put() # Run pipeline with signals that have certain failed output nodes. # Observe new group creation. self.assertTrue( try_job_util._IsBuildFailureUniqueAcrossPlatforms( master_name, builder_name, build_number, failure_type.COMPILE, blame_list, None, signals, heuristic_result_1)) self.assertIsNotNone( WfFailureGroup.Get(master_name, builder_name, build_number)) WfAnalysis.Create(master_name_2, builder_name, build_number).put() # Run pipeline with signals that have different failed output nodes. # Observe new group creation. self.assertTrue( try_job_util._IsBuildFailureUniqueAcrossPlatforms( master_name_2, builder_name, build_number, failure_type.COMPILE, blame_list, None, signals, heuristic_result_2)) self.assertTrue( WfFailureGroup.Get(master_name_2, builder_name, build_number))
def testBailOutForTryJobWithOutdatedTimestamp(self, mock_fn): master_name = 'master1' builder_name = 'builder1' build_number = 223 WfAnalysis.Create(master_name, builder_name, build_number).put() failure_info = { 'master_name': master_name, 'builder_name': builder_name, 'build_number': build_number, 'failed_steps': { 'compile': { 'current_failure': 221, 'first_failure': 221, 'last_pass': 220 } }, 'failure_type': failure_type.COMPILE } yesterday = datetime.utcnow() - timedelta(days=1) build = WfBuild.Create(master_name, builder_name, build_number) build.start_time = yesterday build.put() mock_fn.return_value = True need_try_job, try_job_key = try_job_util.NeedANewWaterfallTryJob( master_name, builder_name, build_number, failure_info, None, None) self.assertFalse(need_try_job) self.assertIsNone(try_job_key)
def testGetSuspectedCLsForTestTryJobWithHeuristicResult(self): suspected_cl = { 'revision': 'rev1', 'commit_position': 1, 'url': 'url_1', 'repo_name': 'chromium', 'failures': { 'step1': ['test1'] }, 'top_score': 2 } analysis = WfAnalysis.Create('m', 'b', 1) analysis.suspected_cls = [suspected_cl] analysis.put() result = { 'report': { 'result': { 'rev1': { 'step1': { 'status': 'failed', 'valid': True, 'failures': ['test1'] } } } } } self.assertEqual( identify_try_job_culprit_pipeline._GetSuspectedCLs( analysis, failure_type.TEST, result, {}), [suspected_cl])
def testWfAnalysisCorrectnessIsUnknownIfUntriaged(self): for status in (result_status.FOUND_UNTRIAGED, result_status.NOT_FOUND_UNTRIAGED): analysis = WfAnalysis.Create('m', 'b', 123) analysis.status = analysis_status.COMPLETED analysis.result_status = status self.assertIsNone(analysis.correct)
def testGetSwarmingTaskInfoReturnIfNonSwarming(self): analysis = WfAnalysis.Create(self.master_name, self.builder_name, self.build_number) analysis.failure_result_map = { 'step1': '%s/%s/%s' % (self.master_name, self.builder_name, 120) } analysis.put() data = handlers_util.GetSwarmingTaskInfo(self.master_name, self.builder_name, self.build_number) expected_data = { 'step1': { 'swarming_tasks': { 'm/b/120': { 'task_info': { 'status': result_status.NON_SWARMING_NO_RERUN } } } } } self.assertEqual(expected_data, data)
def testCorpUserCanViewAnalysisOfFailureOnUnsupportedMaster( self, mocked_ValidateAuthToken): mocked_ValidateAuthToken.side_effect = [(True, False)] master_name = 'm2' builder_name = 'b 1' build_number = 123 build_url = buildbot.CreateBuildUrl(master_name, builder_name, build_number) analysis = WfAnalysis.Create(master_name, builder_name, build_number) analysis.status = analysis_status.COMPLETED analysis.put() self.mock_current_user(user_email='*****@*****.**', is_admin=False) response = self.test_app.post('/failure', params={ 'url': build_url, 'xsrf_token': 'ab' }, status=302) redirect_url = '/waterfall/failure?redirect=1&url=%s' % build_url self.assertTrue( response.headers.get('Location', '').endswith(redirect_url)) self.assertEqual(0, len(self.taskqueue_stub.get_filtered_tasks()))
def testGetFailedStepsForEachCL(self): analysis = WfAnalysis.Create('m', 'b', 0) analysis.result = { 'failures': [{ 'step_name': 'a', 'first_failure': 3, 'last_pass': None, 'suspected_cls': [{ 'repo_name': 'chromium', 'revision': 'r99_1', 'commit_position': 123, 'url': None, 'score': 5, 'hints': { 'added x/y/f99_1.cc (and it was in log)': 5, } }], }, { 'step_name': 'b', 'first_failure': 2, 'last_pass': None, 'suspected_cls': [], }] } expected_failed_steps = {'chromium,r99_1': ['a']} failed_steps = check_duplicate_failures._GetFailedStepsForEachCL( analysis) self.assertEqual(expected_failed_steps, failed_steps)
def testTriggerFlakeAnalysesPipeline(self, mock_monitoring, *_): master_name = 'm' builder_name = 'b' build_number = 2 step_name = 'a_tests' test_name = 'Unittest1.Subtest1' analysis = WfAnalysis.Create(master_name, builder_name, build_number) analysis.flaky_tests = {step_name: [test_name, 'Unittest1.Subtest2']} analysis.put() build_key = BuildKey(master_name=master_name, builder_name=builder_name, build_number=build_number) with mock.patch.object( flake_analysis_service, 'ScheduleAnalysisForFlake') as mocked_ScheduleAnalysisForFlake: pipeline = TriggerFlakeAnalysesPipeline(build_key) pipeline.RunImpl(build_key) self.assertTrue(mocked_ScheduleAnalysisForFlake.called) mock_monitoring.assert_has_calls([ mock.call('a_tests', 'a_tests', 'analyzed', 1), mock.call('a_tests', 'a_tests', 'throttled', 1) ])
def testWfAnalysisCorrectnessIsUnknownIfUntriaged(self): for result_status in (wf_analysis_result_status.FOUND_UNTRIAGED, wf_analysis_result_status.NOT_FOUND_UNTRIAGED): analysis = WfAnalysis.Create('m', 'b', 123) analysis.status = wf_analysis_status.ANALYZED analysis.result_status = result_status self.assertIsNone(analysis.correct)
def testAppendTriageHistoryRecordWithHistory(self): analysis = WfAnalysis.Create( self.master_name, self.builder_name, self.build_number_1) analysis.version = 'version' analysis.triage_history = [{'some_info': True}] analysis.put() cl_info = '%s/%s' % (self.repo_name, self.revision_1) mocked_now = datetime(2017, 05, 01, 10, 10, 10) mocked_timestamp = calendar.timegm(mocked_now.timetuple()) self.MockUTCNow(mocked_now) triage_suspected_cl._AppendTriageHistoryRecord( self.master_name, self.builder_name, self.build_number_1, cl_info, suspected_cl_status.CORRECT, 'test') analysis = WfAnalysis.Get( self.master_name, self.builder_name, self.build_number_1) expected_history = [ {'some_info': True}, { 'triage_timestamp': mocked_timestamp, 'user_name': 'test', 'cl_status': suspected_cl_status.CORRECT, 'version': 'version', 'triaged_cl': cl_info } ] self.assertEqual(analysis.triage_history, expected_history) self.assertFalse(analysis.triage_email_obscured) self.assertEqual(mocked_now, analysis.triage_record_last_add)
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 testNoResultIsReturnedWhenNoAnalysisIsCompleted(self): master_name = 'm' builder_name = 'b' build_number = 5 master_url = 'https://build.chromium.org/p/%s' % master_name builds = { 'builds': [ { 'master_url': master_url, 'builder_name': builder_name, 'build_number': build_number } ] } analysis = WfAnalysis.Create(master_name, builder_name, build_number) analysis.status = wf_analysis_status.ANALYZING analysis.result = None analysis.put() expected_result = [] self._MockMasterIsSupported(supported=True) response = self.call_api('AnalyzeBuildFailures', body=builds) self.assertEqual(200, response.status_int) self.assertEqual(expected_result, response.json_body.get('results', []))
def testUpdateAnalysisPartiallyTriaged(self): analysis = WfAnalysis.Create( self.master_name, self.builder_name, self.build_number_1) analysis.suspected_cls = [self.suspected_cl_1, self.suspected_cl_2] analysis.result_status = result_status.FOUND_UNTRIAGED analysis.put() success = triage_suspected_cl._UpdateAnalysis( self.master_name, self.builder_name, self.build_number_1, self.repo_name, self.revision_1, suspected_cl_status.CORRECT) expected_suspected_cls = [ { 'repo_name': self.repo_name, 'revision': self.revision_1, 'commit_position': self.commit_position, 'url': 'https://codereview.chromium.org/123', 'status': suspected_cl_status.CORRECT }, self.suspected_cl_2 ] analysis = WfAnalysis.Get( self.master_name, self.builder_name, self.build_number_1) self.assertTrue(success) self.assertEqual(analysis.result_status, result_status.FOUND_UNTRIAGED) self.assertEqual(analysis.suspected_cls, expected_suspected_cls)
def testTriggerFlakeAnalysesPipeline(self): master_name = 'm' builder_name = 'b' build_number = 2 step_name = 'a_tests' test_name = 'Unittest1.Subtest1' analysis = WfAnalysis.Create(master_name, builder_name, build_number) analysis.failure_result_map = { step_name: { test_name: '%s/%s/%s' % (master_name, builder_name, build_number) } } analysis.put() swarming_task = WfSwarmingTask.Create(master_name, builder_name, build_number, step_name) swarming_task.tests_statuses = {test_name: {'SUCCESS': 1}} swarming_task.put() with mock.patch.object(flake_analysis_service, 'ScheduleAnalysisForFlake') as ( mocked_ScheduleAnalysisForFlake): pipeline = TriggerFlakeAnalysesPipeline() pipeline.run(master_name, builder_name, build_number) mocked_ScheduleAnalysisForFlake.assert_called_once()
def testNotNeedANewWaterfallTryJobIfNoNewFailure(self, mock_fn): master_name = 'm' builder_name = 'b' build_number = 223 failure_info = { 'failed_steps': { 'a': { 'current_failure': 223, 'first_failure': 222, 'last_pass': 221, 'tests': { 'a.t2': { 'current_failure': 223, 'first_failure': 222, 'last_pass': 221 } } } }, 'failure_type': failure_type.TEST } analysis = WfAnalysis.Create(master_name, builder_name, build_number) analysis.failure_result_map = {'a': {'a.t2': 'm/b/222'}} analysis.put() mock_fn.return_value = False expected_try_job_key = WfTryJob.Create(master_name, builder_name, build_number).key need_try_job, try_job_key = try_job_util.NeedANewWaterfallTryJob( master_name, builder_name, build_number, failure_info, None, None) self.assertFalse(need_try_job) self.assertEqual(expected_try_job_key, try_job_key)
def testIdentifyCulpritForTestTryJobNoTryJobResultNoHeuristicResult(self): master_name = 'm' builder_name = 'b' build_number = 1 try_job_id = '1' self._CreateEntities(master_name, builder_name, build_number, try_job_id, try_job_status=analysis_status.RUNNING) analysis = WfAnalysis.Create(master_name, builder_name, build_number) analysis.put() self.MockPipeline(RevertAndNotifyCulpritPipeline, None, expected_args=[master_name, builder_name, build_number, None, [], failure_type.TEST]) pipeline = IdentifyTryJobCulpritPipeline( master_name, builder_name, build_number, failure_type.TEST, '1', None) pipeline.start() self.execute_queued_tasks() try_job_data = WfTryJobData.Get(try_job_id) self.assertIsNone(try_job_data.culprits) self.assertIsNone(analysis.result_status) self.assertIsNone(analysis.suspected_cls)
def testIdentifyCulpritForCompileTryJobNoCulprit(self): master_name = 'm' builder_name = 'b' build_number = 1 try_job_id = '1' self._CreateEntities(master_name, builder_name, build_number, try_job_id) analysis = WfAnalysis.Create(master_name, builder_name, build_number) analysis.put() self.MockPipeline(RevertAndNotifyCulpritPipeline, None, expected_args=[master_name, builder_name, build_number, None, [], failure_type.COMPILE]) pipeline = IdentifyTryJobCulpritPipeline( master_name, builder_name, build_number, failure_type.COMPILE, '1', None) pipeline.start() self.execute_queued_tasks() try_job = WfTryJob.Get(master_name, builder_name, build_number) try_job_data = WfTryJobData.Get(try_job_id) self.assertEqual(analysis_status.COMPLETED, try_job.status) self.assertEqual([], try_job.compile_results) self.assertIsNone(try_job_data.culprits) self.assertIsNone(analysis.result_status) self.assertIsNone(analysis.suspected_cls)
def testUpdateAnalysisWithFlakeInfoNoAnalysisResult(self, mock_fn): master_name = 'm' builder_name = 'b' build_number = 32 WfAnalysis.Create(master_name, builder_name, build_number).put() test_failure_analysis.UpdateAnalysisWithFlakesFoundBySwarmingReruns( master_name, builder_name, build_number, {'a': ['b']}) self.assertFalse(mock_fn.called)
def _Setup(self, master_name, builder_name, build_number, status=analysis_status.PENDING): analysis = WfAnalysis.Create(master_name, builder_name, build_number) analysis.status = status analysis.put()
def testUpdateWfAnalysisWithTryJobResult(self): master_name = 'm1' builder_name = 'b' build_number = 1 analysis = WfAnalysis.Create(master_name, builder_name, build_number) analysis.put() analysis.UpdateWithNewFindings(result_status.FOUND_CORRECT, None, None) self.assertEqual(analysis.result_status, result_status.FOUND_CORRECT)
def testWfAnalysisHasCorrectResult(self): for status in (result_status.FOUND_CORRECT, result_status.NOT_FOUND_CORRECT, result_status.FOUND_CORRECT_DUPLICATE): analysis = WfAnalysis.Create('m', 'b', 123) analysis.status = analysis_status.COMPLETED analysis.result_status = status self.assertTrue(analysis.correct)
def testObscureTriageRecordsInWfAnalysis(self): mocked_utcnow = datetime(2017, 05, 05, 22, 50, 10) self.MockUTCNow(mocked_utcnow) valid_record_time = obscure_emails._TimeBeforeNow( days=obscure_emails._TRIAGE_RECORD_RENTENSION_DAYS - 10) invalid_record_time = obscure_emails._TimeBeforeNow( days=obscure_emails._TRIAGE_RECORD_RENTENSION_DAYS + 10) old_analysis = WfAnalysis.Create('m', 'b', 1) old_analysis.triage_history = [{ 'user_name': '*****@*****.**', }] old_analysis.triage_email_obscured = False old_analysis.triage_record_last_add = invalid_record_time old_analysis.put() recent_analysis = WfAnalysis.Create('m', 'b', 100000) recent_analysis.triage_history = [{ 'user_name': '*****@*****.**', }] recent_analysis.triage_email_obscured = False recent_analysis.triage_record_last_add = valid_record_time recent_analysis.put() response = self.test_app.get( '/obscure-emails', params={'format': 'json'}, headers={'X-AppEngine-Cron': 'true'}, ) expected_response = { 'failure_triage_count': 1, 'flake_triage_count': 0, 'flake_request_aggregated_count': 0, 'flake_request_count': 0, } self.assertEqual(expected_response, response.json_body) old_analysis = WfAnalysis.Get('m', 'b', 1) self.assertEqual('*****@*****.**', old_analysis.triage_history[0]['user_name']) self.assertTrue(old_analysis.triage_email_obscured) recent_analysis = WfAnalysis.Get('m', 'b', 100000) self.assertEqual('*****@*****.**', recent_analysis.triage_history[0]['user_name']) self.assertFalse(recent_analysis.triage_email_obscured)
def testNotNeedANewWaterfallTryJobIfNotFirstTimeFailure(self, mock_fn): master_name = 'm' builder_name = 'b' build_number = 223 WfAnalysis.Create(master_name, builder_name, build_number).put() failure_info = { 'master_name': master_name, 'builder_name': builder_name, 'build_number': build_number, 'failed_steps': { 'compile': { 'current_failure': 223, 'first_failure': 221, 'last_pass': 220 } }, 'builds': { '220': { 'blame_list': ['220-1', '220-2'], 'chromium_revision': '220-2' }, '221': { 'blame_list': ['221-1', '221-2'], 'chromium_revision': '221-2' }, '222': { 'blame_list': ['222-1'], 'chromium_revision': '222-1' }, '223': { 'blame_list': ['223-1', '223-2', '223-3'], 'chromium_revision': '223-3' } }, 'failure_type': failure_type.COMPILE } WfAnalysis.Create(master_name, builder_name, build_number).put() mock_fn.return_value = False expected_key = WfTryJob.Create(master_name, builder_name, build_number).key need_try_job, try_job_key = try_job_util.NeedANewWaterfallTryJob( master_name, builder_name, build_number, failure_info, None, None) self.assertFalse(need_try_job) self.assertEqual(expected_key, try_job_key)