diff --git a/fuzz/src/main/java/edu/berkeley/cs/jqf/fuzz/ei/ExecutionIndex.java b/fuzz/src/main/java/edu/berkeley/cs/jqf/fuzz/ei/ExecutionIndex.java index 141f0d11d..9ca55056b 100644 --- a/fuzz/src/main/java/edu/berkeley/cs/jqf/fuzz/ei/ExecutionIndex.java +++ b/fuzz/src/main/java/edu/berkeley/cs/jqf/fuzz/ei/ExecutionIndex.java @@ -47,12 +47,14 @@ public class ExecutionIndex implements Comparable { final int[] ei; + private final int hash; public ExecutionIndex(int[] ei) { if (ei.length == 0 || ei.length % 2 == 1) { throw new IllegalArgumentException("Execution index must have non-zero even elements"); } this.ei = ei; + hash = Arrays.hashCode(this.ei); } public ExecutionIndex(Prefix prefix, Suffix suffix) { @@ -72,11 +74,12 @@ public ExecutionIndex(Prefix prefix, Suffix suffix) { for (int i = suffix.offset; i < size; i++) { this.ei[i] = suffixEi[i]; } + hash = Arrays.hashCode(this.ei); } @Override public int hashCode() { - return Arrays.hashCode(ei); + return hash; } @Override diff --git a/fuzz/src/main/java/edu/berkeley/cs/jqf/fuzz/ei/ExecutionIndexingDriver.java b/fuzz/src/main/java/edu/berkeley/cs/jqf/fuzz/ei/ExecutionIndexingDriver.java index 89794105b..3777989bf 100644 --- a/fuzz/src/main/java/edu/berkeley/cs/jqf/fuzz/ei/ExecutionIndexingDriver.java +++ b/fuzz/src/main/java/edu/berkeley/cs/jqf/fuzz/ei/ExecutionIndexingDriver.java @@ -30,8 +30,10 @@ package edu.berkeley.cs.jqf.fuzz.ei; import java.io.File; +import java.util.Random; import edu.berkeley.cs.jqf.fuzz.junit.GuidedFuzzing; +import edu.berkeley.cs.jqf.fuzz.util.IOUtils; /** * Entry point for fuzzing with Execution Indexing. @@ -61,9 +63,15 @@ public static void main(String[] args) { try { // Load the guidance String title = testClassName+"#"+testMethodName; - ZestGuidance guidance = seedFiles != null ? - new ExecutionIndexingGuidance(title, null, outputDirectory, seedFiles) : - new ExecutionIndexingGuidance(title, null, outputDirectory, new File[]{}); + ExecutionIndexingGuidance guidance; + + if (seedFiles == null) { + guidance = new ExecutionIndexingGuidance(title, null, null, outputDirectory, new Random()); + } else if (seedFiles.length == 1 && seedFiles[0].isDirectory()) { + guidance = new ExecutionIndexingGuidance(title, null, null, outputDirectory, seedFiles[0], new Random()); + } else { + guidance = new ExecutionIndexingGuidance(title, null, null, outputDirectory, seedFiles, new Random()); + } // Ensure that generators are being traced System.setProperty("jqf.traceGenerators", "true"); diff --git a/fuzz/src/main/java/edu/berkeley/cs/jqf/fuzz/ei/ExecutionIndexingGuidance.java b/fuzz/src/main/java/edu/berkeley/cs/jqf/fuzz/ei/ExecutionIndexingGuidance.java index 4e012ca1b..e56a05c8b 100644 --- a/fuzz/src/main/java/edu/berkeley/cs/jqf/fuzz/ei/ExecutionIndexingGuidance.java +++ b/fuzz/src/main/java/edu/berkeley/cs/jqf/fuzz/ei/ExecutionIndexingGuidance.java @@ -44,6 +44,7 @@ import java.util.function.Consumer; import java.util.stream.Collectors; +import com.pholser.junit.quickcheck.random.SourceOfRandomness; import edu.berkeley.cs.jqf.fuzz.ei.ExecutionIndex.Prefix; import edu.berkeley.cs.jqf.fuzz.ei.ExecutionIndex.Suffix; import edu.berkeley.cs.jqf.fuzz.ei.state.AbstractExecutionIndexingState; @@ -53,6 +54,7 @@ import edu.berkeley.cs.jqf.fuzz.guidance.Result; import edu.berkeley.cs.jqf.fuzz.junit.quickcheck.FuzzStatement; import edu.berkeley.cs.jqf.fuzz.util.CoverageFactory; +import edu.berkeley.cs.jqf.fuzz.util.IOUtils; import edu.berkeley.cs.jqf.fuzz.util.ProducerHashMap; import edu.berkeley.cs.jqf.instrument.tracing.FastCoverageSnoop; import edu.berkeley.cs.jqf.instrument.tracing.SingleSnoop; @@ -101,9 +103,6 @@ public class ExecutionIndexingGuidance extends ZestGuidance { /** Mean number of contiguous bytes to mutate in each mutation. */ protected final double MEAN_MUTATION_SIZE = 4.0; // Bytes - /** Probability that a standard mutation sets the byte to just zero instead of a random value. */ - protected final double MUTATION_ZERO_PROBABILITY = 0.05; - /** Max number of contiguous bytes to splice in from another input during the splicing stage. */ protected final int MAX_SPLICE_SIZE = 64; // Bytes @@ -148,7 +147,8 @@ public ExecutionIndexingGuidance(String testName, Duration duration, Long trials * @throws IOException if the output directory could not be prepared */ public ExecutionIndexingGuidance(String testName, Duration duration, Long trials, File outputDirectory, File seedInputDir, Random sourceOfRandomness) throws IOException { - super(testName, duration, trials, outputDirectory, seedInputDir, sourceOfRandomness); + this(testName, duration, trials, outputDirectory, IOUtils.resolveInputFileOrDirectory(seedInputDir), + sourceOfRandomness); } /** @@ -158,11 +158,21 @@ public ExecutionIndexingGuidance(String testName, Duration duration, Long trials * @param testName the name of test to display on the status screen * @param duration the amount of time to run fuzzing for, where * {@code null} indicates unlimited time. + * @param trials the number of trials for which to run fuzzing, where + * {@code null} indicates unlimited trials. * @param outputDirectory the directory where fuzzing results will be written + * @param seedFiles the seed input files to be used as initial inputs + * @param sourceOfRandomness a pseudo-random number generator * @throws IOException if the output directory could not be prepared */ - public ExecutionIndexingGuidance(String testName, Duration duration, File outputDirectory, File[] seedFiles) throws IOException { - super(testName, duration, outputDirectory, seedFiles); + public ExecutionIndexingGuidance(String testName, Duration duration, Long trials, File outputDirectory, + File[] seedFiles, Random sourceOfRandomness) throws IOException { + super(testName, duration, trials, outputDirectory, new File[0], sourceOfRandomness); + if (seedFiles != null) { + for (File seedFile : seedFiles) { + seedInputs.add(new MappedSeedInput(seedFile)); + } + } } /** Returns the banner to be displayed on the status screen */ diff --git a/fuzz/src/main/java/edu/berkeley/cs/jqf/fuzz/ei/ZestGuidance.java b/fuzz/src/main/java/edu/berkeley/cs/jqf/fuzz/ei/ZestGuidance.java index bd79a454c..7aed593d6 100644 --- a/fuzz/src/main/java/edu/berkeley/cs/jqf/fuzz/ei/ZestGuidance.java +++ b/fuzz/src/main/java/edu/berkeley/cs/jqf/fuzz/ei/ZestGuidance.java @@ -85,6 +85,9 @@ */ public class ZestGuidance implements Guidance { + /** Probability that a standard mutation sets the byte to just zero instead of a random value. */ + protected final double MUTATION_ZERO_PROBABILITY = 0.1; + /** A pseudo-random number generator for generating fresh values. */ protected Random random; @@ -1305,7 +1308,7 @@ public Input fuzz(Random random) { int numMutations = sampleGeometric(random, MEAN_MUTATION_COUNT); newInput.desc += ",havoc:"+numMutations; - boolean setToZero = random.nextDouble() < 0.1; // one out of 10 times + boolean setToZero = random.nextDouble() < MUTATION_ZERO_PROBABILITY; // one out of 10 times for (int mutation = 1; mutation <= numMutations; mutation++) {