Пример #1
0
    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'])
Пример #3
0
    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')
Пример #4
0
 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))
Пример #5
0
 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)
Пример #6
0
    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')))
Пример #7
0
    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
Пример #8
0
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'])