def testDependencyRoll(self, mock_get_dependency_rolls): """Tests parsing dependency rolls from regression_range.""" dep_roll = DependencyRoll('src/', 'https://repo', 'rev1', 'rev6') regression_rolls = { dep_roll.path: dep_roll, 'src/dummy': DependencyRoll('src/dummy', 'https://r', 'rev2', 'rev4'), 'src/add': DependencyRoll('src/add', 'https://rr', None, 'rev5') } mock_get_dependency_rolls.return_value = regression_rolls dep_data = self._GetDummyDependencyAnalyzer() dep_data._regression_range = ('rev1', 'rev6') chromium_dep = Dependency('src/', 'https://repo', 'rev1') dep_data._regression_version_deps = { chromium_dep.path: chromium_dep, 'src/dummy': Dependency('src/dummy', 'https://r', 'rev2') } stack = stacktrace.CallStack(0, frame_list=[ stacktrace.StackFrame( 0, 'src/', 'func', 'a.cc', 'src/a.cc', [5]) ]) stacks_list = [stack] self.assertEqual(dep_data.GetDependencyRolls(stacks_list), {dep_roll.path: dep_roll})
def testDependencyRoll(self): """Tests parsing ``regression_rolls`` from regression_range.""" dep_roll = DependencyRoll('src/', 'https://repo', 'rev1', 'rev6') regression_rolls = { dep_roll.path: dep_roll, 'src/dummy': DependencyRoll('src/dummy', 'https://r', 'rev2', 'rev4'), 'src/add': DependencyRoll('src/add', 'https://rr', None, 'rev5') } with mock.patch( 'libs.deps.chrome_dependency_fetcher.ChromeDependencyFetcher' '.GetDependencyRollsDict') as mock_get_dependency_rolls: mock_get_dependency_rolls.return_value = regression_rolls crash_data = ChromeCrashData( self.GetDummyChromeCrashData(), ChromeDependencyFetcher(self.GetMockRepoFactory())) crash_data._regression_range = ('rev1', 'rev6') chromium_dep = Dependency('src/', 'https://repo', 'rev1') crash_data._crashed_version_deps = { chromium_dep.path: chromium_dep, 'src/dummy': Dependency('src/dummy', 'https://r', 'rev2')} stack = CallStack(0, frame_list=[ StackFrame(0, 'src/', 'func', 'a.cc', 'src/a.cc', [5])]) stacktrace = Stacktrace([stack], stack) crash_data._stacktrace = stacktrace self.assertEqual(crash_data.dependency_rolls, {dep_roll.path: dep_roll})
def testToDict(self): dep_roll = DependencyRoll('third_party/dep/', 'https://cr.googlesource.com/cr/dep.git', 'rev1', 'rev2') expected_dep_roll_dict = { 'path': 'third_party/dep/', 'repo_url': 'https://cr.googlesource.com/cr/dep.git', 'old_revision': 'rev1', 'new_revision': 'rev2', } self.assertEqual(expected_dep_roll_dict, dep_roll.ToDict())
def _MockGetDependencyRolls(old_revision, new_revision, *_, **kargs): dependency_rolls = [ DependencyRoll('src/dep1', 'https://url_dep1', '7', '9'), DependencyRoll('src/dep2', 'https://url_dep2', '3', None) ] if not kargs['skip_chromium_roll']: dependency_rolls.append( DependencyRoll( 'src', 'https://chromium.googlesource.com/chromium/src.git', old_revision, new_revision)) return dependency_rolls
def testMinDistanceFeatureMiddling(self): """Test that the feature returns middling scores for middling distances.""" report = self._GetDummyReport( deps={'src/': Dependency('src/', 'https://repo', '6')}, dep_rolls={ 'src/': DependencyRoll('src/', 'https://repo', '0', '4') }) frame = StackFrame(0, 'src/', 'func', 'f.cc', 'f.cc', [232], 'https://repo') distance = 42. crashed = CrashedFile('file') matches = { crashed: CrashMatch(crashed, [FileChangeInfo(ChangeType.MODIFY, 'file', 'file')], [FrameInfo(frame, 0)]) } with mock.patch( 'analysis.linear.changelist_features.' 'min_distance.MinDistanceFeature.' 'DistanceBetweenTouchedFileAndFrameInfos') as mock_distance: mock_distance.return_value = min_distance.Distance(distance, frame) self.assertEqual((_MAXIMUM - distance) / _MAXIMUM, min_distance.MinDistanceFeature( self._get_repository, _MAXIMUM)(report)(self._GetMockSuspect(), matches).value)
def testMinDistanceFeatureIsOverMax(self): """Test that we return log(0) when the min_distance is too large.""" report = self._GetDummyReport( deps={'src/': Dependency('src/', 'https://repo', '6')}, dep_rolls={ 'src/': DependencyRoll('src/', 'https://repo', '0', '4') }) distance = _MAXIMUM + 1 frame = _MOCK_FRAME._replace(file_path='file') crashed = CrashedFile('file') matches = { crashed: CrashMatch(crashed, [FileChangeInfo(ChangeType.MODIFY, 'file', 'file')], [FrameInfo(frame, 0)]) } with mock.patch( 'analysis.linear.changelist_features.' 'min_distance.MinDistanceFeature.' 'DistanceBetweenTouchedFileAndFrameInfos') as mock_distance: mock_distance.return_value = min_distance.Distance(distance, None) self.assertEqual( 0.0, min_distance.MinDistanceFeature( self._get_repository, _MAXIMUM)(report)(self._GetMockSuspect(), matches).value)
def testMinDistanceChangedFiles(self): """Tests ``ChangedFile`` method.""" report = self._GetDummyReport( deps={'src/': Dependency('src/', 'https://repo', '6')}, dep_rolls={'src/': DependencyRoll('src/', 'https://repo', '0', '4')}) distance = 42 crashed = CrashedFile(_MOCK_FRAME) matches = { crashed: CrashMatch(crashed, [FileChangeInfo(ChangeType.MODIFY, 'file', 'file')], [FrameInfo(_MOCK_FRAME, 0)]) } frame = StackFrame(0, 'src/', 'func', 'f.cc', 'f.cc', [7], 'https://repo') with mock.patch('analysis.linear.changelist_features.min_distance.' 'MinDistanceFeature.' 'DistanceBetweenTouchedFileAndFrameInfos') as mock_distance: mock_distance.return_value = min_distance.Distance(distance, frame) self.assertEqual( min_distance.MinDistanceFeature( self._get_repository, _MAXIMUM)(report)( self._GetMockSuspect(), matches).changed_files, [ChangedFile(name='file', blame_url=('%s/+blame/%s/f.cc#%d' % (frame.repo_url, report.crashed_version, frame.crashed_line_numbers[0])), reasons=['Distance between touched lines and crashed' ' lines is %d, in frame #%d' % ( distance, frame.index)])])
def testMinDistanceFeatureInfinityDistance(self): """Test that we return log(0) when the min_distance is infinity. The infinity distance means the touched file get overwritten by other cls, and the change didn't show in the final blame file. """ report = self._GetDummyReport( deps={'src/': Dependency('src/', 'https://repo', '6')}, dep_rolls={'src/': DependencyRoll('src/', 'https://repo', '0', '4')}) suspect = self._GetMockSuspect() crashed = CrashedFile(_MOCK_FRAME) matches = { crashed: CrashMatch(crashed, [FileChangeInfo(ChangeType.MODIFY, 'file', 'file')], [FrameInfo(_MOCK_FRAME, 0)]) } with mock.patch('analysis.linear.changelist_features.min_distance.' 'MinDistanceFeature.' 'DistanceBetweenTouchedFileAndFrameInfos') as mock_distance: mock_distance.return_value = None self.assertEqual( 0.0, min_distance.MinDistanceFeature( self._get_repository, _MAXIMUM)(report)(suspect, matches).value) with mock.patch('analysis.linear.changelist_features.min_distance.' 'MinDistanceFeature.' 'DistanceBetweenTouchedFileAndFrameInfos') as mock_distance: mock_distance.return_value = min_distance.Distance(float('inf'), None) self.assertEqual( 0.0, min_distance.MinDistanceFeature(self._get_repository, 100)(report)( suspect, matches).value)
def testDependencyRollsReturnsCache(self): """Tests that ``dependency_rolls`` returns cached ``_dependency_rolls``.""" crash_data = ClusterfuzzData(self.GetDummyClusterfuzzData()) dep_roll = { 'src/': DependencyRoll('src/', 'https://repo', 'rev0', 'rev3') } crash_data._dependency_rolls = dep_roll self.assertEqual(crash_data.dependency_rolls, dep_roll)
def testDependenciesAndDependencyRollsIsFrozenDict(self): crash_report = CrashReport( 'rev', 'sig', 'win', None, ('1', '3'), {'src/': Dependency('src/', 'http://repo', '5')}, {'src/': DependencyRoll('src/', 'http://repo', '1', '3')}) self.assertTrue(isinstance(crash_report.regression_range, tuple)) self.assertTrue(isinstance(crash_report.dependencies, _FrozenDict)) self.assertTrue(isinstance(crash_report.dependency_rolls, _FrozenDict))
def dependency_rolls(self): return { roll['dep_path']: DependencyRoll(roll['dep_path'], roll['repo_url'], roll.get('old_revision'), roll.get('new_revision')) for roll in self._raw_dependency_rolls if roll.get('old_revision') or roll.get('new_revision') }
def dependency_rolls(self): if self._dependency_rolls: return self._dependency_rolls self._dependency_rolls = { roll['dep_path']: DependencyRoll(roll['dep_path'], roll['repo_url'], roll['old_revision'], roll['new_revision']) for roll in self._raw_dependency_rolls } return self._dependency_rolls
def testGenerateSuspectsFilterReverted(self, mock_get_change_logs): """Tests ``GenerateSuspects`` method.""" dep_roll = DependencyRoll('src/', 'https://repo', 'rev1', 'rev5') report = DUMMY_REPORT._replace( dependency_rolls={dep_roll.path: dep_roll}) mock_get_change_logs.return_value = [ DUMMY_CHANGELOG1, DUMMY_CHANGELOG2, DUMMY_CHANGELOG3 ] suspects = self.changelist_classifier.GenerateSuspects(report) self.assertListEqual(suspects, [])
def testGenerateSuspectsFilterReverted(self): """Tests ``GenerateSuspects`` method.""" dep_roll = DependencyRoll('src/', 'https://repo', 'rev1', 'rev5') report = DUMMY_REPORT._replace( dependency_rolls={dep_roll.path: dep_roll}) self.mock( GitilesRepository, 'GetChangeLogs', lambda *_: [DUMMY_CHANGELOG1, DUMMY_CHANGELOG2, DUMMY_CHANGELOG3]) suspects = self.changelist_classifier.GenerateSuspects(report) self.assertListEqual(suspects, [])
def testToJsonForNonEmptyDependencyRolls(self): """Tests ``ToJson`` for non-empty self.dependency_rolls.""" testcase_id = '1234' job_type = 'asan' analysis = ClusterfuzzAnalysis.Create(testcase_id) analysis.testcase_id = testcase_id analysis.job_type = job_type analysis.dependency_rolls = { 'src': DependencyRoll('src', 'https://repo', 'rev1', 'rev2'), 'src/v8': DependencyRoll('src/v8', 'https://repo/v8', 'rev3', 'rev4') } dependency_rolls_json = [{ 'dep_path': dep.path, 'repo_url': dep.repo_url, 'old_revision': dep.old_revision, 'new_revision': dep.new_revision } for dep in analysis.dependency_rolls.itervalues()] expected_json = { 'regression_range': None, 'dependencies': None, 'dependency_rolls': dependency_rolls_json, 'crash_type': None, 'crash_address': None, 'sanitizer': None, 'security_flag': False, 'job_type': job_type, 'testcase_id': testcase_id } self.assertDictEqual( analysis.ToJson(), { 'customized_data': expected_json, 'platform': None, 'stack_trace': None, 'crash_revision': None, 'signature': None, 'crash_identifiers': None, 'client_id': 'clusterfuzz' })
def setUp(self): super(TouchCrashedDirectoryBaseFeatureTest, self).setUp() frame1 = StackFrame(0, 'src/', 'func', 'p/f.cc', 'src/p/f.cc', [2, 3], 'h://repo') stack = CallStack(0, frame_list=[frame1]) stack_trace = Stacktrace([stack], stack) deps = {'src/': Dependency('src/', 'h://repo', '8')} dep_rolls = {'src/': DependencyRoll('src/', 'h://repo', '2', '6')} self._report = CrashReport('8', 'sig', 'linux', stack_trace, ('2', '6'), deps, dep_rolls) self._feature = TouchCrashedDirectoryFeature()
def testGetDependencyRollsDict(self): def _MockGetDependencyRolls(old_revision, new_revision, *_, **kargs): dependency_rolls = [ DependencyRoll('src/dep1', 'https://url_dep1', '7', '9'), DependencyRoll('src/dep2', 'https://url_dep2', '3', None) ] if not kargs['skip_chromium_roll']: dependency_rolls.append( DependencyRoll( 'src', 'https://chromium.googlesource.com/chromium/src.git', old_revision, new_revision)) return dependency_rolls self.mock(self.chrome_dep_fetcher, 'GetDependencyRolls', _MockGetDependencyRolls) expected_deps_rolls_skip_chromium = [ DependencyRoll('src/dep1', 'https://url_dep1', '7', '9'), DependencyRoll('src/dep2', 'https://url_dep2', '3', None) ] self.assertEqual( self.chrome_dep_fetcher.GetDependencyRolls( '4', '5', 'all', skip_chromium_roll=True), expected_deps_rolls_skip_chromium) expected_deps_rolls_dict = { 'src/dep1': DependencyRoll('src/dep1', 'https://url_dep1', '7', '9'), 'src/dep2': DependencyRoll('src/dep2', 'https://url_dep2', '3', None), 'src': DependencyRoll( 'src', 'https://chromium.googlesource.com/chromium/src.git', '4', '5'), } self.assertEqual( self.chrome_dep_fetcher.GetDependencyRollsDict('4', '5', 'all'), expected_deps_rolls_dict)
def testFeatureValueIsZeroWhenNoMatchedComponent(self): """Test that the feature returns 0 when there no matched component.""" frame = StackFrame(0, 'src/', 'func', 'dir/f.cc', 'src/dir/f.cc', [2, 3], 'h://repo') stack = CallStack(0, frame_list=[frame]) stack_trace = Stacktrace([stack], stack) deps = {'src/': Dependency('src/', 'h://repo', '8')} dep_rolls = {'src/': DependencyRoll('src/', 'h://repo', '2', '6')} report = CrashReport('8', 'sig', 'linux', stack_trace, ('2', '6'), deps, dep_rolls) suspect = Suspect(_DUMMY_CHANGELOG, 'src/') feature_value = self.feature(report)(suspect) self.assertEqual(0.0, feature_value.value)
def testFeatureValueIsOneWhenThereIsMatchedComponent(self): """Test that feature value is 1 when there no matched component.""" # One dummy component in config is ['src/comp1.*', '', 'Comp1>Dummy']. frame1 = StackFrame(0, 'src/', 'func', 'comp1/f.cc', 'src/comp1/f.cc', [2, 3], 'h://repo') stack = CallStack(0, frame_list=[frame1]) stack_trace = Stacktrace([stack], stack) deps = {'src/': Dependency('src/', 'h://repo', '8')} dep_rolls = {'src/': DependencyRoll('src/', 'h://repo', '2', '6')} report = CrashReport('8', 'sig', 'linux', stack_trace, ('2', '6'), deps, dep_rolls) suspect = Suspect(_DUMMY_CHANGELOG, 'src/') feature_value = self.feature(report)(suspect) self.assertEqual(1.0, feature_value.value)
def testMinDistanceFeatureIsLogOne(self): """Test that the feature returns log(1) when the min_distance is 0.""" report = self._GetDummyReport( deps={'src/': Dependency('src/', 'https://repo', '6')}, dep_rolls={ 'src/': DependencyRoll('src/', 'https://repo', '0', '4') }) frame = StackFrame(0, 'src/', 'func', 'a.cc', 'a.cc', [2], 'https://repo') with mock.patch( 'analysis.linear.changelist_features.' 'min_distance.MinDistanceFeature.' 'DistanceBetweenTouchedFileAndFrameInfos') as mock_distance: mock_distance.return_value = Distance(0, frame) feature_values = self._feature(report)(self._GetMockSuspect()) self.assertEqual(1.0, feature_values['MinDistance'].value)
def testDependencyRolls(self, mock_get_dependency_rolls, mock_stacktrace): """Tests that ``dependency_rolls`` calls GetDependencyRolls.""" crash_data = ChromeCrashData(self.GetDummyChromeCrashData(), None) dep_roll = { 'src/': DependencyRoll('src/', 'https://repo', 'rev0', 'rev3') } mock_get_dependency_rolls.return_value = dep_roll stack = CallStack(0, frame_list=[ StackFrame(0, 'src/', 'func', 'a.cc', 'src/a.cc', [5]) ]) stacktrace = Stacktrace([stack], stack) mock_stacktrace.return_value = stacktrace self.assertEqual(crash_data.dependency_rolls, dep_roll) mock_get_dependency_rolls.assert_called_with( [crash_data.stacktrace.crash_stack])
def testOnlyOneTouchedFilePerMatchedCrashedFile(self): """Test that ``CrashMatch`` can only have 1 touched file.""" report = self._GetDummyReport( deps={'src/': Dependency('src/', 'https://repo', '6')}, dep_rolls={'src/': DependencyRoll('src/', 'https://repo', '0', '4')}) frame = _MOCK_FRAME._replace(file_path='file') crashed = CrashedFile('file') matches = { crashed: CrashMatch(crashed, [FileChangeInfo(ChangeType.MODIFY, 'file', 'file'), FileChangeInfo(ChangeType.MODIFY, 'dummy', 'dummy')], [FrameInfo(frame, 0)]) } self.assertEqual( 0.0, min_distance.MinDistanceFeature(self._get_repository, _MAXIMUM)(report)( self._GetMockSuspect(), matches).value)
def testDependencyRolls(self, mock_get_dependency_rolls, mock_stacktrace): """Tests that ``dependency_rolls``` calls GetDependencyRolls.""" uma_data = self._GetDummyUMAData() dep_roll = { 'src': DependencyRoll('src', 'https://repo', 'rev0', 'rev3') } mock_get_dependency_rolls.return_value = dep_roll stack = stacktrace.CallStack(0, frame_list=[ stacktrace.StackFrame( 0, 'src', 'func', 'a.cc', 'src/a.cc', [5]) ]) stacktrace_field = stacktrace.Stacktrace([stack], stack) mock_stacktrace.return_value = stacktrace_field self.assertEqual(uma_data.dependency_rolls, dep_roll) mock_get_dependency_rolls.assert_called_with( uma_data.stacktrace.stacks)
def testFeatureValueIsOneWhenThereIsMatchedDirectory(self): """Test that feature value is 1 when there is matched directory.""" frame1 = StackFrame(0, 'src/', 'func', 'p/f.cc', 'src/p/f.cc', [2, 3], 'h://repo') stack = CallStack(0, frame_list=[frame1]) stack_trace = Stacktrace([stack], stack) deps = {'src/': Dependency('src/', 'h://repo', '8')} dep_rolls = {'src/': DependencyRoll('src/', 'h://repo', '2', '6')} report = CrashReport('8', 'sig', 'linux', stack_trace, ('2', '6'), deps, dep_rolls) changelog = self.GetDummyChangeLog()._replace(touched_files=[ FileChangeInfo.FromDict({ 'change_type': 'add', 'new_path': 'p/a.cc', 'old_path': None, }) ]) suspect = Suspect(changelog, 'src/') feature_value = self._feature(report)(suspect) self.assertEqual(1.0, feature_value.value)
def testDependencyRolls(self): """Tests ``regression_rolls`` property.""" dep_roll = DependencyRoll('src/', 'https://repo', 'rev1', 'rev6') crash_data = ClusterfuzzData( self.GetDummyClusterfuzzData( dependency_rolls=[{ 'dep_path': dep_roll.path, 'repo_url': dep_roll.repo_url, 'old_revision': dep_roll.old_revision, 'new_revision': dep_roll.new_revision }])) self.assertEqual(len(crash_data.dependency_rolls), 1) self.assertTrue(dep_roll.path in crash_data.dependency_rolls) self.assertEqual(crash_data.dependency_rolls[dep_roll.path].path, dep_roll.path) self.assertEqual(crash_data.dependency_rolls[dep_roll.path].repo_url, dep_roll.repo_url) self.assertEqual( crash_data.dependency_rolls[dep_roll.path].old_revision, dep_roll.old_revision) self.assertEqual( crash_data.dependency_rolls[dep_roll.path].new_revision, dep_roll.new_revision)