diff --git a/src/clusterfuzz/_internal/bot/tasks/utasks/fuzz_task.py b/src/clusterfuzz/_internal/bot/tasks/utasks/fuzz_task.py index 67169b2e83..9e78c89141 100644 --- a/src/clusterfuzz/_internal/bot/tasks/utasks/fuzz_task.py +++ b/src/clusterfuzz/_internal/bot/tasks/utasks/fuzz_task.py @@ -841,14 +841,15 @@ def upload_job_run_stats( testcases_generated: int = None, testcase_generation_duration: datetime.timedelta = None, testcase_execution_duration: datetime.timedelta = None, - fuzzing_duration: datetime.timedelta = None): + fuzzing_duration: datetime.timedelta = None, + steps_duration: dict[str, datetime.timedelta] | None = None): """Upload job run stats.""" # New format. - job_run = fuzzer_stats.JobRun(fuzzer_name, job_type, revision, timestamp, - testcases_executed, new_crash_count, - known_crash_count, groups, testcases_generated, - testcase_generation_duration, - testcase_execution_duration, fuzzing_duration) + job_run = fuzzer_stats.JobRun( + fuzzer_name, job_type, revision, timestamp, testcases_executed, + new_crash_count, known_crash_count, groups, testcases_generated, + testcase_generation_duration, testcase_execution_duration, + fuzzing_duration, steps_duration) fuzzer_stats.upload_stats([job_run]) _track_testcase_run_result(fuzzer_name, job_type, new_crash_count, @@ -1111,6 +1112,10 @@ def postprocess_process_crashes(uworker_input: uworker_msg_pb2.Input, # Artificial delay to throttle appengine updates. time.sleep(1) + steps_duration = { + name: duration.ToTimedelta() + for name, duration in fuzz_task_output.steps_duration.items() + } # TODO(metzman): Replace fuzz_task_output.fully_qualified_fuzzer_name` with # `fuzz_task_input.fuzz_target` instead. upload_job_run_stats( @@ -1123,8 +1128,8 @@ def postprocess_process_crashes(uworker_input: uworker_msg_pb2.Input, if fuzz_task_output.HasField('testcase_generation_duration') else None, fuzz_task_output.testcase_execution_duration.ToTimedelta() if fuzz_task_output.HasField('testcase_execution_duration') else None, - fuzz_task_output.fuzzing_duration.ToTimedelta() - if fuzz_task_output.HasField('fuzzing_duration') else None) + fuzz_task_output.fuzzing_duration.ToTimedelta() if + fuzz_task_output.HasField('fuzzing_duration') else None, steps_duration) logs.info(f'Finished processing crashes.\nNew crashes: {new_crash_count}, ' f'known crashes: {known_crash_count}, ' @@ -1559,6 +1564,14 @@ def __init__(self, uworker_input, test_timeout): self.gcs_corpus = None self.fuzz_task_output = uworker_msg_pb2.FuzzTaskOutput() # pylint: disable=no-member + self.steps_time_tracker = monitor.TimeStatTracker( + monitoring_metrics.FUZZ_TASK_STEPS_DURATION, + common_labels={ + 'fuzzer': self.fuzzer_name, + 'job': self.job_type, + 'platform': environment.platform(), + 'runtime': environment.get_runtime().value + }) @property def fully_qualified_fuzzer_name(self): @@ -2291,6 +2304,8 @@ def run(self): self.fuzz_task_output.fuzzing_duration.FromTimedelta( datetime.timedelta(seconds=fuzzing_session_duration_seconds)) + for name, duration in self.steps_time_tracker.stats.items(): + self.fuzz_task_output.steps_duration[name].FromTimedelta(duration) return uworker_msg_pb2.Output(fuzz_task_output=self.fuzz_task_output) # pylint: disable=no-member def postprocess(self, uworker_output): diff --git a/src/clusterfuzz/_internal/metrics/fuzzer_stats.py b/src/clusterfuzz/_internal/metrics/fuzzer_stats.py index 63d86cf214..064918dffd 100644 --- a/src/clusterfuzz/_internal/metrics/fuzzer_stats.py +++ b/src/clusterfuzz/_internal/metrics/fuzzer_stats.py @@ -35,84 +35,108 @@ STATS_FILE_EXTENSION = '.stats2' +_STEPS_DURATION_FIELDS = [] JOB_RUN_SCHEMA = { - 'fields': [{ - 'name': 'testcases_executed', - 'type': 'INTEGER', - 'mode': 'NULLABLE' - }, { - 'name': 'build_revision', - 'type': 'INTEGER', - 'mode': 'NULLABLE' - }, { - 'name': 'new_crashes', - 'type': 'INTEGER', - 'mode': 'NULLABLE' - }, { - 'name': 'job', - 'type': 'STRING', - 'mode': 'NULLABLE' - }, { - 'name': 'timestamp', - 'type': 'FLOAT', - 'mode': 'NULLABLE' - }, { - 'name': - 'crashes', - 'type': - 'RECORD', - 'mode': - 'REPEATED', - 'fields': [{ - 'name': 'crash_type', + 'fields': [ + { + 'name': 'testcases_executed', + 'type': 'INTEGER', + 'mode': 'NULLABLE' + }, + { + 'name': 'build_revision', + 'type': 'INTEGER', + 'mode': 'NULLABLE' + }, + { + 'name': 'new_crashes', + 'type': 'INTEGER', + 'mode': 'NULLABLE' + }, + { + 'name': 'job', 'type': 'STRING', 'mode': 'NULLABLE' - }, { - 'name': 'is_new', - 'type': 'BOOLEAN', + }, + { + 'name': 'timestamp', + 'type': 'FLOAT', 'mode': 'NULLABLE' - }, { - 'name': 'crash_state', + }, + { + 'name': + 'crashes', + 'type': + 'RECORD', + 'mode': + 'REPEATED', + 'fields': [{ + 'name': 'crash_type', + 'type': 'STRING', + 'mode': 'NULLABLE' + }, { + 'name': 'is_new', + 'type': 'BOOLEAN', + 'mode': 'NULLABLE' + }, { + 'name': 'crash_state', + 'type': 'STRING', + 'mode': 'NULLABLE' + }, { + 'name': 'security_flag', + 'type': 'BOOLEAN', + 'mode': 'NULLABLE' + }, { + 'name': 'count', + 'type': 'INTEGER', + 'mode': 'NULLABLE' + }] + }, + { + 'name': 'known_crashes', + 'type': 'INTEGER', + 'mode': 'NULLABLE' + }, + { + 'name': 'fuzzer', 'type': 'STRING', 'mode': 'NULLABLE' - }, { - 'name': 'security_flag', - 'type': 'BOOLEAN', + }, + { + 'name': 'kind', + 'type': 'STRING', 'mode': 'NULLABLE' - }, { - 'name': 'count', + }, + { + 'name': 'testcases_generated', 'type': 'INTEGER', 'mode': 'NULLABLE' - }] - }, { - 'name': 'known_crashes', - 'type': 'INTEGER', - 'mode': 'NULLABLE' - }, { - 'name': 'fuzzer', - 'type': 'STRING', - 'mode': 'NULLABLE' - }, { - 'name': 'kind', - 'type': 'STRING', - 'mode': 'NULLABLE' - }, { - 'name': 'testcases_generated', - 'type': 'INTEGER', - 'mode': 'NULLABLE' - }, { - 'name': 'testcase_generation_duration', - 'type': 'INTERVAL', - 'mode': 'NULLABLE' - }, { - 'name': 'testcase_execution_duration', - 'type': 'INTERVAL', - 'mode': 'NULLABLE' - }, { - 'name': 'fuzzing_duration', - 'type': 'INTERVAL', - 'mode': 'NULLABLE' - }] + }, + { + 'name': 'testcase_generation_duration', + 'type': 'INTERVAL', + 'mode': 'NULLABLE' + }, + { + 'name': 'testcase_execution_duration', + 'type': 'INTERVAL', + 'mode': 'NULLABLE' + }, + { + 'name': 'fuzzing_duration', + 'type': 'INTERVAL', + 'mode': 'NULLABLE' + }, + # Measures the duration of each step of the fuzz task for successful + # executions, in contrast to the FUZZ_TASK_STEPS_DURATION metric + # in Cloud Monitoring, which includes failed executions. + { + 'name': 'steps_duration', + 'type': 'RECORD', + 'mode': 'NULLABLE', + 'fields': _STEPS_DURATION_FIELDS + } + ] } @@ -225,7 +249,8 @@ def from_json(json_data): data.get('crashes'), data.get('testcases_generated'), data.get('testcase_generation_duration'), data.get('testcase_execution_duration'), - data.get('fuzzing_duration')) + data.get('fuzzing_duration'), + data.get('steps_duration')) except KeyError: return None @@ -252,7 +277,8 @@ def __init__(self, testcases_generated=None, testcase_generation_duration=None, testcase_execution_duration=None, - fuzzing_duration=None): + fuzzing_duration=None, + steps_duration=None): super().__init__(fuzzer, job, build_revision, timestamp) self._stats_data.update({ 'kind': 'JobRun', @@ -274,6 +300,22 @@ def __init__(self, if fuzzing_duration is not None: self._stats_data['fuzzing_duration'] = _timedelta_to_duration_string( fuzzing_duration) + if steps_duration: + valid_names = frozenset(field['name'] for field in _STEPS_DURATION_FIELDS) + valid_steps_duration = {} + dropped_keys = [] + for name, duration in steps_duration.items(): + if name in valid_names: + valid_steps_duration[name] = _timedelta_to_duration_string(duration) + else: + dropped_keys.append(name) + + if dropped_keys: + keys_str = ', '.join(f'"{key}"' for key in dropped_keys) + logs.error(f'Dropped keys {keys_str} because they are not accepted ' + 'by any field in JobRun.steps_duration schema.') + if valid_steps_duration: + self._stats_data['steps_duration'] = valid_steps_duration class TestcaseRun(BaseRun): diff --git a/src/clusterfuzz/_internal/metrics/monitor.py b/src/clusterfuzz/_internal/metrics/monitor.py index 5e2ebd70ed..c09bcf9c40 100644 --- a/src/clusterfuzz/_internal/metrics/monitor.py +++ b/src/clusterfuzz/_internal/metrics/monitor.py @@ -19,6 +19,7 @@ import bisect import collections import contextlib +import datetime import functools import itertools import re @@ -424,6 +425,12 @@ def monitoring_v3_time_series(self, time_series, labels, start_time, end_time, return time_series + def has_field(self, field): + for f in self.field_spec: + if f.value_type == field.value_type and f.name == field.name: + return True + return False + class _CounterMetric(Metric): """Counter metric.""" @@ -658,6 +665,74 @@ def fail(self): self.failed = True +class TimeStatTrackerFailureException(Exception): + pass + + +class TimeStatTracker: + """Reusable context manager to keep track of time stats. + + Time measurements are emitted to the supplied Cloud Monitoring metric and + are saved as datetime.timedelta in the |self.stats| dictionary as well. + """ + + def __init__(self, metric: Metric | None = None, common_labels=None): + """Initializes the tracker. + + Args: + metric: The Cloud Monitoring metric to submit measurements to, if not + None. The metric must contain the fields "step" and "success", which + are automatically filled by the tracker upon emission. + common_labels: The dictionary of labels to be submitted to the metric. + The "step" and "success" labels are ignored if present. + """ + self.stats: dict[str, datetime.timedelta] = {} + self.metric = metric + self.common_labels = dict(common_labels) if common_labels else {} + if metric: + if not metric.has_field(StringField('step')): + logs.error('Missing "step" string field in the metric.') + self.metric = None + if not metric.has_field(BooleanField('success')): + logs.error('Missing "success" boolean field in the metric.') + self.metric = None + if 'step' in self.common_labels or 'success' in self.common_labels: + logs.warning('Labels "step" or "success" are in common_labels ' + 'and will be overwritten.') + + @contextlib.contextmanager + def track(self, name: str): + """Tracks the stat named |name|. + + Any raised exception is treated as a failure and re-raised, except for + TimeStatTrackerFailureException, which marks the step as failed without + propagating. + """ + start = time.time() + success = True + try: + yield + except TimeStatTrackerFailureException: + success = False + except: + success = False + raise + finally: + duration_secs = time.time() - start + duration = datetime.timedelta(seconds=duration_secs) + if name in self.stats: + self.stats[name] += duration + else: + self.stats[name] = duration + if self.metric: + self.metric.insert( + duration_secs, + labels={ + **self.common_labels, 'step': name, + 'success': success + }) + + # Global state. _metrics_store = _MetricsStore() _monitoring_v3_client = None diff --git a/src/clusterfuzz/_internal/metrics/monitoring_metrics.py b/src/clusterfuzz/_internal/metrics/monitoring_metrics.py index 1fc2addf4b..0ecf644126 100644 --- a/src/clusterfuzz/_internal/metrics/monitoring_metrics.py +++ b/src/clusterfuzz/_internal/metrics/monitoring_metrics.py @@ -273,6 +273,22 @@ ], ) +FUZZ_TASK_STEPS_DURATION = monitor.CumulativeDistributionMetric( + 'task/fuzz/steps_duration', + bucketer=monitor.GeometricBucketer(), + description=('Distribution of the duration of individual steps of the ' + 'fuzz task, in seconds. For steps that run more than once ' + 'in the same fuzz task (e.g. in a loop), each run is ' + 'tracked separately.'), + field_spec=[ + monitor.StringField('fuzzer'), + monitor.StringField('job'), + monitor.StringField('platform'), + monitor.StringField('runtime'), + monitor.StringField('step'), + monitor.BooleanField('success') + ]) + # Global error count. LOG_ERROR_COUNT = monitor.CounterMetric( 'errors/count', diff --git a/src/clusterfuzz/_internal/protos/uworker_msg.proto b/src/clusterfuzz/_internal/protos/uworker_msg.proto index 2380f681aa..8b93def6e9 100644 --- a/src/clusterfuzz/_internal/protos/uworker_msg.proto +++ b/src/clusterfuzz/_internal/protos/uworker_msg.proto @@ -275,6 +275,9 @@ message FuzzTaskOutput { // Total fuzzing session time. Includes time spent updating the fuzzer, build // and test corpus set up, and crash processing. optional google.protobuf.Duration fuzzing_duration = 23; + // Map of {step: duration}, which tracks the duration of each step in the + // fuzz task + map steps_duration = 24; } message MinimizeTaskOutput { diff --git a/src/clusterfuzz/_internal/protos/uworker_msg_pb2.py b/src/clusterfuzz/_internal/protos/uworker_msg_pb2.py index f142bbef90..96c1a478f6 100644 --- a/src/clusterfuzz/_internal/protos/uworker_msg_pb2.py +++ b/src/clusterfuzz/_internal/protos/uworker_msg_pb2.py @@ -31,7 +31,7 @@ from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n.clusterfuzz/_internal/protos/uworker_msg.proto\x12\x0buworker_msg\x1a\x19google/protobuf/any.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/duration.proto\"\x85\x03\n\nSetupInput\x12)\n\x06\x66uzzer\x18\x01 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00\x88\x01\x01\x12\x18\n\x0b\x66uzzer_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\"\n\x15\x66uzzer_log_upload_url\x18\x04 \x01(\tH\x02\x88\x01\x01\x12 \n\x13\x66uzzer_download_url\x18\x05 \x01(\tH\x03\x88\x01\x01\x12\"\n\x15testcase_download_url\x18\x06 \x01(\tH\x04\x88\x01\x01\x12$\n\x1cglobal_blacklisted_functions\x18\x07 \x03(\t\x12;\n\x14\x64\x61ta_bundle_corpuses\x18\x08 \x03(\x0b\x32\x1d.uworker_msg.DataBundleCorpusB\t\n\x07_fuzzerB\x0e\n\x0c_fuzzer_nameB\x18\n\x16_fuzzer_log_upload_urlB\x16\n\x14_fuzzer_download_urlB\x18\n\x16_testcase_download_url\")\n\x10\x41nalyzeTaskInput\x12\x15\n\rbad_revisions\x18\x01 \x03(\x03\"P\n\x12SymbolizeTaskInput\x12!\n\x14old_crash_stacktrace\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x17\n\x15_old_crash_stacktrace\"C\n\rBlobUploadUrl\x12\x10\n\x03key\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x10\n\x03url\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x06\n\x04_keyB\x06\n\x04_url\"\xcb\x04\n\rFuzzTaskInput\x12\'\n\x1asample_testcase_upload_key\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\'\n\x1asample_testcase_upload_url\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\"\n\x15script_log_upload_url\x18\x03 \x01(\tH\x02\x88\x01\x01\x12.\n\x0b\x66uzz_target\x18\x04 \x01(\x0b\x32\x14.google.protobuf.AnyH\x03\x88\x01\x01\x12\x32\n\x06\x63orpus\x18\x05 \x01(\x0b\x32\x1d.uworker_msg.FuzzTargetCorpusH\x04\x88\x01\x01\x12$\n\x1cglobal_blacklisted_functions\x18\x06 \x03(\t\x12\x35\n\x11\x63rash_upload_urls\x18\x07 \x03(\x0b\x32\x1a.uworker_msg.BlobUploadUrl\x12$\n\x06trials\x18\x08 \x03(\x0b\x32\x14.google.protobuf.Any\x12\x1a\n\rweb_tests_url\x18\t \x01(\tH\x05\x88\x01\x01\x12\"\n\x15script_log_upload_key\x18\n \x01(\tH\x06\x88\x01\x01\x42\x1d\n\x1b_sample_testcase_upload_keyB\x1d\n\x1b_sample_testcase_upload_urlB\x18\n\x16_script_log_upload_urlB\x0e\n\x0c_fuzz_targetB\t\n\x07_corpusB\x10\n\x0e_web_tests_urlB\x18\n\x16_script_log_upload_key\"\x89\x01\n\x10\x44\x61taBundleCorpus\x12.\n\x0b\x64\x61ta_bundle\x18\x01 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00\x88\x01\x01\x12\x14\n\x07gcs_url\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x13\n\x0b\x63orpus_urls\x18\x03 \x03(\tB\x0e\n\x0c_data_bundleB\n\n\x08_gcs_url\"\x82\x02\n\x10\x46uzzTargetCorpus\x12(\n\x06\x63orpus\x18\x01 \x01(\x0b\x32\x13.uworker_msg.CorpusH\x00\x88\x01\x01\x12\x34\n\x12regressions_corpus\x18\x02 \x01(\x0b\x32\x13.uworker_msg.CorpusH\x01\x88\x01\x01\x12\x13\n\x06\x65ngine\x18\x03 \x01(\tH\x02\x88\x01\x01\x12*\n\x1dproject_qualified_target_name\x18\x04 \x01(\tH\x03\x88\x01\x01\x42\t\n\x07_corpusB\x15\n\x13_regressions_corpusB\t\n\x07_engineB \n\x1e_project_qualified_target_name\"\xa6\x02\n\x06\x43orpus\x12\x38\n\x0b\x63orpus_urls\x18\x01 \x03(\x0b\x32#.uworker_msg.Corpus.CorpusUrlsEntry\x12:\n\x11last_updated_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x00\x88\x01\x01\x12\x14\n\x07gcs_url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x13\n\x0bupload_urls\x18\x04 \x03(\t\x12\x17\n\nbackup_url\x18\x05 \x01(\tH\x02\x88\x01\x01\x1a\x31\n\x0f\x43orpusUrlsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x14\n\x12_last_updated_timeB\n\n\x08_gcs_urlB\r\n\x0b_backup_url\"\x92\x02\n\x11MinimizeTaskInput\x12 \n\x13testcase_upload_url\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1f\n\x12testcase_blob_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12!\n\x14stacktrace_blob_name\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\"\n\x15stacktrace_upload_url\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x11\n\targuments\x18\x05 \x03(\tB\x16\n\x14_testcase_upload_urlB\x15\n\x13_testcase_blob_nameB\x17\n\x15_stacktrace_blob_nameB\x18\n\x16_stacktrace_upload_url\",\n\x13RegressionTaskInput\x12\x15\n\rbad_revisions\x18\x01 \x03(\x03\"\x81\x02\n\x14ProgressionTaskInput\x12\x1a\n\rcustom_binary\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x15\n\rbad_revisions\x18\x02 \x03(\x03\x12$\n\x17regression_testcase_url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x16\n\tblob_name\x18\x04 \x01(\tH\x02\x88\x01\x01\x12\"\n\x15stacktrace_upload_url\x18\x05 \x01(\tH\x03\x88\x01\x01\x42\x10\n\x0e_custom_binaryB\x1a\n\x18_regression_testcase_urlB\x0c\n\n_blob_nameB\x18\n\x16_stacktrace_upload_url\"\xcb\x01\n\x19\x43rossPollinateFuzzerProto\x12.\n\x0b\x66uzz_target\x18\x01 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00\x88\x01\x01\x12\x1f\n\x12\x62\x61\x63kup_bucket_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1f\n\x12\x63orpus_engine_name\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x0e\n\x0c_fuzz_targetB\x15\n\x13_backup_bucket_nameB\x15\n\x13_corpus_engine_name\"\xb9\x05\n\x16\x43orpusPruningTaskInput\x12.\n\x0b\x66uzz_target\x18\x01 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00\x88\x01\x01\x12\"\n\x15last_execution_failed\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12G\n\x17\x63ross_pollinate_fuzzers\x18\x03 \x03(\x0b\x32&.uworker_msg.CrossPollinateFuzzerProto\x12\x32\n\x06\x63orpus\x18\x04 \x01(\x0b\x32\x1d.uworker_msg.FuzzTargetCorpusH\x02\x88\x01\x01\x12=\n\x11quarantine_corpus\x18\x05 \x01(\x0b\x32\x1d.uworker_msg.FuzzTargetCorpusH\x03\x88\x01\x01\x12%\n\x18\x63orpus_crashes_blob_name\x18\x06 \x01(\tH\x04\x88\x01\x01\x12&\n\x19\x63orpus_crashes_upload_url\x18\x07 \x01(\tH\x05\x88\x01\x01\x12!\n\x14\x64\x61ted_backup_gcs_url\x18\x08 \x01(\tH\x06\x88\x01\x01\x12\"\n\x15latest_backup_gcs_url\x18\t \x01(\tH\x07\x88\x01\x01\x12$\n\x17\x64\x61ted_backup_signed_url\x18\n \x01(\tH\x08\x88\x01\x01\x42\x0e\n\x0c_fuzz_targetB\x18\n\x16_last_execution_failedB\t\n\x07_corpusB\x14\n\x12_quarantine_corpusB\x1b\n\x19_corpus_crashes_blob_nameB\x1c\n\x1a_corpus_crashes_upload_urlB\x17\n\x15_dated_backup_gcs_urlB\x18\n\x16_latest_backup_gcs_urlB\x1a\n\x18_dated_backup_signed_url\"\xa9\x0c\n\x05Input\x12+\n\x08testcase\x18\x01 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00\x88\x01\x01\x12;\n\x18testcase_upload_metadata\x18\x02 \x01(\x0b\x32\x14.google.protobuf.AnyH\x01\x88\x01\x01\x12\x18\n\x0btestcase_id\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x37\n\x0buworker_env\x18\x04 \x03(\x0b\x32\".uworker_msg.Input.UworkerEnvEntry\x12\x15\n\x08job_type\x18\x06 \x01(\tH\x03\x88\x01\x01\x12&\n\x19uworker_output_upload_url\x18\x07 \x01(\tH\x04\x88\x01\x01\x12>\n\x12variant_task_input\x18\x08 \x01(\x0b\x32\x1d.uworker_msg.VariantTaskInputH\x05\x88\x01\x01\x12\x18\n\x0b\x66uzzer_name\x18\t \x01(\tH\x06\x88\x01\x01\x12\x31\n\x0bsetup_input\x18\n \x01(\x0b\x32\x17.uworker_msg.SetupInputH\x07\x88\x01\x01\x12>\n\x12\x61nalyze_task_input\x18\x0b \x01(\x0b\x32\x1d.uworker_msg.AnalyzeTaskInputH\x08\x88\x01\x01\x12K\n\x19\x63orpus_pruning_task_input\x18\x0c \x01(\x0b\x32#.uworker_msg.CorpusPruningTaskInputH\t\x88\x01\x01\x12\x38\n\x0f\x66uzz_task_input\x18\r \x01(\x0b\x32\x1a.uworker_msg.FuzzTaskInputH\n\x88\x01\x01\x12@\n\x13minimize_task_input\x18\x0e \x01(\x0b\x32\x1e.uworker_msg.MinimizeTaskInputH\x0b\x88\x01\x01\x12\x46\n\x16progression_task_input\x18\x0f \x01(\x0b\x32!.uworker_msg.ProgressionTaskInputH\x0c\x88\x01\x01\x12\x44\n\x15regression_task_input\x18\x10 \x01(\x0b\x32 .uworker_msg.RegressionTaskInputH\r\x88\x01\x01\x12\x42\n\x14symbolize_task_input\x18\x11 \x01(\x0b\x32\x1f.uworker_msg.SymbolizeTaskInputH\x0e\x88\x01\x01\x12\x18\n\x0bmodule_name\x18\x12 \x01(\tH\x0f\x88\x01\x01\x12>\n\x15preprocess_start_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x10\x88\x01\x01\x12$\n\x1cglobal_blacklisted_functions\x18\x14 \x03(\t\x12.\n\x0b\x66uzz_target\x18\x15 \x01(\x0b\x32\x14.google.protobuf.AnyH\x11\x88\x01\x01\x12<\n\x13preprocess_end_time\x18\x16 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x12\x88\x01\x01\x1a\x31\n\x0fUworkerEnvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0b\n\t_testcaseB\x1b\n\x19_testcase_upload_metadataB\x0e\n\x0c_testcase_idB\x0b\n\t_job_typeB\x1c\n\x1a_uworker_output_upload_urlB\x15\n\x13_variant_task_inputB\x0e\n\x0c_fuzzer_nameB\x0e\n\x0c_setup_inputB\x15\n\x13_analyze_task_inputB\x1c\n\x1a_corpus_pruning_task_inputB\x12\n\x10_fuzz_task_inputB\x16\n\x14_minimize_task_inputB\x19\n\x17_progression_task_inputB\x18\n\x16_regression_task_inputB\x17\n\x15_symbolize_task_inputB\x0e\n\x0c_module_nameB\x18\n\x16_preprocess_start_timeB\x0e\n\x0c_fuzz_targetB\x16\n\x14_preprocess_end_time\"H\n\x10VariantTaskInput\x12\x1e\n\x11original_job_type\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x14\n\x12_original_job_type\"\xc7\x02\n\x13SymbolizeTaskOutput\x12\x17\n\ncrash_type\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1a\n\rcrash_address\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0b\x63rash_state\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1d\n\x10\x63rash_stacktrace\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x17\n\nsymbolized\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x1b\n\x0e\x63rash_revision\x18\x06 \x01(\x03H\x05\x88\x01\x01\x12\x16\n\tbuild_url\x18\x07 \x01(\tH\x06\x88\x01\x01\x42\r\n\x0b_crash_typeB\x10\n\x0e_crash_addressB\x0e\n\x0c_crash_stateB\x13\n\x11_crash_stacktraceB\r\n\x0b_symbolizedB\x11\n\x0f_crash_revisionB\x0c\n\n_build_url\"\x93\x06\n\x11\x41nalyzeTaskOutput\x12\x1b\n\x0e\x63rash_revision\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x1a\n\rabsolute_path\x18\x02 \x01(\tH\x01\x88\x01\x01\x12 \n\x13minimized_arguments\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1d\n\x10\x63rash_stacktrace\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1b\n\x0e\x63rash_info_set\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x16\n\thttp_flag\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x17\n\ncrash_type\x18\x07 \x01(\tH\x06\x88\x01\x01\x12\x1a\n\rcrash_address\x18\x08 \x01(\tH\x07\x88\x01\x01\x12\x18\n\x0b\x63rash_state\x18\t \x01(\tH\x08\x88\x01\x01\x12\x1a\n\rsecurity_flag\x18\n \x01(\x08H\t\x88\x01\x01\x12\x1e\n\x11security_severity\x18\x0b \x01(\x05H\n\x88\x01\x01\x12\"\n\x15one_time_crasher_flag\x18\x0c \x01(\x08H\x0b\x88\x01\x01\x12\x16\n\tbuild_key\x18\r \x01(\tH\x0c\x88\x01\x01\x12\x16\n\tbuild_url\x18\x0e \x01(\tH\r\x88\x01\x01\x12\x14\n\x07gn_args\x18\x0f \x01(\tH\x0e\x88\x01\x01\x12\x15\n\x08platform\x18\x10 \x01(\tH\x0f\x88\x01\x01\x12\x18\n\x0bplatform_id\x18\x11 \x01(\tH\x10\x88\x01\x01\x42\x11\n\x0f_crash_revisionB\x10\n\x0e_absolute_pathB\x16\n\x14_minimized_argumentsB\x13\n\x11_crash_stacktraceB\x11\n\x0f_crash_info_setB\x0c\n\n_http_flagB\r\n\x0b_crash_typeB\x10\n\x0e_crash_addressB\x0e\n\x0c_crash_stateB\x10\n\x0e_security_flagB\x14\n\x12_security_severityB\x18\n\x16_one_time_crasher_flagB\x0c\n\n_build_keyB\x0c\n\n_build_urlB\n\n\x08_gn_argsB\x0b\n\t_platformB\x0e\n\x0c_platform_id\"\xd1\x02\n\tCrashInfo\x12\x13\n\x06is_new\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12\x17\n\ncrash_type\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x18\n\x0b\x63rash_state\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1a\n\rsecurity_flag\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x1a\n\rcrash_address\x18\x07 \x01(\tH\x05\x88\x01\x01\x12\x1d\n\x10\x63rash_stacktrace\x18\x08 \x01(\tH\x06\x88\x01\x01\x12\x16\n\tunit_path\x18\t \x01(\tH\x07\x88\x01\x01\x42\t\n\x07_is_newB\x08\n\x06_countB\r\n\x0b_crash_typeB\x0e\n\x0c_crash_stateB\x10\n\x0e_security_flagB\x10\n\x0e_crash_addressB\x13\n\x11_crash_stacktraceB\x0c\n\n_unit_path\"\xcb\x01\n\x1bStoreFuzzerRunResultsOutput\x12\x1f\n\x12\x66uzzer_return_code\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12&\n\x19generated_testcase_string\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1b\n\x0e\x63onsole_output\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x15\n\x13_fuzzer_return_codeB\x1c\n\x1a_generated_testcase_stringB\x11\n\x0f_console_output\"\xc8\x07\n\rFuzzTaskCrash\x12\x16\n\tfile_path\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\ncrash_time\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x18\n\x0breturn_code\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x15\n\rresource_list\x18\x04 \x03(\t\x12\x10\n\x08gestures\x18\x05 \x03(\t\x12\x16\n\targuments\x18\x06 \x01(\tH\x03\x88\x01\x01\x12\x1a\n\x12\x66uzzing_strategies\x18\x07 \x03(\t\x12\x1a\n\rsecurity_flag\x18\x08 \x01(\x08H\x04\x88\x01\x01\x12\x1e\n\x11should_be_ignored\x18\t \x01(\x08H\x05\x88\x01\x01\x12\x16\n\thttp_flag\x18\n \x01(\x08H\x06\x88\x01\x01\x12%\n\x18\x61pplication_command_line\x18\x0b \x01(\tH\x07\x88\x01\x01\x12*\n\x1dunsymbolized_crash_stacktrace\x18\x0c \x01(\tH\x08\x88\x01\x01\x12\x17\n\ncrash_type\x18\r \x01(\tH\t\x88\x01\x01\x12\x1a\n\rcrash_address\x18\x0e \x01(\tH\n\x88\x01\x01\x12\x18\n\x0b\x63rash_state\x18\x0f \x01(\tH\x0b\x88\x01\x01\x12\x1d\n\x10\x63rash_stacktrace\x18\x10 \x01(\tH\x0c\x88\x01\x01\x12\x18\n\x10\x63rash_categories\x18\x11 \x03(\t\x12\x10\n\x03key\x18\x12 \x01(\tH\r\x88\x01\x01\x12\x15\n\x08is_valid\x18\x14 \x01(\x08H\x0e\x88\x01\x01\x12\x17\n\nfuzzed_key\x18\x15 \x01(\tH\x0f\x88\x01\x01\x12\x1a\n\rabsolute_path\x18\x16 \x01(\tH\x10\x88\x01\x01\x12\x1d\n\x10\x61rchive_filename\x18\x17 \x01(\tH\x11\x88\x01\x01\x12\x15\n\x08\x61rchived\x18\x18 \x01(\x08H\x12\x88\x01\x01\x42\x0c\n\n_file_pathB\r\n\x0b_crash_timeB\x0e\n\x0c_return_codeB\x0c\n\n_argumentsB\x10\n\x0e_security_flagB\x14\n\x12_should_be_ignoredB\x0c\n\n_http_flagB\x1b\n\x19_application_command_lineB \n\x1e_unsymbolized_crash_stacktraceB\r\n\x0b_crash_typeB\x10\n\x0e_crash_addressB\x0e\n\x0c_crash_stateB\x13\n\x11_crash_stacktraceB\x06\n\x04_keyB\x0b\n\t_is_validB\r\n\x0b_fuzzed_keyB\x10\n\x0e_absolute_pathB\x13\n\x11_archive_filenameB\x0b\n\t_archived\"\xf1\x02\n\x0b\x46uzzContext\x12\x14\n\x07redzone\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x1a\n\rdisable_ubsan\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x1c\n\x0fwindow_argument\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1f\n\x12timeout_multiplier\x18\x04 \x01(\x02H\x03\x88\x01\x01\x12\x19\n\x0ctest_timeout\x18\x05 \x01(\x05H\x04\x88\x01\x01\x12\x45\n\x0f\x66uzzer_metadata\x18\x06 \x03(\x0b\x32,.uworker_msg.FuzzContext.FuzzerMetadataEntry\x1a\x35\n\x13\x46uzzerMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_redzoneB\x10\n\x0e_disable_ubsanB\x12\n\x10_window_argumentB\x15\n\x13_timeout_multiplierB\x0f\n\r_test_timeout\"\xff\x01\n\x12\x46uzzTaskCrashGroup\x12.\n\x07\x63ontext\x18\x01 \x01(\x0b\x32\x18.uworker_msg.FuzzContextH\x00\x88\x01\x01\x12+\n\x07\x63rashes\x18\x02 \x03(\x0b\x32\x1a.uworker_msg.FuzzTaskCrash\x12\x33\n\nmain_crash\x18\x03 \x01(\x0b\x32\x1a.uworker_msg.FuzzTaskCrashH\x01\x88\x01\x01\x12\"\n\x15one_time_crasher_flag\x18\x04 \x01(\x08H\x02\x88\x01\x01\x42\n\n\x08_contextB\r\n\x0b_main_crashB\x18\n\x16_one_time_crasher_flag\"\xae\x01\n\x0f\x46uzzerRunOutput\x12\x13\n\x06output\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x18\n\x0breturn_code\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12-\n\ttimestamp\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x15\n\x08testcase\x18\x04 \x01(\x0cH\x02\x88\x01\x01\x42\t\n\x07_outputB\x0e\n\x0c_return_codeB\x0b\n\t_testcase\"\x94\t\n\x0e\x46uzzTaskOutput\x12(\n\x1b\x66ully_qualified_fuzzer_name\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0e\x63rash_revision\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1e\n\x11job_run_timestamp\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x1f\n\x12testcases_executed\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12I\n\x12\x66uzzer_run_results\x18\x08 \x01(\x0b\x32(.uworker_msg.StoreFuzzerRunResultsOutputH\x04\x88\x01\x01\x12\x1e\n\x11new_targets_count\x18\t \x01(\x05H\x05\x88\x01\x01\x12\x1c\n\x0f\x66uzzer_revision\x18\n \x01(\x05H\x06\x88\x01\x01\x12\x14\n\x0c\x66uzz_targets\x18\x0b \x03(\t\x12\x1a\n\x12testcase_run_jsons\x18\x0c \x03(\t\x12\x35\n\x0c\x63rash_groups\x18\r \x03(\x0b\x32\x1f.uworker_msg.FuzzTaskCrashGroup\x12/\n\nbuild_data\x18\x0e \x01(\x0b\x32\x16.uworker_msg.BuildDataH\x07\x88\x01\x01\x12\x19\n\x0c\x61pp_revision\x18\x0f \x01(\x03H\x08\x88\x01\x01\x12\x38\n\x12\x66uzzer_run_outputs\x18\x10 \x03(\x0b\x32\x1c.uworker_msg.FuzzerRunOutput\x12\x16\n\tbuild_key\x18\x11 \x01(\tH\t\x88\x01\x01\x12\x16\n\tbuild_url\x18\x12 \x01(\tH\n\x88\x01\x01\x12\x14\n\x07gn_args\x18\x13 \x01(\tH\x0b\x88\x01\x01\x12 \n\x13testcases_generated\x18\x14 \x01(\x03H\x0c\x88\x01\x01\x12\x44\n\x1ctestcase_generation_duration\x18\x15 \x01(\x0b\x32\x19.google.protobuf.DurationH\r\x88\x01\x01\x12\x43\n\x1btestcase_execution_duration\x18\x16 \x01(\x0b\x32\x19.google.protobuf.DurationH\x0e\x88\x01\x01\x12\x38\n\x10\x66uzzing_duration\x18\x17 \x01(\x0b\x32\x19.google.protobuf.DurationH\x0f\x88\x01\x01\x42\x1e\n\x1c_fully_qualified_fuzzer_nameB\x11\n\x0f_crash_revisionB\x14\n\x12_job_run_timestampB\x15\n\x13_testcases_executedB\x15\n\x13_fuzzer_run_resultsB\x14\n\x12_new_targets_countB\x12\n\x10_fuzzer_revisionB\r\n\x0b_build_dataB\x0f\n\r_app_revisionB\x0c\n\n_build_keyB\x0c\n\n_build_urlB\n\n\x08_gn_argsB\x16\n\x14_testcases_generatedB\x1f\n\x1d_testcase_generation_durationB\x1e\n\x1c_testcase_execution_durationB\x13\n\x11_fuzzing_duration\"\xef\x05\n\x12MinimizeTaskOutput\x12X\n\x16last_crash_result_dict\x18\x01 \x03(\x0b\x32\x38.uworker_msg.MinimizeTaskOutput.LastCrashResultDictEntry\x12\x18\n\x0b\x66laky_stack\x18\x02 \x01(\x08H\x00\x88\x01\x01\x12&\n\x19security_severity_updated\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x1e\n\x11security_severity\x18\x04 \x01(\x05H\x02\x88\x01\x01\x12\x1f\n\x12minimization_phase\x18\x05 \x01(\x05H\x03\x88\x01\x01\x12\x10\n\x08gestures\x18\x06 \x03(\t\x12\x1b\n\x0eminimized_keys\x18\x07 \x01(\tH\x04\x88\x01\x01\x12 \n\x13minimized_arguments\x18\x08 \x01(\tH\x05\x88\x01\x01\x12\x1a\n\rarchive_state\x18\t \x01(\x05H\x06\x88\x01\x01\x12\x1a\n\rabsolute_path\x18\n \x01(\tH\x07\x88\x01\x01\x12S\n\x13memory_tool_options\x18\x0b \x03(\x0b\x32\x36.uworker_msg.MinimizeTaskOutput.MemoryToolOptionsEntry\x1a:\n\x18LastCrashResultDictEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x38\n\x16MemoryToolOptionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0e\n\x0c_flaky_stackB\x1c\n\x1a_security_severity_updatedB\x14\n\x12_security_severityB\x15\n\x13_minimization_phaseB\x11\n\x0f_minimized_keysB\x16\n\x14_minimized_argumentsB\x10\n\x0e_archive_stateB\x10\n\x0e_absolute_path\"\xfb\x02\n\x14RegressionTaskOutput\x12#\n\x16regression_range_start\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12!\n\x14regression_range_end\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12 \n\x13last_regression_min\x18\x03 \x01(\x03H\x02\x88\x01\x01\x12 \n\x13last_regression_max\x18\x04 \x01(\x03H\x03\x88\x01\x01\x12/\n\x0f\x62uild_data_list\x18\x05 \x03(\x0b\x32\x16.uworker_msg.BuildData\x12%\n\x18is_testcase_reproducible\x18\x06 \x01(\x08H\x04\x88\x01\x01\x42\x19\n\x17_regression_range_startB\x17\n\x15_regression_range_endB\x16\n\x14_last_regression_minB\x16\n\x14_last_regression_maxB\x1b\n\x19_is_testcase_reproducible\"\xa3\x02\n\x11VariantTaskOutput\x12\x13\n\x06status\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x15\n\x08revision\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12\x17\n\ncrash_type\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x18\n\x0b\x63rash_state\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1a\n\rsecurity_flag\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x17\n\nis_similar\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x15\n\x08platform\x18\x07 \x01(\tH\x06\x88\x01\x01\x42\t\n\x07_statusB\x0b\n\t_revisionB\r\n\x0b_crash_typeB\x0e\n\x0c_crash_stateB\x10\n\x0e_security_flagB\r\n\x0b_is_similarB\x0b\n\t_platform\"\xe7\x01\n\tBuildData\x12\x15\n\x08revision\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x19\n\x0cis_bad_build\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\'\n\x1ashould_ignore_crash_result\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12%\n\x18\x62uild_run_console_output\x18\x04 \x01(\tH\x03\x88\x01\x01\x42\x0b\n\t_revisionB\x0f\n\r_is_bad_buildB\x1d\n\x1b_should_ignore_crash_resultB\x1b\n\x19_build_run_console_output\"\xc8\x04\n\x15ProgressionTaskOutput\x12\x19\n\x0cmin_revision\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x19\n\x0cmax_revision\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12\x1c\n\x0f\x63rash_on_latest\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12$\n\x17\x63rash_on_latest_message\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1b\n\x0e\x63rash_revision\x18\x05 \x01(\x03H\x04\x88\x01\x01\x12)\n\x1clast_tested_crash_stacktrace\x18\x06 \x01(\tH\x05\x88\x01\x01\x12!\n\x14last_progression_min\x18\x07 \x01(\x03H\x06\x88\x01\x01\x12!\n\x14last_progression_max\x18\x08 \x01(\x03H\x07\x88\x01\x01\x12#\n\x16\x63lear_min_max_metadata\x18\t \x01(\x08H\x08\x88\x01\x01\x12/\n\x0f\x62uild_data_list\x18\x0b \x03(\x0b\x32\x16.uworker_msg.BuildDataB\x0f\n\r_min_revisionB\x0f\n\r_max_revisionB\x12\n\x10_crash_on_latestB\x1a\n\x18_crash_on_latest_messageB\x11\n\x0f_crash_revisionB\x1f\n\x1d_last_tested_crash_stacktraceB\x17\n\x15_last_progression_minB\x17\n\x15_last_progression_maxB\x19\n\x17_clear_min_max_metadata\"\xc6\x03\n\x1a\x43rossPollinationStatistics\x12#\n\x16project_qualified_name\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07sources\x18\x02 \x01(\tH\x01\x88\x01\x01\x12 \n\x13initial_corpus_size\x18\x03 \x01(\x03H\x02\x88\x01\x01\x12\x18\n\x0b\x63orpus_size\x18\x04 \x01(\x03H\x03\x88\x01\x01\x12\"\n\x15initial_edge_coverage\x18\x05 \x01(\x03H\x04\x88\x01\x01\x12\x1a\n\redge_coverage\x18\x06 \x01(\x03H\x05\x88\x01\x01\x12%\n\x18initial_feature_coverage\x18\x07 \x01(\x03H\x06\x88\x01\x01\x12\x1d\n\x10\x66\x65\x61ture_coverage\x18\x08 \x01(\x03H\x07\x88\x01\x01\x42\x19\n\x17_project_qualified_nameB\n\n\x08_sourcesB\x16\n\x14_initial_corpus_sizeB\x0e\n\x0c_corpus_sizeB\x18\n\x16_initial_edge_coverageB\x10\n\x0e_edge_coverageB\x1b\n\x19_initial_feature_coverageB\x13\n\x11_feature_coverage\"\x97\x04\n\x13\x43overageInformation\x12\x19\n\x0cproject_name\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x32\n\ttimestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01\x88\x01\x01\x12\x1e\n\x11\x63orpus_size_units\x18\x03 \x01(\x03H\x02\x88\x01\x01\x12\x1e\n\x11\x63orpus_size_bytes\x18\x04 \x01(\x03H\x03\x88\x01\x01\x12\x1c\n\x0f\x63orpus_location\x18\x05 \x01(\tH\x04\x88\x01\x01\x12#\n\x16\x63orpus_backup_location\x18\x06 \x01(\tH\x05\x88\x01\x01\x12\"\n\x15quarantine_size_units\x18\x07 \x01(\x03H\x06\x88\x01\x01\x12\"\n\x15quarantine_size_bytes\x18\x08 \x01(\x03H\x07\x88\x01\x01\x12 \n\x13quarantine_location\x18\t \x01(\tH\x08\x88\x01\x01\x42\x0f\n\r_project_nameB\x0c\n\n_timestampB\x14\n\x12_corpus_size_unitsB\x14\n\x12_corpus_size_bytesB\x12\n\x10_corpus_locationB\x19\n\x17_corpus_backup_locationB\x18\n\x16_quarantine_size_unitsB\x18\n\x16_quarantine_size_bytesB\x16\n\x14_quarantine_location\"\xa5\x03\n\x17\x43orpusPruningTaskOutput\x12M\n\x17\x63ross_pollination_stats\x18\x01 \x01(\x0b\x32\'.uworker_msg.CrossPollinationStatisticsH\x00\x88\x01\x01\x12<\n\rcoverage_info\x18\x02 \x01(\x0b\x32 .uworker_msg.CoverageInformationH\x01\x88\x01\x01\x12\x1f\n\x12\x66uzzer_binary_name\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1b\n\x0e\x63rash_revision\x18\x04 \x01(\x03H\x03\x88\x01\x01\x12\'\n\x07\x63rashes\x18\x05 \x03(\x0b\x32\x16.uworker_msg.CrashInfo\x12#\n\x16\x63orpus_backup_uploaded\x18\x06 \x01(\x08H\x04\x88\x01\x01\x42\x1a\n\x18_cross_pollination_statsB\x10\n\x0e_coverage_infoB\x15\n\x13_fuzzer_binary_nameB\x11\n\x0f_crash_revisionB\x19\n\x17_corpus_backup_uploaded\"\xc5\t\n\x06Output\x12/\n\nerror_type\x18\x03 \x01(\x0e\x32\x16.uworker_msg.ErrorTypeH\x00\x88\x01\x01\x12.\n\ruworker_input\x18\x04 \x01(\x0b\x32\x12.uworker_msg.InputH\x01\x88\x01\x01\x12\x19\n\x0ctest_timeout\x18\x05 \x01(\x02H\x02\x88\x01\x01\x12\x17\n\ncrash_time\x18\x06 \x01(\x02H\x03\x88\x01\x01\x12$\n\x17\x63rash_stacktrace_output\x18\x07 \x01(\tH\x04\x88\x01\x01\x12\x15\n\x08\x62ot_name\x18\x12 \x01(\tH\x05\x88\x01\x01\x12\x18\n\x0bplatform_id\x18\x13 \x01(\tH\x06\x88\x01\x01\x12@\n\x13\x61nalyze_task_output\x18\x08 \x01(\x0b\x32\x1e.uworker_msg.AnalyzeTaskOutputH\x07\x88\x01\x01\x12:\n\x10\x66uzz_task_output\x18\t \x01(\x0b\x32\x1b.uworker_msg.FuzzTaskOutputH\x08\x88\x01\x01\x12\x42\n\x14minimize_task_output\x18\n \x01(\x0b\x32\x1f.uworker_msg.MinimizeTaskOutputH\t\x88\x01\x01\x12\x46\n\x16regression_task_output\x18\x0b \x01(\x0b\x32!.uworker_msg.RegressionTaskOutputH\n\x88\x01\x01\x12H\n\x17progression_task_output\x18\x0c \x01(\x0b\x32\".uworker_msg.ProgressionTaskOutputH\x0b\x88\x01\x01\x12\x44\n\x15symbolize_task_output\x18\r \x01(\x0b\x32 .uworker_msg.SymbolizeTaskOutputH\x0c\x88\x01\x01\x12@\n\x13variant_task_output\x18\x0e \x01(\x0b\x32\x1e.uworker_msg.VariantTaskOutputH\r\x88\x01\x01\x12M\n\x1a\x63orpus_pruning_task_output\x18\x10 \x01(\x0b\x32$.uworker_msg.CorpusPruningTaskOutputH\x0e\x88\x01\x01\x12\x1b\n\x0eissue_metadata\x18\x14 \x01(\tH\x0f\x88\x01\x01\x12\x1a\n\rerror_message\x18\x0f \x01(\tH\x10\x88\x01\x01\x42\r\n\x0b_error_typeB\x10\n\x0e_uworker_inputB\x0f\n\r_test_timeoutB\r\n\x0b_crash_timeB\x1a\n\x18_crash_stacktrace_outputB\x0b\n\t_bot_nameB\x0e\n\x0c_platform_idB\x16\n\x14_analyze_task_outputB\x13\n\x11_fuzz_task_outputB\x17\n\x15_minimize_task_outputB\x19\n\x17_regression_task_outputB\x1a\n\x18_progression_task_outputB\x18\n\x16_symbolize_task_outputB\x16\n\x14_variant_task_outputB\x1d\n\x1b_corpus_pruning_task_outputB\x11\n\x0f_issue_metadataB\x10\n\x0e_error_message*\x95\t\n\tErrorType\x12\x0c\n\x08NO_ERROR\x10\x00\x12\x17\n\x13\x41NALYZE_BUILD_SETUP\x10\x01\x12\x14\n\x10\x41NALYZE_NO_CRASH\x10\x02\x12\x1d\n\x19\x41NALYZE_NO_REVISIONS_LIST\x10\x03\x12\x1d\n\x19\x41NALYZE_NO_REVISION_INDEX\x10\x04\x12\x12\n\x0eTESTCASE_SETUP\x10\x05\x12\r\n\tUNHANDLED\x10\x06\x12\x17\n\x13VARIANT_BUILD_SETUP\x10\x07\x12\x12\n\x0eMINIMIZE_SETUP\x10\x08\x12\x1c\n\x18\x46UZZ_BUILD_SETUP_FAILURE\x10\t\x12\"\n\x1e\x46UZZ_DATA_BUNDLE_SETUP_FAILURE\x10\n\x12\x12\n\x0e\x46UZZ_NO_FUZZER\x10\x0b\x12 \n\x1c\x46UZZ_NO_FUZZ_TARGET_SELECTED\x10\r\x12#\n\x1fPROGRESSION_REVISION_LIST_ERROR\x10\x0e\x12\x1f\n\x1bPROGRESSION_BUILD_NOT_FOUND\x10\x0f\x12\x18\n\x14PROGRESSION_NO_CRASH\x10\x10\x12!\n\x1dPROGRESSION_BAD_STATE_MIN_MAX\x10\x11\x12\x17\n\x13PROGRESSION_TIMEOUT\x10\x12\x12\x19\n\x15PROGRESSION_BAD_BUILD\x10\x13\x12!\n\x1dPROGRESSION_BUILD_SETUP_ERROR\x10\x14\x12\"\n\x1eREGRESSION_REVISION_LIST_ERROR\x10\x15\x12\x1e\n\x1aREGRESSION_BUILD_NOT_FOUND\x10\x16\x12 \n\x1cREGRESSION_BUILD_SETUP_ERROR\x10\x17\x12\x1e\n\x1aREGRESSION_BAD_BUILD_ERROR\x10\x18\x12\x17\n\x13REGRESSION_NO_CRASH\x10\x19\x12\x1c\n\x18REGRESSION_TIMEOUT_ERROR\x10\x1a\x12\x31\n-REGRESSION_LOW_CONFIDENCE_IN_REGRESSION_RANGE\x10\x1b\x12\x1f\n\x1bSYMBOLIZE_BUILD_SETUP_ERROR\x10\x1c\x12!\n\x1dMINIMIZE_UNREPRODUCIBLE_CRASH\x10\x1d\x12\x1c\n\x18MINIMIZE_CRASH_TOO_FLAKY\x10\x1e\x12\x1e\n\x1aMINIMIZE_DEADLINE_EXCEEDED\x10\x1f\x12\x31\n-MINIMIZE_DEADLINE_EXCEEDED_IN_MAIN_FILE_PHASE\x10 \x12)\n%LIBFUZZER_MINIMIZATION_UNREPRODUCIBLE\x10!\x12!\n\x1dLIBFUZZER_MINIMIZATION_FAILED\x10\"\x12&\n\"CORPUS_PRUNING_FUZZER_SETUP_FAILED\x10#\x12\x18\n\x14\x43ORPUS_PRUNING_ERROR\x10$\x12\x12\n\x0e\x46UZZ_BAD_BUILD\x10%\x12\"\n\x1e\x41NALYZE_CLOSE_INVALID_UPLOADED\x10&b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n.clusterfuzz/_internal/protos/uworker_msg.proto\x12\x0buworker_msg\x1a\x19google/protobuf/any.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/duration.proto\"\x85\x03\n\nSetupInput\x12)\n\x06\x66uzzer\x18\x01 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00\x88\x01\x01\x12\x18\n\x0b\x66uzzer_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\"\n\x15\x66uzzer_log_upload_url\x18\x04 \x01(\tH\x02\x88\x01\x01\x12 \n\x13\x66uzzer_download_url\x18\x05 \x01(\tH\x03\x88\x01\x01\x12\"\n\x15testcase_download_url\x18\x06 \x01(\tH\x04\x88\x01\x01\x12$\n\x1cglobal_blacklisted_functions\x18\x07 \x03(\t\x12;\n\x14\x64\x61ta_bundle_corpuses\x18\x08 \x03(\x0b\x32\x1d.uworker_msg.DataBundleCorpusB\t\n\x07_fuzzerB\x0e\n\x0c_fuzzer_nameB\x18\n\x16_fuzzer_log_upload_urlB\x16\n\x14_fuzzer_download_urlB\x18\n\x16_testcase_download_url\")\n\x10\x41nalyzeTaskInput\x12\x15\n\rbad_revisions\x18\x01 \x03(\x03\"P\n\x12SymbolizeTaskInput\x12!\n\x14old_crash_stacktrace\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x17\n\x15_old_crash_stacktrace\"C\n\rBlobUploadUrl\x12\x10\n\x03key\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x10\n\x03url\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x06\n\x04_keyB\x06\n\x04_url\"\xcb\x04\n\rFuzzTaskInput\x12\'\n\x1asample_testcase_upload_key\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\'\n\x1asample_testcase_upload_url\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\"\n\x15script_log_upload_url\x18\x03 \x01(\tH\x02\x88\x01\x01\x12.\n\x0b\x66uzz_target\x18\x04 \x01(\x0b\x32\x14.google.protobuf.AnyH\x03\x88\x01\x01\x12\x32\n\x06\x63orpus\x18\x05 \x01(\x0b\x32\x1d.uworker_msg.FuzzTargetCorpusH\x04\x88\x01\x01\x12$\n\x1cglobal_blacklisted_functions\x18\x06 \x03(\t\x12\x35\n\x11\x63rash_upload_urls\x18\x07 \x03(\x0b\x32\x1a.uworker_msg.BlobUploadUrl\x12$\n\x06trials\x18\x08 \x03(\x0b\x32\x14.google.protobuf.Any\x12\x1a\n\rweb_tests_url\x18\t \x01(\tH\x05\x88\x01\x01\x12\"\n\x15script_log_upload_key\x18\n \x01(\tH\x06\x88\x01\x01\x42\x1d\n\x1b_sample_testcase_upload_keyB\x1d\n\x1b_sample_testcase_upload_urlB\x18\n\x16_script_log_upload_urlB\x0e\n\x0c_fuzz_targetB\t\n\x07_corpusB\x10\n\x0e_web_tests_urlB\x18\n\x16_script_log_upload_key\"\x89\x01\n\x10\x44\x61taBundleCorpus\x12.\n\x0b\x64\x61ta_bundle\x18\x01 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00\x88\x01\x01\x12\x14\n\x07gcs_url\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x13\n\x0b\x63orpus_urls\x18\x03 \x03(\tB\x0e\n\x0c_data_bundleB\n\n\x08_gcs_url\"\x82\x02\n\x10\x46uzzTargetCorpus\x12(\n\x06\x63orpus\x18\x01 \x01(\x0b\x32\x13.uworker_msg.CorpusH\x00\x88\x01\x01\x12\x34\n\x12regressions_corpus\x18\x02 \x01(\x0b\x32\x13.uworker_msg.CorpusH\x01\x88\x01\x01\x12\x13\n\x06\x65ngine\x18\x03 \x01(\tH\x02\x88\x01\x01\x12*\n\x1dproject_qualified_target_name\x18\x04 \x01(\tH\x03\x88\x01\x01\x42\t\n\x07_corpusB\x15\n\x13_regressions_corpusB\t\n\x07_engineB \n\x1e_project_qualified_target_name\"\xa6\x02\n\x06\x43orpus\x12\x38\n\x0b\x63orpus_urls\x18\x01 \x03(\x0b\x32#.uworker_msg.Corpus.CorpusUrlsEntry\x12:\n\x11last_updated_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x00\x88\x01\x01\x12\x14\n\x07gcs_url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x13\n\x0bupload_urls\x18\x04 \x03(\t\x12\x17\n\nbackup_url\x18\x05 \x01(\tH\x02\x88\x01\x01\x1a\x31\n\x0f\x43orpusUrlsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x14\n\x12_last_updated_timeB\n\n\x08_gcs_urlB\r\n\x0b_backup_url\"\x92\x02\n\x11MinimizeTaskInput\x12 \n\x13testcase_upload_url\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1f\n\x12testcase_blob_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12!\n\x14stacktrace_blob_name\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\"\n\x15stacktrace_upload_url\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x11\n\targuments\x18\x05 \x03(\tB\x16\n\x14_testcase_upload_urlB\x15\n\x13_testcase_blob_nameB\x17\n\x15_stacktrace_blob_nameB\x18\n\x16_stacktrace_upload_url\",\n\x13RegressionTaskInput\x12\x15\n\rbad_revisions\x18\x01 \x03(\x03\"\x81\x02\n\x14ProgressionTaskInput\x12\x1a\n\rcustom_binary\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x15\n\rbad_revisions\x18\x02 \x03(\x03\x12$\n\x17regression_testcase_url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x16\n\tblob_name\x18\x04 \x01(\tH\x02\x88\x01\x01\x12\"\n\x15stacktrace_upload_url\x18\x05 \x01(\tH\x03\x88\x01\x01\x42\x10\n\x0e_custom_binaryB\x1a\n\x18_regression_testcase_urlB\x0c\n\n_blob_nameB\x18\n\x16_stacktrace_upload_url\"\xcb\x01\n\x19\x43rossPollinateFuzzerProto\x12.\n\x0b\x66uzz_target\x18\x01 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00\x88\x01\x01\x12\x1f\n\x12\x62\x61\x63kup_bucket_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1f\n\x12\x63orpus_engine_name\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x0e\n\x0c_fuzz_targetB\x15\n\x13_backup_bucket_nameB\x15\n\x13_corpus_engine_name\"\xb9\x05\n\x16\x43orpusPruningTaskInput\x12.\n\x0b\x66uzz_target\x18\x01 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00\x88\x01\x01\x12\"\n\x15last_execution_failed\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12G\n\x17\x63ross_pollinate_fuzzers\x18\x03 \x03(\x0b\x32&.uworker_msg.CrossPollinateFuzzerProto\x12\x32\n\x06\x63orpus\x18\x04 \x01(\x0b\x32\x1d.uworker_msg.FuzzTargetCorpusH\x02\x88\x01\x01\x12=\n\x11quarantine_corpus\x18\x05 \x01(\x0b\x32\x1d.uworker_msg.FuzzTargetCorpusH\x03\x88\x01\x01\x12%\n\x18\x63orpus_crashes_blob_name\x18\x06 \x01(\tH\x04\x88\x01\x01\x12&\n\x19\x63orpus_crashes_upload_url\x18\x07 \x01(\tH\x05\x88\x01\x01\x12!\n\x14\x64\x61ted_backup_gcs_url\x18\x08 \x01(\tH\x06\x88\x01\x01\x12\"\n\x15latest_backup_gcs_url\x18\t \x01(\tH\x07\x88\x01\x01\x12$\n\x17\x64\x61ted_backup_signed_url\x18\n \x01(\tH\x08\x88\x01\x01\x42\x0e\n\x0c_fuzz_targetB\x18\n\x16_last_execution_failedB\t\n\x07_corpusB\x14\n\x12_quarantine_corpusB\x1b\n\x19_corpus_crashes_blob_nameB\x1c\n\x1a_corpus_crashes_upload_urlB\x17\n\x15_dated_backup_gcs_urlB\x18\n\x16_latest_backup_gcs_urlB\x1a\n\x18_dated_backup_signed_url\"\xa9\x0c\n\x05Input\x12+\n\x08testcase\x18\x01 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00\x88\x01\x01\x12;\n\x18testcase_upload_metadata\x18\x02 \x01(\x0b\x32\x14.google.protobuf.AnyH\x01\x88\x01\x01\x12\x18\n\x0btestcase_id\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x37\n\x0buworker_env\x18\x04 \x03(\x0b\x32\".uworker_msg.Input.UworkerEnvEntry\x12\x15\n\x08job_type\x18\x06 \x01(\tH\x03\x88\x01\x01\x12&\n\x19uworker_output_upload_url\x18\x07 \x01(\tH\x04\x88\x01\x01\x12>\n\x12variant_task_input\x18\x08 \x01(\x0b\x32\x1d.uworker_msg.VariantTaskInputH\x05\x88\x01\x01\x12\x18\n\x0b\x66uzzer_name\x18\t \x01(\tH\x06\x88\x01\x01\x12\x31\n\x0bsetup_input\x18\n \x01(\x0b\x32\x17.uworker_msg.SetupInputH\x07\x88\x01\x01\x12>\n\x12\x61nalyze_task_input\x18\x0b \x01(\x0b\x32\x1d.uworker_msg.AnalyzeTaskInputH\x08\x88\x01\x01\x12K\n\x19\x63orpus_pruning_task_input\x18\x0c \x01(\x0b\x32#.uworker_msg.CorpusPruningTaskInputH\t\x88\x01\x01\x12\x38\n\x0f\x66uzz_task_input\x18\r \x01(\x0b\x32\x1a.uworker_msg.FuzzTaskInputH\n\x88\x01\x01\x12@\n\x13minimize_task_input\x18\x0e \x01(\x0b\x32\x1e.uworker_msg.MinimizeTaskInputH\x0b\x88\x01\x01\x12\x46\n\x16progression_task_input\x18\x0f \x01(\x0b\x32!.uworker_msg.ProgressionTaskInputH\x0c\x88\x01\x01\x12\x44\n\x15regression_task_input\x18\x10 \x01(\x0b\x32 .uworker_msg.RegressionTaskInputH\r\x88\x01\x01\x12\x42\n\x14symbolize_task_input\x18\x11 \x01(\x0b\x32\x1f.uworker_msg.SymbolizeTaskInputH\x0e\x88\x01\x01\x12\x18\n\x0bmodule_name\x18\x12 \x01(\tH\x0f\x88\x01\x01\x12>\n\x15preprocess_start_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x10\x88\x01\x01\x12$\n\x1cglobal_blacklisted_functions\x18\x14 \x03(\t\x12.\n\x0b\x66uzz_target\x18\x15 \x01(\x0b\x32\x14.google.protobuf.AnyH\x11\x88\x01\x01\x12<\n\x13preprocess_end_time\x18\x16 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x12\x88\x01\x01\x1a\x31\n\x0fUworkerEnvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0b\n\t_testcaseB\x1b\n\x19_testcase_upload_metadataB\x0e\n\x0c_testcase_idB\x0b\n\t_job_typeB\x1c\n\x1a_uworker_output_upload_urlB\x15\n\x13_variant_task_inputB\x0e\n\x0c_fuzzer_nameB\x0e\n\x0c_setup_inputB\x15\n\x13_analyze_task_inputB\x1c\n\x1a_corpus_pruning_task_inputB\x12\n\x10_fuzz_task_inputB\x16\n\x14_minimize_task_inputB\x19\n\x17_progression_task_inputB\x18\n\x16_regression_task_inputB\x17\n\x15_symbolize_task_inputB\x0e\n\x0c_module_nameB\x18\n\x16_preprocess_start_timeB\x0e\n\x0c_fuzz_targetB\x16\n\x14_preprocess_end_time\"H\n\x10VariantTaskInput\x12\x1e\n\x11original_job_type\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x14\n\x12_original_job_type\"\xc7\x02\n\x13SymbolizeTaskOutput\x12\x17\n\ncrash_type\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1a\n\rcrash_address\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0b\x63rash_state\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1d\n\x10\x63rash_stacktrace\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x17\n\nsymbolized\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x1b\n\x0e\x63rash_revision\x18\x06 \x01(\x03H\x05\x88\x01\x01\x12\x16\n\tbuild_url\x18\x07 \x01(\tH\x06\x88\x01\x01\x42\r\n\x0b_crash_typeB\x10\n\x0e_crash_addressB\x0e\n\x0c_crash_stateB\x13\n\x11_crash_stacktraceB\r\n\x0b_symbolizedB\x11\n\x0f_crash_revisionB\x0c\n\n_build_url\"\x93\x06\n\x11\x41nalyzeTaskOutput\x12\x1b\n\x0e\x63rash_revision\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x1a\n\rabsolute_path\x18\x02 \x01(\tH\x01\x88\x01\x01\x12 \n\x13minimized_arguments\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1d\n\x10\x63rash_stacktrace\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1b\n\x0e\x63rash_info_set\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x16\n\thttp_flag\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x17\n\ncrash_type\x18\x07 \x01(\tH\x06\x88\x01\x01\x12\x1a\n\rcrash_address\x18\x08 \x01(\tH\x07\x88\x01\x01\x12\x18\n\x0b\x63rash_state\x18\t \x01(\tH\x08\x88\x01\x01\x12\x1a\n\rsecurity_flag\x18\n \x01(\x08H\t\x88\x01\x01\x12\x1e\n\x11security_severity\x18\x0b \x01(\x05H\n\x88\x01\x01\x12\"\n\x15one_time_crasher_flag\x18\x0c \x01(\x08H\x0b\x88\x01\x01\x12\x16\n\tbuild_key\x18\r \x01(\tH\x0c\x88\x01\x01\x12\x16\n\tbuild_url\x18\x0e \x01(\tH\r\x88\x01\x01\x12\x14\n\x07gn_args\x18\x0f \x01(\tH\x0e\x88\x01\x01\x12\x15\n\x08platform\x18\x10 \x01(\tH\x0f\x88\x01\x01\x12\x18\n\x0bplatform_id\x18\x11 \x01(\tH\x10\x88\x01\x01\x42\x11\n\x0f_crash_revisionB\x10\n\x0e_absolute_pathB\x16\n\x14_minimized_argumentsB\x13\n\x11_crash_stacktraceB\x11\n\x0f_crash_info_setB\x0c\n\n_http_flagB\r\n\x0b_crash_typeB\x10\n\x0e_crash_addressB\x0e\n\x0c_crash_stateB\x10\n\x0e_security_flagB\x14\n\x12_security_severityB\x18\n\x16_one_time_crasher_flagB\x0c\n\n_build_keyB\x0c\n\n_build_urlB\n\n\x08_gn_argsB\x0b\n\t_platformB\x0e\n\x0c_platform_id\"\xd1\x02\n\tCrashInfo\x12\x13\n\x06is_new\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12\x17\n\ncrash_type\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x18\n\x0b\x63rash_state\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1a\n\rsecurity_flag\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x1a\n\rcrash_address\x18\x07 \x01(\tH\x05\x88\x01\x01\x12\x1d\n\x10\x63rash_stacktrace\x18\x08 \x01(\tH\x06\x88\x01\x01\x12\x16\n\tunit_path\x18\t \x01(\tH\x07\x88\x01\x01\x42\t\n\x07_is_newB\x08\n\x06_countB\r\n\x0b_crash_typeB\x0e\n\x0c_crash_stateB\x10\n\x0e_security_flagB\x10\n\x0e_crash_addressB\x13\n\x11_crash_stacktraceB\x0c\n\n_unit_path\"\xcb\x01\n\x1bStoreFuzzerRunResultsOutput\x12\x1f\n\x12\x66uzzer_return_code\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12&\n\x19generated_testcase_string\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1b\n\x0e\x63onsole_output\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x15\n\x13_fuzzer_return_codeB\x1c\n\x1a_generated_testcase_stringB\x11\n\x0f_console_output\"\xc8\x07\n\rFuzzTaskCrash\x12\x16\n\tfile_path\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\ncrash_time\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x18\n\x0breturn_code\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x15\n\rresource_list\x18\x04 \x03(\t\x12\x10\n\x08gestures\x18\x05 \x03(\t\x12\x16\n\targuments\x18\x06 \x01(\tH\x03\x88\x01\x01\x12\x1a\n\x12\x66uzzing_strategies\x18\x07 \x03(\t\x12\x1a\n\rsecurity_flag\x18\x08 \x01(\x08H\x04\x88\x01\x01\x12\x1e\n\x11should_be_ignored\x18\t \x01(\x08H\x05\x88\x01\x01\x12\x16\n\thttp_flag\x18\n \x01(\x08H\x06\x88\x01\x01\x12%\n\x18\x61pplication_command_line\x18\x0b \x01(\tH\x07\x88\x01\x01\x12*\n\x1dunsymbolized_crash_stacktrace\x18\x0c \x01(\tH\x08\x88\x01\x01\x12\x17\n\ncrash_type\x18\r \x01(\tH\t\x88\x01\x01\x12\x1a\n\rcrash_address\x18\x0e \x01(\tH\n\x88\x01\x01\x12\x18\n\x0b\x63rash_state\x18\x0f \x01(\tH\x0b\x88\x01\x01\x12\x1d\n\x10\x63rash_stacktrace\x18\x10 \x01(\tH\x0c\x88\x01\x01\x12\x18\n\x10\x63rash_categories\x18\x11 \x03(\t\x12\x10\n\x03key\x18\x12 \x01(\tH\r\x88\x01\x01\x12\x15\n\x08is_valid\x18\x14 \x01(\x08H\x0e\x88\x01\x01\x12\x17\n\nfuzzed_key\x18\x15 \x01(\tH\x0f\x88\x01\x01\x12\x1a\n\rabsolute_path\x18\x16 \x01(\tH\x10\x88\x01\x01\x12\x1d\n\x10\x61rchive_filename\x18\x17 \x01(\tH\x11\x88\x01\x01\x12\x15\n\x08\x61rchived\x18\x18 \x01(\x08H\x12\x88\x01\x01\x42\x0c\n\n_file_pathB\r\n\x0b_crash_timeB\x0e\n\x0c_return_codeB\x0c\n\n_argumentsB\x10\n\x0e_security_flagB\x14\n\x12_should_be_ignoredB\x0c\n\n_http_flagB\x1b\n\x19_application_command_lineB \n\x1e_unsymbolized_crash_stacktraceB\r\n\x0b_crash_typeB\x10\n\x0e_crash_addressB\x0e\n\x0c_crash_stateB\x13\n\x11_crash_stacktraceB\x06\n\x04_keyB\x0b\n\t_is_validB\r\n\x0b_fuzzed_keyB\x10\n\x0e_absolute_pathB\x13\n\x11_archive_filenameB\x0b\n\t_archived\"\xf1\x02\n\x0b\x46uzzContext\x12\x14\n\x07redzone\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x1a\n\rdisable_ubsan\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x1c\n\x0fwindow_argument\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1f\n\x12timeout_multiplier\x18\x04 \x01(\x02H\x03\x88\x01\x01\x12\x19\n\x0ctest_timeout\x18\x05 \x01(\x05H\x04\x88\x01\x01\x12\x45\n\x0f\x66uzzer_metadata\x18\x06 \x03(\x0b\x32,.uworker_msg.FuzzContext.FuzzerMetadataEntry\x1a\x35\n\x13\x46uzzerMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_redzoneB\x10\n\x0e_disable_ubsanB\x12\n\x10_window_argumentB\x15\n\x13_timeout_multiplierB\x0f\n\r_test_timeout\"\xff\x01\n\x12\x46uzzTaskCrashGroup\x12.\n\x07\x63ontext\x18\x01 \x01(\x0b\x32\x18.uworker_msg.FuzzContextH\x00\x88\x01\x01\x12+\n\x07\x63rashes\x18\x02 \x03(\x0b\x32\x1a.uworker_msg.FuzzTaskCrash\x12\x33\n\nmain_crash\x18\x03 \x01(\x0b\x32\x1a.uworker_msg.FuzzTaskCrashH\x01\x88\x01\x01\x12\"\n\x15one_time_crasher_flag\x18\x04 \x01(\x08H\x02\x88\x01\x01\x42\n\n\x08_contextB\r\n\x0b_main_crashB\x18\n\x16_one_time_crasher_flag\"\xae\x01\n\x0f\x46uzzerRunOutput\x12\x13\n\x06output\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x18\n\x0breturn_code\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12-\n\ttimestamp\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x15\n\x08testcase\x18\x04 \x01(\x0cH\x02\x88\x01\x01\x42\t\n\x07_outputB\x0e\n\x0c_return_codeB\x0b\n\t_testcase\"\xad\n\n\x0e\x46uzzTaskOutput\x12(\n\x1b\x66ully_qualified_fuzzer_name\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0e\x63rash_revision\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1e\n\x11job_run_timestamp\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x1f\n\x12testcases_executed\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12I\n\x12\x66uzzer_run_results\x18\x08 \x01(\x0b\x32(.uworker_msg.StoreFuzzerRunResultsOutputH\x04\x88\x01\x01\x12\x1e\n\x11new_targets_count\x18\t \x01(\x05H\x05\x88\x01\x01\x12\x1c\n\x0f\x66uzzer_revision\x18\n \x01(\x05H\x06\x88\x01\x01\x12\x14\n\x0c\x66uzz_targets\x18\x0b \x03(\t\x12\x1a\n\x12testcase_run_jsons\x18\x0c \x03(\t\x12\x35\n\x0c\x63rash_groups\x18\r \x03(\x0b\x32\x1f.uworker_msg.FuzzTaskCrashGroup\x12/\n\nbuild_data\x18\x0e \x01(\x0b\x32\x16.uworker_msg.BuildDataH\x07\x88\x01\x01\x12\x19\n\x0c\x61pp_revision\x18\x0f \x01(\x03H\x08\x88\x01\x01\x12\x38\n\x12\x66uzzer_run_outputs\x18\x10 \x03(\x0b\x32\x1c.uworker_msg.FuzzerRunOutput\x12\x16\n\tbuild_key\x18\x11 \x01(\tH\t\x88\x01\x01\x12\x16\n\tbuild_url\x18\x12 \x01(\tH\n\x88\x01\x01\x12\x14\n\x07gn_args\x18\x13 \x01(\tH\x0b\x88\x01\x01\x12 \n\x13testcases_generated\x18\x14 \x01(\x03H\x0c\x88\x01\x01\x12\x44\n\x1ctestcase_generation_duration\x18\x15 \x01(\x0b\x32\x19.google.protobuf.DurationH\r\x88\x01\x01\x12\x43\n\x1btestcase_execution_duration\x18\x16 \x01(\x0b\x32\x19.google.protobuf.DurationH\x0e\x88\x01\x01\x12\x38\n\x10\x66uzzing_duration\x18\x17 \x01(\x0b\x32\x19.google.protobuf.DurationH\x0f\x88\x01\x01\x12\x46\n\x0esteps_duration\x18\x18 \x03(\x0b\x32..uworker_msg.FuzzTaskOutput.StepsDurationEntry\x1aO\n\x12StepsDurationEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration:\x02\x38\x01\x42\x1e\n\x1c_fully_qualified_fuzzer_nameB\x11\n\x0f_crash_revisionB\x14\n\x12_job_run_timestampB\x15\n\x13_testcases_executedB\x15\n\x13_fuzzer_run_resultsB\x14\n\x12_new_targets_countB\x12\n\x10_fuzzer_revisionB\r\n\x0b_build_dataB\x0f\n\r_app_revisionB\x0c\n\n_build_keyB\x0c\n\n_build_urlB\n\n\x08_gn_argsB\x16\n\x14_testcases_generatedB\x1f\n\x1d_testcase_generation_durationB\x1e\n\x1c_testcase_execution_durationB\x13\n\x11_fuzzing_duration\"\xef\x05\n\x12MinimizeTaskOutput\x12X\n\x16last_crash_result_dict\x18\x01 \x03(\x0b\x32\x38.uworker_msg.MinimizeTaskOutput.LastCrashResultDictEntry\x12\x18\n\x0b\x66laky_stack\x18\x02 \x01(\x08H\x00\x88\x01\x01\x12&\n\x19security_severity_updated\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x1e\n\x11security_severity\x18\x04 \x01(\x05H\x02\x88\x01\x01\x12\x1f\n\x12minimization_phase\x18\x05 \x01(\x05H\x03\x88\x01\x01\x12\x10\n\x08gestures\x18\x06 \x03(\t\x12\x1b\n\x0eminimized_keys\x18\x07 \x01(\tH\x04\x88\x01\x01\x12 \n\x13minimized_arguments\x18\x08 \x01(\tH\x05\x88\x01\x01\x12\x1a\n\rarchive_state\x18\t \x01(\x05H\x06\x88\x01\x01\x12\x1a\n\rabsolute_path\x18\n \x01(\tH\x07\x88\x01\x01\x12S\n\x13memory_tool_options\x18\x0b \x03(\x0b\x32\x36.uworker_msg.MinimizeTaskOutput.MemoryToolOptionsEntry\x1a:\n\x18LastCrashResultDictEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x38\n\x16MemoryToolOptionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0e\n\x0c_flaky_stackB\x1c\n\x1a_security_severity_updatedB\x14\n\x12_security_severityB\x15\n\x13_minimization_phaseB\x11\n\x0f_minimized_keysB\x16\n\x14_minimized_argumentsB\x10\n\x0e_archive_stateB\x10\n\x0e_absolute_path\"\xfb\x02\n\x14RegressionTaskOutput\x12#\n\x16regression_range_start\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12!\n\x14regression_range_end\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12 \n\x13last_regression_min\x18\x03 \x01(\x03H\x02\x88\x01\x01\x12 \n\x13last_regression_max\x18\x04 \x01(\x03H\x03\x88\x01\x01\x12/\n\x0f\x62uild_data_list\x18\x05 \x03(\x0b\x32\x16.uworker_msg.BuildData\x12%\n\x18is_testcase_reproducible\x18\x06 \x01(\x08H\x04\x88\x01\x01\x42\x19\n\x17_regression_range_startB\x17\n\x15_regression_range_endB\x16\n\x14_last_regression_minB\x16\n\x14_last_regression_maxB\x1b\n\x19_is_testcase_reproducible\"\xa3\x02\n\x11VariantTaskOutput\x12\x13\n\x06status\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x15\n\x08revision\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12\x17\n\ncrash_type\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x18\n\x0b\x63rash_state\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1a\n\rsecurity_flag\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x17\n\nis_similar\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x15\n\x08platform\x18\x07 \x01(\tH\x06\x88\x01\x01\x42\t\n\x07_statusB\x0b\n\t_revisionB\r\n\x0b_crash_typeB\x0e\n\x0c_crash_stateB\x10\n\x0e_security_flagB\r\n\x0b_is_similarB\x0b\n\t_platform\"\xe7\x01\n\tBuildData\x12\x15\n\x08revision\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x19\n\x0cis_bad_build\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\'\n\x1ashould_ignore_crash_result\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12%\n\x18\x62uild_run_console_output\x18\x04 \x01(\tH\x03\x88\x01\x01\x42\x0b\n\t_revisionB\x0f\n\r_is_bad_buildB\x1d\n\x1b_should_ignore_crash_resultB\x1b\n\x19_build_run_console_output\"\xc8\x04\n\x15ProgressionTaskOutput\x12\x19\n\x0cmin_revision\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x19\n\x0cmax_revision\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12\x1c\n\x0f\x63rash_on_latest\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12$\n\x17\x63rash_on_latest_message\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1b\n\x0e\x63rash_revision\x18\x05 \x01(\x03H\x04\x88\x01\x01\x12)\n\x1clast_tested_crash_stacktrace\x18\x06 \x01(\tH\x05\x88\x01\x01\x12!\n\x14last_progression_min\x18\x07 \x01(\x03H\x06\x88\x01\x01\x12!\n\x14last_progression_max\x18\x08 \x01(\x03H\x07\x88\x01\x01\x12#\n\x16\x63lear_min_max_metadata\x18\t \x01(\x08H\x08\x88\x01\x01\x12/\n\x0f\x62uild_data_list\x18\x0b \x03(\x0b\x32\x16.uworker_msg.BuildDataB\x0f\n\r_min_revisionB\x0f\n\r_max_revisionB\x12\n\x10_crash_on_latestB\x1a\n\x18_crash_on_latest_messageB\x11\n\x0f_crash_revisionB\x1f\n\x1d_last_tested_crash_stacktraceB\x17\n\x15_last_progression_minB\x17\n\x15_last_progression_maxB\x19\n\x17_clear_min_max_metadata\"\xc6\x03\n\x1a\x43rossPollinationStatistics\x12#\n\x16project_qualified_name\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07sources\x18\x02 \x01(\tH\x01\x88\x01\x01\x12 \n\x13initial_corpus_size\x18\x03 \x01(\x03H\x02\x88\x01\x01\x12\x18\n\x0b\x63orpus_size\x18\x04 \x01(\x03H\x03\x88\x01\x01\x12\"\n\x15initial_edge_coverage\x18\x05 \x01(\x03H\x04\x88\x01\x01\x12\x1a\n\redge_coverage\x18\x06 \x01(\x03H\x05\x88\x01\x01\x12%\n\x18initial_feature_coverage\x18\x07 \x01(\x03H\x06\x88\x01\x01\x12\x1d\n\x10\x66\x65\x61ture_coverage\x18\x08 \x01(\x03H\x07\x88\x01\x01\x42\x19\n\x17_project_qualified_nameB\n\n\x08_sourcesB\x16\n\x14_initial_corpus_sizeB\x0e\n\x0c_corpus_sizeB\x18\n\x16_initial_edge_coverageB\x10\n\x0e_edge_coverageB\x1b\n\x19_initial_feature_coverageB\x13\n\x11_feature_coverage\"\x97\x04\n\x13\x43overageInformation\x12\x19\n\x0cproject_name\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x32\n\ttimestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01\x88\x01\x01\x12\x1e\n\x11\x63orpus_size_units\x18\x03 \x01(\x03H\x02\x88\x01\x01\x12\x1e\n\x11\x63orpus_size_bytes\x18\x04 \x01(\x03H\x03\x88\x01\x01\x12\x1c\n\x0f\x63orpus_location\x18\x05 \x01(\tH\x04\x88\x01\x01\x12#\n\x16\x63orpus_backup_location\x18\x06 \x01(\tH\x05\x88\x01\x01\x12\"\n\x15quarantine_size_units\x18\x07 \x01(\x03H\x06\x88\x01\x01\x12\"\n\x15quarantine_size_bytes\x18\x08 \x01(\x03H\x07\x88\x01\x01\x12 \n\x13quarantine_location\x18\t \x01(\tH\x08\x88\x01\x01\x42\x0f\n\r_project_nameB\x0c\n\n_timestampB\x14\n\x12_corpus_size_unitsB\x14\n\x12_corpus_size_bytesB\x12\n\x10_corpus_locationB\x19\n\x17_corpus_backup_locationB\x18\n\x16_quarantine_size_unitsB\x18\n\x16_quarantine_size_bytesB\x16\n\x14_quarantine_location\"\xa5\x03\n\x17\x43orpusPruningTaskOutput\x12M\n\x17\x63ross_pollination_stats\x18\x01 \x01(\x0b\x32\'.uworker_msg.CrossPollinationStatisticsH\x00\x88\x01\x01\x12<\n\rcoverage_info\x18\x02 \x01(\x0b\x32 .uworker_msg.CoverageInformationH\x01\x88\x01\x01\x12\x1f\n\x12\x66uzzer_binary_name\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1b\n\x0e\x63rash_revision\x18\x04 \x01(\x03H\x03\x88\x01\x01\x12\'\n\x07\x63rashes\x18\x05 \x03(\x0b\x32\x16.uworker_msg.CrashInfo\x12#\n\x16\x63orpus_backup_uploaded\x18\x06 \x01(\x08H\x04\x88\x01\x01\x42\x1a\n\x18_cross_pollination_statsB\x10\n\x0e_coverage_infoB\x15\n\x13_fuzzer_binary_nameB\x11\n\x0f_crash_revisionB\x19\n\x17_corpus_backup_uploaded\"\xc5\t\n\x06Output\x12/\n\nerror_type\x18\x03 \x01(\x0e\x32\x16.uworker_msg.ErrorTypeH\x00\x88\x01\x01\x12.\n\ruworker_input\x18\x04 \x01(\x0b\x32\x12.uworker_msg.InputH\x01\x88\x01\x01\x12\x19\n\x0ctest_timeout\x18\x05 \x01(\x02H\x02\x88\x01\x01\x12\x17\n\ncrash_time\x18\x06 \x01(\x02H\x03\x88\x01\x01\x12$\n\x17\x63rash_stacktrace_output\x18\x07 \x01(\tH\x04\x88\x01\x01\x12\x15\n\x08\x62ot_name\x18\x12 \x01(\tH\x05\x88\x01\x01\x12\x18\n\x0bplatform_id\x18\x13 \x01(\tH\x06\x88\x01\x01\x12@\n\x13\x61nalyze_task_output\x18\x08 \x01(\x0b\x32\x1e.uworker_msg.AnalyzeTaskOutputH\x07\x88\x01\x01\x12:\n\x10\x66uzz_task_output\x18\t \x01(\x0b\x32\x1b.uworker_msg.FuzzTaskOutputH\x08\x88\x01\x01\x12\x42\n\x14minimize_task_output\x18\n \x01(\x0b\x32\x1f.uworker_msg.MinimizeTaskOutputH\t\x88\x01\x01\x12\x46\n\x16regression_task_output\x18\x0b \x01(\x0b\x32!.uworker_msg.RegressionTaskOutputH\n\x88\x01\x01\x12H\n\x17progression_task_output\x18\x0c \x01(\x0b\x32\".uworker_msg.ProgressionTaskOutputH\x0b\x88\x01\x01\x12\x44\n\x15symbolize_task_output\x18\r \x01(\x0b\x32 .uworker_msg.SymbolizeTaskOutputH\x0c\x88\x01\x01\x12@\n\x13variant_task_output\x18\x0e \x01(\x0b\x32\x1e.uworker_msg.VariantTaskOutputH\r\x88\x01\x01\x12M\n\x1a\x63orpus_pruning_task_output\x18\x10 \x01(\x0b\x32$.uworker_msg.CorpusPruningTaskOutputH\x0e\x88\x01\x01\x12\x1b\n\x0eissue_metadata\x18\x14 \x01(\tH\x0f\x88\x01\x01\x12\x1a\n\rerror_message\x18\x0f \x01(\tH\x10\x88\x01\x01\x42\r\n\x0b_error_typeB\x10\n\x0e_uworker_inputB\x0f\n\r_test_timeoutB\r\n\x0b_crash_timeB\x1a\n\x18_crash_stacktrace_outputB\x0b\n\t_bot_nameB\x0e\n\x0c_platform_idB\x16\n\x14_analyze_task_outputB\x13\n\x11_fuzz_task_outputB\x17\n\x15_minimize_task_outputB\x19\n\x17_regression_task_outputB\x1a\n\x18_progression_task_outputB\x18\n\x16_symbolize_task_outputB\x16\n\x14_variant_task_outputB\x1d\n\x1b_corpus_pruning_task_outputB\x11\n\x0f_issue_metadataB\x10\n\x0e_error_message*\x95\t\n\tErrorType\x12\x0c\n\x08NO_ERROR\x10\x00\x12\x17\n\x13\x41NALYZE_BUILD_SETUP\x10\x01\x12\x14\n\x10\x41NALYZE_NO_CRASH\x10\x02\x12\x1d\n\x19\x41NALYZE_NO_REVISIONS_LIST\x10\x03\x12\x1d\n\x19\x41NALYZE_NO_REVISION_INDEX\x10\x04\x12\x12\n\x0eTESTCASE_SETUP\x10\x05\x12\r\n\tUNHANDLED\x10\x06\x12\x17\n\x13VARIANT_BUILD_SETUP\x10\x07\x12\x12\n\x0eMINIMIZE_SETUP\x10\x08\x12\x1c\n\x18\x46UZZ_BUILD_SETUP_FAILURE\x10\t\x12\"\n\x1e\x46UZZ_DATA_BUNDLE_SETUP_FAILURE\x10\n\x12\x12\n\x0e\x46UZZ_NO_FUZZER\x10\x0b\x12 \n\x1c\x46UZZ_NO_FUZZ_TARGET_SELECTED\x10\r\x12#\n\x1fPROGRESSION_REVISION_LIST_ERROR\x10\x0e\x12\x1f\n\x1bPROGRESSION_BUILD_NOT_FOUND\x10\x0f\x12\x18\n\x14PROGRESSION_NO_CRASH\x10\x10\x12!\n\x1dPROGRESSION_BAD_STATE_MIN_MAX\x10\x11\x12\x17\n\x13PROGRESSION_TIMEOUT\x10\x12\x12\x19\n\x15PROGRESSION_BAD_BUILD\x10\x13\x12!\n\x1dPROGRESSION_BUILD_SETUP_ERROR\x10\x14\x12\"\n\x1eREGRESSION_REVISION_LIST_ERROR\x10\x15\x12\x1e\n\x1aREGRESSION_BUILD_NOT_FOUND\x10\x16\x12 \n\x1cREGRESSION_BUILD_SETUP_ERROR\x10\x17\x12\x1e\n\x1aREGRESSION_BAD_BUILD_ERROR\x10\x18\x12\x17\n\x13REGRESSION_NO_CRASH\x10\x19\x12\x1c\n\x18REGRESSION_TIMEOUT_ERROR\x10\x1a\x12\x31\n-REGRESSION_LOW_CONFIDENCE_IN_REGRESSION_RANGE\x10\x1b\x12\x1f\n\x1bSYMBOLIZE_BUILD_SETUP_ERROR\x10\x1c\x12!\n\x1dMINIMIZE_UNREPRODUCIBLE_CRASH\x10\x1d\x12\x1c\n\x18MINIMIZE_CRASH_TOO_FLAKY\x10\x1e\x12\x1e\n\x1aMINIMIZE_DEADLINE_EXCEEDED\x10\x1f\x12\x31\n-MINIMIZE_DEADLINE_EXCEEDED_IN_MAIN_FILE_PHASE\x10 \x12)\n%LIBFUZZER_MINIMIZATION_UNREPRODUCIBLE\x10!\x12!\n\x1dLIBFUZZER_MINIMIZATION_FAILED\x10\"\x12&\n\"CORPUS_PRUNING_FUZZER_SETUP_FAILED\x10#\x12\x18\n\x14\x43ORPUS_PRUNING_ERROR\x10$\x12\x12\n\x0e\x46UZZ_BAD_BUILD\x10%\x12\"\n\x1e\x41NALYZE_CLOSE_INVALID_UPLOADED\x10&b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -44,12 +44,14 @@ _globals['_INPUT_UWORKERENVENTRY']._serialized_options = b'8\001' _globals['_FUZZCONTEXT_FUZZERMETADATAENTRY']._options = None _globals['_FUZZCONTEXT_FUZZERMETADATAENTRY']._serialized_options = b'8\001' + _globals['_FUZZTASKOUTPUT_STEPSDURATIONENTRY']._options = None + _globals['_FUZZTASKOUTPUT_STEPSDURATIONENTRY']._serialized_options = b'8\001' _globals['_MINIMIZETASKOUTPUT_LASTCRASHRESULTDICTENTRY']._options = None _globals['_MINIMIZETASKOUTPUT_LASTCRASHRESULTDICTENTRY']._serialized_options = b'8\001' _globals['_MINIMIZETASKOUTPUT_MEMORYTOOLOPTIONSENTRY']._options = None _globals['_MINIMIZETASKOUTPUT_MEMORYTOOLOPTIONSENTRY']._serialized_options = b'8\001' - _globals['_ERRORTYPE']._serialized_start=14686 - _globals['_ERRORTYPE']._serialized_end=15859 + _globals['_ERRORTYPE']._serialized_start=14839 + _globals['_ERRORTYPE']._serialized_end=16012 _globals['_SETUPINPUT']._serialized_start=156 _globals['_SETUPINPUT']._serialized_end=545 _globals['_ANALYZETASKINPUT']._serialized_start=547 @@ -103,27 +105,29 @@ _globals['_FUZZERRUNOUTPUT']._serialized_start=8440 _globals['_FUZZERRUNOUTPUT']._serialized_end=8614 _globals['_FUZZTASKOUTPUT']._serialized_start=8617 - _globals['_FUZZTASKOUTPUT']._serialized_end=9789 - _globals['_MINIMIZETASKOUTPUT']._serialized_start=9792 - _globals['_MINIMIZETASKOUTPUT']._serialized_end=10543 - _globals['_MINIMIZETASKOUTPUT_LASTCRASHRESULTDICTENTRY']._serialized_start=10257 - _globals['_MINIMIZETASKOUTPUT_LASTCRASHRESULTDICTENTRY']._serialized_end=10315 - _globals['_MINIMIZETASKOUTPUT_MEMORYTOOLOPTIONSENTRY']._serialized_start=10317 - _globals['_MINIMIZETASKOUTPUT_MEMORYTOOLOPTIONSENTRY']._serialized_end=10373 - _globals['_REGRESSIONTASKOUTPUT']._serialized_start=10546 - _globals['_REGRESSIONTASKOUTPUT']._serialized_end=10925 - _globals['_VARIANTTASKOUTPUT']._serialized_start=10928 - _globals['_VARIANTTASKOUTPUT']._serialized_end=11219 - _globals['_BUILDDATA']._serialized_start=11222 - _globals['_BUILDDATA']._serialized_end=11453 - _globals['_PROGRESSIONTASKOUTPUT']._serialized_start=11456 - _globals['_PROGRESSIONTASKOUTPUT']._serialized_end=12040 - _globals['_CROSSPOLLINATIONSTATISTICS']._serialized_start=12043 - _globals['_CROSSPOLLINATIONSTATISTICS']._serialized_end=12497 - _globals['_COVERAGEINFORMATION']._serialized_start=12500 - _globals['_COVERAGEINFORMATION']._serialized_end=13035 - _globals['_CORPUSPRUNINGTASKOUTPUT']._serialized_start=13038 - _globals['_CORPUSPRUNINGTASKOUTPUT']._serialized_end=13459 - _globals['_OUTPUT']._serialized_start=13462 - _globals['_OUTPUT']._serialized_end=14683 + _globals['_FUZZTASKOUTPUT']._serialized_end=9942 + _globals['_FUZZTASKOUTPUT_STEPSDURATIONENTRY']._serialized_start=9520 + _globals['_FUZZTASKOUTPUT_STEPSDURATIONENTRY']._serialized_end=9599 + _globals['_MINIMIZETASKOUTPUT']._serialized_start=9945 + _globals['_MINIMIZETASKOUTPUT']._serialized_end=10696 + _globals['_MINIMIZETASKOUTPUT_LASTCRASHRESULTDICTENTRY']._serialized_start=10410 + _globals['_MINIMIZETASKOUTPUT_LASTCRASHRESULTDICTENTRY']._serialized_end=10468 + _globals['_MINIMIZETASKOUTPUT_MEMORYTOOLOPTIONSENTRY']._serialized_start=10470 + _globals['_MINIMIZETASKOUTPUT_MEMORYTOOLOPTIONSENTRY']._serialized_end=10526 + _globals['_REGRESSIONTASKOUTPUT']._serialized_start=10699 + _globals['_REGRESSIONTASKOUTPUT']._serialized_end=11078 + _globals['_VARIANTTASKOUTPUT']._serialized_start=11081 + _globals['_VARIANTTASKOUTPUT']._serialized_end=11372 + _globals['_BUILDDATA']._serialized_start=11375 + _globals['_BUILDDATA']._serialized_end=11606 + _globals['_PROGRESSIONTASKOUTPUT']._serialized_start=11609 + _globals['_PROGRESSIONTASKOUTPUT']._serialized_end=12193 + _globals['_CROSSPOLLINATIONSTATISTICS']._serialized_start=12196 + _globals['_CROSSPOLLINATIONSTATISTICS']._serialized_end=12650 + _globals['_COVERAGEINFORMATION']._serialized_start=12653 + _globals['_COVERAGEINFORMATION']._serialized_end=13188 + _globals['_CORPUSPRUNINGTASKOUTPUT']._serialized_start=13191 + _globals['_CORPUSPRUNINGTASKOUTPUT']._serialized_end=13612 + _globals['_OUTPUT']._serialized_start=13615 + _globals['_OUTPUT']._serialized_end=14836 # @@protoc_insertion_point(module_scope) diff --git a/src/clusterfuzz/_internal/protos/uworker_msg_pb2.pyi b/src/clusterfuzz/_internal/protos/uworker_msg_pb2.pyi index e03f125154..b57f4c3b81 100644 --- a/src/clusterfuzz/_internal/protos/uworker_msg_pb2.pyi +++ b/src/clusterfuzz/_internal/protos/uworker_msg_pb2.pyi @@ -1240,6 +1240,24 @@ global___FuzzerRunOutput = FuzzerRunOutput class FuzzTaskOutput(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor + @typing_extensions.final + class StepsDurationEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> google.protobuf.duration_pb2.Duration: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: google.protobuf.duration_pb2.Duration | None = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["value", b"value"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["key", b"key", "value", b"value"]) -> None: ... + FULLY_QUALIFIED_FUZZER_NAME_FIELD_NUMBER: builtins.int CRASH_REVISION_FIELD_NUMBER: builtins.int JOB_RUN_TIMESTAMP_FIELD_NUMBER: builtins.int @@ -1260,6 +1278,7 @@ class FuzzTaskOutput(google.protobuf.message.Message): TESTCASE_GENERATION_DURATION_FIELD_NUMBER: builtins.int TESTCASE_EXECUTION_DURATION_FIELD_NUMBER: builtins.int FUZZING_DURATION_FIELD_NUMBER: builtins.int + STEPS_DURATION_FIELD_NUMBER: builtins.int fully_qualified_fuzzer_name: builtins.str """TODO(metzman): Remove this since tworkers should know what this is based on the input. @@ -1296,6 +1315,11 @@ class FuzzTaskOutput(google.protobuf.message.Message): """Total fuzzing session time. Includes time spent updating the fuzzer, build and test corpus set up, and crash processing. """ + @property + def steps_duration(self) -> google.protobuf.internal.containers.MessageMap[builtins.str, google.protobuf.duration_pb2.Duration]: + """Map of {step: duration}, which tracks the duration of each step in the + fuzz task + """ def __init__( self, *, @@ -1319,9 +1343,10 @@ class FuzzTaskOutput(google.protobuf.message.Message): testcase_generation_duration: google.protobuf.duration_pb2.Duration | None = ..., testcase_execution_duration: google.protobuf.duration_pb2.Duration | None = ..., fuzzing_duration: google.protobuf.duration_pb2.Duration | None = ..., + steps_duration: collections.abc.Mapping[builtins.str, google.protobuf.duration_pb2.Duration] | None = ..., ) -> None: ... def HasField(self, field_name: typing_extensions.Literal["_app_revision", b"_app_revision", "_build_data", b"_build_data", "_build_key", b"_build_key", "_build_url", b"_build_url", "_crash_revision", b"_crash_revision", "_fully_qualified_fuzzer_name", b"_fully_qualified_fuzzer_name", "_fuzzer_revision", b"_fuzzer_revision", "_fuzzer_run_results", b"_fuzzer_run_results", "_fuzzing_duration", b"_fuzzing_duration", "_gn_args", b"_gn_args", "_job_run_timestamp", b"_job_run_timestamp", "_new_targets_count", b"_new_targets_count", "_testcase_execution_duration", b"_testcase_execution_duration", "_testcase_generation_duration", b"_testcase_generation_duration", "_testcases_executed", b"_testcases_executed", "_testcases_generated", b"_testcases_generated", "app_revision", b"app_revision", "build_data", b"build_data", "build_key", b"build_key", "build_url", b"build_url", "crash_revision", b"crash_revision", "fully_qualified_fuzzer_name", b"fully_qualified_fuzzer_name", "fuzzer_revision", b"fuzzer_revision", "fuzzer_run_results", b"fuzzer_run_results", "fuzzing_duration", b"fuzzing_duration", "gn_args", b"gn_args", "job_run_timestamp", b"job_run_timestamp", "new_targets_count", b"new_targets_count", "testcase_execution_duration", b"testcase_execution_duration", "testcase_generation_duration", b"testcase_generation_duration", "testcases_executed", b"testcases_executed", "testcases_generated", b"testcases_generated"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["_app_revision", b"_app_revision", "_build_data", b"_build_data", "_build_key", b"_build_key", "_build_url", b"_build_url", "_crash_revision", b"_crash_revision", "_fully_qualified_fuzzer_name", b"_fully_qualified_fuzzer_name", "_fuzzer_revision", b"_fuzzer_revision", "_fuzzer_run_results", b"_fuzzer_run_results", "_fuzzing_duration", b"_fuzzing_duration", "_gn_args", b"_gn_args", "_job_run_timestamp", b"_job_run_timestamp", "_new_targets_count", b"_new_targets_count", "_testcase_execution_duration", b"_testcase_execution_duration", "_testcase_generation_duration", b"_testcase_generation_duration", "_testcases_executed", b"_testcases_executed", "_testcases_generated", b"_testcases_generated", "app_revision", b"app_revision", "build_data", b"build_data", "build_key", b"build_key", "build_url", b"build_url", "crash_groups", b"crash_groups", "crash_revision", b"crash_revision", "fully_qualified_fuzzer_name", b"fully_qualified_fuzzer_name", "fuzz_targets", b"fuzz_targets", "fuzzer_revision", b"fuzzer_revision", "fuzzer_run_outputs", b"fuzzer_run_outputs", "fuzzer_run_results", b"fuzzer_run_results", "fuzzing_duration", b"fuzzing_duration", "gn_args", b"gn_args", "job_run_timestamp", b"job_run_timestamp", "new_targets_count", b"new_targets_count", "testcase_execution_duration", b"testcase_execution_duration", "testcase_generation_duration", b"testcase_generation_duration", "testcase_run_jsons", b"testcase_run_jsons", "testcases_executed", b"testcases_executed", "testcases_generated", b"testcases_generated"]) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["_app_revision", b"_app_revision", "_build_data", b"_build_data", "_build_key", b"_build_key", "_build_url", b"_build_url", "_crash_revision", b"_crash_revision", "_fully_qualified_fuzzer_name", b"_fully_qualified_fuzzer_name", "_fuzzer_revision", b"_fuzzer_revision", "_fuzzer_run_results", b"_fuzzer_run_results", "_fuzzing_duration", b"_fuzzing_duration", "_gn_args", b"_gn_args", "_job_run_timestamp", b"_job_run_timestamp", "_new_targets_count", b"_new_targets_count", "_testcase_execution_duration", b"_testcase_execution_duration", "_testcase_generation_duration", b"_testcase_generation_duration", "_testcases_executed", b"_testcases_executed", "_testcases_generated", b"_testcases_generated", "app_revision", b"app_revision", "build_data", b"build_data", "build_key", b"build_key", "build_url", b"build_url", "crash_groups", b"crash_groups", "crash_revision", b"crash_revision", "fully_qualified_fuzzer_name", b"fully_qualified_fuzzer_name", "fuzz_targets", b"fuzz_targets", "fuzzer_revision", b"fuzzer_revision", "fuzzer_run_outputs", b"fuzzer_run_outputs", "fuzzer_run_results", b"fuzzer_run_results", "fuzzing_duration", b"fuzzing_duration", "gn_args", b"gn_args", "job_run_timestamp", b"job_run_timestamp", "new_targets_count", b"new_targets_count", "steps_duration", b"steps_duration", "testcase_execution_duration", b"testcase_execution_duration", "testcase_generation_duration", b"testcase_generation_duration", "testcase_run_jsons", b"testcase_run_jsons", "testcases_executed", b"testcases_executed", "testcases_generated", b"testcases_generated"]) -> None: ... @typing.overload def WhichOneof(self, oneof_group: typing_extensions.Literal["_app_revision", b"_app_revision"]) -> typing_extensions.Literal["app_revision"] | None: ... @typing.overload diff --git a/src/clusterfuzz/_internal/tests/appengine/handlers/cron/load_bigquery_stats_test.py b/src/clusterfuzz/_internal/tests/appengine/handlers/cron/load_bigquery_stats_test.py index d9e51324ed..1fffcbb3ec 100644 --- a/src/clusterfuzz/_internal/tests/appengine/handlers/cron/load_bigquery_stats_test.py +++ b/src/clusterfuzz/_internal/tests/appengine/handlers/cron/load_bigquery_stats_test.py @@ -120,85 +120,8 @@ def _assert_load_calls(self, expected_date_str): ], 'sourceFormat': 'NEWLINE_DELIMITED_JSON', - 'schema': { - 'fields': [{ - 'type': 'INTEGER', - 'name': 'testcases_executed', - 'mode': 'NULLABLE' - }, { - 'type': 'INTEGER', - 'name': 'build_revision', - 'mode': 'NULLABLE' - }, { - 'type': 'INTEGER', - 'name': 'new_crashes', - 'mode': 'NULLABLE' - }, { - 'type': 'STRING', - 'name': 'job', - 'mode': 'NULLABLE' - }, { - 'type': 'FLOAT', - 'name': 'timestamp', - 'mode': 'NULLABLE' - }, { - 'fields': [{ - 'type': 'STRING', - 'name': 'crash_type', - 'mode': 'NULLABLE' - }, { - 'type': 'BOOLEAN', - 'name': 'is_new', - 'mode': 'NULLABLE' - }, { - 'type': 'STRING', - 'name': 'crash_state', - 'mode': 'NULLABLE' - }, { - 'type': 'BOOLEAN', - 'name': 'security_flag', - 'mode': 'NULLABLE' - }, { - 'type': 'INTEGER', - 'name': 'count', - 'mode': 'NULLABLE' - }], - 'type': - 'RECORD', - 'name': - 'crashes', - 'mode': - 'REPEATED' - }, { - 'type': 'INTEGER', - 'name': 'known_crashes', - 'mode': 'NULLABLE' - }, { - 'type': 'STRING', - 'name': 'fuzzer', - 'mode': 'NULLABLE' - }, { - 'type': 'STRING', - 'name': 'kind', - 'mode': 'NULLABLE' - }, { - 'type': 'INTEGER', - 'name': 'testcases_generated', - 'mode': 'NULLABLE' - }, { - 'type': 'INTERVAL', - 'name': 'testcase_generation_duration', - 'mode': 'NULLABLE' - }, { - 'type': 'INTERVAL', - 'name': 'testcase_execution_duration', - 'mode': 'NULLABLE' - }, { - 'type': 'INTERVAL', - 'name': 'fuzzing_duration', - 'mode': 'NULLABLE' - }] - }, + 'schema': + fuzzer_stats.JobRun.SCHEMA, } } }, diff --git a/src/clusterfuzz/_internal/tests/core/metrics/fuzzer_stats_test.py b/src/clusterfuzz/_internal/tests/core/metrics/fuzzer_stats_test.py index 766169b45c..891c5a73a0 100644 --- a/src/clusterfuzz/_internal/tests/core/metrics/fuzzer_stats_test.py +++ b/src/clusterfuzz/_internal/tests/core/metrics/fuzzer_stats_test.py @@ -168,7 +168,7 @@ def test_upload_job_run(self): 100, datetime.timedelta(seconds=10.5), datetime.timedelta(seconds=20.5), - datetime.timedelta(seconds=31.0)) + datetime.timedelta(seconds=31.0), {}) fuzzer_stats.upload_stats([fuzzer_run], filename='upload.json') @@ -193,6 +193,76 @@ def test_upload_job_run(self): 'gs://test-bigquery-bucket/fuzzer/JobRun/date/20160902/upload.json', self.mock.write_data.call_args[0][1]) + def _make_job_run(self, steps_duration): + """Creates a JobRun with the given steps_duration.""" + return fuzzer_stats.JobRun( + 'fuzzer', + 'job', + 123, + 1472846341.017923, + 9001, + 0, + 1, [], + steps_duration=steps_duration) + + @mock.patch.object(fuzzer_stats, '_STEPS_DURATION_FIELDS', [{ + 'name': 'fuzzing', + 'type': 'INTERVAL', + 'mode': 'NULLABLE' + }, { + 'name': 'setup', + 'type': 'INTERVAL', + 'mode': 'NULLABLE' + }]) + @mock.patch('clusterfuzz._internal.metrics.logs.error') + def test_job_run_steps_duration_drops_unknown_keys(self, mock_log_error): + """Tests that steps_duration keys not in the schema are dropped.""" + job_run = self._make_job_run({ + 'fuzzing': datetime.timedelta(seconds=1.5), + 'setup': datetime.timedelta(seconds=2), + 'evil_key': datetime.timedelta(seconds=3), + }) + + self.assertEqual({ + 'fuzzing': 'P0DT0H0M1.500000S', + 'setup': 'P0DT0H0M2.000000S', + }, job_run['steps_duration']) + mock_log_error.assert_called_once() + self.assertIn('"evil_key"', mock_log_error.call_args[0][0]) + + @mock.patch.object(fuzzer_stats, '_STEPS_DURATION_FIELDS', [{ + 'name': 'fuzzing', + 'type': 'INTERVAL', + 'mode': 'NULLABLE' + }]) + @mock.patch('clusterfuzz._internal.metrics.logs.error') + def test_job_run_steps_duration_all_unknown(self, mock_log_error): + """Tests that steps_duration is omitted when every key is unknown.""" + job_run = self._make_job_run({ + 'a': datetime.timedelta(seconds=1), + 'b': datetime.timedelta(seconds=2), + }) + + self.assertNotIn('steps_duration', job_run.data) + mock_log_error.assert_called_once() + self.assertIn('"b"', mock_log_error.call_args[0][0]) + self.assertIn('"a"', mock_log_error.call_args[0][0]) + + @mock.patch('clusterfuzz._internal.metrics.logs.error') + def test_job_run_steps_duration_empty_schema(self, mock_log_error): + """Tests that with the default (empty) schema all keys are dropped.""" + job_run = self._make_job_run({'fuzzing': datetime.timedelta(seconds=1)}) + + self.assertNotIn('steps_duration', job_run.data) + mock_log_error.assert_called_once() + + @mock.patch('clusterfuzz._internal.metrics.logs.error') + def test_job_run_steps_duration_none(self, mock_log_error): + """Tests that no steps_duration produces no field and no logs.""" + self.assertNotIn('steps_duration', self._make_job_run(None).data) + self.assertNotIn('steps_duration', self._make_job_run({}).data) + mock_log_error.assert_not_called() + @mock.patch('os.path.exists') def test_testcase_run_read_from_disk(self, mock_path_exists): """Tests TestcaseRun deserialization.""" @@ -244,7 +314,7 @@ def test_job_run_from_json(self): 'testcases_generated': 100, 'testcase_generation_duration': "P0DT0H0M10.500000S", 'testcase_execution_duration': "P0DT0H0M20.500000S", - 'fuzzing_duration': "P0DT0H0M31.000000S" + 'fuzzing_duration': "P0DT0H0M31.000000S", }) job_run = fuzzer_stats.BaseRun.from_json(data) self.assertIsNotNone(job_run) @@ -299,7 +369,7 @@ def test_fuzz_task_upload_job_run_stats(self): 100, datetime.timedelta(seconds=10.5), datetime.timedelta(seconds=20.5), - datetime.timedelta(seconds=31.0)) + datetime.timedelta(seconds=31.0), {}) self.assertEqual(1, self.mock.write_data.call_count) self.assertEqual({ 'kind': diff --git a/src/clusterfuzz/_internal/tests/core/metrics/monitor_test.py b/src/clusterfuzz/_internal/tests/core/metrics/monitor_test.py index 3f31eb4d59..198fbdbcec 100644 --- a/src/clusterfuzz/_internal/tests/core/metrics/monitor_test.py +++ b/src/clusterfuzz/_internal/tests/core/metrics/monitor_test.py @@ -14,6 +14,7 @@ """Tests for monitor.""" # pylint: disable=protected-access +import datetime import os import queue import time @@ -480,3 +481,99 @@ def test_gauge_metric(self): self.mock_time.advance(3.7) self.assertEqual(3, metric.get({'tag': 'val'})) + + +class TimeStatTrackerTest(unittest.TestCase): + """Tests for TimeStatTracker.""" + + def setUp(self): + monitor.metrics_store().reset_for_testing() + helpers.patch(self, [ + 'clusterfuzz._internal.metrics.monitor.check_module_loaded', + 'clusterfuzz._internal.metrics.logs.error', + 'clusterfuzz._internal.metrics.logs.warning', + 'time.time', + ]) + self.mock.check_module_loaded.return_value = True + self.mock_time = helpers.MockTime(start_time=10.0) + self.mock.time.side_effect = self.mock_time.time + self.metric = monitor.CumulativeDistributionMetric( + 'test_steps_duration', + description='test', + bucketer=monitor.FixedWidthBucketer(width=1.0, num_finite_buckets=10), + field_spec=[ + monitor.StringField('tag'), + monitor.StringField('step'), + monitor.BooleanField('success'), + ]) + + def test_track_success(self): + """Test tracking step time on success.""" + tracker = monitor.TimeStatTracker(self.metric, {'tag': 'val'}) + with tracker.track('step_1'): + self.mock_time.advance(4.5) + + self.assertEqual({'step_1': datetime.timedelta(seconds=4.5)}, tracker.stats) + dist = self.metric.get({'tag': 'val', 'step': 'step_1', 'success': True}) + self.assertEqual(1, dist.count) + self.assertAlmostEqual(4.5, dist.sum) + + def test_track_failure_exception_not_reraised(self): + """Test TimeStatTrackerFailureException marks failure without re-raising.""" + tracker = monitor.TimeStatTracker(self.metric, {'tag': 'val'}) + with tracker.track('step_1'): + self.mock_time.advance(3.2) + raise monitor.TimeStatTrackerFailureException() + + self.assertEqual({'step_1': datetime.timedelta(seconds=3.2)}, tracker.stats) + dist = self.metric.get({'tag': 'val', 'step': 'step_1', 'success': False}) + self.assertEqual(1, dist.count) + self.assertAlmostEqual(3.2, dist.sum) + + def test_track_unhandled_exception_reraised(self): + """Test unhandled exception marks failure and is re-raised.""" + tracker = monitor.TimeStatTracker(self.metric, {'tag': 'val'}) + with self.assertRaises(RuntimeError): + with tracker.track('step_1'): + self.mock_time.advance(6.0) + raise RuntimeError('boom') + + self.assertEqual({'step_1': datetime.timedelta(seconds=6.0)}, tracker.stats) + dist = self.metric.get({'tag': 'val', 'step': 'step_1', 'success': False}) + self.assertEqual(1, dist.count) + self.assertAlmostEqual(6.0, dist.sum) + + def test_track_without_metric(self): + """Test tracking stats when metric is None.""" + tracker = monitor.TimeStatTracker() + with tracker.track('step_1'): + self.mock_time.advance(2.0) + + self.assertEqual({'step_1': datetime.timedelta(seconds=2.0)}, tracker.stats) + + def test_missing_required_fields_in_metric(self): + """Test error logged and metric disabled when step/success fields missing.""" + invalid_metric = monitor.CounterMetric( + 'invalid_metric', + description='test', + field_spec=[monitor.StringField('tag')]) + tracker = monitor.TimeStatTracker(invalid_metric, {'tag': 'val'}) + self.assertIsNone(tracker.metric) + self.assertGreater(self.mock.error.call_count, 0) + + with tracker.track('step_1'): + self.mock_time.advance(1.5) + self.assertEqual({'step_1': datetime.timedelta(seconds=1.5)}, tracker.stats) + + def test_time_accumulation(self): + """Test if time measurements are accumulated in stats.""" + tracker = monitor.TimeStatTracker(self.metric, {'tag': 'val'}) + with tracker.track('step_1'): + self.mock_time.advance(4.5) + with tracker.track('step_1'): + self.mock_time.advance(3.2) + + self.assertEqual({'step_1': datetime.timedelta(seconds=7.7)}, tracker.stats) + dist = self.metric.get({'tag': 'val', 'step': 'step_1', 'success': True}) + self.assertEqual(2, dist.count) + self.assertAlmostEqual(7.7, dist.sum)