Skip to content

Commit

Permalink
Merge pull request #69 from dubzzz/fuzzing
Browse files Browse the repository at this point in the history
Add fuzzing test against built-in array
  • Loading branch information
paldepind authored Mar 13, 2019
2 parents e63491a + 2aa3088 commit 6a21d51
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 0 deletions.
111 changes: 111 additions & 0 deletions test/commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { assert } from "chai";
import * as fc from "fast-check";
import * as L from "../src";

type Real = { data: L.List<number> };
type Model = { data: number[] };

export class ConcatCommand implements fc.Command<Model, Real> {
constructor(readonly source: number[]) {}
check(/*m: Readonly<Model>*/): boolean {
return true;
}
run(m: Model, r: Real): void {
m.data = [...m.data, ...this.source];
r.data = L.concat(r.data, L.from(this.source));
assert.deepEqual(L.toArray(r.data), m.data);
}
toString(): string {
return `L.concat(src, L.from([${this.source.join(",")}]))`;
}
}

export class DropCommand implements fc.Command<Model, Real> {
constructor(readonly num: number) {}
check(/*m: Readonly<Model>*/): boolean {
return true;
}
run(m: Model, r: Real): void {
m.data = m.data.slice(this.num);
r.data = L.drop(this.num, r.data);
assert.deepEqual(L.toArray(r.data), m.data);
}
toString(): string {
return `L.drop(${this.num}, src)`;
}
}

export class TakeCommand implements fc.Command<Model, Real> {
constructor(readonly num: number) {}
check(/*m: Readonly<Model>*/): boolean {
return true;
}
run(m: Model, r: Real): void {
m.data = m.data.slice(0, this.num);
r.data = L.take(this.num, r.data);
assert.deepEqual(L.toArray(r.data), m.data);
}
toString(): string {
return `L.take(${this.num}, src)`;
}
}

export class MapCommand implements fc.Command<Model, Real> {
constructor(readonly val: number) {}
check(/*m: Readonly<Model>*/): boolean {
return true;
}
run(m: Model, r: Real): void {
m.data = m.data.map(v => (v * this.val) | 0);
r.data = L.map(v => (v * this.val) | 0, r.data);
assert.deepEqual(L.toArray(r.data), m.data);
}
toString(): string {
return `L.map(v => (v * ${this.val}) | 0, src)`;
}
}

export class ReverseCommand implements fc.Command<Model, Real> {
constructor() {}
check(/*m: Readonly<Model>*/): boolean {
return true;
}
run(m: Model, r: Real): void {
m.data = m.data.reverse();
r.data = L.reverse(r.data);
assert.deepEqual(L.toArray(r.data), m.data);
}
toString(): string {
return `L.reverse(src)`;
}
}

export class ConcatPreCommand implements fc.Command<Model, Real> {
constructor(readonly source: number[]) {}
check(/*m: Readonly<Model>*/): boolean {
return true;
}
run(m: Model, r: Real): void {
m.data = [...this.source, ...m.data];
r.data = L.concat(L.from(this.source), r.data);
assert.deepEqual(L.toArray(r.data), m.data);
}
toString(): string {
return `L.concat(L.from([${this.source.join(",")}]), src)`;
}
}

export class FilterCommand implements fc.Command<Model, Real> {
constructor(readonly val: number) {}
check(/*m: Readonly<Model>*/): boolean {
return true;
}
run(m: Model, r: Real): void {
m.data = m.data.filter(v => v >= this.val);
r.data = L.filter(v => v >= this.val, r.data);
assert.deepEqual(L.toArray(r.data), m.data);
}
toString(): string {
return `L.filter(v => v >= ${this.val}, src)`;
}
}
34 changes: 34 additions & 0 deletions test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ import {
import { checkList, installCheck } from "./check";
import { nothing, just, Maybe, isJust } from "./utils";
import * as R from "ramda";
import {
DropCommand,
ConcatCommand,
TakeCommand,
MapCommand,
ReverseCommand,
ConcatPreCommand,
FilterCommand
} from "./commands";

const L: typeof Loriginal = installCheck(Loriginal);

Expand Down Expand Up @@ -179,6 +188,31 @@ class Identity<A> {
}

describe("List", () => {
it("against built-in array", () => {
const integerArrayArb = fc.array(fc.integer(), 10000);
fc.assert(
fc.property(
integerArrayArb,
fc.commands(
[
integerArrayArb.map(vs => new ConcatCommand(vs)),
integerArrayArb.map(vs => new ConcatPreCommand(vs)),
fc.nat().map(num => new DropCommand(num)),
fc.nat().map(num => new TakeCommand(num)),
fc.integer().map(val => new FilterCommand(val)),
fc.integer().map(val => new MapCommand(val)),
fc.constant(new ReverseCommand())
],
25
),
(initialValues, cmds) => {
const model = { data: Array.from(initialValues) };
const real = { data: L.from(initialValues) };
fc.modelRun(() => ({ model, real }), cmds);
}
)
);
});
describe("repeat", () => {
it("creates list of n repeated elements", () => {
[10, 100].forEach(n => {
Expand Down

0 comments on commit 6a21d51

Please sign in to comment.