def test_temp_raw_crash_json_file(self): config = setup_config_with_mocks() processor = HybridCrashProcessor(config) with mock.patch( 'socorro.processor.hybrid_processor.os.unlink' ) as mocked_unlink: with processor._temp_raw_crash_json_file( {'fake': 'raw_crash'}, 'fake_crash_id' ): pass mocked_unlink.assert_called_once_with( '/tmp/fake_crash_id.MainThread.TEMPORARY.json' ) mocked_unlink.reset_mock() try: with processor._temp_raw_crash_json_file( {'fake': 'raw_crash'}, 'fake_crash_id' ): raise KeyError('oops') except KeyError: pass mocked_unlink.assert_called_once_with( '/tmp/fake_crash_id.MainThread.TEMPORARY.json' ) mocked_unlink.reset_mock()
def test_temp_file_context(self): config = setup_config_with_mocks() processor = HybridCrashProcessor(config) with mock.patch( 'socorro.processor.hybrid_processor.os.unlink' ) as mocked_unlink: with processor._temp_file_context('foo.TEMPORARY.txt'): pass mocked_unlink.assert_called_once_with('foo.TEMPORARY.txt') mocked_unlink.reset_mock() with processor._temp_file_context('foo.txt'): pass self.assertEqual(mocked_unlink.call_count, 0) mocked_unlink.reset_mock() try: with processor._temp_file_context('foo.TEMPORARY.txt'): raise KeyError('oops') except KeyError: pass mocked_unlink.assert_called_once_with('foo.TEMPORARY.txt') mocked_unlink.reset_mock() try: with processor._temp_file_context('foo.txt'): raise KeyError('oops') except KeyError: pass self.assertEqual(mocked_unlink.call_count, 0)
def test_create_pipe_dump_entry(self): # case where there are line feeds on the end of the lines t1 = [ 'a\n', 'b\n', 'c\n', '\n', 'e\n', 'f\n', ] self.assertEqual( 'a\nb\nc\n\ne\nf\n', HybridCrashProcessor._create_pipe_dump_entry(t1) ) # case where there are no line feeds on the end of the lines t2 = [ 'a', 'b', 'c', '', 'e', 'f', ] self.assertEqual( 'a\nb\nc\n\ne\nf\n', HybridCrashProcessor._create_pipe_dump_entry(t2) )
def test_process_list_of_addons(self): config = setup_config_with_mocks() config.collect_addon = False config.collect_crash_process = False mocked_transform_rules_str = \ 'socorro.processor.hybrid_processor.TransformRuleSystem' with mock.patch(mocked_transform_rules_str) as m_transform_class: m_transform = mock.Mock() m_transform_class.return_value = m_transform m_transform.attach_mock(mock.Mock(), 'apply_all_rules') utc_now_str = 'socorro.processor.hybrid_processor.utc_now' with mock.patch(utc_now_str) as m_utc_now: m_utc_now.return_value = datetime(2012, 5, 4, 15, 11, tzinfo=UTC) leg_proc = HybridCrashProcessor(config, config.mock_quit_fn) # test successful case raw_crash = canonical_standard_raw_crash processor_notes = [] addon_list = leg_proc._process_list_of_addons( raw_crash, processor_notes ) expected_addon_list = [ ('*****@*****.**', '0.3'), ('*****@*****.**', '1,4.8'), ('*****@*****.**', '1.9.1'), ('*****@*****.**', '2.4'), ('*****@*****.**', '1.0'), ('*****@*****.**', '2.1'), ('{a0d7ccb3-214d-498b-b4aa-0e8fda9a7bf7}', '20111107'), ('{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d}', '2.0.3'), ('*****@*****.**', '2.4.6.4'), ('{972ce4c6-7e08-4474-a285-3208198ce6fd}', '12.0'), ('*****@*****.**', '1.2.1') ] self.assertEqual(addon_list, expected_addon_list) # test colon in version case raw_crash = copy.copy(canonical_standard_raw_crash) raw_crash['Add-ons'] = '[email protected]:0:3:1' processor_notes = [] addon_list = leg_proc._process_list_of_addons( raw_crash, processor_notes ) expected_addon_list = [ ('*****@*****.**', '0:3:1'), ] self.assertEqual(addon_list, expected_addon_list) leg_proc._statistics.assert_has_calls( [ mock.call.incr('restarts'), ], any_order=True )
def test_process_list_of_addons(self): config = setup_config_with_mocks() config.collect_addon = False config.collect_crash_process = False mocked_transform_rules_str = \ 'socorro.processor.hybrid_processor.TransformRuleSystem' with mock.patch(mocked_transform_rules_str) as m_transform_class: m_transform = mock.Mock() m_transform_class.return_value = m_transform m_transform.attach_mock(mock.Mock(), 'apply_all_rules') utc_now_str = 'socorro.processor.hybrid_processor.utc_now' with mock.patch(utc_now_str) as m_utc_now: m_utc_now.return_value = datetime(2012, 5, 4, 15, 11, tzinfo=UTC) leg_proc = HybridCrashProcessor(config, config.mock_quit_fn) # test successful case raw_crash = canonical_standard_raw_crash processor_notes = [] addon_list = leg_proc._process_list_of_addons( raw_crash, processor_notes) expected_addon_list = [ ('*****@*****.**', '0.3'), ('*****@*****.**', '1,4.8'), ('*****@*****.**', '1.9.1'), ('*****@*****.**', '2.4'), ('*****@*****.**', '1.0'), ('*****@*****.**', '2.1'), ('{a0d7ccb3-214d-498b-b4aa-0e8fda9a7bf7}', '20111107'), ('{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d}', '2.0.3'), ('*****@*****.**', '2.4.6.4'), ('{972ce4c6-7e08-4474-a285-3208198ce6fd}', '12.0'), ('*****@*****.**', '1.2.1') ] self.assertEqual(addon_list, expected_addon_list) # test colon in version case raw_crash = copy.copy(canonical_standard_raw_crash) raw_crash['Add-ons'] = '[email protected]:0:3:1' processor_notes = [] addon_list = leg_proc._process_list_of_addons( raw_crash, processor_notes) expected_addon_list = [ ('*****@*****.**', '0:3:1'), ] self.assertEqual(addon_list, expected_addon_list) leg_proc._statistics.assert_has_calls([ mock.call.incr('restarts'), ], any_order=True)
def test_temp_raw_crash_json_file(self): config = setup_config_with_mocks() processor = HybridCrashProcessor(config) with mock.patch('socorro.processor.hybrid_processor.os.unlink' ) as mocked_unlink: with processor._temp_raw_crash_json_file({'fake': 'raw_crash'}, 'fake_crash_id'): pass mocked_unlink.assert_called_once_with( '/tmp/fake_crash_id.MainThread.TEMPORARY.json') mocked_unlink.reset_mock() try: with processor._temp_raw_crash_json_file({'fake': 'raw_crash'}, 'fake_crash_id'): raise KeyError('oops') except KeyError: pass mocked_unlink.assert_called_once_with( '/tmp/fake_crash_id.MainThread.TEMPORARY.json') mocked_unlink.reset_mock()
def test_temp_file_context(self): config = setup_config_with_mocks() processor = HybridCrashProcessor(config) with mock.patch('socorro.processor.hybrid_processor.os.unlink' ) as mocked_unlink: with processor._temp_file_context('foo.TEMPORARY.txt'): pass mocked_unlink.assert_called_once_with('foo.TEMPORARY.txt') mocked_unlink.reset_mock() with processor._temp_file_context('foo.txt'): pass self.assertEqual(mocked_unlink.call_count, 0) mocked_unlink.reset_mock() try: with processor._temp_file_context('foo.TEMPORARY.txt'): raise KeyError('oops') except KeyError: pass mocked_unlink.assert_called_once_with('foo.TEMPORARY.txt') mocked_unlink.reset_mock() try: with processor._temp_file_context('foo.txt'): raise KeyError('oops') except KeyError: pass self.assertEqual(mocked_unlink.call_count, 0)
def test_hybrid_processor_basics(self): config = setup_config_with_mocks() mocked_transform_rules_str = \ 'socorro.processor.hybrid_processor.TransformRuleSystem' with mock.patch(mocked_transform_rules_str) as m_transform: leg_proc = HybridCrashProcessor(config, config.mock_quit_fn) self.assertEqual(leg_proc.quit_check, config.mock_quit_fn) self.assertEqual(config.transaction, leg_proc.transaction) self.assertEqual(config.database, leg_proc.database) self.assertEqual( leg_proc.mdsw_command_line, '/bin/mdsw -m DUMPFILEPATHNAME "/a/a" "/b/b" "/c/c" 2>/dev/null' ) self.assertEqual(m_transform.call_count, 3)
def test_create_pipe_dump_entry(self): # case where there are line feeds on the end of the lines t1 = [ 'a\n', 'b\n', 'c\n', '\n', 'e\n', 'f\n', ] self.assertEqual('a\nb\nc\n\ne\nf\n', HybridCrashProcessor._create_pipe_dump_entry(t1)) # case where there are no line feeds on the end of the lines t2 = [ 'a', 'b', 'c', '', 'e', 'f', ] self.assertEqual('a\nb\nc\n\ne\nf\n', HybridCrashProcessor._create_pipe_dump_entry(t2))
def test_convert_raw_crash_to_processed_crash_basic(self): config = setup_config_with_mocks() mocked_transform_rules_str = \ 'socorro.processor.hybrid_processor.TransformRuleSystem' with mock.patch(mocked_transform_rules_str) as m_transform_class: m_transform = mock.Mock() m_transform_class.return_value = m_transform m_transform.attach_mock(mock.Mock(), 'apply_all_rules') utc_now_str = 'socorro.processor.hybrid_processor.utc_now' with mock.patch(utc_now_str) as m_utc_now: m_utc_now.return_value = datetime(2012, 5, 4, 15, 11, tzinfo=UTC) raw_crash = DotDict() raw_crash.uuid = '3bc4bcaa-b61d-4d1f-85ae-30cb32120504' raw_crash.submitted_timestamp = '2012-05-04T15:33:33' raw_dump = { 'upload_file_minidump': '/some/path/%s.dump' % raw_crash.uuid, 'aux_dump_001': '/some/path/aux_001.%s.dump' % raw_crash.uuid, } leg_proc = HybridCrashProcessor(config, config.mock_quit_fn) started_timestamp = datetime(2012, 5, 4, 15, 10, tzinfo=UTC) leg_proc._log_job_start = mock.Mock( return_value=started_timestamp) basic_processed_crash = DotDict() basic_processed_crash.uuid = raw_crash.uuid basic_processed_crash.hang_type = 0 basic_processed_crash.java_stack_trace = None leg_proc._create_basic_processed_crash = mock.Mock( return_value=basic_processed_crash) leg_proc._log_job_end = mock.Mock() processed_crash_update_dict = DotDict() processed_crash_update_dict.success = True leg_proc._do_breakpad_stack_dump_analysis = mock.Mock( return_value=processed_crash_update_dict) leg_proc._cleanup_temp_file = mock.Mock() # Here's the call being tested processed_crash = \ leg_proc.convert_raw_crash_to_processed_crash( raw_crash, raw_dump ) # test the result self.assertEqual(1, leg_proc._log_job_start.call_count) leg_proc._log_job_start.assert_called_with(raw_crash.uuid) self.assertEqual(1, m_transform.apply_all_rules.call_count) m_transform.apply_all_rules.has_calls( mock.call(raw_crash, leg_proc), ) self.assertEqual( 2, m_transform.apply_until_action_succeeds.call_count) m_transform.apply_all_rules.has_calls( mock.call(raw_crash, processed_crash, leg_proc)) self.assertEqual( 1, leg_proc._create_basic_processed_crash.call_count) leg_proc._create_basic_processed_crash.assert_called_with( raw_crash.uuid, raw_crash, datetime(2012, 5, 4, 15, 33, 33, tzinfo=UTC), started_timestamp, ['testing_processor:2012', 'HybridCrashProcessor']) self.assertEqual( 2, leg_proc._do_breakpad_stack_dump_analysis.call_count) first_call, second_call = \ leg_proc._do_breakpad_stack_dump_analysis.call_args_list self.assertEqual( first_call, ((raw_crash.uuid, '/some/path/%s.dump' % raw_crash.uuid, 0, None, datetime(2012, 5, 4, 15, 33, 33, tzinfo=UTC), ['testing_processor:2012', 'HybridCrashProcessor']), )) self.assertEqual( second_call, ((raw_crash.uuid, '/some/path/aux_001.%s.dump' % raw_crash.uuid, 0, None, datetime(2012, 5, 4, 15, 33, 33, tzinfo=UTC), ['testing_processor:2012', 'HybridCrashProcessor']), )) self.assertEqual(1, leg_proc._log_job_end.call_count) leg_proc._log_job_end.assert_called_with( datetime(2012, 5, 4, 15, 11, tzinfo=UTC), True, raw_crash.uuid) epc = DotDict() epc.uuid = raw_crash.uuid epc.topmost_filenames = '' epc.processor_notes = \ "testing_processor:2012; HybridCrashProcessor" epc.success = True epc.completeddatetime = datetime(2012, 5, 4, 15, 11, tzinfo=UTC) epc.hang_type = 0 epc.java_stack_trace = None epc.Winsock_LSP = None epc.additional_minidumps = ['aux_dump_001'] epc.aux_dump_001 = {'success': True} self.assertEqual(processed_crash, dict(epc)) leg_proc._statistics.assert_has_calls( [mock.call.incr('jobs'), mock.call.incr('restarts')], any_order=True)
def test_analyze_header(self): # verify fix for Bug 881623 in test one """test some of the possibilities in reading the first three lines from MDSW. This does not provide comprehensive coverage.""" config = setup_config_with_mocks() config.collect_addon = False config.collect_crash_process = True mocked_transform_rules_str = \ 'socorro.processor.hybrid_processor.TransformRuleSystem' with mock.patch(mocked_transform_rules_str) as m_transform_class: m_transform = mock.Mock() m_transform_class.return_value = m_transform m_transform.attach_mock(mock.Mock(), 'apply_all_rules') utc_now_str = 'socorro.processor.hybrid_processor.utc_now' with mock.patch(utc_now_str) as m_utc_now: m_utc_now.return_value = datetime(2012, 5, 4, 15, 11, tzinfo=UTC) leg_proc = HybridCrashProcessor(config, config.mock_quit_fn) # test one - all ok def dump_iter(): lines = [ 'OS|Windows NT|6.1.7601 Service Pack 1 ', 'CPU|x86|GenuineIntel family 6 model 42 stepping 7|8', 'Crash|EXCEPTION_ACCESS_VIOLATION_READ|0xffffffffdadadada|0' ] for a_line in lines: yield a_line processor_notes = [] result = leg_proc._analyze_header( '1fcdec5e-face-404a-8622-babda2130605', dump_iter(), m_utc_now(), processor_notes) self.assertTrue(result.success) self.assertEqual(result.os_name, 'Windows NT') self.assertEqual(result.os_version, '6.1.7601 Service Pack 1') self.assertEqual(result.cpu_name, 'x86') self.assertEqual( result.cpu_info, 'GenuineIntel family 6 model 42 stepping 7 | 8') self.assertEqual(result.reason, 'EXCEPTION_ACCESS_VIOLATION_READ') self.assertEqual(result.address, '0xffffffffdadadada') self.assertEqual(result.crashedThread, 0) # test two - crashed thread missing def dump_iter(): lines = [ 'OS|Windows NT|6.1.7601 Service Pack 1 ', 'CPU|x86|GenuineIntel family 6 model 42 stepping 7|8', 'Crash|EXCEPTION_ACCESS_VIOLATION_READ|0xffffffffdadadada|' ] for a_line in lines: yield a_line processor_notes = [] result = leg_proc._analyze_header( '1fcdec5e-face-404a-8622-babda2130605', dump_iter(), m_utc_now(), processor_notes) self.assertTrue(result.success) self.assertEqual(result.os_name, 'Windows NT') self.assertEqual(result.os_version, '6.1.7601 Service Pack 1') self.assertEqual(result.cpu_name, 'x86') self.assertEqual( result.cpu_info, 'GenuineIntel family 6 model 42 stepping 7 | 8') self.assertEqual(result.reason, 'EXCEPTION_ACCESS_VIOLATION_READ') self.assertEqual(result.address, '0xffffffffdadadada') self.assertEqual(result.crashedThread, None) self.assertTrue('MDSW did not identify the crashing thread' in processor_notes) # test three - no lines def dump_iter(): for a_line in []: yield a_line processor_notes = [] result = leg_proc._analyze_header( '1fcdec5e-face-404a-8622-babda2130605', dump_iter(), m_utc_now(), processor_notes) self.assertTrue(result.success) self.assertEqual(result.os_name, None) self.assertEqual(result.os_version, None) self.assertEqual(result.cpu_name, None) self.assertEqual(result.cpu_info, None) self.assertEqual(result.reason, None) self.assertEqual(result.address, None) self.assertEqual(result.crashedThread, None) self.assertTrue('MDSW did not identify the crashing thread' in processor_notes) self.assertTrue( 'MDSW emitted no header lines' in processor_notes)
def test_create_basic_processed_crash_normal(self): config = setup_config_with_mocks() config.collect_addon = False config.collect_crash_process = False mocked_transform_rules_str = \ 'socorro.processor.hybrid_processor.TransformRuleSystem' with mock.patch(mocked_transform_rules_str) as m_transform_class: m_transform = mock.Mock() m_transform_class.return_value = m_transform m_transform.attach_mock(mock.Mock(), 'apply_all_rules') utc_now_str = 'socorro.processor.hybrid_processor.utc_now' with mock.patch(utc_now_str) as m_utc_now: m_utc_now.return_value = datetime(2012, 5, 4, 15, 11, tzinfo=UTC) started_timestamp = datetime(2012, 5, 4, 15, 10, tzinfo=UTC) raw_crash = canonical_standard_raw_crash leg_proc = HybridCrashProcessor(config, config.mock_quit_fn) processor_notes = [] # test 01 processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', raw_crash, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) assert 'exploitability' in processed_crash self.assertEqual( processed_crash, dict(cannonical_basic_processed_crash) ) # test 02 processor_notes = [] raw_crash_missing_product = copy.deepcopy(raw_crash) del raw_crash_missing_product['ProductName'] processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', raw_crash_missing_product, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) processed_crash_missing_product = \ copy.copy(cannonical_basic_processed_crash) processed_crash_missing_product.product = None self.assertEqual( processed_crash, processed_crash_missing_product ) self.assertTrue('WARNING: raw_crash missing ProductName' in processor_notes) self.assertEqual(len(processor_notes), 1) # test 03 processor_notes = [] raw_crash_missing_version = copy.deepcopy(raw_crash) del raw_crash_missing_version['Version'] processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', raw_crash_missing_version, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) processed_crash_missing_version = \ copy.copy(cannonical_basic_processed_crash) processed_crash_missing_version.version = None self.assertEqual( processed_crash, processed_crash_missing_version ) self.assertTrue('WARNING: raw_crash missing Version' in processor_notes) self.assertEqual(len(processor_notes), 1) # test 04 processor_notes = [] raw_crash_with_hangid = copy.deepcopy(raw_crash) raw_crash_with_hangid.HangID = \ '30cb3212-b61d-4d1f-85ae-3bc4bcaa0504' processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', raw_crash_with_hangid, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) processed_crash_with_hangid = \ copy.copy(cannonical_basic_processed_crash) processed_crash_with_hangid.hangid = \ raw_crash_with_hangid.HangID processed_crash_with_hangid.hang_type = -1 self.assertEqual( processed_crash, processed_crash_with_hangid ) self.assertEqual(len(processor_notes), 0) # test 05 processor_notes = [] raw_crash_with_pluginhang = copy.deepcopy(raw_crash) raw_crash_with_pluginhang.PluginHang = '1' processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', raw_crash_with_pluginhang, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) processed_crash_with_pluginhang = \ copy.copy(cannonical_basic_processed_crash) processed_crash_with_pluginhang.hangid = \ 'fake-3bc4bcaa-b61d-4d1f-85ae-30cb32120504' processed_crash_with_pluginhang.hang_type = -1 self.assertEqual( processed_crash, processed_crash_with_pluginhang ) self.assertEqual(len(processor_notes), 0) # test 06 processor_notes = [] raw_crash_with_hang_only = copy.deepcopy(raw_crash) raw_crash_with_hang_only.Hang = 16 processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', raw_crash_with_hang_only, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) processed_crash_with_hang_only = \ copy.copy(cannonical_basic_processed_crash) processed_crash_with_hang_only.hang_type = 1 self.assertEqual( processed_crash, processed_crash_with_hang_only ) self.assertEqual(len(processor_notes), 0) leg_proc._statistics.assert_has_calls( [ mock.call.incr('restarts'), ], any_order=True ) # test 07 processor_notes = [] raw_crash_with_hang_only = copy.deepcopy(raw_crash) raw_crash_with_hang_only.Hang = 'bad value' processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', raw_crash_with_hang_only, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) processed_crash_with_hang_only = \ copy.copy(cannonical_basic_processed_crash) processed_crash_with_hang_only.hang_type = 0 self.assertEqual( processed_crash, processed_crash_with_hang_only ) self.assertEqual(len(processor_notes), 0) leg_proc._statistics.assert_has_calls( [ mock.call.incr('restarts'), ], any_order=True ) # test 08 processor_notes = [] bad_raw_crash = copy.deepcopy(raw_crash) bad_raw_crash['SecondsSinceLastCrash'] = 'badness' processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', bad_raw_crash, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) self.assertEqual(processed_crash.last_crash, None) self.assertTrue( 'non-integer value of "SecondsSinceLastCrash"' in processor_notes ) # test 09 processor_notes = [] bad_raw_crash = copy.deepcopy(raw_crash) bad_raw_crash['CrashTime'] = 'badness' processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', bad_raw_crash, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) self.assertEqual(processed_crash.crash_time, 0) self.assertTrue( 'non-integer value of "CrashTime"' in processor_notes ) # test 10 processor_notes = [] bad_raw_crash = copy.deepcopy(raw_crash) bad_raw_crash['StartupTime'] = 'badness' bad_raw_crash['InstallTime'] = 'more badness' bad_raw_crash['CrashTime'] = 'even more badness' processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', bad_raw_crash, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) self.assertEqual(processed_crash.install_age, 0) self.assertTrue( 'non-integer value of "StartupTime"' in processor_notes ) self.assertTrue( 'non-integer value of "InstallTime"' in processor_notes ) self.assertTrue( 'non-integer value of "CrashTime"' in processor_notes )
def test_convert_raw_crash_to_processed_crash_unexpected_error(self): config = setup_config_with_mocks() mocked_transform_rules_str = \ 'socorro.processor.hybrid_processor.TransformRuleSystem' with mock.patch(mocked_transform_rules_str) as m_transform_class: m_transform = mock.Mock() m_transform_class.return_value = m_transform m_transform.attach_mock(mock.Mock(), 'apply_all_rules') utc_now_str = 'socorro.processor.hybrid_processor.utc_now' with mock.patch(utc_now_str) as m_utc_now: m_utc_now.return_value = datetime(2012, 5, 4, 15, 11, tzinfo=UTC) raw_crash = DotDict() raw_crash.uuid = '3bc4bcaa-b61d-4d1f-85ae-30cb32120504' raw_crash.submitted_timestamp = '2012-05-04T15:33:33' raw_dump = {'upload_file_minidump': 'abcdef'} leg_proc = HybridCrashProcessor(config, config.mock_quit_fn) started_timestamp = datetime(2012, 5, 4, 15, 10, tzinfo=UTC) leg_proc._log_job_start = mock.Mock( return_value=started_timestamp ) basic_processed_crash = DotDict() basic_processed_crash.uuid = raw_crash.uuid basic_processed_crash.success = False basic_processed_crash.hang_type = 0 basic_processed_crash.java_stack_trace = None leg_proc._create_basic_processed_crash = mock.Mock( return_value=basic_processed_crash) leg_proc._get_temp_dump_pathname = mock.Mock( return_value='/tmp/x' ) leg_proc._log_job_end = mock.Mock() processed_crash_update_dict = DotDict() processed_crash_update_dict.success = True leg_proc._do_breakpad_stack_dump_analysis = mock.Mock( side_effect=Exception('nobody expects the spanish ' 'inquisition') ) # Here's the call being tested processed_crash = \ leg_proc.convert_raw_crash_to_processed_crash( raw_crash, raw_dump ) self.assertEqual(1, leg_proc._log_job_end.call_count) leg_proc._log_job_end.assert_called_with( datetime(2012, 5, 4, 15, 11, tzinfo=UTC), False, raw_crash.uuid ) e = { 'processor_notes': 'testing_processor:2012; HybridCrashProcessor; ' 'unrecoverable processor error: ' 'nobody expects the spanish inquisition', 'completeddatetime': datetime(2012, 5, 4, 15, 11, tzinfo=UTC), 'success': False, 'uuid': raw_crash.uuid, 'hang_type': 0, 'java_stack_trace': None, 'additional_minidumps': [], } self.assertEqual(e, processed_crash) leg_proc._statistics.assert_has_calls( [ mock.call.incr('jobs'), mock.call.incr('restarts'), mock.call.incr('errors'), ], any_order=True )
def test_convert_raw_crash_to_processed_crash_basic(self): config = setup_config_with_mocks() mocked_transform_rules_str = \ 'socorro.processor.hybrid_processor.TransformRuleSystem' with mock.patch(mocked_transform_rules_str) as m_transform_class: m_transform = mock.Mock() m_transform_class.return_value = m_transform m_transform.attach_mock(mock.Mock(), 'apply_all_rules') utc_now_str = 'socorro.processor.hybrid_processor.utc_now' with mock.patch(utc_now_str) as m_utc_now: m_utc_now.return_value = datetime(2012, 5, 4, 15, 11, tzinfo=UTC) raw_crash = DotDict() raw_crash.uuid = '3bc4bcaa-b61d-4d1f-85ae-30cb32120504' raw_crash.submitted_timestamp = '2012-05-04T15:33:33' raw_dump = {'upload_file_minidump': '/some/path/%s.dump' % raw_crash.uuid, 'aux_dump_001': '/some/path/aux_001.%s.dump' % raw_crash.uuid, } leg_proc = HybridCrashProcessor(config, config.mock_quit_fn) started_timestamp = datetime(2012, 5, 4, 15, 10, tzinfo=UTC) leg_proc._log_job_start = mock.Mock( return_value=started_timestamp ) basic_processed_crash = DotDict() basic_processed_crash.uuid = raw_crash.uuid basic_processed_crash.hang_type = 0 basic_processed_crash.java_stack_trace = None leg_proc._create_basic_processed_crash = mock.Mock( return_value=basic_processed_crash) leg_proc._log_job_end = mock.Mock() processed_crash_update_dict = DotDict() processed_crash_update_dict.success = True leg_proc._do_breakpad_stack_dump_analysis = mock.Mock( return_value=processed_crash_update_dict ) leg_proc._cleanup_temp_file = mock.Mock() # Here's the call being tested processed_crash = \ leg_proc.convert_raw_crash_to_processed_crash( raw_crash, raw_dump ) # test the result self.assertEqual(1, leg_proc._log_job_start.call_count) leg_proc._log_job_start.assert_called_with(raw_crash.uuid) self.assertEqual(1, m_transform.apply_all_rules.call_count) m_transform.apply_all_rules.has_calls( mock.call(raw_crash, leg_proc), ) self.assertEqual( 2, m_transform.apply_until_action_succeeds.call_count ) m_transform.apply_all_rules.has_calls( mock.call(raw_crash, processed_crash, leg_proc) ) self.assertEqual( 1, leg_proc._create_basic_processed_crash.call_count ) leg_proc._create_basic_processed_crash.assert_called_with( raw_crash.uuid, raw_crash, datetime(2012, 5, 4, 15, 33, 33, tzinfo=UTC), started_timestamp, [ 'testing_processor:2012', 'HybridCrashProcessor' ] ) self.assertEqual( 2, leg_proc._do_breakpad_stack_dump_analysis.call_count ) first_call, second_call = \ leg_proc._do_breakpad_stack_dump_analysis.call_args_list self.assertEqual( first_call, ((raw_crash.uuid, '/some/path/%s.dump' % raw_crash.uuid, 0, None, datetime(2012, 5, 4, 15, 33, 33, tzinfo=UTC), [ 'testing_processor:2012', 'HybridCrashProcessor' ]),) ) self.assertEqual( second_call, ((raw_crash.uuid, '/some/path/aux_001.%s.dump' % raw_crash.uuid, 0, None, datetime(2012, 5, 4, 15, 33, 33, tzinfo=UTC), [ 'testing_processor:2012', 'HybridCrashProcessor' ]),) ) self.assertEqual(1, leg_proc._log_job_end.call_count) leg_proc._log_job_end.assert_called_with( datetime(2012, 5, 4, 15, 11, tzinfo=UTC), True, raw_crash.uuid ) epc = DotDict() epc.uuid = raw_crash.uuid epc.topmost_filenames = '' epc.processor_notes = \ "testing_processor:2012; HybridCrashProcessor" epc.success = True epc.completeddatetime = datetime(2012, 5, 4, 15, 11, tzinfo=UTC) epc.hang_type = 0 epc.java_stack_trace = None epc.Winsock_LSP = None epc.additional_minidumps = ['aux_dump_001'] epc.aux_dump_001 = {'success': True} self.assertEqual( processed_crash, dict(epc) ) leg_proc._statistics.assert_has_calls( [ mock.call.incr('jobs'), mock.call.incr('restarts') ], any_order=True )
def test_convert_raw_crash_to_processed_crash_unexpected_error(self): config = setup_config_with_mocks() mocked_transform_rules_str = \ 'socorro.processor.hybrid_processor.TransformRuleSystem' with mock.patch(mocked_transform_rules_str) as m_transform_class: m_transform = mock.Mock() m_transform_class.return_value = m_transform m_transform.attach_mock(mock.Mock(), 'apply_all_rules') utc_now_str = 'socorro.processor.hybrid_processor.utc_now' with mock.patch(utc_now_str) as m_utc_now: m_utc_now.return_value = datetime(2012, 5, 4, 15, 11, tzinfo=UTC) raw_crash = DotDict() raw_crash.uuid = '3bc4bcaa-b61d-4d1f-85ae-30cb32120504' raw_crash.submitted_timestamp = '2012-05-04T15:33:33' raw_dump = {'upload_file_minidump': 'abcdef'} leg_proc = HybridCrashProcessor(config, config.mock_quit_fn) started_timestamp = datetime(2012, 5, 4, 15, 10, tzinfo=UTC) leg_proc._log_job_start = mock.Mock( return_value=started_timestamp) basic_processed_crash = DotDict() basic_processed_crash.uuid = raw_crash.uuid basic_processed_crash.success = False basic_processed_crash.hang_type = 0 basic_processed_crash.java_stack_trace = None leg_proc._create_basic_processed_crash = mock.Mock( return_value=basic_processed_crash) leg_proc._get_temp_dump_pathname = mock.Mock( return_value='/tmp/x') leg_proc._log_job_end = mock.Mock() processed_crash_update_dict = DotDict() processed_crash_update_dict.success = True leg_proc._do_breakpad_stack_dump_analysis = mock.Mock( side_effect=Exception('nobody expects the spanish ' 'inquisition')) # Here's the call being tested processed_crash = \ leg_proc.convert_raw_crash_to_processed_crash( raw_crash, raw_dump ) self.assertEqual(1, leg_proc._log_job_end.call_count) leg_proc._log_job_end.assert_called_with( datetime(2012, 5, 4, 15, 11, tzinfo=UTC), False, raw_crash.uuid) e = { 'processor_notes': 'testing_processor:2012; HybridCrashProcessor; ' 'unrecoverable processor error: ' 'nobody expects the spanish inquisition', 'completeddatetime': datetime(2012, 5, 4, 15, 11, tzinfo=UTC), 'success': False, 'uuid': raw_crash.uuid, 'hang_type': 0, 'java_stack_trace': None, 'additional_minidumps': [], } self.assertEqual(e, processed_crash) leg_proc._statistics.assert_has_calls([ mock.call.incr('jobs'), mock.call.incr('restarts'), mock.call.incr('errors'), ], any_order=True)
def test_create_basic_processed_crash_normal(self): config = setup_config_with_mocks() config.collect_addon = False config.collect_crash_process = False mocked_transform_rules_str = \ 'socorro.processor.hybrid_processor.TransformRuleSystem' with mock.patch(mocked_transform_rules_str) as m_transform_class: m_transform = mock.Mock() m_transform_class.return_value = m_transform m_transform.attach_mock(mock.Mock(), 'apply_all_rules') utc_now_str = 'socorro.processor.hybrid_processor.utc_now' with mock.patch(utc_now_str) as m_utc_now: m_utc_now.return_value = datetime(2012, 5, 4, 15, 11, tzinfo=UTC) started_timestamp = datetime(2012, 5, 4, 15, 10, tzinfo=UTC) raw_crash = canonical_standard_raw_crash leg_proc = HybridCrashProcessor(config, config.mock_quit_fn) processor_notes = [] # test 01 processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', raw_crash, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) assert 'exploitability' in processed_crash self.assertEqual(processed_crash, dict(cannonical_basic_processed_crash)) # test 02 processor_notes = [] raw_crash_missing_product = copy.deepcopy(raw_crash) del raw_crash_missing_product['ProductName'] processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', raw_crash_missing_product, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) processed_crash_missing_product = \ copy.copy(cannonical_basic_processed_crash) processed_crash_missing_product.product = None self.assertEqual(processed_crash, processed_crash_missing_product) self.assertTrue('WARNING: raw_crash missing ProductName' in processor_notes) self.assertEqual(len(processor_notes), 1) # test 03 processor_notes = [] raw_crash_missing_version = copy.deepcopy(raw_crash) del raw_crash_missing_version['Version'] processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', raw_crash_missing_version, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) processed_crash_missing_version = \ copy.copy(cannonical_basic_processed_crash) processed_crash_missing_version.version = None self.assertEqual(processed_crash, processed_crash_missing_version) self.assertTrue( 'WARNING: raw_crash missing Version' in processor_notes) self.assertEqual(len(processor_notes), 1) # test 04 processor_notes = [] raw_crash_with_hangid = copy.deepcopy(raw_crash) raw_crash_with_hangid.HangID = \ '30cb3212-b61d-4d1f-85ae-3bc4bcaa0504' processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', raw_crash_with_hangid, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) processed_crash_with_hangid = \ copy.copy(cannonical_basic_processed_crash) processed_crash_with_hangid.hangid = \ raw_crash_with_hangid.HangID processed_crash_with_hangid.hang_type = -1 self.assertEqual(processed_crash, processed_crash_with_hangid) self.assertEqual(len(processor_notes), 0) # test 05 processor_notes = [] raw_crash_with_pluginhang = copy.deepcopy(raw_crash) raw_crash_with_pluginhang.PluginHang = '1' processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', raw_crash_with_pluginhang, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) processed_crash_with_pluginhang = \ copy.copy(cannonical_basic_processed_crash) processed_crash_with_pluginhang.hangid = \ 'fake-3bc4bcaa-b61d-4d1f-85ae-30cb32120504' processed_crash_with_pluginhang.hang_type = -1 self.assertEqual(processed_crash, processed_crash_with_pluginhang) self.assertEqual(len(processor_notes), 0) # test 06 processor_notes = [] raw_crash_with_hang_only = copy.deepcopy(raw_crash) raw_crash_with_hang_only.Hang = 16 processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', raw_crash_with_hang_only, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) processed_crash_with_hang_only = \ copy.copy(cannonical_basic_processed_crash) processed_crash_with_hang_only.hang_type = 1 self.assertEqual(processed_crash, processed_crash_with_hang_only) self.assertEqual(len(processor_notes), 0) leg_proc._statistics.assert_has_calls([ mock.call.incr('restarts'), ], any_order=True) # test 07 processor_notes = [] raw_crash_with_hang_only = copy.deepcopy(raw_crash) raw_crash_with_hang_only.Hang = 'bad value' processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', raw_crash_with_hang_only, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) processed_crash_with_hang_only = \ copy.copy(cannonical_basic_processed_crash) processed_crash_with_hang_only.hang_type = 0 self.assertEqual(processed_crash, processed_crash_with_hang_only) self.assertEqual(len(processor_notes), 0) leg_proc._statistics.assert_has_calls([ mock.call.incr('restarts'), ], any_order=True) # test 08 processor_notes = [] bad_raw_crash = copy.deepcopy(raw_crash) bad_raw_crash['SecondsSinceLastCrash'] = 'badness' processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', bad_raw_crash, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) self.assertEqual(processed_crash.last_crash, None) self.assertTrue('non-integer value of "SecondsSinceLastCrash"' in processor_notes) # test 09 processor_notes = [] bad_raw_crash = copy.deepcopy(raw_crash) bad_raw_crash['CrashTime'] = 'badness' processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', bad_raw_crash, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) self.assertEqual(processed_crash.crash_time, 0) self.assertTrue( 'non-integer value of "CrashTime"' in processor_notes) # test 10 processor_notes = [] bad_raw_crash = copy.deepcopy(raw_crash) bad_raw_crash['StartupTime'] = 'badness' bad_raw_crash['InstallTime'] = 'more badness' bad_raw_crash['CrashTime'] = 'even more badness' processed_crash = leg_proc._create_basic_processed_crash( '3bc4bcaa-b61d-4d1f-85ae-30cb32120504', bad_raw_crash, datetimeFromISOdateString(raw_crash.submitted_timestamp), started_timestamp, processor_notes, ) self.assertEqual(processed_crash.install_age, 0) self.assertTrue( 'non-integer value of "StartupTime"' in processor_notes) self.assertTrue( 'non-integer value of "InstallTime"' in processor_notes) self.assertTrue( 'non-integer value of "CrashTime"' in processor_notes)
def test_add_process_type_to_processed_crash(self): config = setup_config_with_mocks() config.collect_addon = False config.collect_crash_process = True mocked_transform_rules_str = \ 'socorro.processor.hybrid_processor.TransformRuleSystem' with mock.patch(mocked_transform_rules_str) as m_transform_class: m_transform = mock.Mock() m_transform_class.return_value = m_transform m_transform.attach_mock(mock.Mock(), 'apply_all_rules') utc_now_str = 'socorro.processor.hybrid_processor.utc_now' with mock.patch(utc_now_str) as m_utc_now: m_utc_now.return_value = datetime(2012, 5, 4, 15, 11, tzinfo=UTC) leg_proc = HybridCrashProcessor(config, config.mock_quit_fn) # test null case raw_crash = canonical_standard_raw_crash processor_notes = [] pc_update = leg_proc._add_process_type_to_processed_crash( raw_crash ) self.assertEqual(pc_update, {}) self.assertEqual(processor_notes, []) # test unknown case raw_crash = copy.copy(canonical_standard_raw_crash) raw_crash.ProcessType = 'unknown' processor_notes = [] pc_update = leg_proc._add_process_type_to_processed_crash( raw_crash ) self.assertEqual( pc_update, { 'process_type': 'unknown', } ) self.assertEqual(processor_notes, []) #test plugin null case raw_crash = copy.copy(canonical_standard_raw_crash) raw_crash.ProcessType = 'plugin' processor_notes = [] pc_update = leg_proc._add_process_type_to_processed_crash( raw_crash ) self.assertEqual( pc_update, { 'process_type': 'plugin', 'PluginFilename': '', 'PluginName': '', 'PluginVersion': '', } ) self.assertEqual(processor_notes, []) #test plugin case raw_crash = copy.copy(canonical_standard_raw_crash) raw_crash.ProcessType = 'plugin' raw_crash.PluginFilename = 'myfile.dll' raw_crash.PluginName = 'myplugin' raw_crash.PluginVersion = '6.6.6' processor_notes = [] pc_update = leg_proc._add_process_type_to_processed_crash( raw_crash ) self.assertEqual( pc_update, { 'process_type': 'plugin', 'PluginFilename': 'myfile.dll', 'PluginName': 'myplugin', 'PluginVersion': '6.6.6', } ) self.assertEqual(processor_notes, [])
def test_add_process_type_to_processed_crash(self): config = setup_config_with_mocks() config.collect_addon = False config.collect_crash_process = True mocked_transform_rules_str = \ 'socorro.processor.hybrid_processor.TransformRuleSystem' with mock.patch(mocked_transform_rules_str) as m_transform_class: m_transform = mock.Mock() m_transform_class.return_value = m_transform m_transform.attach_mock(mock.Mock(), 'apply_all_rules') utc_now_str = 'socorro.processor.hybrid_processor.utc_now' with mock.patch(utc_now_str) as m_utc_now: m_utc_now.return_value = datetime(2012, 5, 4, 15, 11, tzinfo=UTC) leg_proc = HybridCrashProcessor(config, config.mock_quit_fn) # test null case raw_crash = canonical_standard_raw_crash processor_notes = [] pc_update = leg_proc._add_process_type_to_processed_crash( raw_crash) self.assertEqual(pc_update, {}) self.assertEqual(processor_notes, []) # test unknown case raw_crash = copy.copy(canonical_standard_raw_crash) raw_crash.ProcessType = 'unknown' processor_notes = [] pc_update = leg_proc._add_process_type_to_processed_crash( raw_crash) self.assertEqual(pc_update, { 'process_type': 'unknown', }) self.assertEqual(processor_notes, []) #test plugin null case raw_crash = copy.copy(canonical_standard_raw_crash) raw_crash.ProcessType = 'plugin' processor_notes = [] pc_update = leg_proc._add_process_type_to_processed_crash( raw_crash) self.assertEqual( pc_update, { 'process_type': 'plugin', 'PluginFilename': '', 'PluginName': '', 'PluginVersion': '', }) self.assertEqual(processor_notes, []) #test plugin case raw_crash = copy.copy(canonical_standard_raw_crash) raw_crash.ProcessType = 'plugin' raw_crash.PluginFilename = 'myfile.dll' raw_crash.PluginName = 'myplugin' raw_crash.PluginVersion = '6.6.6' processor_notes = [] pc_update = leg_proc._add_process_type_to_processed_crash( raw_crash) self.assertEqual( pc_update, { 'process_type': 'plugin', 'PluginFilename': 'myfile.dll', 'PluginName': 'myplugin', 'PluginVersion': '6.6.6', }) self.assertEqual(processor_notes, [])
def test_analyze_header(self): # verify fix for Bug 881623 in test one """test some of the possibilities in reading the first three lines from MDSW. This does not provide comprehensive coverage.""" config = setup_config_with_mocks() config.collect_addon = False config.collect_crash_process = True mocked_transform_rules_str = \ 'socorro.processor.hybrid_processor.TransformRuleSystem' with mock.patch(mocked_transform_rules_str) as m_transform_class: m_transform = mock.Mock() m_transform_class.return_value = m_transform m_transform.attach_mock(mock.Mock(), 'apply_all_rules') utc_now_str = 'socorro.processor.hybrid_processor.utc_now' with mock.patch(utc_now_str) as m_utc_now: m_utc_now.return_value = datetime(2012, 5, 4, 15, 11, tzinfo=UTC) leg_proc = HybridCrashProcessor(config, config.mock_quit_fn) # test one - all ok def dump_iter(): lines = [ 'OS|Windows NT|6.1.7601 Service Pack 1 ', 'CPU|x86|GenuineIntel family 6 model 42 stepping 7|8', 'Crash|EXCEPTION_ACCESS_VIOLATION_READ|0xffffffffdadadada|0' ] for a_line in lines: yield a_line processor_notes = [] result = leg_proc._analyze_header( '1fcdec5e-face-404a-8622-babda2130605', dump_iter(), m_utc_now(), processor_notes ) self.assertTrue(result.success) self.assertEqual(result.os_name, 'Windows NT') self.assertEqual(result.os_version, '6.1.7601 Service Pack 1') self.assertEqual(result.cpu_name, 'x86') self.assertEqual(result.cpu_info, 'GenuineIntel family 6 model 42 stepping 7 | 8') self.assertEqual(result.reason, 'EXCEPTION_ACCESS_VIOLATION_READ') self.assertEqual(result.address, '0xffffffffdadadada') self.assertEqual(result.crashedThread, 0) # test two - crashed thread missing def dump_iter(): lines = [ 'OS|Windows NT|6.1.7601 Service Pack 1 ', 'CPU|x86|GenuineIntel family 6 model 42 stepping 7|8', 'Crash|EXCEPTION_ACCESS_VIOLATION_READ|0xffffffffdadadada|' ] for a_line in lines: yield a_line processor_notes = [] result = leg_proc._analyze_header( '1fcdec5e-face-404a-8622-babda2130605', dump_iter(), m_utc_now(), processor_notes ) self.assertTrue(result.success) self.assertEqual(result.os_name, 'Windows NT') self.assertEqual(result.os_version, '6.1.7601 Service Pack 1') self.assertEqual(result.cpu_name, 'x86') self.assertEqual(result.cpu_info, 'GenuineIntel family 6 model 42 stepping 7 | 8') self.assertEqual(result.reason, 'EXCEPTION_ACCESS_VIOLATION_READ') self.assertEqual(result.address, '0xffffffffdadadada') self.assertEqual(result.crashedThread, None) self.assertTrue( 'MDSW did not identify the crashing thread' in processor_notes ) # test three - no lines def dump_iter(): for a_line in []: yield a_line processor_notes = [] result = leg_proc._analyze_header( '1fcdec5e-face-404a-8622-babda2130605', dump_iter(), m_utc_now(), processor_notes ) self.assertTrue(result.success) self.assertEqual(result.os_name, None) self.assertEqual(result.os_version, None) self.assertEqual(result.cpu_name, None) self.assertEqual(result.cpu_info, None) self.assertEqual(result.reason, None) self.assertEqual(result.address, None) self.assertEqual(result.crashedThread, None) self.assertTrue( 'MDSW did not identify the crashing thread' in processor_notes ) self.assertTrue( 'MDSW emitted no header lines' in processor_notes )