@@ -814,6 +814,7 @@ func (f *Fuzzer) spawnWorkersLoop(baseTestChain *chain.TestChain) error {
814814 if err == nil && workerCreatedErr != nil {
815815 err = workerCreatedErr
816816 }
817+
817818 if err == nil {
818819 // Publish an event indicating we created a worker.
819820 workerCreatedErr = f .Events .WorkerCreated .Publish (FuzzerWorkerCreatedEvent {Worker : worker })
@@ -894,13 +895,6 @@ func (f *Fuzzer) Start() error {
894895 f .ctx , f .ctxCancelFunc = context .WithTimeout (f .ctx , time .Duration (f .config .Fuzzing .Timeout )* time .Second )
895896 }
896897
897- // Set up the corpus
898- f .logger .Info ("Initializing corpus" )
899- f .corpus , err = corpus .NewCorpus (f .config .Fuzzing .CorpusDirectory )
900- if err != nil {
901- f .logger .Error ("Failed to create the corpus" , err )
902- return err
903- }
904898 // Start the revert reporter
905899 f .revertReporter .Start (f .ctx )
906900
@@ -933,28 +927,25 @@ func (f *Fuzzer) Start() error {
933927 }
934928 f .logger .Info ("Finished setting up test chain" )
935929
936- // Initialize our coverage maps by measuring the coverage we get from the corpus.
937- var corpusActiveSequences , corpusTotalSequences int
938- if totalCallSequences , testResults := f .corpus .CallSequenceEntryCount (); totalCallSequences > 0 || testResults > 0 {
939- f .logger .Info ("Running call sequences in the corpus" )
940- }
941- startTime := time .Now ()
942- corpusActiveSequences , corpusTotalSequences , err = f .corpus .Initialize (baseTestChain , f .contractDefinitions )
943- if corpusTotalSequences > 0 {
944- f .logger .Info ("Finished running call sequences in the corpus in " , time .Since (startTime ).Round (time .Second ))
930+ // Create and initialize the corpus
931+ f .logger .Info ("Creating corpus..." )
932+ f .corpus , err = corpus .NewCorpus (f .config .Fuzzing .CorpusDirectory )
933+ if err != nil {
934+ f .logger .Error ("Failed to create the corpus" , err )
935+ return err
945936 }
937+ err = f .corpus .Initialize (baseTestChain , f .contractDefinitions )
946938 if err != nil {
947939 f .logger .Error ("Failed to initialize the corpus" , err )
948940 return err
949941 }
950942
951- // Log corpus health statistics, if we have any existing sequences.
952- if corpusTotalSequences > 0 {
953- f .logger .Info (
954- colors .Bold , "corpus: " , colors .Reset ,
955- "health: " , colors .Bold , int (float32 (corpusActiveSequences )/ float32 (corpusTotalSequences )* 100.0 ), "%" , colors .Reset , ", " ,
956- "sequences: " , colors .Bold , corpusTotalSequences , " (" , corpusActiveSequences , " valid, " , corpusTotalSequences - corpusActiveSequences , " invalid)" , colors .Reset ,
957- )
943+ // Log that we will initialize corpus if there are any call sequences or test results
944+ if totalCallSequences , testResults := f .corpus .CallSequenceEntryCount (); totalCallSequences > 0 || testResults > 0 {
945+ f .logger .Info ("Initializing corpus..." )
946+
947+ // Monitor corpus initialization
948+ go f .monitorCorpusInitialization ()
958949 }
959950
960951 // Start the corpus pruner.
@@ -1081,6 +1072,45 @@ func (f *Fuzzer) Terminate() {
10811072 }
10821073}
10831074
1075+ // monitorCorpusInitialization monitors the corpus initialization process and logs the corpus health when it is complete.
1076+ // This goroutine is short-lived and exits when the corpus is initialized.
1077+ func (f * Fuzzer ) monitorCorpusInitialization () {
1078+ // There is nothing to do if there are no corpus elements or unexecuted call sequences
1079+ totalSequences , totalTestResults := f .corpus .CallSequenceEntryCount ()
1080+ if ! f .corpus .InitializingCorpus () || totalSequences == 0 || totalTestResults == 0 {
1081+ return
1082+ }
1083+
1084+ // Capture an approximate start time
1085+ startTime := time .Now ()
1086+ for ! utils .CheckContextDone (f .ctx ) && ! utils .CheckContextDone (f .emergencyCtx ) {
1087+ // Go to sleep if corpus is still initializing
1088+ if f .corpus .InitializingCorpus () {
1089+ time .Sleep (200 * time .Millisecond )
1090+ continue
1091+ }
1092+
1093+ // Calculate the necessary variables for corpus health
1094+ totalSequences , totalTestResults := f .corpus .CallSequenceEntryCount ()
1095+ totalCorpusEntries := totalSequences + totalTestResults
1096+ validSequences := f .corpus .ValidCallSequences ()
1097+ invalidSequences := int (totalSequences - int (validSequences ))
1098+
1099+ // Log how much time it took to initialize the corpus
1100+ f .logger .Info ("Finished running call sequences in the corpus in " , time .Since (startTime ).Round (time .Second ))
1101+
1102+ // Log the overall corpus health
1103+ f .logger .Info (
1104+ colors .Bold , "corpus: " , colors .Reset ,
1105+ "health: " , colors .Bold , int (float32 (validSequences )/ float32 (totalCorpusEntries )* 100 ), "%" , colors .Reset , ", " ,
1106+ "sequences: " , colors .Bold , totalCorpusEntries , " (" , validSequences , " valid, " , invalidSequences , " invalid)" , colors .Reset ,
1107+ )
1108+
1109+ // Now we can exit the goroutine
1110+ break
1111+ }
1112+ }
1113+
10841114// printMetricsLoop prints metrics to the console in a loop until ctx signals a stopped operation.
10851115func (f * Fuzzer ) printMetricsLoop () {
10861116 // Define our start time
0 commit comments