def testCheckTestsRunStatuses(self, mocked_fn, _): build_info = BuildInfo(self.master_name, self.build_number, self.build_number) build_info.commit_position = 12345 build_info.chromium_revision = 'a1b2c3d4' mocked_fn.return_value = build_info analysis = MasterFlakeAnalysis.Create(self.master_name, self.builder_name, self.build_number, self.step_name, self.test_name) analysis.Save() task = FlakeSwarmingTask.Create(self.master_name, self.builder_name, self.build_number, self.step_name, self.test_name) task.put() call_params = ProcessFlakeSwarmingTaskResultPipeline._GetArgs( self.pipeline, self.master_name, self.builder_name, self.build_number, self.step_name, self.build_number, self.test_name, self.version_number) tests_statuses = ( ProcessFlakeSwarmingTaskResultPipeline._CheckTestsRunStatuses( self.pipeline, base_test._SAMPLE_FAILURE_LOG, *call_params)) self.assertEqual(base_test._EXPECTED_TESTS_STATUS, tests_statuses)
def testAdminCanRequestAnalysisOfFailureOnUnsupportedMaster(self): self.mock_current_user(user_email='*****@*****.**', is_admin=True) build = WfBuild.Create('m', 'b', 1) build.data = '{}' self._MockDownloadBuildData(build) build_info = BuildInfo('m', 'b', 1) build_info.completed = True self._MockExtractBuildInfo(build_info) requests = [] self._MockScheduleAnalysisIfNeeded(requests) builds = [ { 'master_name': 'm', 'builder_name': 'b', 'build_number': 1, 'failed_steps': [], }, ] response = self.test_app.post( '/trigger-analyses', params=json.dumps({'builds': builds})) self.assertEquals(200, response.status_int) self.assertEqual(1, len(requests)) self.assertTrue(requests[0][1]['build_completed'])
def testCannotRerunIncompleteBuild(self, mock_fn, mocked_ValidateAuthToken): mocked_ValidateAuthToken.side_effect = [(True, False)] master_name = 'm' builder_name = 'b 1' build_number = 123 build_url = buildbot.CreateBuildUrl(master_name, builder_name, build_number) build_info = BuildInfo(master_name, builder_name, build_number) build_info.completed = False mock_fn.return_value = build_info self.mock_current_user(user_email='*****@*****.**', is_admin=True) self.assertRaisesRegexp( webtest.app.AppError, re.compile( '.*501 Not Implemented.*Can't force a rerun for an ' 'incomplete build "%s/%s/%s".*' % (master_name, builder_name, build_number), re.MULTILINE | re.DOTALL), self.test_app.post, '/failure', params={ 'url': build_url, 'force': '1', 'xsrf_token': 'abc' })
def testCannotRerunIncompleteBuild(self, mock_fn): master_name = 'm2' builder_name = 'b 1' build_number = 123 build_url = buildbot.CreateBuildUrl(master_name, builder_name, build_number) build_info = BuildInfo(master_name, builder_name, build_number) build_info.completed = False mock_fn.return_value = build_info self.mock_current_user(user_email='*****@*****.**', is_admin=True) self.assertRaisesRegexp( webtest.app.AppError, re.compile( '.*501 Not Implemented.*Can't rerun an incomplete' ' build "%s/%s/%s".*' % (master_name, builder_name, build_number), re.MULTILINE | re.DOTALL), self.test_app.get, '/failure', params={ 'url': build_url, 'force': '1' })
def testNotEveryoneCanRequestNewAnalysisOfFailureOnSupportedMaster( self, mock_fn, mocked_ValidateAuthToken): mocked_ValidateAuthToken.side_effect = [(True, False)] master_name = 'm' builder_name = 'b 1' build_number = 123 build_url = buildbot.CreateBuildUrl(master_name, builder_name, build_number) build_info = BuildInfo(master_name, builder_name, build_number) build_info.completed = False mock_fn.return_value = build_info self.mock_current_user(user_email='*****@*****.**', is_admin=False) response = self.test_app.post('/failure', params={ 'url': build_url, 'xsrf_token': 'abc' }, 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 testMonitorSwarmingTaskBuildException(self, mocked_fn, _): task_id = NO_TASK_EXCEPTION build_info = BuildInfo(self.master_name, self.build_number, self.build_number) build_info.commit_position = 12345 build_info.chromium_revision = 'a1b2c3d4' mocked_fn.return_value = build_info task = FlakeSwarmingTask.Create(self.master_name, self.builder_name, self.build_number, self.step_name, self.test_name) task.task_id = 'task_id' task.put() analysis = MasterFlakeAnalysis.Create(self.master_name, self.builder_name, self.build_number, self.step_name, self.test_name) analysis.Save() pipeline = ProcessFlakeSwarmingTaskResultPipeline() pipeline.start_test() pipeline.run(self.master_name, self.builder_name, self.build_number, self.step_name, task_id, self.build_number, self.test_name, 1) self.assertIsNone(task.task_id) self.assertEqual(analysis_status.SKIPPED, task.status) self.assertEqual(-1, analysis.data_points[-1].pass_rate) self.assertFalse(analysis.data_points[-1].has_valid_artifact)
def testTaskQueueCanRequestAnalysis(self): build_info = BuildInfo('m', 'b', 1) build_info.completed = True self._MockGetBuildInfo(build_info) requests = [] self._MockScheduleAnalysisIfNeeded(requests) builds = [ { 'master_name': 'm', 'builder_name': 'b', 'build_number': 1, 'failed_steps': [], }, ] response = self.test_app.post( '/process-failure-analysis-requests', params=json.dumps({ 'builds': builds }), headers={'X-AppEngine-QueueName': 'task_queue'}, ) self.assertEquals(200, response.status_int) self.assertEqual(1, len(requests)) self.assertTrue(requests[0][1]['build_completed'])
def ExtractBuildInfo(master_name, builder_name, build_number, build_data): """Extracts and returns build information as an instance of BuildInfo.""" build_info = BuildInfo(master_name, builder_name, build_number) data_json = json.loads(build_data) chromium_revision = GetBuildProperty(data_json.get('properties', []), 'got_revision') commit_position_line = GetBuildProperty(data_json.get('properties', []), 'got_revision_cp') parent_buildername = GetBuildProperty(data_json.get('properties', []), 'parent_buildername') parent_mastername = GetBuildProperty(data_json.get('properties', []), 'parent_mastername') build_info.build_start_time = GetBuildStartTime(data_json) build_info.build_end_time = GetBuildEndTime(data_json) build_info.chromium_revision = chromium_revision build_info.commit_position = _GetCommitPosition(commit_position_line) build_info.completed = data_json.get('currentStep') is None build_info.result = GetBuildResult(data_json) build_info.parent_buildername = parent_buildername build_info.parent_mastername = parent_mastername changes = data_json.get('sourceStamp', {}).get('changes', []) for change in changes: if change['revision'] not in build_info.blame_list: build_info.blame_list.append(change['revision']) # Step categories: # 1. A step is passed if it is in SUCCESS or WARNINGS status. # 2. A step is failed if it is in FAILED status. # 3. A step is not passed if it is not in SUCCESS or WARNINGS status. This # category includes steps in statuses: FAILED, SKIPPED, EXCEPTION, RETRY, # CANCELLED, etc. steps = data_json.get('steps', []) for step_data in steps: step_name = step_data['name'] if not step_data.get('isFinished', False): # Skip steps that haven't started yet or are still running. continue step_result = GetStepResult(step_data) if step_result not in (SUCCESS, WARNINGS): build_info.not_passed_steps.append(step_name) step_logs = step_data.get('logs') if step_logs and 'preamble' == step_logs[0][0]: # Skip a annotating step like "steps" or "slave_steps", which wraps other # steps. A failed annotated step like "content_browsertests" will make # the annotating step like "steps" fail too. Such annotating steps have a # log with name "preamble". continue if step_result in (SUCCESS, WARNINGS): build_info.passed_steps.append(step_name) elif step_result == FAILURE: build_info.failed_steps.append(step_name) return build_info
def _MockExtractBuildInfo(*_): build_info = BuildInfo('m', 'b', 25409) build_info.failed_steps = { 'compile': { 'last_pass': '******', 'current_failure': '25409', 'first_failure': '25409' } } return build_info
def testGetBuildInfo(self, mocked_fn, mock_build_info, _): build = WfBuild.Create('m', 'b', 123) build.build_id = '8000000123' mocked_fn.return_value = build expected_build_info = BuildInfo('m', 'b', 123) expected_build_info.chromium_revision = 'a_git_hash' mock_build_info.return_value = expected_build_info build_info = build_util.GetBuildInfo('m', 'b', 123) self.assertEqual(build_info.chromium_revision, 'a_git_hash')
def testGetFailureType(self): cases = { failure_type.UNKNOWN: [], failure_type.COMPILE: ['compile', 'slave_steps'], failure_type.TEST: ['browser_tests'], } for expected_type, failed_steps in cases.iteritems(): build_info = BuildInfo('m', 'b', 123) build_info.failed_steps = failed_steps self.assertEqual( expected_type, detect_first_failure_pipeline._GetFailureType(build_info))
def testRerunAnalysisWithAnalyzeFlakePipeline( self, mocked_analysis, mocked_pipeline, mocked_need_analysis, mocked_build_info, mock_dimensions, *_): buildbucket_id = 'id' mock_dimensions.return_value = ['os:Mac', 'cpu:x86'] start_commit_position = 1000 start_build_info = BuildInfo('m', 'b 1', 123) start_build_info.commit_position = start_commit_position start_build_info.chromium_revision = 'r1000' start_build_info.buildbucket_id = buildbucket_id mocked_build_info.return_value = start_build_info mocked_analysis.pipeline_status_path.return_value = 'status' mocked_analysis.key.urlsafe.return_value = 'urlsafe_key' mocked_need_analysis.return_value = (True, mocked_analysis) test = TestInfo('m', 'b 1', 123, 's', 't') manually_triggered = False flake = Flake.Create('chromium', 's', 't', 'l') analysis = initialize_flake_pipeline.ScheduleAnalysisIfNeeded( test, test, flake.key, bug_id=None, allow_new_analysis=True, manually_triggered=manually_triggered, force=True, queue_name=constants.DEFAULT_QUEUE) self.assertIsNotNone(analysis) self.assertEqual(buildbucket_id, analysis.build_id) self.assertEqual(buildbucket_id, analysis.original_build_id) analyze_flake_input = AnalyzeFlakeInput( analysis_urlsafe_key='urlsafe_key', analyze_commit_position_parameters=NextCommitPositionOutput( culprit_commit_id=None, next_commit_id=CommitID( commit_position=start_commit_position, revision=start_build_info.chromium_revision)), commit_position_range=IntRange(lower=None, upper=start_commit_position), dimensions=ListOfBasestring.FromSerializable( ['os:Mac', 'cpu:x86', 'pool:luci.chromium.findit']), manually_triggered=manually_triggered, rerun=True, retries=0, step_metadata=StepMetadata.FromSerializable({})) mocked_pipeline.assert_has_calls([ mock.call(analyze_flake_input), mock.call().start(queue_name=constants.DEFAULT_QUEUE) ])
def testMonitorSwarmingTaskTimeOut(self, mocked_fn, _): build_info = BuildInfo(self.master_name, self.builder_name, self.build_number) build_info.commit_position = 12345 build_info.chromium_revision = 'a1b2c3d4' mocked_fn.return_value = build_info # Override swarming config settings to force a timeout. override_swarming_settings = {'task_timeout_hours': -1} self.UpdateUnitTestConfigSettings('swarming_settings', override_swarming_settings) task = FlakeSwarmingTask.Create(self.master_name, self.builder_name, self.build_number, self.step_name, self.test_name) task.task_id = 'task_id1' task.put() analysis = MasterFlakeAnalysis.Create(self.master_name, self.builder_name, self.build_number, self.step_name, self.test_name) analysis.Save() pipeline = ProcessFlakeSwarmingTaskResultPipeline(self.master_name, self.builder_name, self.build_number, self.step_name, self.build_number, self.test_name, 1, task_id='task_id1') pipeline.start_test() pipeline.run(self.master_name, self.builder_name, self.build_number, self.step_name, 'task_id1', self.build_number, self.test_name, 1) pipeline.callback(callback_params=pipeline.last_params) # Reload from ID to get all internal properties in sync. pipeline = ProcessFlakeSwarmingTaskResultPipeline.from_id( pipeline.pipeline_id) pipeline.finalized() step_name, task_info = pipeline.outputs.default.value self.assertEqual('abc_tests', task_info) self.assertEqual(self.step_name, step_name) task = FlakeSwarmingTask.Get(self.master_name, self.builder_name, self.build_number, self.step_name, self.test_name) self.assertEqual(analysis_status.ERROR, task.status) self.assertEqual({}, task.tests_statuses)
def ExtractBuildInfo(master_name, builder_name, build_number, build_data): """Extracts and returns build information as an instance of BuildInfo.""" build_info = BuildInfo(master_name, builder_name, build_number) data_json = json.loads(build_data) chromium_revision = GetBuildProperty( data_json.get('properties', []), 'got_revision') build_info.build_start_time = GetBuildStartTime(data_json) build_info.chromium_revision = chromium_revision build_info.completed = data_json.get('currentStep') is None build_info.result = GetBuildResult(data_json) changes = data_json.get('sourceStamp', {}).get('changes', []) for change in changes: if change['revision'] not in build_info.blame_list: build_info.blame_list.append(change['revision']) # Step categories: # 1. A step is passed if it is in SUCCESS or WARNINGS status. # 2. A step is failed if it is in FAILED status. # 3. A step is not passed if it is not in SUCCESS or WARNINGS status. This # category includes steps in statuses: FAILED, SKIPPED, EXCEPTION, RETRY, # CANCELLED, etc. steps = data_json.get('steps', []) for step_data in steps: step_name = step_data['name'] if not step_data.get('isFinished', False): # Skip steps that haven't started yet or are still running. continue step_result = GetStepResult(step_data) if step_result not in (SUCCESS, WARNINGS): build_info.not_passed_steps.append(step_name) step_logs = step_data.get('logs') if step_logs and 'preamble' == step_logs[0][0]: # Skip a annotating step like "steps" or "slave_steps", which wraps other # steps. A failed annotated step like "content_browsertests" will make # the annotating step like "steps" fail too. Such annotating steps have a # log with name "preamble". continue if step_result in (SUCCESS, WARNINGS): build_info.passed_steps.append(step_name) elif step_result == FAILURE: build_info.failed_steps.append(step_name) return build_info
def testAnyoneCanRequestAnalysisOfFailureOnSupportedMaster(self, mock_fn): master_name = 'm' builder_name = 'b 1' build_number = 123 build_url = buildbot.CreateBuildUrl(master_name, builder_name, build_number) build_info = BuildInfo(master_name, builder_name, build_number) build_info.completed = False mock_fn.return_value = build_info response = self.test_app.get('/failure', params={'url': build_url}) self.assertEquals(200, response.status_int) self.assertEqual(1, len(self.taskqueue_stub.get_filtered_tasks()))
def testAdminCanRequestAnalysisOfFailureOnUnsupportedMaster(self, mock_fn): master_name = 'm2' builder_name = 'b' build_number = 123 build_url = buildbot.CreateBuildUrl(master_name, builder_name, build_number) build_info = BuildInfo(master_name, builder_name, build_number) build_info.completed = False mock_fn.return_value = build_info self.mock_current_user(user_email='*****@*****.**', is_admin=True) response = self.test_app.get('/failure', params={'url': build_url}) self.assertEquals(200, response.status_int) self.assertEqual(1, len(self.taskqueue_stub.get_filtered_tasks()))
def testGetValidBuildSearchAscendingOutOfRange(self, mocked_get_build_info): master_name = 'm' builder_name = 'b' step_name = 's' invalid_build_100 = BuildInfo(master_name, builder_name, 100) invalid_build_101 = BuildInfo(master_name, builder_name, 101) valid_build_102 = BuildInfo(master_name, builder_name, 102) valid_build_102.commit_position = 1020 mocked_get_build_info.side_effect = [ invalid_build_100, invalid_build_101, valid_build_102, ] self.assertIsNone( step_util.GetValidBuild(master_name, builder_name, 100, step_name, True, 1))
def testWhenBuildDataIsDownloadedSuccessfully(self): build_info = BuildInfo('m', 'b', 1) build_info.completed = False self._MockGetBuildInfo(build_info) requests = [] self._MockScheduleAnalysisIfNeeded(requests) builds = [ { 'master_name': 'm', 'builder_name': 'b', 'build_number': 1, 'failed_steps': [], }, ] process_failure_analysis_requests._TriggerNewAnalysesOnDemand(builds) self.assertEqual(1, len(requests)) self.assertFalse(requests[0][1]['build_completed'])
def testGetValidBuildSearchDescending(self, mocked_get_build_info): master_name = 'm' builder_name = 'b' step_name = 's' invalid_build_100 = BuildInfo(master_name, builder_name, 100) invalid_build_99 = BuildInfo(master_name, builder_name, 99) valid_build_98 = BuildInfo(master_name, builder_name, 98) valid_build_98.commit_position = 980 mocked_get_build_info.side_effect = [ invalid_build_100, invalid_build_99, valid_build_98, ] self.assertEqual( valid_build_98, step_util.GetValidBuild(master_name, builder_name, 100, step_name, True, 2))
def testCheckTestsRunStatusesZeroBuildNumber(self, mocked_fn, _): build_info = BuildInfo(self.master_name, self.build_number, 0) build_info.commit_position = 12345 build_info.chromium_revision = 'a1b2c3d4' mocked_fn.return_value = build_info analysis = MasterFlakeAnalysis.Create(self.master_name, self.builder_name, 0, self.step_name, self.test_name) analysis.Save() task = FlakeSwarmingTask.Create(self.master_name, self.builder_name, 0, self.step_name, self.test_name) task.put() ProcessFlakeSwarmingTaskResultPipeline()._CheckTestsRunStatuses( {}, self.master_name, self.builder_name, 0, self.step_name, 0, self.test_name, 1) self.assertIsNone( analysis.data_points[0].previous_build_commit_position)
def testCheckTestsRunStatusesWhenTestDoesNotExist(self, mocked_fn, _): build_info = BuildInfo(self.master_name, self.builder_name, self.build_number) build_info.commit_position = 12345 build_info.chromium_revision = 'a1b2c3d4' mocked_fn.return_value = build_info test_name = 'TestSuite1.new_test' analysis = MasterFlakeAnalysis.Create(self.master_name, self.builder_name, self.build_number, self.step_name, test_name) analysis.Save() task = FlakeSwarmingTask.Create(self.master_name, self.builder_name, self.build_number, self.step_name, test_name) task.put() pipeline = ProcessFlakeSwarmingTaskResultPipeline() tests_statuses = pipeline._CheckTestsRunStatuses( base_test._SAMPLE_FAILURE_LOG, self.master_name, self.builder_name, self.build_number, self.step_name, self.build_number, test_name, self.version_number) self.assertEqual(base_test._EXPECTED_TESTS_STATUS, tests_statuses) task = FlakeSwarmingTask.Get(self.master_name, self.builder_name, self.build_number, self.step_name, test_name) self.assertEqual(0, task.tries) self.assertEqual(0, task.successes) analysis = MasterFlakeAnalysis.GetVersion(self.master_name, self.builder_name, self.build_number, self.step_name, test_name, self.version_number) self.assertTrue(analysis.data_points[-1].pass_rate < 0)
def testWhenBuildDataIsDownloadedSuccessfully(self): build = WfBuild.Create('m', 'b', 1) build.data = '{}' self._MockDownloadBuildData(build) build_info = BuildInfo('m', 'b', 1) build_info.completed = False self._MockExtractBuildInfo(build_info) requests = [] self._MockScheduleAnalysisIfNeeded(requests) builds = [ { 'master_name': 'm', 'builder_name': 'b', 'build_number': 1, 'failed_steps': [], }, ] trigger_analyses._TriggerNewAnalysesOnDemand(builds) self.assertEqual(1, len(requests)) self.assertFalse(requests[0][1]['build_completed'])
def testMonitorSwarmingTaskStepNotExist(self, mocked_fn, _): task_id = NO_TASK build_info = BuildInfo(self.master_name, self.build_number, self.build_number) build_info.commit_position = 12345 build_info.chromium_revision = 'a1b2c3d4' mocked_fn.return_value = build_info task = FlakeSwarmingTask.Create(self.master_name, self.builder_name, self.build_number, self.step_name, self.test_name) task.put() analysis = MasterFlakeAnalysis.Create(self.master_name, self.builder_name, self.build_number, self.step_name, self.test_name) analysis.Save() pipeline = ProcessFlakeSwarmingTaskResultPipeline( self.master_name, self.builder_name, self.build_number, self.step_name, task_id, self.build_number, self.test_name, 1) pipeline.start_test() pipeline.run(self.master_name, self.builder_name, self.build_number, self.step_name, task_id, self.build_number, self.test_name, 1) # Reload from ID to get all internal properties in sync. pipeline = ProcessFlakeSwarmingTaskResultPipeline.from_id( pipeline.pipeline_id) pipeline.finalized() _, step_name_no_platform = pipeline.outputs.default.value self.assertIsNone(task.task_id) self.assertEqual(analysis_status.SKIPPED, task.status) self.assertEqual(-1, analysis.data_points[-1].pass_rate) self.assertIsNone(step_name_no_platform)
def testAdminCanRequestAnalysisOfFailureOnUnsupportedMaster(self): self.mock_current_user(user_email='*****@*****.**', is_admin=True) build_info = BuildInfo('m', 'b', 1) build_info.completed = True self._MockGetBuildInfo(build_info) requests = [] self._MockScheduleAnalysisIfNeeded(requests) builds = [ { 'master_name': 'm', 'builder_name': 'b', 'build_number': 1, 'failed_steps': [], }, ] response = self.test_app.post('/process-failure-analysis-requests', params=json.dumps({'builds': builds})) self.assertEquals(200, response.status_int) self.assertEqual(1, len(requests)) self.assertTrue(requests[0][1]['build_completed'])
def testUpdateSuspectedBuildUsingBuildInfo(self): analysis = MasterFlakeAnalysis.Create('m', 'b', 123, 's', 't') analysis.data_points = [ DataPoint.Create(commit_position=100, pass_rate=0.4), DataPoint.Create(commit_position=90, pass_rate=1.0), ] analysis.Save() lower_bound_build = BuildInfo('m', 'b', 122) lower_bound_build.commit_position = 90 upper_bound_build = BuildInfo('m', 'b', 123) upper_bound_build.commit_position = 100 analysis.UpdateSuspectedBuildUsingBuildInfo(lower_bound_build, upper_bound_build) self.assertEqual(123, analysis.suspected_flake_build_number)
def ExtractBuildInfoFromV2Build(master_name, builder_name, build_number, build): """Generates BuildInfo using bb v2 build info. This conversion is needed to keep Findit v1 running, will be deprecated in v2 (TODO: crbug.com/966982). Args: master_name (str): The name of the master. builder_name (str): The name of the builder. build_number (int): The build number. build (build_pb2.Build): All info about the build. Returns: (BuildInfo) """ build_info = BuildInfo(master_name, builder_name, build_number) input_properties = json_format.MessageToDict(build.input.properties) chromium_revision = build.input.gitiles_commit.id runtime = input_properties.get('$recipe_engine/runtime') or {} build_info.chromium_revision = chromium_revision repo_url = git.GetRepoUrlFromV2Build(build) build_info.commit_position = git.GetCommitPositionFromRevision( build.input.gitiles_commit.id, repo_url=repo_url) build_info.build_start_time = build.create_time.ToDatetime() build_info.build_end_time = build.end_time.ToDatetime() build_info.completed = bool(build_info.build_end_time) build_info.result = build.status build_info.parent_buildername = input_properties.get('parent_buildername') build_info.parent_mastername = input_properties.get('parent_mastername') build_info.buildbucket_id = str(build.id) build_info.buildbucket_bucket = build.builder.bucket build_info.is_luci = runtime.get('is_luci') build_info.blame_list = GetBlameListForV2Build(build) # Step categories: # 1. A step is passed if it is in SUCCESS status. # 2. A step is failed if it is in FAILURE status. # 3. A step is not passed if it is not in SUCCESS status. This category # includes steps in statuses: FAILURE, INFRA_FAILURE, CANCELED, etc. for step in build.steps: step_name = step.name step_status = step.status if step_status in [ common_pb2.STATUS_UNSPECIFIED, common_pb2.SCHEDULED, common_pb2.STARTED ]: continue if step_status != common_pb2.SUCCESS: build_info.not_passed_steps.append(step_name) if step_name == 'Failure reason': # 'Failure reason' is always red when the build breaks or has exception, # but it is not a failed step. continue if not step.logs: # Skip wrapping steps. continue if step_status == common_pb2.SUCCESS: build_info.passed_steps.append(step_name) elif step_status == common_pb2.FAILURE: build_info.failed_steps.append(step_name) return build_info
class ProcessFlakeSwarmingTaskResultPipelineTest(wf_testcase.WaterfallTestCase ): def _MockedGetSwarmingTaskResultById(self, task_id, _): return base_test._SWARMING_TASK_RESULTS[task_id], None def setUp(self): super(ProcessFlakeSwarmingTaskResultPipelineTest, self).setUp() self.pipeline = ProcessFlakeSwarmingTaskResultPipeline() self.master_name = 'm' self.builder_name = 'b' self.build_number = 121 self.step_name = 'abc_tests on platform' self.test_name = 'TestSuite1.test1' self.version_number = 1 self.mock(swarming_util, 'GetSwarmingTaskResultById', self._MockedGetSwarmingTaskResultById) @mock.patch.object(process_flake_swarming_task_result_pipeline, '_GetCommitsBetweenRevisions', return_value=['r4', 'r3', 'r2', 'r1']) @mock.patch.object(build_util, 'GetBuildInfo') def testCheckTestsRunStatuses(self, mocked_fn, _): build_info = BuildInfo(self.master_name, self.build_number, self.build_number) build_info.commit_position = 12345 build_info.chromium_revision = 'a1b2c3d4' mocked_fn.return_value = build_info analysis = MasterFlakeAnalysis.Create(self.master_name, self.builder_name, self.build_number, self.step_name, self.test_name) analysis.Save() task = FlakeSwarmingTask.Create(self.master_name, self.builder_name, self.build_number, self.step_name, self.test_name) task.put() call_params = ProcessFlakeSwarmingTaskResultPipeline._GetArgs( self.pipeline, self.master_name, self.builder_name, self.build_number, self.step_name, self.build_number, self.test_name, self.version_number) tests_statuses = ( ProcessFlakeSwarmingTaskResultPipeline._CheckTestsRunStatuses( self.pipeline, base_test._SAMPLE_FAILURE_LOG, *call_params)) self.assertEqual(base_test._EXPECTED_TESTS_STATUS, tests_statuses) @mock.patch.object(process_flake_swarming_task_result_pipeline, '_GetCommitsBetweenRevisions', return_value=['r4', 'r3', 'r2', 'r1']) @mock.patch.object(build_util, 'GetBuildInfo') def testCheckTestsRunStatusesZeroBuildNumber(self, mocked_fn, _): build_info = BuildInfo(self.master_name, self.build_number, 0) build_info.commit_position = 12345 build_info.chromium_revision = 'a1b2c3d4' mocked_fn.return_value = build_info analysis = MasterFlakeAnalysis.Create(self.master_name, self.builder_name, 0, self.step_name, self.test_name) analysis.Save() task = FlakeSwarmingTask.Create(self.master_name, self.builder_name, 0, self.step_name, self.test_name) task.put() ProcessFlakeSwarmingTaskResultPipeline()._CheckTestsRunStatuses( {}, self.master_name, self.builder_name, 0, self.step_name, 0, self.test_name, 1) self.assertIsNone( analysis.data_points[0].previous_build_commit_position) @mock.patch.object(process_flake_swarming_task_result_pipeline, '_GetCommitsBetweenRevisions', return_value=['r4', 'r3', 'r2', 'r1']) @mock.patch.object(build_util, 'GetBuildInfo') def testCheckTestsRunStatusesWhenTestDoesNotExist(self, mocked_fn, _): build_info = BuildInfo(self.master_name, self.builder_name, self.build_number) build_info.commit_position = 12345 build_info.chromium_revision = 'a1b2c3d4' mocked_fn.return_value = build_info test_name = 'TestSuite1.new_test' analysis = MasterFlakeAnalysis.Create(self.master_name, self.builder_name, self.build_number, self.step_name, test_name) analysis.Save() task = FlakeSwarmingTask.Create(self.master_name, self.builder_name, self.build_number, self.step_name, test_name) task.put() pipeline = ProcessFlakeSwarmingTaskResultPipeline() tests_statuses = pipeline._CheckTestsRunStatuses( base_test._SAMPLE_FAILURE_LOG, self.master_name, self.builder_name, self.build_number, self.step_name, self.build_number, test_name, self.version_number) self.assertEqual(base_test._EXPECTED_TESTS_STATUS, tests_statuses) task = FlakeSwarmingTask.Get(self.master_name, self.builder_name, self.build_number, self.step_name, test_name) self.assertEqual(0, task.tries) self.assertEqual(0, task.successes) analysis = MasterFlakeAnalysis.GetVersion(self.master_name, self.builder_name, self.build_number, self.step_name, test_name, self.version_number) self.assertTrue(analysis.data_points[-1].pass_rate < 0) @mock.patch.object(swarming_util, 'GetSwarmingTaskFailureLog', return_value=(base_test._SAMPLE_FAILURE_LOG, None)) @mock.patch.object(build_util, 'GetBuildInfo', return_value=BuildInfo('m', 'b', 123)) def testProcessFlakeSwarmingTaskResultPipeline(self, *_): # End to end test. task = FlakeSwarmingTask.Create(self.master_name, self.builder_name, self.build_number, self.step_name, self.test_name) task.task_id = 'task_id1' task.put() analysis = MasterFlakeAnalysis.Create(self.master_name, self.builder_name, self.build_number, self.step_name, self.test_name) analysis.Save() pipeline = ProcessFlakeSwarmingTaskResultPipeline() pipeline.start_test() pipeline.run(self.master_name, self.builder_name, self.build_number, self.step_name, 'task_id1', self.build_number, self.test_name, analysis.version_number) pipeline.callback(callback_params=pipeline.last_params) # Reload from ID to get all internal properties in sync. pipeline = ProcessFlakeSwarmingTaskResultPipeline.from_id( pipeline.pipeline_id) step_name, task_info = pipeline.outputs.default.value self.assertEqual('abc_tests', task_info) self.assertEqual(self.step_name, step_name) task = FlakeSwarmingTask.Get(self.master_name, self.builder_name, self.build_number, self.step_name, self.test_name) self.assertEqual(analysis_status.COMPLETED, task.status) self.assertEqual(base_test._EXPECTED_TESTS_STATUS, task.tests_statuses) self.assertEqual(datetime.datetime(2016, 2, 10, 18, 32, 6, 538220), task.created_time) self.assertEqual(datetime.datetime(2016, 2, 10, 18, 32, 9, 90550), task.started_time) self.assertEqual(datetime.datetime(2016, 2, 10, 18, 33, 9), task.completed_time) self.assertEqual(analysis.last_attempted_swarming_task_id, 'task_id1') @mock.patch.object(CachedGitilesRepository, 'GetCommitsBetweenRevisions', return_value=['r4', 'r3', 'r2', 'r1']) def testGetCommitsBetweenRevisions(self, _): self.assertEqual( process_flake_swarming_task_result_pipeline. _GetCommitsBetweenRevisions('r0', 'r4'), ['r1', 'r2', 'r3', 'r4'])
def testGetFailureTypeUnknown(self): build_info = BuildInfo('m', 'b', 123) self.assertEqual(failure_type.UNKNOWN, build_util.GetFailureType(build_info))
def testGetFailureTypeInfra(self): build_info = BuildInfo('m', 'b', 123) build_info.result = common_pb2.INFRA_FAILURE build_info.failed_steps = ['compile'] self.assertEqual(failure_type.INFRA, build_util.GetFailureType(build_info))
def testGetTryJobResultForCompileFailure(self, mock_fn1, mock_fn2, _): master_name = 'm' builder_name = 'b' build_number = 123 build = WfBuild.Create(master_name, builder_name, build_number) build.build_id = '8000000000000123' build.put() mock_fn1.return_value = build build_info = BuildInfo(master_name, builder_name, build_number) build_info.completed = False mock_fn2.return_value = build_info analysis = WfAnalysis.Create(master_name, builder_name, build_number) analysis.result = { 'failures': [ { 'step_name': 'compile', 'first_failure': 122, 'last_pass': 121, 'suspected_cls': [], }, { 'step_name': 'steps', }, ] } analysis.failure_result_map = { 'compile': 'm/b/122', } analysis.status = analysis_status.COMPLETED analysis.suspected_cls = [{ 'repo_name': 'chromium', 'revision': 'rev', 'commit_position': 122, 'url': None }] analysis.put() try_job = WfTryJob.Create('m', 'b', 122) try_job.status = analysis_status.COMPLETED try_job.compile_results = [{ 'url': 'build/url', 'culprit': { 'compile': { 'revision': 'rev', } } }] try_job.put() suspected_cl = WfSuspectedCL.Create('chromium', 'rev', 122) suspected_cl.builds = { 'm/b/123': { 'failure_type': failure_type.COMPILE, 'failures': None, 'status': suspected_cl_status.CORRECT, 'approaches': [ analysis_approach_type.HEURISTIC, analysis_approach_type.TRY_JOB ], 'top_score': 5 } } suspected_cl.put() expected_try_job_result = { 'status': 'completed', 'url': 'build/url', 'completed': True, 'culprit': { 'revision': 'rev', }, 'failed': False, } expected_suspected_cls = [{ 'repo_name': 'chromium', 'revision': 'rev', 'commit_position': 122, 'url': None, 'status': suspected_cl_status.CORRECT, 'confidence': self._PercentFormat( self.cl_confidences.compile_heuristic_try_job.confidence) }] build_url = buildbot.CreateBuildUrl('m', 'b', 123) response = self.test_app.get('/failure', params={ 'url': build_url, 'format': 'json' }) self.assertEquals(200, response.status_int) self.assertEqual(expected_try_job_result, response.json_body['try_job']) self.assertEqual(expected_suspected_cls, response.json_body['suspected_cls'])
def _MockedGetBuildInfo(master_name, builder_name, build_number): build = BuildInfo(master_name, builder_name, build_number) build.commit_position = (build_number + 1) * 10 build.result = (common_pb2.SUCCESS if build_number > 4 else common_pb2.INFRA_FAILURE) return build
def testGetFailureTypeTest(self): build_info = BuildInfo('m', 'b', 123) build_info.failed_steps = ['abc_tests'] self.assertEqual(failure_type.TEST, build_util.GetFailureType(build_info))
def testGetFailureTypeCompile(self): build_info = BuildInfo('m', 'b', 123) build_info.failed_steps = ['compile'] self.assertEqual(failure_type.COMPILE, build_util.GetFailureType(build_info))