Skip to content

Commit

Permalink
Add the ability to select one of the constants using fc.constantFrom
Browse files Browse the repository at this point in the history
  • Loading branch information
dubzzz committed Feb 19, 2018
1 parent 6db53f2 commit 262b809
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 7 deletions.
24 changes: 20 additions & 4 deletions src/check/arbitrary/ConstantArbitrary.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
import Arbitrary from './definition/Arbitrary'
import Shrinkable from './definition/Shrinkable'
import MutableRandomGenerator from '../../random/generator/MutableRandomGenerator'
import { nat } from './IntegerArbitrary'
import { stream, Stream } from '../../stream/Stream'

class ConstantArbitrary<T> extends Arbitrary<T> {
constructor(readonly value: T) {
readonly idArb: Arbitrary<number>;
constructor(readonly values: T[]) {
super();
this.idArb = nat(values.length -1);
}
generate(mrng: MutableRandomGenerator): Shrinkable<T> {
return new Shrinkable(this.value);
if (this.values.length === 1)
return new Shrinkable(this.values[0]);

const id = this.idArb.generate(mrng).value;
if (id === 0)
return new Shrinkable(this.values[0]);

function* g(v: T) { yield new Shrinkable(v); }
return new Shrinkable(this.values[id], () => stream(g(this.values[0])));
}
}

function constant<T>(value: T): Arbitrary<T> {
return new ConstantArbitrary<T>(value);
return new ConstantArbitrary<T>([value]);
}

export { constant };
function constantFrom<T>(v0: T, ...values: T[]): Arbitrary<T> {
return new ConstantArbitrary<T>([v0, ...values]);
}

export { constant, constantFrom };
4 changes: 2 additions & 2 deletions src/fast-check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Shrinkable from './check/arbitrary/definition/Shrinkable'
import { array } from './check/arbitrary/ArrayArbitrary'
import { boolean } from './check/arbitrary/BooleanArbitrary'
import { char, ascii, char16bits, unicode, fullUnicode, hexa, base64 } from './check/arbitrary/CharacterArbitrary'
import { constant } from './check/arbitrary/ConstantArbitrary'
import { constant, constantFrom } from './check/arbitrary/ConstantArbitrary'
import { dictionary } from './check/arbitrary/DictionaryArbitrary'
import { float, double } from './check/arbitrary/FloatingPointArbitrary'
import { frequency } from './check/arbitrary/FrequencyArbitrary'
Expand Down Expand Up @@ -43,7 +43,7 @@ export {
integer, nat, // integer types
char, ascii, char16bits, unicode, fullUnicode, hexa, base64, // single character
string, asciiString, string16bits, unicodeString, fullUnicodeString, hexaString, base64String, lorem, // strings
constant, option, oneof, frequency, array, set, tuple, generic_tuple, // combination of others
constant, constantFrom, option, oneof, frequency, array, set, tuple, generic_tuple, // combination of others
anything, object, json, unicodeJson, // complex combinations
// extend the framework
Arbitrary, Shrinkable,
Expand Down
33 changes: 32 additions & 1 deletion test/unit/check/arbitrary/ConstantArbitrary.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as assert from 'power-assert';
import * as fc from '../../../../lib/fast-check';

import { constant } from '../../../../src/check/arbitrary/ConstantArbitrary';
import { constant, constantFrom } from '../../../../src/check/arbitrary/ConstantArbitrary';

import * as stubRng from '../../stubs/generators';

Expand All @@ -20,4 +21,34 @@ describe("ConstantArbitrary", () => {
assert.deepEqual(g, ["hello", "world"]);
});
});
describe('constantFrom', () => {
it('Should always return one of the constants', () => fc.assert(
fc.property(fc.array(fc.string(), 1, 10), fc.integer(), (data, seed) => {
const mrng = stubRng.mutable.fastincrease(seed);
const g = constant(data[0], ...data.slice(1)).generate(mrng).value;
return data.indexOf(g) !== -1;
})
));
it('Should be able to produce all the constants', () => fc.assert(
fc.property(fc.array(fc.string(), 1, 10), fc.integer(), (data, seed) => {
const mrng = stubRng.mutable.fastincrease(seed);
const arb = constant(data[0], ...data.slice(1));
for (let id = 0 ; id != 10000 ; ++id) {
const g = arb.generate(mrng).value;
if (data.indexOf(g) !== -1) return true;
}
return false;
})
));
it('Should shrink any of the constants towards the first one', () => fc.assert(
fc.property(fc.set(fc.string(), 1, 10), fc.integer(), (data, seed) => {
const mrng = stubRng.mutable.fastincrease(seed);
const shrinkable = constant(data[0], ...data.slice(1)).generate(mrng);
if (data.indexOf(shrinkable.value) === 0)
assert.deepStrictEqual([...shrinkable.shrink()], []);
else
assert.deepStrictEqual([...shrinkable.shrink()].map(s => s.value), [data[0]]);
})
));
});
});

0 comments on commit 262b809

Please sign in to comment.