edu.berkeley.cs.jqf.fuzz.junit.quickcheck.FastSourceOfRandomness Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jqf-fuzz Show documentation
Show all versions of jqf-fuzz Show documentation
JQF: Feedback-directed Quickcheck for Java - Guided fuzzing interface
/*
* 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.junit.quickcheck;
import java.util.Random;
import com.pholser.junit.quickcheck.internal.Ranges;
import com.pholser.junit.quickcheck.internal.Ranges.Type;
import com.pholser.junit.quickcheck.random.SourceOfRandomness;
import edu.berkeley.cs.jqf.fuzz.guidance.StreamBackedRandom;
/**
* A source of randomness with better performance but looser
* statistical guarantees.
*
* This class is meant for use with guided fuzzing, where the
* {@link Random} delegate is usually a {@link StreamBackedRandom}.
* In this case, the random source does not have to give any
* statistical guarantees such as uniformity or independentness,
* and therefore is amenable to several optimizations, which are
* implemented in this class.
*
* @author Rohan Padhye
*/
public class FastSourceOfRandomness extends SourceOfRandomness {
private StreamBackedRandom delegate;
public FastSourceOfRandomness(StreamBackedRandom delegate) {
super(delegate);
// Gotta make a copy of the reference because
// super-class declares the field as private :-\
this.delegate = delegate;
}
@Override
public Random toJDKRandom() {
return this.delegate;
}
@Override
public byte nextByte(byte min, byte max) {
if (min == Byte.MIN_VALUE && max == Byte.MAX_VALUE) {
return delegate.nextByte();
} else if (min >= Byte.MIN_VALUE && max <= Byte.MAX_VALUE) {
}
return this.fastChooseByteInRange(min, max);
}
@Override
public short nextShort(short min, short max) {
if (min == Short.MIN_VALUE && max == Short.MAX_VALUE) {
return delegate.nextShort();
}
return (short)(this.fastChooseIntInRange(min, max));
}
@Override
public char nextChar(char min, char max) {
Ranges.checkRange(Type.CHARACTER, min, max);
return (char)(this.fastChooseIntInRange(min, max));
}
@Override
public int nextInt(int min, int max) {
if (min == Integer.MIN_VALUE && max == Integer.MAX_VALUE) {
return delegate.nextInt();
}
return this.fastChooseIntInRange(min, max);
}
@Override
public long nextLong(long min, long max) {
int comparison = Ranges.checkRange(Type.INTEGRAL, min, max);
if (min == Long.MIN_VALUE && max == Long.MAX_VALUE) {
return delegate.nextLong();
}
return comparison == 0 ? min : Ranges.choose(this, min, max);
}
private int fastChooseIntInRange(int min, int max) {
int range = max - min;
// If range is too wide, overflow will make it negative
if (range > 0) {
int random = delegate.nextInt() % range;
if (random < 0) {
random += range;
}
return min + random;
} else {
return (int) Ranges.choose(this, min, max);
}
}
private byte fastChooseByteInRange(byte min, byte max) {
int range = max - min;
// If range is too wide, overflow will make it negative
if (range > 0 && range <= (Byte.MAX_VALUE)) {
int random = delegate.nextByte() % range;
if (random < 0) {
random += range;
}
byte result = (byte) (min + random);
assert (result >= min && result <= max);
return result;
} else {
return (byte) fastChooseIntInRange((int) min, (int) max);
}
}
}