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'])
Exemple #3
0
    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'
            })
Exemple #4
0
    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'
            })
Exemple #5
0
    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)
Exemple #7
0
  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'])
Exemple #8
0
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
Exemple #9
0
 def _MockExtractBuildInfo(*_):
     build_info = BuildInfo('m', 'b', 25409)
     build_info.failed_steps = {
         'compile': {
             'last_pass': '******',
             'current_failure': '25409',
             'first_failure': '25409'
         }
     }
     return build_info
Exemple #10
0
    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')
Exemple #11
0
 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)
Exemple #14
0
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
Exemple #15
0
    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()))
Exemple #16
0
    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()))
Exemple #17
0
  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))
Exemple #18
0
    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'])
Exemple #19
0
    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)
Exemple #24
0
    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'])
Exemple #25
0
    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)
Exemple #26
0
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'])
Exemple #28
0
 def testGetFailureTypeUnknown(self):
     build_info = BuildInfo('m', 'b', 123)
     self.assertEqual(failure_type.UNKNOWN,
                      build_util.GetFailureType(build_info))
Exemple #29
0
 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))
Exemple #30
0
    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'])
Exemple #31
0
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
Exemple #32
0
 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))
Exemple #33
0
 def testGetFailureTypeCompile(self):
     build_info = BuildInfo('m', 'b', 123)
     build_info.failed_steps = ['compile']
     self.assertEqual(failure_type.COMPILE,
                      build_util.GetFailureType(build_info))