def _StartTestLevelCheckForFirstFailure(master_name, builder_name, build_number, step_name, failed_step, http_client): """Downloads test results and initiates first failure info at test level.""" list_isolated_data = failed_step.list_isolated_data list_isolated_data = (list_isolated_data.ToSerializable() if list_isolated_data else []) result_log = swarmed_test_util.RetrieveShardedTestResultsFromIsolatedServer( list_isolated_data, http_client) test_results_object = test_results_util.GetTestResultObject(result_log) if not test_results_object or not step_util.IsStepSupportedByFindit( test_results_object, step_util.GetCanonicalStepName(master_name, builder_name, build_number, step_name), master_name): return False failed_test_log, reliable_failed_tests = ( test_results_service.GetFailedTestsInformationFromTestResult( test_results_object)) _SaveIsolatedResultToStep(master_name, builder_name, build_number, step_name, failed_test_log) return _InitiateTestLevelFirstFailure(reliable_failed_tests, failed_step)
def NormalizeStepName(step_name, master_name, builder_name, build_number): """Normalizes step name according to the above mentioned definitions. The most reliable solution to obtain base test target names is to add a base_test_target field in the GN templates that define the tests and expose them through step_metadata, but unfortunately, it doesn't exist yet. The closest thing that exists is isolate_target_name in the step_metadata. Though the isolate_target_name may go away eventually, it will be kept as it is until base_test_target is in place, so it is safe to use isolate_target_name as a temporary workaround. Args: step_name: The original step name, and it may contain hardware information and 'with(out) patch' suffixes. master_name: Master name of the build of the step. builder_name: Builder name of the build of the step. build_number: Build number of the build of the step. Returns: Normalized version of the given step name. """ isolate_target_name = step_util.GetIsolateTargetName( master_name=master_name, builder_name=builder_name, build_number=build_number, step_name=step_name) if isolate_target_name: if 'webkit_layout_tests' in isolate_target_name: return 'webkit_layout_tests' return isolate_target_name # In case isolate_target_name doesn't exist, fall back to # canonical_step_name or step_name.split()[0]. logging.error(( 'Failed to obtain isolate_target_name for step: %s in build: %s/%s/%s. ' 'Fall back to use canonical_step_name.') % (step_name, master_name, builder_name, build_number)) canonical_step_name = step_util.GetCanonicalStepName( master_name=master_name, builder_name=builder_name, build_number=build_number, step_name=step_name) if canonical_step_name: return canonical_step_name logging.error(( 'Failed to obtain canonical_step_name for step: %s in build: %s/%s/%s. ' 'Fall back to use step_name.split()[0].') % (step_name, master_name, builder_name, build_number)) return step_name.split()[0]
def GetTestComponentsForGPUTest(build_id, step_name): """Use canonical step name to find the best matched components in the mapping. Args: step_name (str): The name of the step. build_id (int): Build id of the build. Returns: components ([str]): sorted list of components mapped to canonical step name. """ canonical_step_name = step_util.GetCanonicalStepName( build_id, step_name) or step_name.split()[0] return sorted( _MAP_GPU_TEST_STEP_NAME_TO_COMPONENTS.get(canonical_step_name, []))
def NormalizeStepName(build_id, step_name, partial_match=True): """Normalizes step name according to the above mentioned definitions. The most reliable solution to obtain base test target names is to add a base_test_target field in the GN templates that define the tests and expose them through step_metadata, but unfortunately, it doesn't exist yet. The closest thing that exists is isolate_target_name in the step_metadata. Though the isolate_target_name may go away eventually, it will be kept as it is until base_test_target is in place, so it is safe to use isolate_target_name as a temporary workaround. Args: build_id: Build id of the build of the step. step_name: The original step name, and it may contain hardware information and 'with(out) patch' suffixes. partial_match: If the step_name is not found among the steps in the builder, allow the function to retrieve step metadata from a step whose name contains step_name as a prefix. Returns: Normalized version of the given step name. """ isolate_target_name = step_util.GetIsolateTargetName( build_id=build_id, step_name=step_name, partial_match=partial_match) if isolate_target_name: if 'webkit_layout_tests' in isolate_target_name: return 'webkit_layout_tests' return isolate_target_name # In case isolate_target_name doesn't exist, fall back to # canonical_step_name or step_name.split()[0]. logging.error( 'Failed to obtain isolate_target_name for step: %s in build id: %s. ' 'Fall back to use canonical_step_name.', step_name, build_id) canonical_step_name = step_util.GetCanonicalStepName( build_id=build_id, step_name=step_name, partial_match=partial_match) if canonical_step_name: return canonical_step_name logging.error( 'Failed to obtain canonical_step_name for step: %s in build id: %s. ' 'Fall back to use step_name.split()[0].', step_name, build_id) return step_name.split()[0]
def GetSuspectedCLsWithFailures(master_name, builder_name, build_number, heuristic_result): """Generates a list of suspected CLs with failures. Args: master_name (str): Name of the master. builder_name (str): Name of the builder. build_number (int): Number of the failed build. heuristic_result (TestHeuristicResult): the heuristic_result from which to generate the list of suspected CLs with failures. Returns: A list of suspected CLs with failures that each could look like: [step_name, revision, test_name] or could look like: [step_name, revision, None] """ if not heuristic_result: return [] suspected_cls_with_failures = [] # Iterates through the failures, tests, and suspected_cls, appending suspected # CLs and failures to the list. for failure in heuristic_result['failures']: if failure.tests: for test in failure.tests: for suspected_cl in test.suspected_cls or []: suspected_cls_with_failures.append([ step_util.GetCanonicalStepName(master_name, builder_name, build_number, failure.step_name), suspected_cl.revision, test.test_name ]) else: for suspected_cl in failure.suspected_cls: suspected_cls_with_failures.append( [failure.step_name, suspected_cl.revision, None]) return suspected_cls_with_failures
def _GetTestSuiteForOccurrence(row, normalized_test_name, normalized_step_name): """ Gets test suite name from test_name or step_name Args: row: A row of query result. normalized_test_name: Test name without parameters. normalized_step_name: Isolated target of the step. """ step_ui_name = row['step_ui_name'] if normalized_step_name == 'telemetry_gpu_integration_test': # Special case for Telemetry-based GPU tests (identified by # telemetry_gpu_integration_test isolate). Suite not related to test # names but step names. return step_util.GetCanonicalStepName( master_name=row['legacy_master_name'], builder_name=row['luci_builder'], build_number=row['legacy_build_number'], step_name=step_ui_name) or step_ui_name.split()[0] return test_name_util.GetTestSuiteName(normalized_test_name, step_ui_name)
def testGetCanonicalStepNamePartialMatch(self, mock_get_step_metadata): step_util.GetCanonicalStepName(123, 'full step name') self.assertIn(False, mock_get_step_metadata.call_args[0]) step_util.GetCanonicalStepName(123, 'full step name', True) self.assertIn(True, mock_get_step_metadata.call_args[0])
def testGetCanonicalStepName(self, step_metadata, expected_canonical_step, mocked_get_step): mocked_get_step.return_value = step_metadata self.assertEqual( expected_canonical_step, step_util.GetCanonicalStepName(123, 'step_name (with patch)'))
def testGetCanonicalStep(self, _): self.assertEqual( 'step_name', step_util.GetCanonicalStepName('m', 'b', 200, 'step_name on a platform'))
def _UpdateTestLocationAndTags(flake, occurrences, component_mapping, watchlists): """Updates the test location and tags of the given flake. Currently only support gtests and webkit layout tests in chromium/src. Returns: True if flake is updated; otherwise False. """ chromium_tag = 'gerrit_project::chromium/src' if chromium_tag not in flake.tags: logging.debug('Flake is not from chromium/src: %r', flake) return False # No need to update if the test location and related tags were updated within # the last 7 days. if (flake.last_test_location_based_tag_update_time and (flake.last_test_location_based_tag_update_time > time_util.GetDateDaysBeforeNow(7))): logging.debug('Flake test location tags were updated recently : %r', flake) return False # Update the test definition location, and then components/tags, etc. test_location = None if 'webkit_layout_tests' in occurrences[0].step_ui_name: # For Webkit layout tests, assume that the normalized test name is # the directory name. # TODO(crbug.com/835960): use new location third_party/blink/web_tests. test_location = TestLocation( file_path=_NormalizePath('third_party/blink/web_tests/%s' % flake.normalized_test_name)) elif test_name_util.GTEST_REGEX.match(flake.normalized_test_name): # For Gtest, we read the test location from the output.json test_location = _GetTestLocation(occurrences[0]) updated = False # Ignore old test-location-based tags. all_tags = set([ t for t in (flake.tags or []) if not t.startswith(('watchlist::', 'directory::', 'source::', 'parent_component::', 'component::')) ]) if test_location: updated = True flake.test_location = test_location file_path = test_location.file_path # Use watchlist to set the watchlist tags for the flake. for watchlist, pattern in watchlists.iteritems(): if re.search(pattern, file_path): all_tags.add('watchlist::%s' % watchlist) component = None # Use test file path to find the best matched component in the mapping. # Each parent directory will become a tag. index = len(file_path) while index > 0: index = file_path.rfind('/', 0, index) if index > 0: if not component and file_path[0:index + 1] in component_mapping: component = component_mapping[file_path[0:index + 1]] all_tags.add('directory::%s' % file_path[0:index + 1]) all_tags.add('source::%s' % file_path) if component: flake.component = component all_tags.add('component::%s' % component) all_tags.add('parent_component::%s' % component) index = len(component) while index > 0: index = component.rfind('>', 0, index) if index > 0: all_tags.add('parent_component::%s' % component[0:index]) else: flake.component = DEFAULT_COMPONENT all_tags.add('component::%s' % DEFAULT_COMPONENT) all_tags.add('parent_component::%s' % DEFAULT_COMPONENT) flake.tags = sorted(all_tags) flake.last_test_location_based_tag_update_time = time_util.GetUTCNow() else: if flake.normalized_step_name == 'telemetry_gpu_integration_test': # Special case for telemetry_gpu_integration_test. components = [] for occurrence in occurrences: canonical_step_name = step_util.GetCanonicalStepName( master_name=occurrence.build_configuration. legacy_master_name, builder_name=occurrence.build_configuration.luci_builder, build_number=occurrence.build_configuration. legacy_build_number, step_name=occurrence.step_ui_name ) or occurrence.step_ui_name.split()[0] components.extend( _MAP_STEP_NAME_TO_COMPONENTS.get(canonical_step_name, [])) components = list(set(components)) # To remove duplicates. if components: flake.component = components[0] all_tags = all_tags.union( set([ 'component::%s' % component for component in components ])) flake.tags = sorted(all_tags) updated = True return updated