def record_stats(self): """Use fuzzer.get_stats if it is offered, validate the stats and then save them to a file so that they will be synced to the filestore.""" # TODO(metzman): Make this more resilient so we don't wait forever and # so that breakages in stats parsing doesn't break runner. fuzzer_module = get_fuzzer_module(self.fuzzer) fuzzer_module_get_stats = getattr(fuzzer_module, 'get_stats', None) if fuzzer_module_get_stats is None: # Stats support is optional. return try: output_corpus = environment.get('OUTPUT_CORPUS_DIR') stats_json_str = fuzzer_module_get_stats(output_corpus, self.log_file) except Exception: # pylint: disable=broad-except logs.error('Call to %d failed.', fuzzer_module_get_stats) return try: fuzzer_stats.validate_fuzzer_stats(stats_json_str) except (ValueError, json.decoder.JSONDecodeError): logs.error('Stats are invalid.') return stats_filename = experiment_utils.get_stats_filename(self.cycle) stats_path = os.path.join(self.results_dir, stats_filename) with open(stats_path, 'w') as stats_file_handle: stats_file_handle.write(stats_json_str)
def get_fuzzer_stats(stats_filestore_path): """Reads, validates and returns the stats in |stats_filestore_path|.""" with tempfile.NamedTemporaryFile() as temp_file: result = filestore_utils.cp(stats_filestore_path, temp_file.name, expect_zero=False) if result.retcode != 0: return None stats_str = temp_file.read() fuzzer_stats.validate_fuzzer_stats(stats_str) return json.loads(stats_str)