Skip to content

Commit f5c948e

Browse files
addisoncrumptokatoka
authored andcommitted
Archive coverage data alongside corpus archives (from AFL++ fork) (google#2028)
Supercedes google#2020. Moving so we (AFL++ people) can collaborate on this PR. From the original: > Currently, only corpora are saved in the archive and the summaries of coverage are provided at the end of the experiment. This change simply incorporates the saving of the coverage data snapshots next to the trial corpus snapshots. --------- Co-authored-by: Toka <[email protected]>
1 parent 5997776 commit f5c948e

File tree

6 files changed

+34
-3
lines changed

6 files changed

+34
-3
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,6 @@ docker/generated.mk
4444

4545
# Vim backup files.
4646
.*.swp
47+
48+
# Diff files from matplotlib
49+
*-failed-diff.png
Binary file not shown.

common/experiment_utils.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,11 @@ def get_corpus_archive_name(cycle: int) -> str:
129129
return get_cycle_filename('corpus-archive', cycle) + '.tar.gz'
130130

131131

132+
def get_coverage_archive_name(cycle: int) -> str:
133+
"""Returns a corpus archive name given a cycle."""
134+
return get_cycle_filename('coverage-archive', cycle) + '.json'
135+
136+
132137
def get_stats_filename(cycle: int) -> str:
133138
"""Returns a corpus archive name given a cycle."""
134139
return get_cycle_filename('stats', cycle) + '.json'

experiment/measurer/measure_manager.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import collections
1717
import gc
1818
import glob
19+
import gzip
1920
import multiprocessing
2021
import json
2122
import os
@@ -614,10 +615,33 @@ def measure_snapshot_coverage( # pylint: disable=too-many-locals
614615
# Generate profdata and transform it into json form.
615616
snapshot_measurer.generate_coverage_information(cycle)
616617

618+
# Compress and save the exported profdata snapshot.
619+
coverage_archive_zipped = os.path.join(
620+
snapshot_measurer.trial_dir, 'coverage',
621+
experiment_utils.get_coverage_archive_name(cycle) + '.gz')
622+
623+
coverage_archive_dir = os.path.dirname(coverage_archive_zipped)
624+
if not os.path.exists(coverage_archive_dir):
625+
os.makedirs(coverage_archive_dir)
626+
627+
with gzip.open(str(coverage_archive_zipped), 'wb') as compressed:
628+
with open(snapshot_measurer.cov_summary_file, 'rb') as uncompressed:
629+
# avoid saving warnings so we can direct import with pandas
630+
compressed.write(uncompressed.readlines()[-1])
631+
632+
coverage_archive_dst = exp_path.filestore(coverage_archive_zipped)
633+
if filestore_utils.cp(coverage_archive_zipped,
634+
coverage_archive_dst,
635+
expect_zero=False).retcode:
636+
snapshot_logger.warning('Coverage not found for cycle: %d.', cycle)
637+
return None
638+
639+
os.remove(coverage_archive_zipped) # no reason to keep this around
640+
617641
# Run crashes again, parse stacktraces and generate crash signatures.
618642
crashes = snapshot_measurer.process_crashes(cycle)
619643

620-
# Get the coverage of the new corpus units.
644+
# Get the coverage summary of the new corpus units.
621645
branches_covered = snapshot_measurer.get_current_coverage()
622646
fuzzer_stats_data = snapshot_measurer.get_fuzzer_stats(cycle)
623647
snapshot = models.Snapshot(time=this_time,

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ redis==4.3.4
2121
rq==1.11.1
2222
scikit-posthocs==0.7.0
2323
scipy==1.9.2
24-
seaborn==0.12.0
24+
seaborn==0.13.2
2525
sqlalchemy==1.4.41
2626
protobuf==3.20.3
2727

service/gcbrun_experiment.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
TRIGGER_COMMAND = '/gcbrun'
2929
RUN_EXPERIMENT_COMMAND_STR = f'{TRIGGER_COMMAND} run_experiment.py '
3030
SKIP_COMMAND_STR = f'{TRIGGER_COMMAND} skip'
31-
# A DUMMY COMMENT
3231

3332

3433
def get_comments(pull_request_number):

0 commit comments

Comments
 (0)