def testStacktraceBool(self): """Tests ``bool`` for ``Stacktrace`` object.""" self.assertFalse(bool(Stacktrace([], None))) frame_list1 = [ StackFrame(0, 'src/', 'func', 'file0.cc', 'src/file0.cc', [32]) ] frame_list2 = [ StackFrame(0, 'src/', 'func2', 'file0.cc', 'src/file0.cc', [32]) ] stack1 = CallStack(0, frame_list1, None, None) stack2 = CallStack(1, frame_list2, None, None) self.assertTrue(bool(Stacktrace((stack1, stack2), stack1)))
def testChromeCrashParserParseLineMultipleCallstacks(self): parser = ChromeCrashParser() deps = {'src/': Dependency('src/', 'https://repo', '1')} stacktrace_string = textwrap.dedent( """ CRASHED [EXC @ 0x66] #0 0x7fee in a::b::c(p* &d) src/f0.cc:177 #1 0x4b6e in a::b::d(a* c) src/f1.cc:227 CRASHED [EXC @ 0x508] #0 0x8fee in e::f::g(p* &d) src/f.cc:20:2 #1 0x1fae in h::i::j(p* &d) src/ff.cc:9:1 """ ) stacktrace = parser.Parse(stacktrace_string, deps) expected_callstack0 = CallStack(0, frame_list=[ StackFrame(0, 'src/', 'a::b::c(p* &d)', 'f0.cc', 'src/f0.cc', [177]), StackFrame(1, 'src/', 'a::b::d(a* c)', 'f1.cc', 'src/f1.cc', [227])]) expected_callstack1 = CallStack(0, frame_list=[ StackFrame( 0, 'src/', 'e::f::g(p* &d)', 'f.cc', 'src/f.cc', [20, 21, 22]), StackFrame( 1, 'src/', 'h::i::j(p* &d)', 'ff.cc', 'src/ff.cc', [9, 10])]) expected_stacktrace = Stacktrace([expected_callstack0, expected_callstack1], expected_callstack0) self._VerifyTwoStacktracesEqual(stacktrace, expected_stacktrace)
def testUpdateInvetedIndexHandlerWithStacktraces(self): """Tests ``UpdateInvertedIndex`` handler when there are stacktraces.""" crash_analysis = FracasCrashAnalysis.Create('sig1') crash_analysis.identifiers = {'signature': 'sig1'} crash_analysis.requested_time = datetime.utcnow() - timedelta(hours=1) frames = [ StackFrame(0, 'src/', 'fun1', 'f1.cc', 'src/f1.cc', [2, 3], 'http://repo'), StackFrame(0, 'src/', 'fun2', 'f2.cc', 'xx/src/f2.cc', [8, 10], 'http://repo'), StackFrame(0, 'src/', 'fun3', 'f3.cc', 'y/src/f3.cc', [20, 30], 'http://repo') ] callstack = CallStack(0, frames) crash_analysis.stacktrace = Stacktrace([callstack], callstack) crash_analysis.put() response = self.test_app.get('/process/update-inverted-index', headers={'X-AppEngine-Cron': 'true'}) self.assertEqual(response.status_int, 200) self.assertEqual(ChromeCrashInvertedIndex.GetRoot().n_of_doc, 1) self.assertEqual(ChromeCrashInvertedIndex.Get('src/f1.cc').n_of_doc, 1) self.assertEqual(ChromeCrashInvertedIndex.Get('src/f2.cc').n_of_doc, 1) self.assertEqual(ChromeCrashInvertedIndex.Get('src/f3.cc').n_of_doc, 1)
def testParseStacktraceReturnsCache(self): """Tests that ``stacktrace`` returns cached ``_stacktrace`` value.""" crash_data = ClusterfuzzData(self.GetDummyClusterfuzzData()) stack = CallStack(1) stacktrace = Stacktrace([stack], stack) crash_data._stacktrace = stacktrace self._VerifyTwoStacktracesEqual(crash_data.stacktrace, stacktrace)
def _GetDummyReport(self, deps=None, dep_rolls=None): crash_stack = CallStack(0, [ StackFrame(0, 'src/', 'func', 'a.cc', 'a.cc', [2], 'https://repo') ]) return CrashReport('rev', 'sig', 'win', Stacktrace([crash_stack], crash_stack), ('rev0', 'rev9'), deps, dep_rolls)
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 testClusterfuzzParserParseStacktrace(self): parser = ClusterfuzzParser() deps = {'src/': Dependency('src/', 'https://repo', '1')} stacktrace_string = textwrap.dedent(""" Blabla... ==1==ERROR: AddressSanitizer: stack-overflow on address 0x7ffec59ebec0 #0 0x7f5b944a37bb in a::aa(p* d) src/a.h:225 #1 0x7f5b9449a880 in b::bb(p* d) src/b.h:266:1 #2 0x7f5b9449a880 in c::cc(p* d) src/c.h:281 """) stacktrace = parser.Parse(stacktrace_string, deps, 'asan_job', SanitizerType.ADDRESS_SANITIZER) stack = CallStack(0, frame_list=[ StackFrame(0, 'src/', 'a::aa(p* d)', 'a.h', 'src/a.h', [225]), StackFrame(1, 'src/', 'b::bb(p* d)', 'b.h', 'src/b.h', [266, 267]), StackFrame(2, 'src/', 'c::cc(p* d)', 'c.h', 'src/c.h', [281]) ]) expected_stacktrace = Stacktrace([stack], stack) self._VerifyTwoStacktracesEqual(stacktrace, expected_stacktrace)
def testToJson(self): """Tests ``ToJson`` method.""" analysis = MockCrashAnalysis() analysis.crashed_version = '50.0.1234.0' analysis.signature = 'sig' analysis.platform = 'win' analysis.stack_trace = 'stack trace' self.assertDictEqual( analysis.ToJson(), { 'signature': analysis.signature, 'platform': analysis.platform, 'stack_trace': analysis.stack_trace, 'client_id': 'mock_client', 'crash_identifiers': 'crash_identifiers' }) frame = StackFrame(0, 'src/', 'func', 'a.cc', 'src/a.cc', [3]) callstack = CallStack(0, [frame]) analysis.stack_trace = None analysis.stacktrace = Stacktrace([callstack], callstack) self.assertDictEqual( analysis.ToJson(), { 'signature': analysis.signature, 'platform': analysis.platform, 'stack_trace': analysis.stacktrace.ToString(), 'client_id': 'mock_client', 'crash_identifiers': 'crash_identifiers' })
def testChromeCrashParserParseLineJavaCallstack(self): parser = ChromeCrashParser() deps = {'src/': Dependency('src/', 'https://repo', '1')} stacktrace_string = textwrap.dedent( """ (JAVA) CRASHED [EXC @ 0x508] #0 0x7fee in a.f0.c f0.java:177 #1 0x4b6e in org.chromium.chrome.browser.a.f1.d f1.java:227 #2 0x7ff9 in a.f2.e f2.java:87:1 """ ) stacktrace = parser.Parse(stacktrace_string, deps) stack = CallStack(0, language_type=LanguageType.JAVA, frame_list=[ StackFrame(0, '', 'a.f0.c', 'a/f0.java', 'a/f0.java', [177]), StackFrame( 1, 'src/', 'org.chromium.chrome.browser.a.f1.d', 'chrome/android/java/src/org/chromium/chrome/browser/a/f1.java', 'src/chrome/android/java/src/org/chromium/chrome/' 'browser/a/f1.java', [227]), StackFrame(2, '', 'a.f2.e', 'a/f2.java', 'a/f2.java', [87, 88])]) expected_stacktrace = Stacktrace([stack], stack) self._VerifyTwoStacktracesEqual(stacktrace, expected_stacktrace)
def testParseStacktraceSucceeded(self): """Tests parsing ``stacktrace``.""" crash_data = ClusterfuzzData(self.GetDummyClusterfuzzData()) stack = CallStack(0) stacktrace = Stacktrace([stack], stack) with mock.patch('analysis.clusterfuzz_parser.ClusterfuzzParser.Parse' ) as mock_parse: mock_parse.return_value = stacktrace self._VerifyTwoStacktracesEqual(crash_data.stacktrace, stacktrace)
def testDoNotIndexFramesWithNoneCrashedGroup(self): """Tests ``IndexFramesWithCrashedGroup`` function.""" frame = StackFrame(0, 'src/', 'func', '', '', [2], 'h://repo') stack = CallStack(0, frame_list=[frame]) stack_trace = Stacktrace([stack], stack) deps = {'src/': Dependency('src/', 'h://repo', 'rev3')} indexed_frame_infos = crash_util.IndexFramesWithCrashedGroup( stack_trace, Factory, deps) self.assertEqual(indexed_frame_infos, {})
def testParseStacktraceSucceeded(self, mock_get_dependency): """Tests parsing ``stacktrace``.""" mock_get_dependency.return_value = {} crash_data = CracasCrashData( self.GetDummyChromeCrashData(), ChromeDependencyFetcher(self.GetMockRepoFactory())) stack = CallStack(0) stacktrace = Stacktrace([stack], stack) with mock.patch('analysis.chromecrash_parser.CracasCrashParser.Parse' ) as mock_parse: mock_parse.return_value = stacktrace self._VerifyTwoStacktracesEqual(crash_data.stacktrace, stacktrace)
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 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 testDependencies(self): """Tests that ``dependencies`` returns filtered ``_CrashedVersionDeps``.""" crash_data = ChromeCrashData(self.GetDummyChromeCrashData(), None) 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.dependencies, {chromium_dep.path: chromium_dep})
def testStacktraceLen(self): """Tests ``len`` for ``Stacktrace`` object.""" frame_list1 = [ StackFrame(0, 'src/', 'func', 'file0.cc', 'src/file0.cc', [32]) ] frame_list2 = [ StackFrame(0, 'src/', 'func2', 'file0.cc', 'src/file0.cc', [32]) ] stack1 = CallStack(0, frame_list1, None, None) stack2 = CallStack(1, frame_list2, None, None) stacktrace = Stacktrace((stack1, stack2), stack1) self.assertEqual(len(stacktrace), 2)
def testDisplayAnanlysisResultWithParsedStactrace(self): analysis = self.analysis frame = StackFrame(0, 'src/', 'func', 'file0.cc', 'src/file0.cc', [32]) stack = CallStack(0, [frame]) stacktrace = Stacktrace([stack], stack) analysis.stacktrace = stacktrace analysis.stack_trace = None expected_result = self._GenerateDisplayData(analysis) response_json = self.test_app.get('/result-feedback?format=json&' 'key=%s' % self.analysis.key.urlsafe()) self.assertEqual(200, response_json.status_int) self.assertEqual(expected_result, response_json.json_body)
def testIndexFramesWithCrashedGroupWhenFrameHasNoDepPath(self): """Tests a bug with ``IndexFramesWithCrashedGroup``. This function would crash when passed a frame with a ``None`` dep path. Instead it should ignore this frame. """ frame = ProfilerStackFrame(0, 0.1, 0.5, True, dep_path=None) stack = CallStack(0, frame_list=[frame]) stack_trace = Stacktrace([stack], stack) deps = {'src': Dependency('src', 'h://repo', 'rev3')} indexed_frame_infos = crash_util.IndexFramesWithCrashedGroup( stack_trace, Factory, deps) self.assertDictEqual(indexed_frame_infos, {})
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 Parse(self, stacktrace_list, deps, signature=None, top_n_frames=None): """Parses a list of stacktrace strings. Note that Cracas sends stacktrace strings from different reports, if they are different, every single stacktrace has the same format as Fracas stacktrace string. So we can use FracasCrashParser as sub parser to parse each string in the list. """ callstacks = [] for stacktrace_str in stacktrace_list: sub_stacktrace = self._sub_parser.Parse(stacktrace_str, deps, signature=signature, top_n_frames=top_n_frames) if sub_stacktrace: callstacks.extend(sub_stacktrace.stacks) return Stacktrace(callstacks, callstacks[0]) if callstacks else None
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 testDependencies(self, mock_get_dependencies, mock_stacktrace): """Tests that ``dependencies`` calls GetDependencies.""" crash_data = ChromeCrashData(self.GetDummyChromeCrashData(), None) crashed_version_deps = { 'src/': Dependency('src/', 'https://repo', 'rev') } mock_get_dependencies.return_value = crashed_version_deps 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.dependencies, crashed_version_deps) mock_get_dependencies.assert_called_with( [crash_data.stacktrace.crash_stack])
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 testIndexFramesWithCrashedGroup(self): """Tests ``IndexFramesWithCrashedGroup`` function.""" frame1 = StackFrame(0, 'src/', 'func', 'f.cc', 'src/f.cc', [2, 3], 'h://repo') frame2 = StackFrame(1, 'src/', 'func', 'a.cc', 'src/a.cc', [31, 32], 'h://repo') frame3 = StackFrame(1, 'src/dummy', 'func', 'a.cc', 'src/dummy/a.cc', [131, 132], 'h://repo') stack = CallStack(0, frame_list=[frame1, frame2, frame3]) stack_trace = Stacktrace([stack], stack) deps = {'src/': Dependency('src/', 'h://repo', 'rev3')} indexed_frame_infos = crash_util.IndexFramesWithCrashedGroup( stack_trace, Factory, deps) expected_frame_infos = { 'src/': { MockCrashedGroup('src/f.cc'): [FrameInfo(frame1, 0)], MockCrashedGroup('src/a.cc'): [FrameInfo(frame2, 0)] } } self.assertEqual(indexed_frame_infos, expected_frame_infos)
def testChromeCrashParserParseLineOneCallstack(self): parser = ChromeCrashParser() deps = {'src/': Dependency('src/', 'https://repo', '1')} stacktrace_string = textwrap.dedent( """ CRASHED [EXC @ 0x508] #0 0x7fee in a::c(p* &d) src/f0.cc:177 #1 0x4b6e in a::d(a* c) src/f1.cc:227 #2 0x7ff9 in a::e(int) src/f2.cc:87:1 """ ) stacktrace = parser.Parse(stacktrace_string, deps) stack = CallStack(0, frame_list=[ StackFrame(0, 'src/', 'a::c(p* &d)', 'f0.cc', 'src/f0.cc', [177]), StackFrame(1, 'src/', 'a::d(a* c)', 'f1.cc', 'src/f1.cc', [227]), StackFrame(2, 'src/', 'a::e(int)', 'f2.cc', 'src/f2.cc', [87, 88])]) expected_stacktrace = Stacktrace([stack], stack) self._VerifyTwoStacktracesEqual(stacktrace, expected_stacktrace)
def testLogFailedToFindSuspectedClsMessage(self, mock_generate_suspects, mock_find_suspects): """Tests logging messages if predator cannot find suspected cls.""" suspect = Suspect(DUMMY_CHANGELOG1, 'src/') mock_generate_suspects.return_value = [suspect, suspect] mock_find_suspects.return_value = [] report = CrashReport(None, None, None, Stacktrace(DUMMY_CALLSTACKS, DUMMY_CALLSTACKS[0]), (None, None), None, None) self.changelist_classifier(report) self.assertIsNone(self.changelist_classifier._log) self.changelist_classifier.SetLog(self.GetMockLog()) self.changelist_classifier(report) self.assertEqual(self.changelist_classifier._log.logs, [{ 'level': 'warning', 'name': 'FailedToFindSuspectedCls', 'message': ('Cannot find any match between cls in ' 'regression range and stacktrace') }])
def testCallWhenThereIsStacktrace(self): """Tests ``__call__`` when there is stacktrace in crash_report.""" file_paths = set(['a.cc', 'b.cc', 'c.cc']) frames = [] for index, file_path in enumerate(file_paths): frames.append( StackFrame(index, 'src/', 'func', file_path, os.path.join('src/', file_path), [index], 'https://repo')) callstacks = [ CallStack(0, frames, CallStackFormatType.DEFAULT, LanguageType.CPP) ] crash_report = CrashReport(None, None, None, Stacktrace(callstacks, callstacks[0]), (None, None), None, None) file_path_extractor = FilePathExtractor() keywords = file_path_extractor(crash_report) expected_keywords = [ os.path.join('src/', file_path) for file_path in file_paths ] self.assertSetEqual(set(keywords.keys()), set(expected_keywords))
def testIncludeRenamedPathsFlag(self): """Tests the ``include_renamed_paths`` flag.""" feature_with_flag = TouchCrashedFileMetaFeature( [TouchCrashedFileFeature()], include_renamed_paths=True) feature_without_flag = TouchCrashedFileMetaFeature( [TouchCrashedFileFeature()], include_renamed_paths=False) deps = {'src/': Dependency('src/', 'https://repo', '6')} # Stack frame in old version of file before it was renamed: stackframe = CallStack(0, [ StackFrame(0, 'src/', 'func', 'old_name.cc', 'old_name.cc', [4], 'https://repo') ]) report = CrashReport('rev', 'sig', 'win', Stacktrace([stackframe], stackframe), ('rev0', 'rev9'), deps, None) feature_values = feature_with_flag(report)(self._GetMockSuspect()) self.assertEqual(1.0, feature_values['TouchCrashedFile'].value) feature_values = feature_without_flag(report)(self._GetMockSuspect()) self.assertEqual(0, feature_values['TouchCrashedFile'].value)
'commit_url': 'https://repo.test/+/3', 'code_review_url': 'https://codereview.chromium.org/3281', 'revision': '3', 'reverted_revision': '0' }) DUMMY_CALLSTACKS = [ CallStack(0, [], CallStackFormatType.DEFAULT, LanguageType.CPP), CallStack(1, [], CallStackFormatType.DEFAULT, LanguageType.CPP) ] DUMMY_REPORT = CrashReport(None, None, None, Stacktrace(DUMMY_CALLSTACKS, DUMMY_CALLSTACKS[0]), (None, None), None, None) class ChangelistClassifierTest(AppengineTestCase): """Tests ``ChangelistClassifier`` class.""" def setUp(self): super(ChangelistClassifierTest, self).setUp() meta_weight = MetaWeight({ 'TouchCrashedFileMeta': MetaWeight({ 'MinDistance': Weight(1.), 'TopFrameIndex': Weight(1.), 'TouchCrashedFile': Weight(1.), }) })