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

Commit 89a3590

Browse files
committed
feat: allow customizable max length of array fuzzing
1 parent c8ed240 commit 89a3590

File tree

5 files changed

+117
-12
lines changed

5 files changed

+117
-12
lines changed

src/core/core.ts

+20-7
Original file line numberDiff line numberDiff line change
@@ -155,26 +155,39 @@ export function fuzzInterface(
155155
func: (n, ...h) => {
156156
const ret = Object.create(null);
157157
h.forEach((v, i) => {
158-
ret[keys[i]] = v.encode(n);
158+
ret[keys[i]] = v.encode(n + i);
159159
});
160160
return ret;
161161
},
162162
};
163163
}
164164

165-
export function fuzzArray(b: t.ArrayType<t.Mixed>): ConcreteFuzzer<unknown[]> {
165+
export const defaultMaxArrayLength = 13;
166+
167+
const fuzzArrayWithMaxLength = (maxLength: number = defaultMaxArrayLength) => (
168+
b: t.ArrayType<t.Mixed>
169+
): ConcreteFuzzer<unknown[]> => {
166170
return {
167171
children: [b.type],
168172
func: (n, h0) => {
169173
const ret = [];
170-
for (let index = 0; index < n % 13; index++) {
174+
for (let index = 0; index < n % maxLength; index++) {
171175
ret.push(h0.encode(n + index));
172176
}
173177
return ret;
174178
},
175179
};
180+
};
181+
182+
export function arrayFuzzer(maxLength: number = defaultMaxArrayLength) {
183+
return gen(fuzzArrayWithMaxLength(maxLength), 'ArrayType');
176184
}
177185

186+
/**
187+
* @deprecated
188+
*/
189+
export const fuzzArray = fuzzArrayWithMaxLength();
190+
178191
export function fuzzPartial(
179192
b: t.PartialType<t.Props>
180193
): ConcreteFuzzer<unknown> {
@@ -186,7 +199,7 @@ export function fuzzPartial(
186199
const ret = Object.create(null);
187200
h.forEach((v, i) => {
188201
if (n & (2 ** i)) {
189-
ret[keys[i]] = v.encode(n);
202+
ret[keys[i]] = v.encode(n + i);
190203
}
191204
});
192205
return ret;
@@ -203,9 +216,9 @@ export function fuzzIntersection(
203216
let ret: unknown = undefined;
204217
h.forEach((v, i) => {
205218
if (ret === undefined) {
206-
ret = v.encode(n);
219+
ret = v.encode(n + i);
207220
} else {
208-
ret = { ...ret, ...v.encode(n) };
221+
ret = { ...ret, ...v.encode(n + i) };
209222
}
210223
});
211224
return ret;
@@ -225,7 +238,7 @@ export const coreFuzzers = [
225238
gen(fuzzUnion, 'UnionType'),
226239
gen(fuzzInterface, 'InterfaceType'),
227240
gen(fuzzPartial, 'PartialType'),
228-
gen(fuzzArray, 'ArrayType'),
241+
arrayFuzzer(),
229242
gen(fuzzIntersection, 'IntersectionType'),
230243
gen(fuzzLiteral, 'LiteralType'),
231244
gen(fuzzKeyof, 'KeyofType'),

src/core/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export { coreFuzzers } from './core';
1+
export { coreFuzzers, arrayFuzzer } from './core';

src/registry.ts

+35-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Fuzzer, ExampleGenerator, exampleGenerator } from './fuzzer';
22
import * as t from 'io-ts';
3-
import { coreFuzzers } from './core/';
3+
import { coreFuzzers, arrayFuzzer } from './core/';
44

55
export interface Registry {
66
register<T, U extends t.Decoder<unknown, T>>(v0: Fuzzer<T, U>): Registry;
@@ -11,6 +11,40 @@ export interface Registry {
1111
getFuzzer<T>(a: t.Decoder<unknown, T>): Fuzzer<T> | null;
1212
}
1313

14+
export interface FluentRegistry extends Registry {
15+
withArrayFuzzer(maxLength: number): FluentRegistry;
16+
}
17+
18+
class FluentifiedRegistry implements FluentRegistry {
19+
private readonly pimpl: Registry;
20+
constructor(pimpl: Registry) {
21+
this.pimpl = pimpl;
22+
}
23+
24+
register<T, U extends t.Decoder<unknown, T>>(v0: Fuzzer<T, U>): Registry;
25+
register(...vv: Fuzzer[]): FluentRegistry {
26+
this.pimpl.register(...vv);
27+
return this;
28+
}
29+
30+
exampleGenerator<T>(d: t.Decoder<unknown, T>): ExampleGenerator<T> {
31+
return this.pimpl.exampleGenerator(d);
32+
}
33+
34+
getFuzzer<T>(a: t.Decoder<unknown, T>): Fuzzer<T> | null {
35+
return this.pimpl.getFuzzer(a);
36+
}
37+
38+
withArrayFuzzer(maxLength: number): FluentRegistry {
39+
this.register(arrayFuzzer(maxLength));
40+
return this;
41+
}
42+
}
43+
44+
export function fluent(r: Registry): FluentRegistry {
45+
return new FluentifiedRegistry(r);
46+
}
47+
1448
type Key = string;
1549

1650
function fuzzerKey(f: Fuzzer): Key {
@@ -41,7 +75,6 @@ class RegistryC implements Registry {
4175
) => ExampleGenerator<T>;
4276
}
4377

44-
register<T, U extends t.Decoder<unknown, T>>(v0: Fuzzer<T, U>): Registry;
4578
register(...vv: Fuzzer[]) {
4679
for (const v of vv) {
4780
this.fuzzers.set(fuzzerKey(v), v);

test/test-registry.ts

+58
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,62 @@ describe('registry', () => {
127127
}
128128
});
129129
});
130+
131+
describe('#fluent', () => {
132+
describe('#getFuzzer', () => {
133+
describe('on the core registry', () => {
134+
for (const b of types) {
135+
it(`has a fuzzer for \`${b.name}\` type`, () => {
136+
const r = lib.fluent(lib.createCoreRegistry()).getFuzzer(b);
137+
assert.ok(r);
138+
const x = r!;
139+
assert.ok(x.idType === 'tag' || x.idType === 'name');
140+
if (x.idType === 'name') {
141+
assert.deepStrictEqual(x.id, b.name);
142+
} else {
143+
assert.deepStrictEqual(x.id, b._tag);
144+
}
145+
});
146+
}
147+
});
148+
149+
describe('#exampleGenerator', () => {
150+
describe('on the core registry', () => {
151+
for (const b of types) {
152+
it(`can create an example generator for \`${b.name}\` type`, () => {
153+
const r = lib
154+
.fluent(lib.createCoreRegistry())
155+
.exampleGenerator(b);
156+
assert.ok(r);
157+
});
158+
}
159+
});
160+
});
161+
162+
describe('#withArrayFuzzer', () => {
163+
describe('on the core registry', () => {
164+
const b = t.array(t.number);
165+
it(`overrides the array fuzzer max length`, () => {
166+
const r0 = lib.createCoreRegistry();
167+
const r = lib
168+
.fluent(r0)
169+
.withArrayFuzzer(3)
170+
.exampleGenerator(b);
171+
for (let i = 0; i < 100; i++) {
172+
assert.ok(r.encode(i).length <= 3);
173+
}
174+
});
175+
176+
it(`overrides the array fuzzer max length on the underlying registry`, () => {
177+
const r0 = lib.createCoreRegistry();
178+
lib.fluent(r0).withArrayFuzzer(3);
179+
const r = r0.exampleGenerator(b);
180+
for (let i = 0; i < 100; i++) {
181+
assert.ok(r.encode(i).length <= 3);
182+
}
183+
});
184+
});
185+
});
186+
});
187+
});
130188
});

tslint.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"allow-leading-underscore",
1414
"allow-trailing-underscore",
1515
"require-const-for-all-caps"
16-
]
16+
],
17+
"no-unused-variable": true
1718
}
18-
}
19+
}

0 commit comments

Comments
 (0)