def _action(self, raw_crash, raw_dumps, processed_crash, processor_meta): processor_notes = processor_meta.processor_notes processed_crash.submitted_timestamp = raw_crash.get("submitted_timestamp", dateFromOoid(raw_crash.uuid)) if isinstance(processed_crash.submitted_timestamp, basestring): processed_crash.submitted_timestamp = datetimeFromISOdateString(processed_crash.submitted_timestamp) processed_crash.date_processed = processed_crash.submitted_timestamp # defaultCrashTime: must have crashed before date processed submitted_timestamp_as_epoch = int(time.mktime(processed_crash.submitted_timestamp.timetuple())) try: timestampTime = int(raw_crash.get("timestamp", submitted_timestamp_as_epoch)) # the old name for crash time except ValueError: timestampTime = 0 processor_notes.append('non-integer value of "timestamp"') try: crash_time = int(self._get_truncate_or_warn(raw_crash, "CrashTime", processor_notes, timestampTime, 10)) except ValueError: crash_time = 0 processor_notes.append('non-integer value of "CrashTime" (%s)' % raw_crash.CrashTime) processed_crash.crash_time = crash_time if crash_time == submitted_timestamp_as_epoch: processor_notes.append("client_crash_date is unknown") # StartupTime: must have started up some time before crash try: startupTime = int(raw_crash.get("StartupTime", crash_time)) except ValueError: startupTime = 0 processor_notes.append('non-integer value of "StartupTime"') # InstallTime: must have installed some time before startup try: installTime = int(raw_crash.get("InstallTime", startupTime)) except ValueError: installTime = 0 processor_notes.append('non-integer value of "InstallTime"') processed_crash.client_crash_date = datetime.datetime.fromtimestamp(crash_time, UTC) processed_crash.install_age = crash_time - installTime processed_crash.uptime = max(0, crash_time - startupTime) try: last_crash = int(raw_crash.SecondsSinceLastCrash) except (KeyError, TypeError, ValueError): last_crash = None processor_notes.append('non-integer value of "SecondsSinceLastCrash"') if last_crash > maxint: last_crash = None processor_notes.append('"SecondsSinceLastCrash" larger than MAXINT - set to NULL') processed_crash.last_crash = last_crash return True
def get_list(self, **kwargs): """ List all crashes with a given signature and return them. Both `from_date` and `to_date` (and their aliases `from` and `to`) are required and can not be greater than 30 days apart. Optional arguments: see SearchCommon.get_parameters() """ # aliases if "from" in kwargs and "from_date" not in kwargs: kwargs["from_date"] = kwargs.get("from") if "to" in kwargs and "to_date" not in kwargs: kwargs["to_date"] = kwargs.get("to") if not kwargs.get('from_date'): raise MissingArgumentError('from_date') if not kwargs.get('to_date'): raise MissingArgumentError('to_date') from_date = datetimeutil.datetimeFromISOdateString(kwargs['from_date']) to_date = datetimeutil.datetimeFromISOdateString(kwargs['to_date']) span_days = (to_date - from_date).days if span_days > 30: raise BadArgumentError( 'Span between from_date and to_date can not be more than 30' ) # start with the default sort_order = { 'key': 'date_processed', 'direction': 'DESC' } if 'sort' in kwargs: sort_order['key'] = kwargs.pop('sort') _recognized_sort_orders = ( 'date_processed', 'uptime', 'user_comments', 'uuid', 'uuid_text', 'product', 'version', 'build', 'signature', 'url', 'os_name', 'os_version', 'cpu_name', 'cpu_info', 'address', 'reason', 'last_crash', 'install_age', 'hangid', 'process_type', 'release_channel', 'install_time', 'duplicate_of', ) if sort_order['key'] not in _recognized_sort_orders: raise BadArgumentError( '%s is not a recognized sort order key' % sort_order['key'] ) sort_order['direction'] = 'ASC' if str(kwargs.get('reverse', '')).lower() == 'true': if kwargs.pop('reverse'): sort_order['direction'] = 'DESC' include_raw_crash = kwargs.get('include_raw_crash') or False params = search_common.get_parameters(kwargs) if not params["signature"]: raise MissingArgumentError('signature') params["terms"] = params["signature"] params["search_mode"] = "is_exactly" # Default mode falls back to starts_with for postgres if params["plugin_search_mode"] == "default": params["plugin_search_mode"] = "starts_with" # Limiting to a signature if params["terms"]: params["terms"] = self.prepare_terms(params["terms"], params["search_mode"]) # Searching for terms in plugins if params["report_process"] == "plugin" and params["plugin_terms"]: params["plugin_terms"] = " ".join(params["plugin_terms"]) params["plugin_terms"] = self.prepare_terms( params["plugin_terms"], params["plugin_search_mode"] ) # Get information about the versions util_service = Util(config=self.context) params["versions_info"] = util_service.versions_info(**params) # Parsing the versions params["versions_string"] = params["versions"] (params["versions"], params["products"]) = self.parse_versions( params["versions"], params["products"] ) if hasattr(self.context, 'webapi'): context = self.context.webapi else: # old middleware context = self.context # Changing the OS ids to OS names for i, elem in enumerate(params["os"]): for platform in context.platforms: if platform["id"][:3] == elem[:3]: params["os"][i] = platform["name"] # Creating the parameters for the sql query sql_params = { } # Preparing the different parts of the sql query sql_select = """ SELECT r.date_processed, r.uptime, r.user_comments, r.uuid::uuid, r.uuid as uuid_text, r.product, r.version, r.build, r.signature, r.url, r.os_name, r.os_version, r.cpu_name, r.cpu_info, r.address, r.reason, r.last_crash, r.install_age, r.hangid, r.process_type, r.release_channel, (r.client_crash_date - (r.install_age * INTERVAL '1 second')) AS install_time """ if include_raw_crash: pass else: sql_select += """ , rd.duplicate_of """ wrapped_select = """ WITH report_slice AS ( %s ), dupes AS ( SELECT report_slice.uuid, rd.duplicate_of FROM reports_duplicates rd JOIN report_slice ON report_slice.uuid_text = rd.uuid WHERE rd.date_processed BETWEEN %%(from_date)s AND %%(to_date)s ) SELECT rs.*, dupes.duplicate_of, rc.raw_crash FROM report_slice rs LEFT OUTER JOIN dupes USING (uuid) LEFT OUTER JOIN raw_crashes rc ON rs.uuid = rc.uuid AND rc.date_processed BETWEEN %%(from_date)s AND %%(to_date)s """ sql_from = self.build_reports_sql_from(params) if not include_raw_crash: sql_from = """%s LEFT OUTER JOIN reports_duplicates rd ON r.uuid = rd.uuid """ % sql_from sql_where, sql_params = self.build_reports_sql_where( params, sql_params, self.context ) sql_order = """ ORDER BY %(key)s %(direction)s """ % sort_order sql_limit, sql_params = self.build_reports_sql_limit( params, sql_params ) # Assembling the query if include_raw_crash: sql_query = "\n".join(( "/* socorro.external.postgresql.report.Report.list */", sql_select, sql_from, sql_where, sql_order, sql_limit) ) else: sql_query = "\n".join(( "/* socorro.external.postgresql.report.Report.list */", sql_select, sql_from, sql_where, sql_order, sql_limit) ) # Query for counting the results sql_count_query = "\n".join(( "/* socorro.external.postgresql.report.Report.list */", "SELECT count(*)", sql_from, sql_where) ) # Querying the DB with self.get_connection() as connection: total = self.count( sql_count_query, sql_params, error_message="Failed to count crashes from reports.", connection=connection ) # No need to call Postgres if we know there will be no results if total: if include_raw_crash: sql_query = wrapped_select % sql_query results = self.query( sql_query, sql_params, error_message="Failed to retrieve crashes from reports", connection=connection ).zipped() else: results = [] crashes = [] for crash in results: assert crash['uuid'] == crash['uuid_text'] crash.pop('uuid_text') if not include_raw_crash and 'raw_crash' in crash: crash.pop('raw_crash') for i in crash: try: crash[i] = datetimeutil.date_to_string(crash[i]) except TypeError: pass crashes.append(crash) return { "hits": crashes, "total": total }
def _action(self, raw_crash, raw_dumps, processed_crash, processor_meta): processor_notes = processor_meta.processor_notes processed_crash.submitted_timestamp = raw_crash.get( 'submitted_timestamp', dateFromOoid(raw_crash.uuid)) if isinstance(processed_crash.submitted_timestamp, basestring): processed_crash.submitted_timestamp = datetimeFromISOdateString( processed_crash.submitted_timestamp) processed_crash.date_processed = processed_crash.submitted_timestamp # defaultCrashTime: must have crashed before date processed submitted_timestamp_as_epoch = int( time.mktime(processed_crash.submitted_timestamp.timetuple())) try: timestampTime = int( raw_crash.get('timestamp', submitted_timestamp_as_epoch) ) # the old name for crash time except ValueError: timestampTime = 0 processor_notes.append('non-integer value of "timestamp"') try: crash_time = int( self._get_truncate_or_warn(raw_crash, 'CrashTime', processor_notes, timestampTime, 10)) except ValueError: crash_time = 0 processor_notes.append('non-integer value of "CrashTime" (%s)' % raw_crash.CrashTime) processed_crash.crash_time = crash_time if crash_time == submitted_timestamp_as_epoch: processor_notes.append("client_crash_date is unknown") # StartupTime: must have started up some time before crash try: startupTime = int(raw_crash.get('StartupTime', crash_time)) except ValueError: startupTime = 0 processor_notes.append('non-integer value of "StartupTime"') # InstallTime: must have installed some time before startup try: installTime = int(raw_crash.get('InstallTime', startupTime)) except ValueError: installTime = 0 processor_notes.append('non-integer value of "InstallTime"') processed_crash.client_crash_date = datetime.datetime.fromtimestamp( crash_time, UTC) processed_crash.install_age = crash_time - installTime processed_crash.uptime = max(0, crash_time - startupTime) try: last_crash = int(raw_crash.SecondsSinceLastCrash) except (KeyError, TypeError, ValueError): last_crash = None processor_notes.append( 'non-integer value of "SecondsSinceLastCrash"') if last_crash > maxint: last_crash = None processor_notes.append( '"SecondsSinceLastCrash" larger than MAXINT - set to NULL') processed_crash.last_crash = last_crash return 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.legacy_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.legacy_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 = LegacyCrashProcessor(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 eq_(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 eq_(processed_crash, processed_crash_missing_product) ok_('WARNING: raw_crash missing ProductName' in processor_notes) eq_(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 eq_(processed_crash, processed_crash_missing_version) ok_('WARNING: raw_crash missing Version' in processor_notes) eq_(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 eq_(processed_crash, processed_crash_with_hangid) eq_(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 eq_(processed_crash, processed_crash_with_pluginhang) eq_(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 eq_(processed_crash, processed_crash_with_hang_only) eq_(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 eq_(processed_crash, processed_crash_with_hang_only) eq_(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, ) eq_(processed_crash.last_crash, None) ok_('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, ) eq_(processed_crash.crash_time, 0) ok_('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, ) eq_(processed_crash.install_age, 0) ok_('non-integer value of "StartupTime"' in processor_notes) ok_('non-integer value of "InstallTime"' in processor_notes) ok_('non-integer value of "CrashTime"' 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.legacy_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.legacy_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 = LegacyCrashProcessor(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 eq_( 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 eq_( processed_crash, processed_crash_missing_product ) ok_('WARNING: raw_crash missing ProductName' in processor_notes) eq_(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 eq_( processed_crash, processed_crash_missing_version ) ok_('WARNING: raw_crash missing Version' in processor_notes) eq_(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 eq_( processed_crash, processed_crash_with_hangid ) eq_(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 eq_( processed_crash, processed_crash_with_pluginhang ) eq_(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 eq_( processed_crash, processed_crash_with_hang_only ) eq_(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 eq_( processed_crash, processed_crash_with_hang_only ) eq_(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, ) eq_(processed_crash.last_crash, None) ok_( '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, ) eq_(processed_crash.crash_time, 0) ok_( '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, ) eq_(processed_crash.install_age, 0) ok_( 'non-integer value of "StartupTime"' in processor_notes ) ok_( 'non-integer value of "InstallTime"' in processor_notes ) ok_( 'non-integer value of "CrashTime"' in processor_notes )