def testCIFlakes(self, _):
        luci_project = 'chromium'
        normalized_step_name = 'normalized_step_name'

        flake4 = Flake.Create(luci_project=luci_project,
                              normalized_step_name=normalized_step_name,
                              normalized_test_name='normalized_test_name_4',
                              test_label_name='test_label4')
        flake4.last_occurred_time = datetime(2018, 9, 1)
        flake4.put()
        flake4_key = flake4.key

        step_ui_name = 'step'
        luci_bucket = 'try'
        luci_builder = 'luci builder'
        legacy_master_name = 'buildbot master'

        for i in xrange(98761, 98765):
            occurrence = FlakeOccurrence.Create(
                flake_type=FlakeType.CQ_HIDDEN_FLAKE,
                build_id=i,
                step_ui_name=step_ui_name,
                test_name='t4',
                luci_project=luci_project,
                luci_bucket=luci_bucket,
                luci_builder=luci_builder,
                legacy_master_name=legacy_master_name,
                legacy_build_number=i,
                time_happened=datetime(2018, 8, 31),
                gerrit_cl_id=i,
                parent_flake_key=flake4_key)
            occurrence.put()

        occurrence10 = FlakeOccurrence.Create(
            flake_type=FlakeType.CI_FAILED_STEP,
            build_id=76543,
            step_ui_name=step_ui_name,
            test_name='t4',
            luci_project=luci_project,
            luci_bucket=luci_bucket,
            luci_builder=luci_builder,
            legacy_master_name=legacy_master_name,
            legacy_build_number=76543,
            time_happened=datetime(2018, 8, 31),
            gerrit_cl_id=-1,
            parent_flake_key=flake4_key)
        occurrence10.put()

        UpdateFlakeCounts()

        flake4 = flake4_key.get()
        self.assertEqual([
            FlakeCountsByType(flake_type=FlakeType.CQ_HIDDEN_FLAKE,
                              impacted_cl_count=4,
                              occurrence_count=4),
            FlakeCountsByType(flake_type=FlakeType.CI_FAILED_STEP,
                              impacted_cl_count=-1,
                              occurrence_count=1)
        ], flake4.flake_counts_last_week)
        self.assertEqual(14, flake4.flake_score_last_week)
예제 #2
0
    def testCreate(self):
        luci_project = 'chromium'
        step_ui_name = 'step'
        test_name = 'test'

        normalized_step_name = 'normalized_step_name'
        normalized_test_name = 'normalized_test_name'
        test_label_name = 'test_label'
        flake = Flake.Create(luci_project=luci_project,
                             normalized_step_name=normalized_step_name,
                             normalized_test_name=normalized_test_name,
                             test_label_name=test_label_name)
        flake.put()

        build_id = 123
        luci_bucket = 'try'
        luci_builder = 'luci builder'
        legacy_master_name = 'buildbot master'
        legacy_build_number = 999
        time_happened = datetime.datetime(2018, 1, 1)
        gerrit_cl_id = 98765

        cq_false_rejection_occurrence = FlakeOccurrence.Create(
            FlakeType.CQ_FALSE_REJECTION,
            build_id=build_id,
            step_ui_name=step_ui_name,
            test_name=test_name,
            luci_project=luci_project,
            luci_bucket=luci_bucket,
            luci_builder=luci_builder,
            legacy_master_name=legacy_master_name,
            legacy_build_number=legacy_build_number,
            time_happened=time_happened,
            gerrit_cl_id=gerrit_cl_id,
            parent_flake_key=flake.key)
        cq_false_rejection_occurrence.put()

        retry_with_patch_occurrence = FlakeOccurrence.Create(
            FlakeType.RETRY_WITH_PATCH,
            build_id=build_id,
            step_ui_name=step_ui_name,
            test_name=test_name,
            luci_project=luci_project,
            luci_bucket=luci_bucket,
            luci_builder=luci_builder,
            legacy_master_name=legacy_master_name,
            legacy_build_number=legacy_build_number,
            time_happened=time_happened,
            gerrit_cl_id=gerrit_cl_id,
            parent_flake_key=flake.key)
        retry_with_patch_occurrence.put()

        fetched_flake_occurrences = FlakeOccurrence.query().fetch()
        self.assertEqual(2, len(fetched_flake_occurrences))
        self.assertIn(cq_false_rejection_occurrence, fetched_flake_occurrences)
        self.assertIn(retry_with_patch_occurrence, fetched_flake_occurrences)
        self.assertIsNotNone(fetched_flake_occurrences[0].time_detected)
        self.assertIsNotNone(fetched_flake_occurrences[1].time_detected)
  def testDetectCQHiddenFlakesShouldRun(self, _):
    flake = Flake.Create(
        luci_project='luci_project',
        normalized_step_name='s',
        normalized_test_name='t',
        test_label_name='t')
    flake.put()
    existing_occurrence = FlakeOccurrence.Create(
        flake_type=FlakeType.CQ_HIDDEN_FLAKE,
        build_id=123,
        step_ui_name='s',
        test_name='t',
        luci_project='luci_project',
        luci_bucket='luci_bucket',
        luci_builder='luci_builder',
        legacy_master_name='legacy_master_name',
        legacy_build_number=123,
        time_happened=datetime(2018, 12, 19, 20),
        gerrit_cl_id=654321,
        parent_flake_key=flake.key,
        tags=[])
    existing_occurrence.time_detected = datetime(2018, 12, 19, 20)
    existing_occurrence.put()

    self.assertEqual(('2018-12-19 19:40:00 UTC', '2018-12-19 22:00:00 UTC'),
                     detect_flake_occurrences._GetCQHiddenFlakeQueryStartTime())
  def testDetectCQHiddenFlakesShouldSkip(self, mock_query, *_):
    flake = Flake.Create(
        luci_project='luci_project',
        normalized_step_name='s',
        normalized_test_name='t',
        test_label_name='t')
    flake.put()
    existing_occurrence = FlakeOccurrence.Create(
        flake_type=FlakeType.CQ_HIDDEN_FLAKE,
        build_id=123,
        step_ui_name='s',
        test_name='t',
        luci_project='luci_project',
        luci_bucket='luci_bucket',
        luci_builder='luci_builder',
        legacy_master_name='legacy_master_name',
        legacy_build_number=123,
        time_happened=datetime(2018, 12, 19, 23),
        gerrit_cl_id=654321,
        parent_flake_key=flake.key,
        tags=[])
    existing_occurrence.time_detected = datetime(2018, 12, 19, 23, 30)
    existing_occurrence.put()

    mock_query.side_effect = [(False, []), (True, [])]

    detect_flake_occurrences.QueryAndStoreHiddenFlakes()
    self.assertIsNone(detect_flake_occurrences._GetLastCQHiddenFlakeQueryTime())
    detect_flake_occurrences.QueryAndStoreHiddenFlakes()
    self.assertEqual(
        datetime(2018, 12, 20),
        detect_flake_occurrences._GetLastCQHiddenFlakeQueryTime())
    detect_flake_occurrences.QueryAndStoreHiddenFlakes()
예제 #5
0
def _CreateFlake(flake_data, with_component=True):
    """
  Args:
    with_component (bool): Sets flake.component if True, otherwise sets tags.
  """

    luci_project = 'chromium'
    normalized_step_name = 'normalized_step_name'

    flake_issue = _GetOrCreateFlakeIssue(flake_data['bug_id'])

    flake = Flake.Create(normalized_test_name=flake_data['test'],
                         luci_project=luci_project,
                         normalized_step_name=normalized_step_name,
                         test_label_name='test_label')

    if with_component:
        flake.component = flake_data['component']
    else:
        flake.tags = ['component::{}'.format(flake_data['component'])]
    flake.flake_issue_key = flake_issue.key
    flake.flake_counts_last_week = []
    for flake_type, counts in flake_data['counts'].iteritems():
        flake.flake_counts_last_week.append(
            FlakeCountsByType(flake_type=flake_type,
                              occurrence_count=counts[0],
                              impacted_cl_count=counts[1]))
    flake.last_occurred_time = datetime.strptime(
        flake_data['last_occurred_time'], '%Y-W%W-%w')
    flake.put()

    for occurrence_data in flake_data['occurrences']:
        time_happened = datetime.strptime('2018-%d-4' % occurrence_data[2],
                                          '%Y-%W-%w')
        hour = occurrence_data[3]
        time_happened += timedelta(hours=hour)
        occurrence = FlakeOccurrence.Create(
            flake_type=occurrence_data[0],
            build_id=123 + hour,
            step_ui_name='step',
            test_name=flake.normalized_test_name,
            luci_project='chromium',
            luci_bucket='try',
            luci_builder='builder',
            legacy_master_name='master',
            legacy_build_number=42,
            time_happened=time_happened,
            gerrit_cl_id=occurrence_data[1],
            parent_flake_key=flake.key)
        occurrence.put()
예제 #6
0
 def testAnalyzeDetectedFlakeOccurrence(self):
     step = 'step1'
     test = 'test1'
     luci_project = 'chromium'
     bug_id = 12345
     flake = Flake.Create(luci_project, step, test, 'l')
     flake_issue = FlakeIssue.Create(luci_project, bug_id)
     flake.flake_issue_key = flake_issue.key
     occurrence = FlakeOccurrence.Create(
         flake_type=FlakeType.CQ_FALSE_REJECTION,
         build_id=111,
         step_ui_name=step,
         test_name=test,
         luci_project=luci_project,
         luci_bucket='try',
         luci_builder='tryserver.chromium.linux',
         legacy_master_name='linux_chromium_rel_ng',
         legacy_build_number=999,
         time_happened=None,
         gerrit_cl_id=98765,
         parent_flake_key=None)
     apis.AnalyzeDetectedFlakeOccurrence(flake, occurrence, bug_id)
     self.assertEqual(1, len(self.taskqueue_requests))
    def testFlakeUpdates(self, _):
        luci_project = 'chromium'
        step_ui_name = 'step'
        normalized_step_name = 'normalized_step_name'
        flake1 = Flake.Create(luci_project=luci_project,
                              normalized_step_name=normalized_step_name,
                              normalized_test_name='normalized_test_name_1',
                              test_label_name='test_label1')
        flake1.last_occurred_time = datetime(2018, 9, 1)
        flake1.put()
        flake1_key = flake1.key

        luci_bucket = 'try'
        luci_builder = 'luci builder'
        legacy_master_name = 'buildbot master'
        legacy_build_number = 999

        occurrence1 = FlakeOccurrence.Create(
            flake_type=FlakeType.CQ_FALSE_REJECTION,
            build_id=1,
            step_ui_name=step_ui_name,
            test_name='t1',
            luci_project=luci_project,
            luci_bucket=luci_bucket,
            luci_builder=luci_builder,
            legacy_master_name=legacy_master_name,
            legacy_build_number=legacy_build_number,
            time_happened=datetime(2018, 9, 1),
            gerrit_cl_id=98761,
            parent_flake_key=flake1_key)
        occurrence1.put()

        occurrence2 = FlakeOccurrence.Create(
            flake_type=FlakeType.CQ_FALSE_REJECTION,
            build_id=2,
            step_ui_name=step_ui_name,
            test_name='t1',
            luci_project=luci_project,
            luci_bucket=luci_bucket,
            luci_builder=luci_builder,
            legacy_master_name=legacy_master_name,
            legacy_build_number=legacy_build_number,
            time_happened=datetime(2018, 8, 31),
            gerrit_cl_id=98761,
            parent_flake_key=flake1_key)
        occurrence2.put()

        occurrence3 = FlakeOccurrence.Create(
            flake_type=FlakeType.CQ_FALSE_REJECTION,
            build_id=3,
            step_ui_name=step_ui_name,
            test_name='t2',
            luci_project=luci_project,
            luci_bucket=luci_bucket,
            luci_builder=luci_builder,
            legacy_master_name=legacy_master_name,
            legacy_build_number=legacy_build_number,
            time_happened=datetime(2018, 7, 31),
            gerrit_cl_id=98763,
            parent_flake_key=flake1_key)
        occurrence3.put()

        occurrence5 = FlakeOccurrence.Create(
            flake_type=FlakeType.RETRY_WITH_PATCH,
            build_id=5,
            step_ui_name=step_ui_name,
            test_name='t2',
            luci_project=luci_project,
            luci_bucket=luci_bucket,
            luci_builder=luci_builder,
            legacy_master_name=legacy_master_name,
            legacy_build_number=legacy_build_number,
            time_happened=datetime(2018, 8, 31),
            gerrit_cl_id=98761,
            parent_flake_key=flake1_key)
        occurrence5.put()

        occurrence6 = FlakeOccurrence.Create(
            flake_type=FlakeType.RETRY_WITH_PATCH,
            build_id=6,
            step_ui_name=step_ui_name,
            test_name='t2',
            luci_project=luci_project,
            luci_bucket=luci_bucket,
            luci_builder=luci_builder,
            legacy_master_name=legacy_master_name,
            legacy_build_number=legacy_build_number,
            time_happened=datetime(2018, 8, 31),
            gerrit_cl_id=98766,
            parent_flake_key=flake1_key)
        occurrence6.put()

        occurrence7 = FlakeOccurrence.Create(
            flake_type=FlakeType.RETRY_WITH_PATCH,
            build_id=7,
            step_ui_name=step_ui_name,
            test_name='t2',
            luci_project=luci_project,
            luci_bucket=luci_bucket,
            luci_builder=luci_builder,
            legacy_master_name=legacy_master_name,
            legacy_build_number=legacy_build_number,
            time_happened=datetime(2018, 8, 31),
            gerrit_cl_id=98767,
            parent_flake_key=flake1_key)
        occurrence7.put()

        UpdateFlakeCounts()

        flake1 = flake1_key.get()
        self.assertEqual(5, flake1.false_rejection_count_last_week)
        self.assertEqual(3, flake1.impacted_cl_count_last_week)
        self.assertEqual([
            FlakeCountsByType(flake_type=FlakeType.CQ_FALSE_REJECTION,
                              impacted_cl_count=1,
                              occurrence_count=2),
            FlakeCountsByType(flake_type=FlakeType.RETRY_WITH_PATCH,
                              impacted_cl_count=2,
                              occurrence_count=3)
        ], flake1.flake_counts_last_week)
        self.assertEqual(120, flake1.flake_score_last_week)
    def testFlakesWithCQHiddenFlakes(self, _):
        luci_project = 'chromium'
        normalized_step_name = 'normalized_step_name'

        flake3 = Flake.Create(luci_project=luci_project,
                              normalized_step_name=normalized_step_name,
                              normalized_test_name='normalized_test_name_3',
                              test_label_name='test_label3')
        flake3.last_occurred_time = datetime(2018, 9, 1)
        flake3.false_rejection_count_last_week = 5
        flake3.impacted_cl_count_last_week = 3
        flake3.put()
        flake3_key = flake3.key

        step_ui_name = 'step'
        luci_bucket = 'try'
        luci_builder = 'luci builder'
        legacy_master_name = 'buildbot master'
        legacy_build_number = 999

        occurrence4 = FlakeOccurrence.Create(
            flake_type=FlakeType.CQ_FALSE_REJECTION,
            build_id=4,
            step_ui_name=step_ui_name,
            test_name='t1',
            luci_project=luci_project,
            luci_bucket=luci_bucket,
            luci_builder=luci_builder,
            legacy_master_name=legacy_master_name,
            legacy_build_number=legacy_build_number,
            time_happened=datetime(2018, 8, 31),
            gerrit_cl_id=98764,
            parent_flake_key=flake3_key)
        occurrence4.put()

        for i in xrange(98760, 98790):
            occurrence = FlakeOccurrence.Create(
                flake_type=FlakeType.CQ_HIDDEN_FLAKE,
                build_id=i,
                step_ui_name=step_ui_name,
                test_name='t1',
                luci_project=luci_project,
                luci_bucket=luci_bucket,
                luci_builder=luci_builder,
                legacy_master_name=legacy_master_name,
                legacy_build_number=i,
                time_happened=datetime(2018, 8, 31),
                gerrit_cl_id=i,
                parent_flake_key=flake3_key)
            occurrence.put()

        UpdateFlakeCounts()

        flake3 = flake3_key.get()
        self.assertEqual([
            FlakeCountsByType(flake_type=FlakeType.CQ_FALSE_REJECTION,
                              impacted_cl_count=1,
                              occurrence_count=1),
            FlakeCountsByType(flake_type=FlakeType.CQ_HIDDEN_FLAKE,
                              impacted_cl_count=29,
                              occurrence_count=30)
        ], flake3.flake_counts_last_week)
        self.assertEqual(129, flake3.flake_score_last_week)
  def testUpdateMetadataForFlakes(self, *_):
    luci_project = 'chromium'
    normalized_step_name = 'normalized_step_name'
    normalized_test_name = 'normalized_test_name'
    test_label_name = 'test_label'
    flake = Flake.Create(
        luci_project=luci_project,
        normalized_step_name=normalized_step_name,
        normalized_test_name=normalized_test_name,
        test_label_name=test_label_name)
    flake.archived = True
    flake.put()
    flake_key = flake.key

    step_ui_name = 'step'
    test_name = 'test'
    luci_bucket = 'try'
    luci_builder = 'luci builder'
    legacy_master_name = 'buildbot master'
    legacy_build_number = 999
    gerrit_cl_id = 98765

    # Flake's last_occurred_time and tags are empty, updated.
    occurrence_1 = FlakeOccurrence.Create(
        flake_type=FlakeType.CQ_FALSE_REJECTION,
        build_id=123,
        step_ui_name=step_ui_name,
        test_name=test_name,
        luci_project=luci_project,
        luci_bucket=luci_bucket,
        luci_builder=luci_builder,
        legacy_master_name=legacy_master_name,
        legacy_build_number=legacy_build_number,
        time_happened=datetime(2018, 1, 1, 1),
        gerrit_cl_id=gerrit_cl_id,
        parent_flake_key=flake_key,
        tags=['tag1::v1'])
    occurrence_1.put()
    _UpdateFlakeMetadata([occurrence_1])
    flake = flake_key.get()
    self.assertEqual(flake.last_occurred_time, datetime(2018, 1, 1, 1))
    self.assertEqual(flake.tags, ['tag1::v1'])
    self.assertFalse(flake.archived)

    # Flake's last_occurred_time is earlier and tags are different, updated.
    occurrence_2 = FlakeOccurrence.Create(
        flake_type=FlakeType.CQ_FALSE_REJECTION,
        build_id=124,
        step_ui_name=step_ui_name,
        test_name=test_name,
        luci_project=luci_project,
        luci_bucket=luci_bucket,
        luci_builder=luci_builder,
        legacy_master_name=legacy_master_name,
        legacy_build_number=legacy_build_number,
        time_happened=datetime(2018, 1, 1, 2),
        gerrit_cl_id=gerrit_cl_id,
        parent_flake_key=flake_key,
        tags=['tag2::v2'])
    occurrence_2.put()
    _UpdateFlakeMetadata([occurrence_2])
    flake = flake_key.get()
    self.assertEqual(flake.last_occurred_time, datetime(2018, 1, 1, 2))
    self.assertEqual(flake.tags, ['tag1::v1', 'tag2::v2'])

    # Flake's last_occurred_time is later and tags are the same, not updated.
    occurrence_3 = FlakeOccurrence.Create(
        flake_type=FlakeType.CQ_FALSE_REJECTION,
        build_id=125,
        step_ui_name=step_ui_name,
        test_name=test_name,
        luci_project=luci_project,
        luci_bucket=luci_bucket,
        luci_builder=luci_builder,
        legacy_master_name=legacy_master_name,
        legacy_build_number=legacy_build_number,
        time_happened=datetime(2018, 1, 1),
        gerrit_cl_id=gerrit_cl_id,
        parent_flake_key=flake_key,
        tags=['tag2::v2'])
    occurrence_3.put()
    _UpdateFlakeMetadata([occurrence_3])
    flake = flake_key.get()
    self.assertEqual(flake.last_occurred_time, datetime(2018, 1, 1, 2))
    self.assertEqual(flake.tags, ['tag1::v1', 'tag2::v2'])
예제 #10
0
    def testShowFlake(self, *_):
        flake_issue = FlakeIssue.Create(monorail_project='chromium',
                                        issue_id=900)
        flake_issue.last_updated_time_by_flake_detection = datetime(2018, 1, 1)
        flake_issue.status = 'Assigned'
        flake_issue.last_updated_time_in_monorail = datetime(2018, 1, 1)
        flake_issue.put()

        luci_project = 'chromium'
        step_ui_name = 'step'
        test_name = 'test'
        normalized_step_name = 'normalized_step_name'
        normalized_test_name = 'normalized_test_name'
        test_label_name = 'test_label'
        flake = Flake.Create(
            luci_project=luci_project,
            normalized_step_name=normalized_step_name,
            normalized_test_name=normalized_test_name,
            test_label_name=test_label_name,
        )
        flake.component = 'Mock>Component'
        flake.test_location = TestLocation()
        flake.test_location.file_path = '../../some/test/path/a.cc'
        flake.test_location.line_number = 42
        flake.flake_issue_key = flake_issue.key
        flake.put()

        build_id = 123
        luci_bucket = 'try'
        luci_builder = 'luci builder'
        legacy_master_name = 'buildbot master'
        legacy_build_number = 999
        time_happened = datetime(2018, 1, 1)
        gerrit_cl_id = 98765
        occurrence = FlakeOccurrence.Create(
            flake_type=FlakeType.CQ_FALSE_REJECTION,
            build_id=build_id,
            step_ui_name=step_ui_name,
            test_name=test_name,
            luci_project=luci_project,
            luci_bucket=luci_bucket,
            luci_builder=luci_builder,
            legacy_master_name=legacy_master_name,
            legacy_build_number=legacy_build_number,
            time_happened=time_happened,
            gerrit_cl_id=gerrit_cl_id,
            parent_flake_key=flake.key)
        occurrence.time_detected = datetime(2018, 1, 1)
        occurrence.put()

        response = self.test_app.get('/flake/detection/ui/show-flake',
                                     params={
                                         'key': flake.key.urlsafe(),
                                         'format': 'json',
                                     },
                                     status=200)

        flake_dict = {
            'flake_issue': {
                'flake_culprit_key':
                None,
                'issue_id':
                900,
                'issue_link':
                ('https://monorail-prod.appspot.com/p/chromium/issues'
                 '/detail?id=900'),
                'last_updated_time_by_flake_detection':
                '2018-01-01 00:00:00',
                'monorail_project':
                'chromium',
                'merge_destination_key':
                None,
                'last_updated_time_in_monorail':
                '2 days, 00:00:00',
                'last_updated_time_with_analysis_results':
                None,
                'create_time_in_monorail':
                None,
                'labels': [],
                'status':
                'Assigned',
            },
            'flake_issue_key':
            flake_issue.key,
            'luci_project':
            'chromium',
            'last_occurred_time':
            None,
            'last_test_location_based_tag_update_time':
            None,
            'normalized_step_name':
            'normalized_step_name',
            'normalized_test_name':
            'normalized_test_name',
            'test_label_name':
            'test_label',
            'false_rejection_count_last_week':
            0,
            'impacted_cl_count_last_week':
            0,
            'archived':
            False,
            'flake_counts_last_week': [
                {
                    'flake_type': 'cq false rejection',
                    'impacted_cl_count': 0,
                    'occurrence_count': 0
                },
                {
                    'flake_type': 'cq step level retry',
                    'impacted_cl_count': 0,
                    'occurrence_count': 0
                },
                {
                    'flake_type': 'cq hidden flake',
                    'impacted_cl_count': 0,
                    'occurrence_count': 0
                },
                {
                    'flake_type': 'ci failed step',
                    'impacted_cl_count': 0,
                    'occurrence_count': 0
                },
            ],
            'flake_score_last_week':
            0,
            'component':
            'Mock>Component',
            'tags': [],
            'test_location': {
                'file_path': '../../some/test/path/a.cc',
                'line_number': 42,
            },
            'culprits': [],
            'sample_analysis':
            None,
            'occurrences': [{
                'group_by_field':
                'luci builder',
                'occurrences': [{
                    'build_configuration': {
                        'legacy_build_number': 999,
                        'legacy_master_name': 'buildbot master',
                        'luci_bucket': 'try',
                        'luci_builder': 'luci builder',
                        'luci_project': 'chromium'
                    },
                    'tags': [],
                    'build_id': '123',
                    'flake_type': 'cq false rejection',
                    'gerrit_cl_id': 98765,
                    'step_ui_name': 'step',
                    'test_name': 'test',
                    'time_detected': '2018-01-01 00:00:00 UTC',
                    'time_happened': '2018-01-01 00:00:00 UTC'
                }]
            }]
        }
        self.assertEqual(
            json.dumps(
                {
                    'flake_json':
                    flake_dict,
                    'key':
                    flake.key.urlsafe(),
                    'show_all_occurrences':
                    '',
                    'weights': [('cq false rejection', 100),
                                ('cq step level retry', 10),
                                ('cq hidden flake', 1), ('ci failed step', 10)]
                },
                default=str,
                sort_keys=True,
                indent=2),
            json.dumps(json.loads(response.body), sort_keys=True, indent=2))
def _CreateFlakeOccurrenceFromRow(row, flake_type_enum):
    """Creates a FlakeOccurrence from a row fetched from BigQuery."""
    luci_project = row['luci_project']
    luci_builder = row['luci_builder']
    step_ui_name = row['step_ui_name']
    test_name = row['test_name']
    legacy_master_name = row['legacy_master_name']
    legacy_build_number = row['legacy_build_number']

    normalized_step_name = Flake.NormalizeStepName(
        step_name=step_ui_name,
        master_name=legacy_master_name,
        builder_name=luci_builder,
        build_number=legacy_build_number)
    normalized_test_name = Flake.NormalizeTestName(test_name, step_ui_name)

    flake_id = Flake.GetId(luci_project=luci_project,
                           normalized_step_name=normalized_step_name,
                           normalized_test_name=normalized_test_name)
    flake_key = ndb.Key(Flake, flake_id)

    gerrit_project = row['gerrit_project']
    build_id = row['build_id']
    luci_bucket = row['luci_bucket']
    time_happened = row['test_start_msec']
    gerrit_cl_id = row['gerrit_cl_id']

    # Not add the original test name as a tag here, because all the tags will be
    # merged into Flake model, and there might be 100s of parameterized tests
    # which might lead to too large data for a single Flake entity.
    tags = [
        'gerrit_project::%s' % gerrit_project,
        'luci_project::%s' % luci_project,
        'bucket::%s' % luci_bucket,
        'master::%s' % legacy_master_name,
        'builder::%s' % luci_builder,
        'binary::%s' % normalized_step_name,  # e.g. "tests"
        'test_type::%s' %
        step_ui_name.split(' ', 1)[0],  # e.g. "flavored_tests"
        'step::%s' % step_ui_name,  # e.g. "flavored_tests on Mac 10.13"
        'flake::%s' % normalized_test_name,
    ]

    suite = _GetTestSuiteForOccurrence(row, normalized_test_name,
                                       normalized_step_name)
    if suite:
        tags.append('suite::%s' % suite)
    tags.sort()

    flake_occurrence = FlakeOccurrence.Create(
        flake_type=flake_type_enum,
        build_id=build_id,
        step_ui_name=step_ui_name,
        test_name=test_name,
        luci_project=luci_project,
        luci_bucket=luci_bucket,
        luci_builder=luci_builder,
        legacy_master_name=legacy_master_name,
        legacy_build_number=legacy_build_number,
        time_happened=time_happened,
        gerrit_cl_id=gerrit_cl_id,
        parent_flake_key=flake_key,
        tags=tags)

    return flake_occurrence
    def testGetFlakeInformationNoIssue(self, *_):

        luci_project = 'chromium'
        step_ui_name = 'step'
        test_name = 'test'
        normalized_step_name = 'normalized_step_name'
        normalized_test_name = 'normalized_test_name_3'
        test_label_name = 'test_label'
        flake = Flake.Create(luci_project=luci_project,
                             normalized_step_name=normalized_step_name,
                             normalized_test_name=normalized_test_name,
                             test_label_name=test_label_name)
        flake.put()

        build_id = 123
        luci_bucket = 'try'
        luci_builder = 'luci builder'
        legacy_master_name = 'buildbot master'
        legacy_build_number = 999
        time_happened = datetime(2018, 1, 1)
        gerrit_cl_id = 98765
        occurrence = FlakeOccurrence.Create(
            flake_type=FlakeType.CQ_FALSE_REJECTION,
            build_id=build_id,
            step_ui_name=step_ui_name,
            test_name=test_name,
            luci_project=luci_project,
            luci_bucket=luci_bucket,
            luci_builder=luci_builder,
            legacy_master_name=legacy_master_name,
            legacy_build_number=legacy_build_number,
            time_happened=time_happened,
            gerrit_cl_id=gerrit_cl_id,
            parent_flake_key=flake.key)
        occurrence.time_detected = datetime(2018, 1, 1)
        occurrence.put()

        expected_flake_dict = {
            'luci_project':
            'chromium',
            'normalized_step_name':
            normalized_step_name,
            'normalized_test_name':
            normalized_test_name,
            'test_label_name':
            test_label_name,
            'flake_issue_key':
            None,
            'last_occurred_time':
            None,
            'last_test_location_based_tag_update_time':
            None,
            'false_rejection_count_last_week':
            0,
            'impacted_cl_count_last_week':
            0,
            'archived':
            False,
            'flake_counts_last_week': [
                {
                    'flake_type': 'cq false rejection',
                    'impacted_cl_count': 0,
                    'occurrence_count': 0
                },
                {
                    'flake_type': 'cq step level retry',
                    'impacted_cl_count': 0,
                    'occurrence_count': 0
                },
                {
                    'flake_type': 'cq hidden flake',
                    'impacted_cl_count': 0,
                    'occurrence_count': 0
                },
                {
                    'flake_type': 'ci failed step',
                    'impacted_cl_count': 0,
                    'occurrence_count': 0
                },
            ],
            'flake_score_last_week':
            0,
            'component':
            None,
            'test_location':
            None,
            'tags': [],
            'occurrences': [{
                'group_by_field':
                'luci builder',
                'occurrences': [{
                    'flake_type': 'cq false rejection',
                    'build_id': '123',
                    'step_ui_name': step_ui_name,
                    'test_name': test_name,
                    'tags': [],
                    'build_configuration': {
                        'luci_project': 'chromium',
                        'luci_bucket': 'try',
                        'luci_builder': 'luci builder',
                        'legacy_master_name': 'buildbot master',
                        'legacy_build_number': 999
                    },
                    'time_happened': '2018-01-01 00:00:00 UTC',
                    'time_detected': '2018-01-01 00:00:00 UTC',
                    'gerrit_cl_id': gerrit_cl_id
                }]
            }],
        }

        self.assertEqual(expected_flake_dict,
                         flake_detection_utils.GetFlakeInformation(flake, 1))
    def testGetFlakeInformationOldFlakes(self, *_):
        flake_issue = FlakeIssue.Create(monorail_project='chromium',
                                        issue_id=900)
        flake_issue.last_updated_time_by_flake_detection = datetime(2018, 1, 1)
        flake_issue.last_updated_time_in_monorail = datetime(2018, 1, 2)
        flake_issue.status = 'Started'
        flake_issue.put()

        luci_project = 'chromium'
        step_ui_name = 'step'
        test_name = 'test'
        normalized_step_name = 'normalized_step_name'
        normalized_test_name = 'normalized_test_name'
        test_label_name = 'test_label'
        flake = Flake.Create(
            luci_project=luci_project,
            normalized_step_name=normalized_step_name,
            normalized_test_name=normalized_test_name,
            test_label_name=test_label_name,
        )

        flake.component = 'Mock>Component'
        flake.test_location = TestLocation()
        flake.test_location.file_path = '../../some/test/path/a.cc'
        flake.test_location.line_number = 42
        flake.flake_issue_key = flake_issue.key
        flake.put()

        build_id = 123
        luci_bucket = 'try'
        luci_builder = 'luci builder'
        legacy_master_name = 'buildbot master'
        legacy_build_number = 999
        time_happened = datetime(2018, 1, 1)
        gerrit_cl_id = 98765
        occurrence = FlakeOccurrence.Create(
            flake_type=FlakeType.CQ_FALSE_REJECTION,
            build_id=build_id,
            step_ui_name=step_ui_name,
            test_name=test_name,
            luci_project=luci_project,
            luci_bucket=luci_bucket,
            luci_builder=luci_builder,
            legacy_master_name=legacy_master_name,
            legacy_build_number=legacy_build_number,
            time_happened=time_happened,
            gerrit_cl_id=gerrit_cl_id,
            parent_flake_key=flake.key)
        occurrence.time_detected = datetime(2018, 1, 1)
        occurrence.put()

        occurrence2 = FlakeOccurrence.Create(
            flake_type=FlakeType.RETRY_WITH_PATCH,
            build_id=124,
            step_ui_name=step_ui_name,
            test_name=test_name,
            luci_project=luci_project,
            luci_bucket=luci_bucket,
            luci_builder='luci builder 2',
            legacy_master_name=legacy_master_name,
            legacy_build_number=legacy_build_number,
            time_happened=datetime(2018, 1, 2, 3),
            gerrit_cl_id=gerrit_cl_id,
            parent_flake_key=flake.key)
        occurrence2.time_detected = datetime(2018, 1, 2, 3)
        occurrence2.put()

        occurrence3 = FlakeOccurrence.Create(
            flake_type=FlakeType.CQ_FALSE_REJECTION,
            build_id=125,
            step_ui_name=step_ui_name,
            test_name=test_name,
            luci_project=luci_project,
            luci_bucket=luci_bucket,
            luci_builder='luci builder 2',
            legacy_master_name=legacy_master_name,
            legacy_build_number=legacy_build_number,
            time_happened=datetime(2018, 1, 2, 2),
            gerrit_cl_id=gerrit_cl_id,
            parent_flake_key=flake.key)
        occurrence3.time_detected = datetime(2018, 1, 2, 2)
        occurrence3.put()

        occurrence4 = FlakeOccurrence.Create(
            flake_type=FlakeType.CQ_HIDDEN_FLAKE,
            build_id=126,
            step_ui_name=step_ui_name,
            test_name=test_name,
            luci_project=luci_project,
            luci_bucket=luci_bucket,
            luci_builder='luci builder 2',
            legacy_master_name=legacy_master_name,
            legacy_build_number=legacy_build_number,
            time_happened=datetime(2018, 1, 2, 2),
            gerrit_cl_id=gerrit_cl_id,
            parent_flake_key=flake.key)
        occurrence4.time_detected = datetime(2018, 1, 2, 2)
        occurrence4.put()

        occurrence5 = FlakeOccurrence.Create(
            flake_type=FlakeType.CI_FAILED_STEP,
            build_id=127,
            step_ui_name=step_ui_name,
            test_name=test_name,
            luci_project=luci_project,
            luci_bucket=luci_bucket,
            luci_builder='luci builder 2',
            legacy_master_name=legacy_master_name,
            legacy_build_number=legacy_build_number,
            time_happened=datetime(2018, 1, 2, 2),
            gerrit_cl_id=-1,
            parent_flake_key=flake.key)
        occurrence5.time_detected = datetime(2018, 1, 2, 2)
        occurrence5.put()

        culprit1 = FlakeCulprit.Create('chromium', 'rev1', 123456,
                                       'culprit_url')
        culprit1.put()

        analysis = MasterFlakeAnalysis.Create(legacy_master_name, luci_builder,
                                              legacy_build_number,
                                              step_ui_name, test_name)
        analysis.bug_id = 900
        analysis.culprit_urlsafe_key = culprit1.key.urlsafe()
        analysis.confidence_in_culprit = 0.98
        analysis.put()

        culprit2 = FlakeCulprit.Create('chromium', 'rev2', 123457,
                                       'culprit_url')
        culprit2.put()
        analysis_1 = MasterFlakeAnalysis.Create(legacy_master_name,
                                                luci_builder,
                                                legacy_build_number - 1,
                                                step_ui_name, test_name)
        analysis_1.bug_id = 900
        analysis_1.culprit_urlsafe_key = culprit2.key.urlsafe()
        analysis_1.put()

        expected_flake_dict = {
            'luci_project':
            'chromium',
            'normalized_step_name':
            'normalized_step_name',
            'normalized_test_name':
            'normalized_test_name',
            'test_label_name':
            'test_label',
            'flake_issue_key':
            flake_issue.key,
            'last_occurred_time':
            None,
            'last_test_location_based_tag_update_time':
            None,
            'false_rejection_count_last_week':
            0,
            'impacted_cl_count_last_week':
            0,
            'archived':
            False,
            'flake_counts_last_week': [
                {
                    'flake_type': 'cq false rejection',
                    'impacted_cl_count': 0,
                    'occurrence_count': 0
                },
                {
                    'flake_type': 'cq step level retry',
                    'impacted_cl_count': 0,
                    'occurrence_count': 0
                },
                {
                    'flake_type': 'cq hidden flake',
                    'impacted_cl_count': 0,
                    'occurrence_count': 0
                },
                {
                    'flake_type': 'ci failed step',
                    'impacted_cl_count': 0,
                    'occurrence_count': 0
                },
            ],
            'flake_score_last_week':
            0,
            'flake_issue': {
                'flake_culprit_key':
                None,
                'monorail_project':
                'chromium',
                'issue_id':
                900,
                'last_updated_time_by_flake_detection':
                datetime(2018, 1, 1),
                'issue_link': ('https://monorail-prod.appspot.com/p/chromium/'
                               'issues/detail?id=900'),
                'merge_destination_key':
                None,
                'last_updated_time_in_monorail':
                '366 days, 00:00:00',
                'last_updated_time_with_analysis_results':
                None,
                'create_time_in_monorail':
                None,
                'labels': [],
                'status':
                'Started',
            },
            'component':
            'Mock>Component',
            'test_location': {
                'file_path': '../../some/test/path/a.cc',
                'line_number': 42,
            },
            'tags': [],
            'culprits': [{
                'revision': 'rev1',
                'commit_position': culprit1.commit_position,
                'culprit_key': culprit1.key.urlsafe()
            }],
            'sample_analysis':
            None,
            'occurrences': [{
                'group_by_field':
                'luci builder 2',
                'occurrences': [
                    {
                        'flake_type': 'cq step level retry',
                        'build_id': '124',
                        'step_ui_name': step_ui_name,
                        'test_name': test_name,
                        'tags': [],
                        'build_configuration': {
                            'luci_project': 'chromium',
                            'luci_bucket': 'try',
                            'luci_builder': 'luci builder 2',
                            'legacy_master_name': 'buildbot master',
                            'legacy_build_number': 999
                        },
                        'time_happened': '2018-01-02 03:00:00 UTC',
                        'time_detected': '2018-01-02 03:00:00 UTC',
                        'gerrit_cl_id': gerrit_cl_id
                    },
                    {
                        'flake_type': 'cq false rejection',
                        'build_id': '125',
                        'step_ui_name': step_ui_name,
                        'test_name': test_name,
                        'tags': [],
                        'build_configuration': {
                            'luci_project': 'chromium',
                            'luci_bucket': 'try',
                            'luci_builder': 'luci builder 2',
                            'legacy_master_name': 'buildbot master',
                            'legacy_build_number': 999
                        },
                        'time_happened': '2018-01-02 02:00:00 UTC',
                        'time_detected': '2018-01-02 02:00:00 UTC',
                        'gerrit_cl_id': gerrit_cl_id
                    },
                    {
                        'flake_type': 'ci failed step',
                        'build_id': '127',
                        'step_ui_name': step_ui_name,
                        'test_name': test_name,
                        'tags': [],
                        'build_configuration': {
                            'luci_project': 'chromium',
                            'luci_bucket': 'try',
                            'luci_builder': 'luci builder 2',
                            'legacy_master_name': 'buildbot master',
                            'legacy_build_number': 999
                        },
                        'time_happened': '2018-01-02 02:00:00 UTC',
                        'time_detected': '2018-01-02 02:00:00 UTC',
                        'gerrit_cl_id': -1,
                    },
                    {
                        'flake_type': 'cq hidden flake',
                        'build_id': '126',
                        'step_ui_name': step_ui_name,
                        'test_name': test_name,
                        'tags': [],
                        'build_configuration': {
                            'luci_project': 'chromium',
                            'luci_bucket': 'try',
                            'luci_builder': 'luci builder 2',
                            'legacy_master_name': 'buildbot master',
                            'legacy_build_number': 999
                        },
                        'time_happened': '2018-01-02 02:00:00 UTC',
                        'time_detected': '2018-01-02 02:00:00 UTC',
                        'gerrit_cl_id': gerrit_cl_id,
                    },
                ]
            }, {
                'group_by_field':
                'luci builder',
                'occurrences': [{
                    'flake_type': 'cq false rejection',
                    'build_id': '123',
                    'step_ui_name': step_ui_name,
                    'test_name': test_name,
                    'tags': [],
                    'build_configuration': {
                        'luci_project': 'chromium',
                        'luci_bucket': 'try',
                        'luci_builder': 'luci builder',
                        'legacy_master_name': 'buildbot master',
                        'legacy_build_number': 999
                    },
                    'time_happened': '2018-01-01 00:00:00 UTC',
                    'time_detected': '2018-01-01 00:00:00 UTC',
                    'gerrit_cl_id': gerrit_cl_id
                }]
            }],
        }
        self.assertEqual(expected_flake_dict,
                         flake_detection_utils.GetFlakeInformation(flake, 5))