Ejemplo n.º 1
0
    def testNormalizeTestName(self):
        self.assertEqual('suite.test', Flake.NormalizeTestName('suite.test'))

        self.assertEqual('suite.test',
                         Flake.NormalizeTestName('a/suite.test/0', ))

        self.assertEqual('suite.test', Flake.NormalizeTestName('suite.test/1'))

        self.assertEqual('suite.test', Flake.NormalizeTestName('suite.test/*'))

        self.assertEqual('suite.test',
                         Flake.NormalizeTestName('*/suite.test/*'))

        self.assertEqual('suite.test',
                         Flake.NormalizeTestName('suite.PRE_PRE_test'))

        self.assertEqual('suite.test',
                         Flake.NormalizeTestName('a/suite.PRE_PRE_test/0'))

        self.assertEqual('a/b/c/d.html',
                         Flake.NormalizeTestName('a/b/c/d.html'))

        self.assertEqual('a/b/c/d.html',
                         Flake.NormalizeTestName('a/b/c/d.html?1000-2000'))

        self.assertEqual('a/b/c/d.html',
                         Flake.NormalizeTestName('a/b/c/d.html?*'))
Ejemplo n.º 2
0
    def testNormalizeTestNameWithStepName(self):
        self.assertEqual('suite.test',
                         Flake.NormalizeTestName('a/suite.test/1'))

        self.assertEqual('a.html', Flake.NormalizeTestName('a/b.html'))
        self.assertEqual(
            'a/b.html',
            Flake.NormalizeTestName('a/b.html', 'webkit_layout_tests'))
Ejemplo n.º 3
0
def GetFlake(luci_project, original_step_name, original_test_name, master_name,
             builder_name, build_number):
    """Returns an existing Flake or creates one as needed.

  Args:
    luci_project (str): The project being analyzed, e.g. 'chromium'.
    original_step_name (str): The original step name which may contain hardware
      information and 'with(out) patch' etc. suffixes.
    original_test_name (str): The original test name.
    master_name (str): Master name of the build of the step.
    builder_name (str): Builder name of the build of the step.
    build_number (int): Build number of the build of the step.
  """
    normalized_step_name = Flake.LegacyNormalizeStepName(
        original_step_name, master_name, builder_name, build_number)
    normalized_test_name = Flake.NormalizeTestName(original_test_name,
                                                   original_step_name)
    flake = Flake.Get(luci_project, normalized_step_name, normalized_test_name)

    if not flake:  # pragma: no branch
        label = Flake.GetTestLabelName(original_test_name, original_step_name)
        flake = Flake.Create(luci_project, normalized_step_name,
                             normalized_test_name, label)
        flake.put()

    return flake
Ejemplo n.º 4
0
    def testGetTestLabelName(self):
        self.assertEqual(
            'suite.test', Flake.GetTestLabelName('suite.test',
                                                 'base_unittests'))

        self.assertEqual(
            'suite.test/*',
            Flake.GetTestLabelName('suite.test/1', 'base_unittests'))

        self.assertEqual(
            '*/suite.test/*',
            Flake.GetTestLabelName('a/suite.test/0', 'base_unittests'))

        self.assertEqual(
            'suite.*test',
            Flake.GetTestLabelName('suite.PRE_PRE_test', 'base_unittests'))

        self.assertEqual(
            '*/suite.*test/*',
            Flake.GetTestLabelName('a/suite.PRE_PRE_test/0', 'base_unittests'))

        self.assertEqual(
            'a/b.html',
            Flake.NormalizeTestName('a/b.html', 'webkit_layout_tests'))

        self.assertEqual(
            'a/b.html?*',
            Flake.GetTestLabelName('a/b.html?1000-2000',
                                   'webkit_layout_tests'))
Ejemplo n.º 5
0
def _CreateLocalTests(row, local_tests, component_mapping, watchlists):
    """Creates a LuciTest key-test variant pair for a row fetched from BigQuery.

  Args:
    row: A row of query results.
    local_tests (dict): LuciTest entities in local memory in the format
      {LuciTest.key: {'disabled_test_variants : set(), issue_keys: set()},
      mutated by this function.
    component_mapping (dict): Mapping from directories to crbug components.
    watchlists (dict): Mapping from directories to watchlists.
  """
    build_id = row['build_id']
    builder_name = row['builder_name']
    step_name = row['step_name']
    test_name = row['test_name']
    bugs = row['bugs']

    if int(build_id) == 1:
        # To filter out tests results with invalid build_id.
        # TODO (crbug.com/999215): Remove this check after test-results is fixed.
        logging.info(
            'Failed to define test variant for build_id: %s, row is %r',
            build_id, row)
        return

    normalized_step_name = Flake.NormalizeStepName(build_id, step_name)
    normalized_test_name = Flake.NormalizeTestName(test_name, step_name)
    test_key = LuciTest.CreateKey(_DEFAULT_LUCI_PROJECT, normalized_step_name,
                                  normalized_test_name)
    if not local_tests.get(test_key):
        local_tests[test_key] = {
            'disabled_test_variants': set(),
            'issue_keys': set(),
            'tags': set()
        }
    local_tests[test_key]['tags'].update(
        _GetNewTestTags(local_tests[test_key]['tags'], step_name, test_name,
                        normalized_step_name, normalized_test_name, build_id,
                        component_mapping, watchlists))

    disabled_variant = _CreateDisabledVariant(build_id, builder_name,
                                              step_name)
    local_tests[test_key]['disabled_test_variants'].add(disabled_variant)
    local_tests[test_key]['issue_keys'].update(_CreateIssueKeys(bugs))
def _CreateFlakeFromRow(row):
    """Creates a Flake entity from a row fetched from BigQuery."""
    luci_project = row['luci_project']
    luci_builder = row['luci_builder']
    legacy_master_name = row['legacy_master_name']
    legacy_build_number = row['legacy_build_number']
    step_ui_name = row['step_ui_name']
    test_name = row['test_name']

    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)
    test_label_name = Flake.GetTestLabelName(test_name, step_ui_name)

    return Flake.Create(luci_project=luci_project,
                        normalized_step_name=normalized_step_name,
                        normalized_test_name=normalized_test_name,
                        test_label_name=test_label_name)
Ejemplo n.º 7
0
def GetFlakesByFilter(flake_filter,
                      luci_project,
                      cursor,
                      direction,
                      page_size=None):  # pragma: no cover.
    """Gets flakes by the given filter, then sorts them by the flake score.

  Args:
    flake_filter (str): It could be a test name, or a tag-based filter in the
      following forms:
      * tag::value
      * tag1::value1@tag2::value2
      * tag1::value1@-tag2:value2
    luci_project (str): The Luci project that the flakes are for.
    cursor (None or str): The cursor provides a cursor in the current query
      results, allowing you to retrieve the next set based on the offset.
    direction (str): Either previous or next.
    page_size (int): Limit of results required in one page.

  Returns:
    (flakes, prev_cursor, cursor, grouping_search, error_message)
    flakes (list): A list of Flakes filtered by tags.
    prev_cursor (str): The urlsafe encoding of the cursor, which is at the
      top position of entities of the current page.
    cursor (str): The urlsafe encoding of the cursor, which is at the
      bottom position of entities of the current page.
    grouping_search (bool): Whether it is a group searching.
    error_message (str): An error message if there is one; otherwise None.
  """
    logging.info('Searching filter: %s', flake_filter)

    flakes = []
    error_message = None

    grouping_search = True
    filters = [f.strip() for f in flake_filter.split('@') if f.strip()]

    # The resulted flakes are those:
    # * Match all of positive filters
    # * Not match any of negative filters
    positive_filters = []
    negative_filters = []
    invalid_filters = []
    for f in filters:
        parts = [p.strip() for p in f.split(TAG_DELIMITER)]
        if len(parts) != 2 or not parts[1]:
            invalid_filters.append(f)
            continue

        if parts[0] == _TEST_FILTER_NAME:
            # Search for a specific test.
            grouping_search = False
            flakes = Flake.query(
                Flake.normalized_test_name == Flake.NormalizeTestName(parts[1])
            ).filter(Flake.luci_project == luci_project).fetch()
            return flakes, '', '', grouping_search, error_message

        negative = False
        if parts[0][0] == '-':
            parts[0] = parts[0][1:]
            negative = True

        if parts[0] not in SUPPORTED_TAGS:
            invalid_filters.append(f)
            continue

        if negative:
            negative_filters.append(TAG_DELIMITER.join(parts))
        else:
            positive_filters.append(TAG_DELIMITER.join(parts))

    if invalid_filters:
        error_message = 'Unsupported tag filters: %s' % ', '.join(
            invalid_filters)
        return flakes, '', '', grouping_search, error_message

    if not positive_filters:
        # At least one positive filter should be given.
        error_message = 'At least one positive filter required'
        return flakes, '', '', grouping_search, error_message

    logging.info('Positive filters: %r', positive_filters)
    logging.info('Negative filters: %r', negative_filters)

    query = Flake.query(
        ndb.AND(Flake.luci_project == luci_project, Flake.archived == False))  # pylint: disable=singleton-comparison
    for tag in positive_filters:
        query = query.filter(Flake.tags == tag)
    query = query.filter(Flake.flake_score_last_week > 0)
    minimum_flake_count_in_page = max(
        1, page_size / 2) if page_size else DEFAULT_PAGE_SIZE / 2

    while True:
        results, prev_cursor, cursor = dashboard_util.GetPagedResults(
            query,
            order_properties=[
                (Flake.flake_score_last_week, dashboard_util.DESC),
                (Flake.last_occurred_time, dashboard_util.DESC),
                (Flake.normalized_step_name, dashboard_util.ASC),
                (Flake.test_label_name, dashboard_util.ASC),
            ],
            cursor=cursor,
            direction=direction,
            page_size=page_size or DEFAULT_PAGE_SIZE)

        for result in results:
            if negative_filters and any(t in result.tags
                                        for t in negative_filters):
                continue
            flakes.append(result)

        if ((direction == dashboard_util.PREVIOUS and prev_cursor == '')
                or cursor == '' or len(flakes) >= minimum_flake_count_in_page):
            # No more results or gets enough flakes on a page.
            # Ideally we expect the page shows the same amount of flakes as the
            # page_size suggests, but in the case with negative_filters, the number of
            # flakes left after filtering out negative_filters is unknown.
            # Uses minimum_flake_count_in_page to cap the flake count in one page from
            # 0.5 page_size to 1.5 page_size.
            break

    return flakes, prev_cursor, cursor, grouping_search, error_message
Ejemplo n.º 8
0
 def GetTestName(self):
     return Flake.NormalizeTestName(self._analysis.test_name,
                                    self._analysis.step_name)
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