Skip to content
This repository was archived by the owner on Jan 2, 2024. It is now read-only.

Commit 9d7e0b0

Browse files
committed
feat: support interfaces and partials
1 parent 0c69ed0 commit 9d7e0b0

File tree

3 files changed

+77
-11
lines changed

3 files changed

+77
-11
lines changed

README.md

+10-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function fuzz() {
1616
const r = fuzz.createCoreRegistry();
1717

1818
// Type to fuzz
19-
const target = t.union([t.string, t.number, t.boolean]);
19+
const target = t.union([t.string, t.type({n:t.number, b:t.boolean})]);
2020

2121
// Builds a particular fuzzer from the registry.
2222
const fuzzer = fuzz.exampleGenerator(r, target);
@@ -29,6 +29,15 @@ function fuzz() {
2929
}
3030
````
3131

32+
Currently supports:
33+
34+
* `t.number`
35+
* `t.string`
36+
* `t.boolean`
37+
* `t.union`
38+
* `t.type` (interface)
39+
* `t.partial`
40+
3241

3342
## License
3443

src/core/core.ts

+42-4
Original file line numberDiff line numberDiff line change
@@ -73,20 +73,20 @@ export function gen<T, C extends t.Decoder<unknown, T> & BasicType>(
7373
};
7474
}
7575

76-
export function fuzzBoolean(n: number) {
76+
export function fuzzBoolean(n: number): boolean {
7777
return n % 2 === 0;
7878
}
7979

80-
export function fuzzNumber(n: number) {
80+
export function fuzzNumber(n: number): number {
8181
return n;
8282
}
8383

84-
export function fuzzString(n: number) {
84+
export function fuzzString(n: number): string {
8585
return `${n}`;
8686
}
8787

8888
// tslint:disable-next-line:no-any
89-
export function fuzzUnion(b: t.UnionC<any>): ConcreteFuzzer<any> {
89+
export function fuzzUnion(b: t.UnionType<t.Any[]>): ConcreteFuzzer<any> {
9090
return {
9191
children: b.types,
9292
func: (n, ...h) => {
@@ -95,9 +95,47 @@ export function fuzzUnion(b: t.UnionC<any>): ConcreteFuzzer<any> {
9595
};
9696
}
9797

98+
export function fuzzInterface(
99+
b: t.InterfaceType<t.Props>
100+
// tslint:disable-next-line:no-any
101+
): ConcreteFuzzer<any> {
102+
const keys = Object.getOwnPropertyNames(b.props);
103+
const vals = keys.map(k => b.props[k]);
104+
return {
105+
children: vals,
106+
func: (n, ...h) => {
107+
const ret = Object.create(null);
108+
h.forEach((v, i) => {
109+
ret[keys[i]] = v.encode(n);
110+
});
111+
return ret;
112+
},
113+
};
114+
}
115+
116+
// tslint:disable-next-line:no-any
117+
export function fuzzPartial(b: t.PartialType<t.Props>): ConcreteFuzzer<any> {
118+
const keys = Object.getOwnPropertyNames(b.props);
119+
const vals = keys.map(k => b.props[k]);
120+
return {
121+
children: vals,
122+
func: (n, ...h) => {
123+
const ret = Object.create(null);
124+
h.forEach((v, i) => {
125+
if (n & (2 ** i)) {
126+
ret[keys[i]] = v.encode(n);
127+
}
128+
});
129+
return ret;
130+
},
131+
};
132+
}
133+
98134
export const coreFuzzers = [
99135
concrete(fuzzNumber, 'NumberType'),
100136
concrete(fuzzBoolean, 'BooleanType'),
101137
concrete(fuzzString, 'StringType'),
102138
gen(fuzzUnion, 'UnionType'),
139+
gen(fuzzInterface, 'InterfaceType'),
140+
gen(fuzzPartial, 'PartialType'),
103141
];

test/test-index.ts

+25-6
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,46 @@ import * as lib from '../src/';
33

44
import * as t from 'io-ts';
55
import { exampleGenerator } from '../src/';
6-
import { isRight } from 'fp-ts/lib/Either';
6+
import { isRight, Right } from 'fp-ts/lib/Either';
77

88
describe('io-ts-fuzzer', () => {
9-
const basicTypes = [
9+
const types = [
10+
// Simple 0- or 1-depth types
1011
t.number,
1112
t.string,
1213
t.boolean,
1314
t.union([t.string, t.number, t.boolean]),
15+
t.type({ s: t.string, m: t.number }),
16+
t.partial({ s: t.string, m: t.number }),
17+
18+
// Complex types
19+
t.type({ s: t.string, m: t.type({ n: t.number }) }),
20+
t.type({
21+
s: t.union([t.string, t.number, t.partial({ n: t.number, z: t.string })]),
22+
m: t.type({ n: t.number }),
23+
}),
1424
];
1525

1626
describe('correctly fuzzes', () => {
17-
for (const b of basicTypes) {
27+
for (const b of types) {
1828
describe(`\`${b.name}\` objects`, () => {
1929
const r = lib.createCoreRegistry()!;
2030

2131
// tslint:disable-next-line:ban
22-
for (const n of [...Array(5).keys()]) {
32+
for (const n of [...Array(100).keys()]) {
2333
it(`for input ${n}`, () => {
24-
const p = exampleGenerator(r, b).encode;
34+
// tslint:disable-next-line:no-any
35+
const p = exampleGenerator<any>(r, b).encode;
2536
const v = p(n);
26-
assert.ok(isRight(b.decode(v)), `must decode ${v}`);
37+
// tslint:disable-next-line:no-any
38+
const d = b.decode(v) as any;
39+
assert.ok(isRight(d), `must decode ${JSON.stringify(v)}`);
40+
assert.deepStrictEqual(
41+
// tslint:disable-next-line:no-any
42+
(d as Right<any>).right,
43+
v,
44+
`must decode ${JSON.stringify(v)}`
45+
);
2746
});
2847
}
2948
});

0 commit comments

Comments
 (0)