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

Commit 9860450

Browse files
committed
feat: support arrays, intersection, null, undefined, void, unknown
1 parent 2ef3c69 commit 9860450

File tree

5 files changed

+94
-28
lines changed

5 files changed

+94
-28
lines changed

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ Currently supports:
3737
* `t.union`
3838
* `t.type` (interface)
3939
* `t.partial`
40+
* `t.intersection`
41+
* `t.array`
42+
* `t.null`
43+
* `t.undefined`
44+
* `t.void`
45+
* `t.unknown`
4046

4147

4248
## License

src/core/core.ts

+58
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export type BasicType =
2222
| t.PartialType<any>
2323
| t.DictionaryType<t.Any, t.Any>
2424
| t.UnionType<t.Any[]>
25+
| t.IntersectionType<t.Any[]>
2526
// tslint:disable-next-line:no-any
2627
| t.InterfaceType<any>
2728
| t.TupleType<t.Any[]>
@@ -85,6 +86,20 @@ export function fuzzString(n: number): string {
8586
return `${n}`;
8687
}
8788

89+
export function fuzzNull(): null {
90+
return null;
91+
}
92+
93+
export function fuzzUndefined(): undefined {
94+
return undefined;
95+
}
96+
97+
export function fuzzVoid(): void {}
98+
99+
export function fuzzUnknown(n: number): unknown {
100+
return n;
101+
}
102+
88103
// tslint:disable-next-line:no-any
89104
export function fuzzUnion(b: t.UnionType<t.Any[]>): ConcreteFuzzer<any> {
90105
return {
@@ -113,6 +128,22 @@ export function fuzzInterface(
113128
};
114129
}
115130

131+
export function fuzzArray(
132+
b: t.ArrayType<t.Mixed>
133+
// tslint:disable-next-line:no-any
134+
): ConcreteFuzzer<any[]> {
135+
return {
136+
children: [b.type],
137+
func: (n, h0) => {
138+
const ret = [];
139+
for (let index = 0; index < n % 103; index++) {
140+
ret.push(h0.encode(n + index));
141+
}
142+
return ret;
143+
},
144+
};
145+
}
146+
116147
// tslint:disable-next-line:no-any
117148
export function fuzzPartial(b: t.PartialType<t.Props>): ConcreteFuzzer<any> {
118149
const keys = Object.getOwnPropertyNames(b.props);
@@ -131,11 +162,38 @@ export function fuzzPartial(b: t.PartialType<t.Props>): ConcreteFuzzer<any> {
131162
};
132163
}
133164

165+
export function fuzzIntersection(
166+
b: t.IntersectionType<t.Any[]>
167+
// tslint:disable-next-line:no-any
168+
): ConcreteFuzzer<any> {
169+
return {
170+
children: b.types,
171+
func: (n, ...h) => {
172+
// tslint:disable-next-line:no-any
173+
let ret: any = undefined;
174+
h.forEach((v, i) => {
175+
if (ret === undefined) {
176+
ret = v.encode(n);
177+
} else {
178+
ret = { ...ret, ...v.encode(n) };
179+
}
180+
});
181+
return ret;
182+
},
183+
};
184+
}
185+
134186
export const coreFuzzers = [
135187
concrete(fuzzNumber, 'NumberType'),
136188
concrete(fuzzBoolean, 'BooleanType'),
137189
concrete(fuzzString, 'StringType'),
190+
concrete(fuzzNull, 'NullType'),
191+
concrete(fuzzUndefined, 'UndefinedType'),
192+
concrete(fuzzVoid, 'VoidType'),
193+
concrete(fuzzUnknown, 'UnknownType'),
138194
gen(fuzzUnion, 'UnionType'),
139195
gen(fuzzInterface, 'InterfaceType'),
140196
gen(fuzzPartial, 'PartialType'),
197+
gen(fuzzArray, 'ArrayType'),
198+
gen(fuzzIntersection, 'IntersectionType'),
141199
];

test/helpers.ts

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import * as t from 'io-ts';
2+
3+
export const types = [
4+
// Simple 0- or 1-depth types
5+
t.number,
6+
t.string,
7+
t.boolean,
8+
t.union([t.string, t.number, t.boolean]),
9+
t.intersection([t.type({ s: t.string }), t.type({ m: t.number })]),
10+
t.type({ s: t.string, m: t.number }),
11+
t.partial({ s: t.string, m: t.number }),
12+
t.null,
13+
t.undefined,
14+
t.void,
15+
t.unknown,
16+
t.array(t.string),
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+
}),
24+
];

test/test-index.ts

+4-19
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,20 @@
11
import * as assert from 'assert';
22
import * as lib from '../src/';
33

4-
import * as t from 'io-ts';
54
import { exampleGenerator } from '../src/';
65
import { isRight, Right } from 'fp-ts/lib/Either';
6+
import { types } from './helpers';
77

8-
describe('io-ts-fuzzer', () => {
9-
const types = [
10-
// Simple 0- or 1-depth types
11-
t.number,
12-
t.string,
13-
t.boolean,
14-
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-
}),
24-
];
8+
const count = 103;
259

10+
describe('io-ts-fuzzer', () => {
2611
describe('correctly fuzzes', () => {
2712
for (const b of types) {
2813
describe(`\`${b.name}\` objects`, () => {
2914
const r = lib.createCoreRegistry()!;
3015

3116
// tslint:disable-next-line:ban
32-
for (const n of [...Array(100).keys()]) {
17+
for (const n of [...Array(count).keys()]) {
3318
it(`for input ${n}`, () => {
3419
// tslint:disable-next-line:no-any
3520
const p = exampleGenerator<any>(r, b).encode;

test/test-registry.ts

+2-9
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
import * as assert from 'assert';
22
import * as lib from '../src/registry';
33

4-
import * as t from 'io-ts';
4+
import { types } from './helpers';
55

66
describe('registry', () => {
77
describe('#createCoreRegistry', () => {
8-
const basicTypes = [
9-
t.number,
10-
t.string,
11-
t.boolean,
12-
t.union([t.string, t.number, t.boolean]),
13-
];
14-
158
describe('#getFuzzer', () => {
16-
for (const b of basicTypes) {
9+
for (const b of types) {
1710
it(`has a fuzzer for \`${b.name}\` type`, () => {
1811
const r = lib.createCoreRegistry().getFuzzer(b);
1912
assert.ok(r);

0 commit comments

Comments
 (0)