def test_stackwalker_fails_2(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() processor_meta = get_basic_processor_meta() mocked_subprocess_handle = mocked_subprocess_module.Popen.return_value # This will cause json.loads to throw an error mocked_subprocess_handle.stdout.read.return_value = '{ff' mocked_subprocess_handle.wait.return_value = -1 rule = BreakpadStackwalkerRule2015(config) rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processed_crash.json_dump == {} assert processed_crash.mdsw_return_code == -1 assert processed_crash.mdsw_status_string == "unknown error" assert not processed_crash.success assert ( config.command_pathname + ' output failed in json: Expecting property name' in processor_meta.processor_notes[0] ) assert ( processor_meta.processor_notes[1] == 'MDSW failed with -1: unknown error' )
def test_subprocess_fail(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 386' processed_crash.cpu_name = 'x86' processed_crash.signature = 'EnterBaseline' processed_crash['json_dump.crashing_thread.frames'] = [ DotDict({'not_module': 'not-a-module'}), DotDict({'module': 'a-module'}) ] processor_meta = get_basic_processor_meta() mocked_subprocess_handle = mocked_subprocess_module.Popen.return_value mocked_subprocess_handle.stdout.read.return_value = None mocked_subprocess_handle.wait.return_value = -1 rule = JitCrashCategorizeRule(config) rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processor_meta.processor_notes == [] assert processed_crash.classifications.jit.category is None assert processed_crash.classifications.jit.category_return_code == -1
def test_stackwalker_fails(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() processor_meta = get_basic_processor_meta() mocked_subprocess_handle = mocked_subprocess_module.Popen.return_value mocked_subprocess_handle.stdout.read.return_value = '{}\n' mocked_subprocess_handle.wait.return_value = 124 with MetricsMock() as mm: rule = BreakpadStackwalkerRule2015(config) rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processed_crash.json_dump == {} assert processed_crash.mdsw_return_code == 124 assert processed_crash.mdsw_status_string == 'unknown error' assert processed_crash.success is False assert processor_meta.processor_notes == ['MDSW timeout (SIGKILL)'] assert mm.has_record( 'incr', stat='processor.breakpadstackwalkerrule.run', value=1, tags=['outcome:fail', 'exitcode:124'] )
def test_everything_we_hoped_for(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() processor_meta = get_basic_processor_meta() mocked_subprocess_handle = mocked_subprocess_module.Popen.return_value mocked_subprocess_handle.stdout.read.return_value = canonical_external_output_str mocked_subprocess_handle.wait.return_value = 0 rule = ExternalProcessRule(config) # the call to be tested rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) mocked_subprocess_module.Popen.assert_called_with( [ 'timeout', '-s', 'KILL', '30', 'bogus_command', 'a_fake_dump.dump', '/mnt/socorro/symbols/symbols_ffx,/mnt/socorro/symbols/symbols_sea,/mnt/socorro/symbols/symbols_tbrd,/mnt/socorro/symbols/symbols_sbrd,/mnt/socorro/symbols/symbols_os' # noqa ], stderr=mocked_subprocess_module.DEVNULL, stdout=mocked_subprocess_module.PIPE ) assert processed_crash.bogus_command_result == canonical_external_output assert processed_crash.bogus_command_return_code == 0
def test_everything_we_hoped_for(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() processor_meta = get_basic_processor_meta() mocked_subprocess_handle = mocked_subprocess_module.Popen.return_value mocked_subprocess_handle.stdout.read.return_value = canonical_stackwalker_output_str mocked_subprocess_handle.wait.return_value = 0 with MetricsMock() as mm: rule = BreakpadStackwalkerRule2015(config) rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processed_crash.json_dump == canonical_stackwalker_output assert processed_crash.mdsw_return_code == 0 assert processed_crash.mdsw_status_string == "OK" assert processed_crash.success is True assert mm.has_record( 'incr', stat='processor.breakpadstackwalkerrule.run', value=1, tags=['outcome:success', 'exitcode:0'] )
def test_hash_not_in_raw_crash(self): config = get_basic_config() raw_crash = DotDict() raw_dumps = {} processed_crash = DotDict() processor_meta = get_basic_processor_meta() rule = MinidumpSha256Rule(config) assert rule.predicate(raw_crash, raw_dumps, processed_crash, processor_meta) is False
def test_everything_we_hoped_for(self): config = get_basic_config() raw_crash = copy.copy(canonical_standard_raw_crash) raw_dumps = {} processed_crash = DotDict() processed_crash.json_dump = copy.copy(canonical_stackwalker_output) processor_meta = get_basic_processor_meta() rule = CrashingThreadRule(config) rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processed_crash.crashedThread == 0
def test_stuff_missing(self): config = get_basic_config() raw_crash = copy.copy(canonical_standard_raw_crash) raw_dumps = {} processed_crash = DotDict() processed_crash.json_dump = {} processor_meta = get_basic_processor_meta() rule = CrashingThreadRule(config) rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processed_crash.crashedThread is None assert processor_meta.processor_notes == ['MDSW did not identify the crashing thread']
def test_uuid_missing(self): config = get_basic_config() raw_crash = {} raw_dumps = {} processed_crash = {} processor_meta = get_basic_processor_meta() rule = IdentifierRule(config) rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) # raw crash and processed crashes should be unchanged assert raw_crash == {} assert processed_crash == {}
def test_hash_in_raw_crash(self): config = get_basic_config() raw_crash = DotDict({ 'MinidumpSha256Hash': 'hash' }) raw_dumps = {} processed_crash = DotDict() processor_meta = get_basic_processor_meta() rule = MinidumpSha256Rule(config) assert rule.predicate(raw_crash, raw_dumps, processed_crash, processor_meta) is True rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processed_crash['minidump_sha256_hash'] == 'hash'
def test_everything_we_hoped_for(self): config = get_basic_config() uuid = '00000000-0000-0000-0000-000002140504' raw_crash = { 'uuid': uuid } raw_dumps = {} processed_crash = {} processor_meta = get_basic_processor_meta() rule = IdentifierRule(config) rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processed_crash['crash_id'] == uuid assert processed_crash['uuid'] == uuid
def test_rule_with_dict(self): raw_crash = { 'key1': 'val1', b'\0key2': b'val2\0', '\0key3': '\0val3' } config = get_basic_config() rule = DeNullRule(config) rule.act(raw_crash, {}, {}, get_basic_processor_meta()) assert raw_crash == { 'key1': 'val1', b'key2': b'val2', 'key3': 'val3' }
def test_stuff_missing(self): config = get_basic_config() raw_crash = {} processed_crash = DotDict() processor_meta = get_basic_processor_meta() rule = OSInfoRule(config) # the call to be tested rule.act(raw_crash, {}, processed_crash, processor_meta) # processed crash should have empties assert processed_crash['os_name'] == 'Unknown' assert processed_crash['os_version'] == '' # raw crash should be unchanged assert raw_crash == {}
def test_rule_with_dotdict(self): # NOTE(willkg): DotDict doesn't like bytes keys raw_crash = DotDict({ 'key1': 'val1', '\0key2': b'val2\0', '\0key3': '\0val3' }) config = get_basic_config() rule = DeNullRule(config) rule.act(raw_crash, {}, {}, get_basic_processor_meta()) assert raw_crash == DotDict({ 'key1': 'val1', 'key2': b'val2', 'key3': 'val3' })
def test_external_fails(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() processor_meta = get_basic_processor_meta() mocked_subprocess_handle = mocked_subprocess_module.Popen.return_value mocked_subprocess_handle.stdout.read.return_value = '{}' mocked_subprocess_handle.wait.return_value = 124 rule = ExternalProcessRule(config) rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processed_crash.bogus_command_result == {} assert processed_crash.bogus_command_return_code == 124 assert processor_meta.processor_notes == []
def test_missing_json_dump(self): config = get_basic_config() raw_crash = {} raw_dumps = {} processed_crash = {} processor_meta = get_basic_processor_meta() rule = CPUInfoRule(config) # the call to be tested rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processed_crash['cpu_info'] == '' assert processed_crash['cpu_name'] == '' # raw crash should be unchanged assert raw_crash == {}
def test_everything_we_hoped_for(self): config = get_basic_config() raw_crash = copy.copy(canonical_standard_raw_crash) raw_dumps = {} processed_crash = copy.copy(canonical_processed_crash) processor_meta = get_basic_processor_meta() rule = CPUInfoRule(config) # the call to be tested rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processed_crash.cpu_name == 'x86' assert processed_crash.cpu_info == 'GenuineIntel family 6 model 42 stepping 7' assert processed_crash.cpu_count == 4 # raw crash should be unchanged assert raw_crash == canonical_standard_raw_crash
def test_external_fails_2(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() processor_meta = get_basic_processor_meta() mocked_subprocess_handle = mocked_subprocess_module.Popen.return_value # This data will fail in json.loads and throw an error mocked_subprocess_handle.stdout.read.return_value = '{ff' mocked_subprocess_handle.wait.return_value = -1 rule = ExternalProcessRule(config) rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processed_crash.bogus_command_result == {} assert processed_crash.bogus_command_return_code == -1 assert ( 'bogus_command output failed in json: Expecting property name' in processor_meta.processor_notes[0] )
def test_everything_we_hoped_for(self): config = get_basic_config() raw_crash = {} processed_crash = DotDict({ 'json_dump': { 'system_info': { 'os': 'Windows NT', 'os_ver': '6.1.7601 Service Pack 1' } } }) processor_meta = get_basic_processor_meta() rule = OSInfoRule(config) # the call to be tested rule.act(raw_crash, {}, processed_crash, processor_meta) assert processed_crash['os_name'] == "Windows NT" assert processed_crash['os_version'] == "6.1.7601 Service Pack 1" # raw crash should be unchanged assert raw_crash == {}
def test_missing_cpu_count(self): config = get_basic_config() raw_crash = copy.copy(canonical_standard_raw_crash) raw_dumps = {} system_info = copy.copy(canonical_processed_crash['json_dump']['system_info']) del system_info['cpu_count'] processed_crash = DotDict() processed_crash.json_dump = { 'system_info': system_info } processor_meta = get_basic_processor_meta() rule = CPUInfoRule(config) # the call to be tested rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processed_crash.cpu_info == 'GenuineIntel family 6 model 42 stepping 7' assert processed_crash.cpu_name == 'x86' # raw crash should be unchanged assert raw_crash == canonical_standard_raw_crash
def test_everything_we_hoped_for(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() processor_meta = get_basic_processor_meta() mocked_subprocess_handle = ( mocked_subprocess_module.Popen.return_value) mocked_subprocess_handle.stdout.read.return_value = ( cannonical_stackwalker_output_str) mocked_subprocess_handle.wait.return_value = 0 rule = BreakpadStackwalkerRule2015(config) # the call to be tested rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processed_crash.json_dump == cannonical_stackwalker_output assert processed_crash.mdsw_return_code == 0 assert processed_crash.mdsw_status_string == "OK" assert processed_crash.success
def test_wrong_signature(self, mocked_subprocess_module): rule = self.build_rule() raw_crash = copy.copy(canonical_standard_raw_crash) raw_dumps = {rule.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 = 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.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_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 = 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) 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_success_all_types_of_signatures(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'} base_processed_crash = DotDict() base_processed_crash.product = 'Firefox' base_processed_crash.os_name = 'Windows 386' base_processed_crash.cpu_name = 'x86' base_processed_crash['json_dump.crashing_thread.frames'] = [ DotDict({'not_module': 'not-a-module'}), DotDict({'module': 'a-module'}) ] processor_meta = 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) signatures = [ 'EnterBaseline', 'moz::something | EnterBaseline', 'EnterIon', 'js::jit::FastInvoke', 'Foo::Bar__js::jit::IonCannon', 'Small | js::irregexp::ExecuteCode<T>', ] for signature in signatures: processed_crash = DotDict(base_processed_crash) processed_crash.signature = signature rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processor_meta.processor_notes == [] assert processed_crash.classifications.jit.category == 'EXTRA-SPECIAL' assert processed_crash.classifications.jit.category_return_code == 0
def test_everything_we_hoped_for(self): raw_crash = {} processed_crash = DotDict( { "json_dump": { "system_info": { "os": "Windows NT", "os_ver": "6.1.7601 Service Pack 1", } } } ) processor_meta = get_basic_processor_meta() rule = OSInfoRule() # the call to be tested rule.act(raw_crash, {}, processed_crash, processor_meta) assert processed_crash["os_name"] == "Windows NT" assert processed_crash["os_version"] == "6.1.7601 Service Pack 1" # raw crash should be unchanged assert raw_crash == {}
def test_subprocess_fail(self, mocked_subprocess_module): rule = self.build_rule() raw_crash = copy.copy(canonical_standard_raw_crash) raw_dumps = {rule.dump_field: 'a_fake_dump.dump'} processed_crash = DotDict() processed_crash.product = 'Firefox' processed_crash.os_name = 'Windows 386' processed_crash.cpu_name = 'x86' processed_crash.signature = 'EnterBaseline' processed_crash['json_dump.crashing_thread.frames'] = [ DotDict({'not_module': 'not-a-module'}), DotDict({'module': 'a-module'}) ] processor_meta = get_basic_processor_meta() mocked_subprocess_handle = mocked_subprocess_module.Popen.return_value mocked_subprocess_handle.stdout.read.return_value = None mocked_subprocess_handle.wait.return_value = -1 rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processor_meta.processor_notes == [] assert processed_crash.classifications.jit.category is None assert processed_crash.classifications.jit.category_return_code == -1
def test_everything_we_hoped_for(self, mocked_subprocess_module): rule = self.build_rule() raw_crash = copy.copy(canonical_standard_raw_crash) raw_dumps = {rule.dump_field: 'a_fake_dump.dump'} processed_crash = DotDict() processor_meta = get_basic_processor_meta() mocked_subprocess_handle = mocked_subprocess_module.Popen.return_value mocked_subprocess_handle.stdout.read.return_value = canonical_stackwalker_output_str mocked_subprocess_handle.wait.return_value = 0 with MetricsMock() as mm: rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processed_crash.json_dump == canonical_stackwalker_output assert processed_crash.mdsw_return_code == 0 assert processed_crash.mdsw_status_string == "OK" assert processed_crash.success is True assert mm.has_record('incr', stat='processor.breakpadstackwalkerrule.run', value=1, tags=['outcome:success', 'exitcode:0'])
def test_stackwalker_fails_2(self, mocked_subprocess_module): rule = self.build_rule() raw_crash = copy.copy(canonical_standard_raw_crash) raw_dumps = {rule.dump_field: 'a_fake_dump.dump'} processed_crash = DotDict() processor_meta = get_basic_processor_meta() mocked_subprocess_handle = mocked_subprocess_module.Popen.return_value # This will cause json.loads to throw an error mocked_subprocess_handle.stdout.read.return_value = '{ff' mocked_subprocess_handle.wait.return_value = -1 rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processed_crash.json_dump == {} assert processed_crash.mdsw_return_code == -1 assert processed_crash.mdsw_status_string == "unknown error" assert not processed_crash.success assert (rule.command_pathname + ' output failed in json: Expecting property name' in processor_meta.processor_notes[0]) assert (processor_meta.processor_notes[1] == 'MDSW failed with -1: unknown error')
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 = 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) 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_stackwalker_fails_2(self, mocked_subprocess_module): rule = self.build_rule() raw_crash = copy.deepcopy(canonical_standard_raw_crash) raw_dumps = {rule.dump_field: "a_fake_dump.dump"} processed_crash = {} processor_meta = get_basic_processor_meta() mocked_subprocess_handle = mocked_subprocess_module.Popen.return_value # This will cause json.loads to throw an error mocked_subprocess_handle.stdout.read.return_value = "{ff" mocked_subprocess_handle.wait.return_value = -1 rule.act(raw_crash, raw_dumps, processed_crash, processor_meta) assert processed_crash["json_dump"] == {} assert processed_crash["mdsw_return_code"] == -1 assert processed_crash["mdsw_status_string"] == "unknown error" assert not processed_crash["success"] assert (rule.command_pathname + " output failed in json: Expecting property name" in processor_meta["processor_notes"][0]) assert (processor_meta["processor_notes"][1] == "MDSW failed with -1: unknown error")