def testClassifyRepoUrl(self): """Tests ``ClassifyRepoUrl`` method.""" components = [ Component('Blink>JavaScript', ['src/v8', 'src/v8/src/base/blabla...'], None, None) ] classifier = ComponentClassifier(components, 3, _MOCK_REPO_TO_DEP_PATH) self.assertEqual(['Blink>JavaScript'], classifier.ClassifyRepoUrl('https://chromium.v8.git'))
def setUp(self): super(ComponentClassifierTest, self).setUp() components = [ Component(info['component'], info['dirs'], info.get('function'), info.get('team')) for info in COMPONENT_CONFIG['component_info'] ] # Only construct the classifier once, rather than making a new one every # time we call a method on it. self.classifier = ComponentClassifier(components, COMPONENT_CONFIG['top_n'])
def testMatchComponents(self): """Tests classifier matches the component with longest directory path.""" components = [ Component('Blink>JavaScript', ['src/v8', 'src/v8/src/base/blabla...'], None, None), Component('Blink>JavaScript>GC', ['src/v8/src/heap'], None, None) ] classifier = ComponentClassifier(components, 3, _MOCK_REPO_TO_DEP_PATH) self.assertEqual(classifier.ClassifyFilePath('src/v8/src/heap/a.cc'), 'Blink>JavaScript>GC')
def testCrashedGroupFactoryReturnsNoneWhenComponentIsBlacklisted(self): """Tests that ``CrashGroupFactory`` returns None when comp blacklisted.""" components = [Component('bad_comp', 'bad_dir', '', 'team')] # Only construct the classifier once, rather than making a new one every # time we call a method on it. classifier = ComponentClassifier(components, 3, _MOCK_REPO_TO_DEP_PATH) feature = TouchCrashedComponentFeature( classifier, options={'blacklist': ['bad_comp']}) frame = StackFrame(0, 'src/', 'func', 'bad_dir/f.cc', 'src/bad_dir/f.cc', [2, 3], 'h://repo') self.assertIsNone(feature.CrashedGroupFactory(frame))
def setUp(self): super(TouchCrashedComponentFeatureTest, self).setUp() components = [ Component(info['component'], info['dirs'], info.get('function'), info.get('team')) for info in COMPONENT_CONFIG['component_info'] ] # Only construct the classifier once, rather than making a new one every # time we call a method on it. self.classifier = ComponentClassifier(components, COMPONENT_CONFIG['top_n'], _MOCK_REPO_TO_DEP_PATH) self.feature = TouchCrashedComponentFeature(self.classifier)
def testReplacePath(self): """Tests feature can still match components with files after file move.""" components = [Component('new_comp', ['src/dep/b/new_dir'], '', 'team')] # Only construct the classifier once, rather than making a new one every # time we call a method on it. classifier = ComponentClassifier(components, 3, _MOCK_REPO_TO_DEP_PATH) feature = TouchCrashedComponentFeature( classifier, options={'replace_path': { 'a/old_dir': 'b/new_dir' }}) match_func = feature.GetMatchFunction('src/dep') self.assertTrue( match_func( CrashedComponent('new_comp'), FileChangeInfo(ChangeType.MODIFY, 'a/old_dir/f.cc', 'a/old_dir/f.cc')))
def __init__(self, get_repository, config): """ Args: get_repository (callable): a function from DEP urls to ``Repository`` objects, so we can get changelogs and blame for each dep. Notably, to keep the code here generic, we make no assumptions about which subclass of ``Repository`` this function returns. Thus, it is up to the caller to decide what class to return and handle any other arguments that class may require (e.g., an http client for ``GitilesRepository``). config (ndb.CrashConfig): Config for clients and project and component classifiers. """ self._get_repository = get_repository # The top_n is the number of frames we want to check to get project # classifications. projects = [ Project(name, path_regexs, function_regexs, host_directories) for name, path_regexs, function_regexs, host_directories in config.project_classifier['project_path_function_hosts'] ] self._project_classifier = ProjectClassifier( projects, config.project_classifier['top_n'], config.project_classifier['non_chromium_project_rank_priority']) # The top_n is the number of frames we want to check to get component # classifications. components = [ Component(info['component'], info['dirs'], info.get('function'), info.get('team')) for info in config.component_classifier['component_info'] ] self._component_classifier = ComponentClassifier( components, config.component_classifier['top_n']) self._config = config
class ComponentClassifierTest(AnalysisTestCase): """Tests ``ComponentClassifier`` class.""" def setUp(self): super(ComponentClassifierTest, self).setUp() components = [ Component(info['component'], info['dirs'], info.get('function'), info.get('team')) for info in COMPONENT_CONFIG['component_info'] ] # Only construct the classifier once, rather than making a new one every # time we call a method on it. self.classifier = ComponentClassifier(components, COMPONENT_CONFIG['top_n'], _MOCK_REPO_TO_DEP_PATH) def testClassifyStackFrameEmptyFrame(self): """Tests that ``ClassifyStackFrame`` returns None for empty frame.""" frame = StackFrame(0, None, 'func', 'comp1/a.cc', 'src/comp1/a.cc', [2]) self.assertIsNone(self.classifier.ClassifyStackFrame(frame)) frame = StackFrame(0, 'src/', 'func', None, 'src/comp1/a.cc', [2]) self.assertIsNone(self.classifier.ClassifyStackFrame(frame)) def testClassifyCallStack(self): """Tests ``ClassifyCallStack`` method.""" callstack = CallStack(0, [ StackFrame(0, 'src/', 'func', 'comp1/a.cc', 'src/comp1/a.cc', [2], repo_url='https://chromium.git') ]) self.assertEqual(self.classifier.ClassifyCallStack(callstack), ['Comp1>Dummy']) callstack = CallStack(0, [ StackFrame(0, 'dummy/', 'no_func', 'comp2/a.cc', 'dummy/comp2.cc', [32], repo_url='dummy_url') ]) self.assertEqual(self.classifier.ClassifyCallStack(callstack), []) crash_stack = CallStack( 0, frame_list=[ StackFrame(0, 'src/', 'func', 'comp1/a.cc', 'src/comp1/a.cc', [2], repo_url='https://chromium.git'), StackFrame(1, 'src/', 'ff', 'comp1/a.cc', 'src/comp1/a.cc', [21], repo_url='https://chromium.git'), StackFrame(2, 'src/', 'func2', 'comp2/b.cc', 'src/comp2/b.cc', [8], repo_url='https://chromium.git') ]) self.assertEqual(self.classifier.ClassifyCallStack(crash_stack), ['Comp1>Dummy', 'Comp2>Dummy']) def testMergeComponents(self): """Tests ``MergeComponents`` merge components with the same hierarchy.""" components1 = ['A', 'A>B>C', 'A>B', 'E>F', 'G>H>I', 'G>H'] merged_components1 = MergeComponents(components1) expected_components1 = ['A>B>C', 'E>F', 'G>H>I'] self.assertListEqual(merged_components1, expected_components1) components2 = ['A', 'AB>C', 'AB>E', 'AB>ED'] merged_components2 = MergeComponents(components2) expected_components2 = ['A', 'AB>C', 'AB>E', 'AB>ED'] self.assertListEqual(merged_components2, expected_components2) components3 = ['A', 'A>B', 'A>C'] merged_components3 = MergeComponents(components3) expected_components3 = ['A>B', 'A>C'] self.assertListEqual(merged_components3, expected_components3) def testMatchComponents(self): """Tests classifier matches the component with longest directory path.""" components = [ Component('Blink>JavaScript', ['src/v8', 'src/v8/src/base/blabla...'], None, None), Component('Blink>JavaScript>GC', ['src/v8/src/heap'], None, None) ] classifier = ComponentClassifier(components, 3, _MOCK_REPO_TO_DEP_PATH) self.assertEqual(classifier.ClassifyFilePath('src/v8/src/heap/a.cc'), 'Blink>JavaScript>GC') def testClassifyTouchedFile(self): """Tests ``ClassifyTouchedFile`` method.""" touched_file = FileChangeInfo(ChangeType.MODIFY, 'comp1/a.cc', 'comp1/b.cc') self.assertEqual( self.classifier.ClassifyTouchedFile('src', touched_file), 'Comp1>Dummy') def testClassifyRepoUrl(self): """Tests ``ClassifyRepoUrl`` method.""" components = [ Component('Blink>JavaScript', ['src/v8', 'src/v8/src/base/blabla...'], None, None) ] classifier = ComponentClassifier(components, 3, _MOCK_REPO_TO_DEP_PATH) self.assertEqual(['Blink>JavaScript'], classifier.ClassifyRepoUrl('https://chromium.v8.git'))
class ComponentClassifierTest(AnalysisTestCase): """Tests ``ComponentClassifier`` class.""" def setUp(self): super(ComponentClassifierTest, self).setUp() components = [ Component(info['component'], info['dirs'], info.get('function'), info.get('team')) for info in COMPONENT_CONFIG['component_info'] ] # Only construct the classifier once, rather than making a new one every # time we call a method on it. self.classifier = ComponentClassifier(components, COMPONENT_CONFIG['top_n']) def testClassifyCallStack(self): """Tests ``ClassifyCallStack`` method.""" callstack = CallStack(0, [ StackFrame(0, 'src/', 'func', 'comp1/a.cc', 'src/comp1/a.cc', [2]) ]) self.assertEqual(self.classifier.ClassifyCallStack(callstack), ['Comp1>Dummy']) callstack = CallStack(0, [ StackFrame(0, 'dummy/', 'no_func', 'comp2/a.cc', 'dummy/comp2.cc', [32]) ]) self.assertEqual(self.classifier.ClassifyCallStack(callstack), []) crash_stack = CallStack(0, frame_list=[ StackFrame(0, 'src/', 'func', 'comp1/a.cc', 'src/comp1/a.cc', [2]), StackFrame(1, 'src/', 'ff', 'comp1/a.cc', 'src/comp1/a.cc', [21]), StackFrame(2, 'src/', 'func2', 'comp2/b.cc', 'src/comp2/b.cc', [8]) ]) self.assertEqual(self.classifier.ClassifyCallStack(crash_stack), ['Comp1>Dummy', 'Comp2>Dummy']) def testClassifySuspect(self): """Tests ``ClassifySuspect`` method.""" suspect = Suspect(self.GetDummyChangeLog(), 'src/') suspect.changelog = suspect.changelog._replace(touched_files=[ FileChangeInfo(ChangeType.MODIFY, 'comp1/a.cc', 'comp1/b.cc') ]) self.assertEqual(self.classifier.ClassifySuspect(suspect), ['Comp1>Dummy']) def testClassifyEmptySuspect(self): """Tests ``ClassifySuspect`` returns None for empty suspect.""" self.assertIsNone(self.classifier.ClassifySuspect(None)) def testClassifySuspectNoMatch(self): """Tests ``ClassifySuspect`` returns None if there is no file match.""" suspect = Suspect(self.GetDummyChangeLog(), 'dummy') suspect.changelog = suspect.changelog._replace(touched_files=[ FileChangeInfo(ChangeType.MODIFY, 'comp1.cc', 'comp1.cc') ]) self.assertEqual(self.classifier.ClassifySuspect(suspect), []) def testClassifySuspects(self): """Tests ``ClassifySuspects`` classify a list of ``Suspect``s.""" suspect1 = Suspect(self.GetDummyChangeLog(), 'src/') suspect1.changelog = suspect1.changelog._replace(touched_files=[ FileChangeInfo(ChangeType.MODIFY, 'comp1/a.cc', 'comp1/b.cc') ]) suspect2 = Suspect(self.GetDummyChangeLog(), 'src/') suspect2.changelog = suspect2.changelog._replace(touched_files=[ FileChangeInfo(ChangeType.MODIFY, 'comp2/a.cc', 'comp2/b.cc') ]) self.assertEqual( self.classifier.ClassifySuspects([suspect1, suspect2]), ['Comp1>Dummy', 'Comp2>Dummy'])