edu.berkeley.cs.jqf.fuzz.random.NoGuidance Maven / Gradle / Ivy
Show all versions of jqf-fuzz Show documentation
/*
* Copyright (c) 2017-2018 The Regents of the University of California
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package edu.berkeley.cs.jqf.fuzz.random;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Random;
import java.util.function.Consumer;
import edu.berkeley.cs.jqf.fuzz.guidance.Guidance;
import edu.berkeley.cs.jqf.fuzz.guidance.GuidanceException;
import edu.berkeley.cs.jqf.fuzz.guidance.Result;
import edu.berkeley.cs.jqf.fuzz.util.Coverage;
import edu.berkeley.cs.jqf.instrument.tracing.events.TraceEvent;
/**
* A front-end that only generates random inputs.
*
* This class provides no guidance to quickcheck. It seeds random values from
* {@link Random}, making it effectively an unguided random test input
* generator.
*/
public class NoGuidance implements Guidance {
private boolean keepGoing = true;
private long numTrials = 0;
private long numDiscards = 0;
private final long maxTrials;
private final float maxDiscardRatio = 0.9f;
private final PrintStream out;
private Random random = new Random();
private Coverage coverage = new Coverage();
private static boolean KEEP_GOING_ON_ERROR = true;
/**
* Creates a NoGuidance instance that will run a maximum number
* of trials.
*
* @param maxTrials the maximum number of runs to execute
* @param out an optional stream for logging error traces
*/
public NoGuidance(long maxTrials, PrintStream out) {
if (maxTrials <= 0) {
throw new IllegalArgumentException("maxTrials must be greater than 0");
}
this.maxTrials = maxTrials;
this.out = out;
}
/**
* Returns a stream of random numbers
*
* @return An infinitely long input stream that generates random numbers
*/
@Override
public InputStream getInput() {
return Guidance.createInputStream(() -> random.nextInt(256));
}
/**
* Returns true as long as maxTrials has not been reached.
* @return true as long as maxTrials has not been reached
*/
@Override
public boolean hasInput() {
return keepGoing;
}
/**
* Handles the result of a fuzz run.
*
* @param result the result of the fuzzing trial
* @param error the error thrown during the trial, or null
*/
@Override
public void handleResult(Result result, Throwable error) {
numTrials++;
// Display error stack trace in case of failure
if (result == Result.FAILURE) {
if (out != null) {
error.printStackTrace(out);
}
this.keepGoing = KEEP_GOING_ON_ERROR;
}
// Keep track of discards
if (result == Result.INVALID) {
numDiscards++;
}
// Stopping criteria
if (numTrials >= maxTrials) {
this.keepGoing = false;
}
if (numTrials > 10 && ((float) numDiscards)/((float) (numTrials)) > maxDiscardRatio) {
throw new GuidanceException("Assumption is too strong; too many inputs discarded");
}
}
/**
* Returns a callback that does almost nothing.
*
*
Since this is unguided random guidance, the trace events are
* not used in generating inputs.
*
* The handler here merely updates coverage statistics.
*
* @param thread the thread whose events to handle
* @return a callback that does nothing.
*/
@Override
public Consumer generateCallBack(Thread thread) {
return coverage::handleEvent;
}
/**
* Returns a reference to the coverage statistics.
* @return a reference to the coverage statistics
*/
public Coverage getCoverage() {
return coverage;
}
}