diff --git a/src/clusterfuzz/_internal/bot/tasks/utasks/fuzz_task.py b/src/clusterfuzz/_internal/bot/tasks/utasks/fuzz_task.py index 44926c9310..e25f5e12ef 100644 --- a/src/clusterfuzz/_internal/bot/tasks/utasks/fuzz_task.py +++ b/src/clusterfuzz/_internal/bot/tasks/utasks/fuzz_task.py @@ -2129,17 +2129,21 @@ def do_blackbox_fuzzing(self, fuzzer, fuzzer_directory, job_type): def run(self): """Run the fuzzing session.""" start_time = time.time() - # Update LSAN local blacklist with global blacklist. - global_blacklisted_functions = ( - self.uworker_input.fuzz_task_input.global_blacklisted_functions) - if global_blacklisted_functions: - leak_blacklist.copy_global_to_local_blacklist( - global_blacklisted_functions) - - # Ensure that that the fuzzer still exists. - logs.info('Setting up fuzzer and data bundles.') - self.fuzzer = setup.update_fuzzer_and_data_bundles( - self.uworker_input.setup_input) + with self.steps_time_tracker.track('fuzzer_setup'): + # Update LSAN local blacklist with global blacklist. + global_blacklisted_functions = ( + self.uworker_input.fuzz_task_input.global_blacklisted_functions) + if global_blacklisted_functions: + leak_blacklist.copy_global_to_local_blacklist( + global_blacklisted_functions) + + # Ensure that that the fuzzer still exists. + logs.info('Setting up fuzzer and data bundles.') + self.fuzzer = setup.update_fuzzer_and_data_bundles( + self.uworker_input.setup_input) + if not self.fuzzer: + raise monitor.TimeStatTrackerFailureException + if not self.fuzzer: logs.error(f'Unable to setup fuzzer {self.fuzzer_name}.') diff --git a/src/clusterfuzz/_internal/metrics/fuzzer_stats.py b/src/clusterfuzz/_internal/metrics/fuzzer_stats.py index 0c274c15e9..fd40840591 100644 --- a/src/clusterfuzz/_internal/metrics/fuzzer_stats.py +++ b/src/clusterfuzz/_internal/metrics/fuzzer_stats.py @@ -46,6 +46,11 @@ 'type': 'INTERVAL', 'mode': 'NULLABLE', }, + { + 'name': 'fuzzer_setup', + 'type': 'INTERVAL', + 'mode': 'NULLABLE', + }, ] JOB_RUN_SCHEMA = { 'fields': [ diff --git a/src/clusterfuzz/_internal/tests/core/bot/tasks/utasks/fuzz_task_test.py b/src/clusterfuzz/_internal/tests/core/bot/tasks/utasks/fuzz_task_test.py index 06690f8db2..ca66f0b364 100644 --- a/src/clusterfuzz/_internal/tests/core/bot/tasks/utasks/fuzz_task_test.py +++ b/src/clusterfuzz/_internal/tests/core/bot/tasks/utasks/fuzz_task_test.py @@ -1596,6 +1596,9 @@ def test_utask_main_blackbox_fuzzer(self, mock_generate_blackbox_testcases): self.assertGreater( actual.fuzz_task_output.fuzzing_duration.ToTimedelta().total_seconds(), 0) + self.assertGreater( + actual.fuzz_task_output.steps_duration['fuzzer_setup'] + .ToTimedelta().total_seconds(), 0) self.assertGreater( actual.fuzz_task_output.testcase_generation_duration.ToTimedelta() .total_seconds(), 0) @@ -1634,6 +1637,17 @@ def test_utask_main_blackbox_fuzzer(self, mock_generate_blackbox_testcases): self.assertEqual(1, dist.count) self.assertGreater(dist.sum, 0) + dist = monitoring_metrics.FUZZ_TASK_STEPS_DURATION.get({ + 'fuzzer': fuzzer.name, + 'job': 'asan_test', + 'platform': environment.platform(), + 'runtime': environment.get_runtime().value, + 'step': 'fuzzer_setup', + 'success': True, + }) + self.assertEqual(1, dist.count) + self.assertGreater(dist.sum, 0) + @mock.patch( 'clusterfuzz._internal.bot.tasks.utasks.fuzz_task.FuzzingSession.generate_blackbox_testcases' ) @@ -1721,6 +1735,41 @@ def test_utask_main_build_setup_failure(self): **labels, 'success': True }).count) + @mock.patch('time.sleep') + @mock.patch( + 'clusterfuzz._internal.bot.tasks.setup.update_fuzzer_and_data_bundles') + def test_utask_main_fuzzer_setup_failure(self, mock_update_fuzzer, _): + """Test utask_main records failed setup step when fuzzer setup fails.""" + self._setup_utask_env() + fuzzer = self._create_test_fuzzer() + mock_update_fuzzer.return_value = None + + fuzz_task_input = uworker_msg_pb2.FuzzTaskInput() + setup_input = uworker_msg_pb2.SetupInput( + fuzzer_name=fuzzer.name, fuzzer=uworker_io.entity_to_protobuf(fuzzer)) + + uworker_input = uworker_msg_pb2.Input( + fuzzer_name=fuzzer.name, + job_type='asan_test', + fuzz_task_input=fuzz_task_input, + setup_input=setup_input, + uworker_env={'FUZZ_TEST_TIMEOUT': '10'}) + + actual = fuzz_task.utask_main(uworker_input) + + self.assertEqual(uworker_msg_pb2.ErrorType.FUZZ_NO_FUZZER, + actual.error_type) + dist = monitoring_metrics.FUZZ_TASK_STEPS_DURATION.get({ + 'fuzzer': fuzzer.name, + 'job': 'asan_test', + 'platform': environment.platform(), + 'runtime': environment.get_runtime().value, + 'step': 'fuzzer_setup', + 'success': False, + }) + self.assertEqual(1, dist.count) + self.assertGreater(dist.sum, 0) + class DoBlackboxFuzzingDeferredLoggingTest(fake_filesystem_unittest.TestCase): """do_blackbox_fuzzing deferred log upload unit tests without datastore dependency."""