def test_wrong_signature(self, mocked_subprocess_module): config = self.get_basic_config() raw_crash = copy.copy(canonical_standard_raw_crash) raw_dumps = {config.dump_field: 'a_fake_dump.dump'} processed_crash = DotDict() processed_crash.product = 'Firefox' processed_crash.os_name = 'Windows NT' processed_crash.cpu_name = 'x86' processed_crash.signature = 'this-is-not-a-JIT-signature' processed_crash['json_dump.crashing_thread.frames'] = [ DotDict({'not_module': 'not-a-module',}), DotDict({'module': 'a-module',}) ] processor_meta = self.get_basic_processor_meta() mocked_subprocess_handle = ( mocked_subprocess_module.Popen.return_value ) mocked_subprocess_handle.stdout.read.return_value = ( 'EXTRA-SPECIAL' ) mocked_subprocess_handle.wait.return_value = 0 rule = JitCrashCategorizeRule(config) # the call to be tested rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) ok_('classifications.jit.category' not in processed_crash) ok_('classifications.jit.category_return_code' not in processed_crash)
def test_module_on_stack_top(self, mocked_subprocess_module): config = self.get_basic_config() raw_crash = copy.copy(canonical_standard_raw_crash) raw_dumps = {config.dump_field: 'a_fake_dump.dump'} processed_crash = DotDict() processed_crash.product = 'Firefox' processed_crash.os_name = 'Windows NT' processed_crash.cpu_name = 'x86' processed_crash.signature = 'EnterBaseline' processed_crash['json_dump.crashing_thread.frames'] = [ DotDict({'module': 'a-module'}), DotDict({'not_module': 'not-a-module'}), ] processor_meta = self.get_basic_processor_meta() mocked_subprocess_handle = ( mocked_subprocess_module.Popen.return_value) mocked_subprocess_handle.stdout.read.return_value = ('EXTRA-SPECIAL') mocked_subprocess_handle.wait.return_value = 0 rule = JitCrashCategorizeRule(config) # the call to be tested rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert 'classifications.jit.category' not in processed_crash assert 'classifications.jit.category_return_code' not in processed_crash
def test_no_crashing_thread(self, mocked_subprocess_module): config = self.get_basic_config() raw_crash = copy.copy(canonical_standard_raw_crash) raw_dumps = {config.dump_field: 'a_fake_dump.dump'} processed_crash = DotDict() processed_crash.product = 'Firefox' processed_crash.os_name = 'Windows NT' processed_crash.cpu_name = 'x86' processed_crash.signature = 'EnterBaseline' processed_crash['json_dump'] = {} # note the empty json_dump processor_meta = self.get_basic_processor_meta() mocked_subprocess_handle = ( mocked_subprocess_module.Popen.return_value) mocked_subprocess_handle.stdout.read.return_value = ('EXTRA-SPECIAL') mocked_subprocess_handle.wait.return_value = 0 rule = JitCrashCategorizeRule(config) # the call to be tested res = rule._predicate(raw_crash, raw_dumps, processed_crash, processor_meta) # Simply verify that no exception is raised. ok_(res)
def test_no_crashing_thread(self, mocked_subprocess_module): config = self.get_basic_config() raw_crash = copy.copy(canonical_standard_raw_crash) raw_dumps = {config.dump_field: 'a_fake_dump.dump'} processed_crash = DotDict() processed_crash.product = 'Firefox' processed_crash.os_name = 'Windows NT' processed_crash.cpu_name = 'x86' processed_crash.signature = 'EnterBaseline' processed_crash['json_dump'] = {} # note the empty json_dump processor_meta = self.get_basic_processor_meta() mocked_subprocess_handle = ( mocked_subprocess_module.Popen.return_value ) mocked_subprocess_handle.stdout.read.return_value = ( 'EXTRA-SPECIAL' ) mocked_subprocess_handle.wait.return_value = 0 rule = JitCrashCategorizeRule(config) # the call to be tested res = rule._predicate( raw_crash, raw_dumps, processed_crash, processor_meta ) # Simply verify that no exception is raised. ok_(res)
def _analyze_header(self, crash_id, dump_analysis_line_iterator, submitted_timestamp, processor_notes): """ Scan through the lines of the dump header: - extract data to update the record for this crash in 'reports', including the id of the crashing thread Returns: Dictionary of the various values that were updated in the database Input parameters: - dump_analysis_line_iterator - an iterator object that feeds lines from crash dump data - submitted_timestamp - processor_notes """ crashed_thread = None processed_crash_update = DotDict() # minimal update requirements processed_crash_update.success = True processed_crash_update.os_name = None processed_crash_update.os_version = None processed_crash_update.cpu_name = None processed_crash_update.cpu_info = None processed_crash_update.reason = None processed_crash_update.address = None header_lines_were_found = False flash_version = None for line in dump_analysis_line_iterator: line = line.strip() # empty line separates header data from thread data if line == '': break header_lines_were_found = True values = map(lambda x: x.strip(), line.split('|')) if len(values) < 3: processor_notes.append('Cannot parse header line "%s"' % line) continue values = map(emptyFilter, values) if values[0] == 'OS': name = self._truncate_or_none(values[1], 100) version = self._truncate_or_none(values[2], 100) processed_crash_update.os_name = name processed_crash_update.os_version = version elif values[0] == 'CPU': processed_crash_update.cpu_name = \ self._truncate_or_none(values[1], 100) processed_crash_update.cpu_info = \ self._truncate_or_none(values[2], 100) try: processed_crash_update.cpu_info = ('%s | %s' % ( processed_crash_update.cpu_info, self._get_truncate_or_none(values[3], 100) )) except IndexError: pass elif values[0] == 'Crash': processed_crash_update.reason = \ self._truncate_or_none(values[1], 255) try: processed_crash_update.address = \ self._truncate_or_none(values[2], 20) except IndexError: processed_crash_update.address = None try: crashed_thread = int(values[3]) except Exception: crashed_thread = None elif values[0] == 'Module': # grab only the flash version, which is not quite as easy as # it looks if not flash_version: flash_version = self._get_flash_version(values) if not header_lines_were_found: message = "%s returned no header lines for crash_id: %s" % \ (self.config.minidump_stackwalk_pathname, crash_id) processor_notes.append(message) #self.config.logger.warning("%s", message) if crashed_thread is None: message = "No thread was identified as the cause of the crash" processor_notes.append(message) self.config.logger.info("%s", message) processed_crash_update.crashedThread = crashed_thread if not flash_version: flash_version = '[blank]' processed_crash_update.flash_version = flash_version #self.config.logger.debug( # " updated values %s", # processed_crash_update #) return processed_crash_update
def _analyze_header(self, crash_id, dump_analysis_line_iterator, submitted_timestamp, processor_notes): """ Scan through the lines of the dump header: - extract data to update the record for this crash in 'reports', including the id of the crashing thread Returns: Dictionary of the various values that were updated in the database Input parameters: - dump_analysis_line_iterator - an iterator object that feeds lines from crash dump data - submitted_timestamp - processor_notes """ crashed_thread = None processed_crash_update = DotDict() # minimal update requirements processed_crash_update.success = True processed_crash_update.os_name = None processed_crash_update.os_version = None processed_crash_update.cpu_name = None processed_crash_update.cpu_info = None processed_crash_update.reason = None processed_crash_update.address = None header_lines_were_found = False flash_version = None for line in dump_analysis_line_iterator: line = line.strip() # empty line separates header data from thread data if line == '': break header_lines_were_found = True values = map(lambda x: x.strip(), line.split('|')) if len(values) < 3: processor_notes.append('Cannot parse header line "%s"' % line) continue values = map(emptyFilter, values) if values[0] == 'OS': name = self._truncate_or_none(values[1], 100) version = self._truncate_or_none(values[2], 100) processed_crash_update.os_name = name processed_crash_update.os_version = version elif values[0] == 'CPU': processed_crash_update.cpu_name = \ self._truncate_or_none(values[1], 100) processed_crash_update.cpu_info = \ self._truncate_or_none(values[2], 100) try: processed_crash_update.cpu_info = ( '%s | %s' % (processed_crash_update.cpu_info, self._get_truncate_or_none(values[3], 100))) except IndexError: pass elif values[0] == 'Crash': processed_crash_update.reason = \ self._truncate_or_none(values[1], 255) try: processed_crash_update.address = \ self._truncate_or_none(values[2], 20) except IndexError: processed_crash_update.address = None try: crashed_thread = int(values[3]) except Exception: crashed_thread = None elif values[0] == 'Module': # grab only the flash version, which is not quite as easy as # it looks if not flash_version: flash_version = self._get_flash_version(values) if not header_lines_were_found: message = "%s returned no header lines for crash_id: %s" % \ (self.config.minidump_stackwalk_pathname, crash_id) processor_notes.append(message) #self.config.logger.warning("%s", message) if crashed_thread is None: message = "No thread was identified as the cause of the crash" processor_notes.append(message) self.config.logger.info("%s", message) processed_crash_update.crashedThread = crashed_thread if not flash_version: flash_version = '[blank]' processed_crash_update.flash_version = flash_version #self.config.logger.debug( # " updated values %s", # processed_crash_update #) return processed_crash_update