Skip to content

Commit

Permalink
fix(sampler): able to sample pattern format with nested infinite quan…
Browse files Browse the repository at this point in the history
…tifiers and max-length constraint

closes #246
  • Loading branch information
ostridm committed Aug 9, 2024
1 parent 70d8afe commit c610687
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 11 deletions.
53 changes: 42 additions & 11 deletions packages/openapi-sampler/src/samplers/StringSampler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,30 +55,61 @@ export class StringSampler implements Sampler {
const randExp = new RandExp(pattern);

if (min) {
// ADHOC: make a probe for regex using min quantifier value
// e.g. ^[a]+[b]+$ expect 'ab', ^[a-z]*$ expect ''
return this.sampleMinLength(randExp, min, max);
}

randExp.max = max ?? randExp.max;
randExp.randInt = (a, b) => Math.floor((a + b) / 2);

const result = randExp.gen();

return !!max && result.length > max && this.hasInfiniteQuantifier(pattern)
? this.sampleInfiniteQuantifier(randExp, max)
: result;
}

private hasInfiniteQuantifier(pattern: string | RegExp) {
const pat = pattern.toString();

return ['+', '*', ',}'].some((q) => pat.includes(q));
}

randExp.max = 0;
randExp.randInt = (a, _) => a;
private sampleInfiniteQuantifier(randExp: RandExp, max: number): string {

randExp.randInt = (a, b) => Math.floor((a + b) / 2);

for (let i = 1, lmax = max; lmax > 0; lmax = Math.floor(max / ++i)) {
randExp.max = lmax;

const result = randExp.gen();

if (result.length >= min) {
if (result.length <= max) {
return result;
}
}

// ADHOC: fallback for failed min quantifier probe with doubled min length
return '';
}

randExp.max = 2 * min;
randExp.randInt = (a, b) => Math.floor((a + b) / 2);
private sampleMinLength(randExp: RandExp, min: number, max: number) {
// ADHOC: make a probe for regex using min quantifier value
// e.g. ^[a]+[b]+$ expect 'ab', ^[a-z]*$ expect ''

return this.adjustMaxLength(randExp.gen(), max);
randExp.max = 0;
randExp.randInt = (a, _) => a;

const result = randExp.gen();

if (result.length >= min) {
return result;
}

randExp.max = max ?? randExp.max;
// ADHOC: fallback for failed min quantifier probe with doubled min length

randExp.max = 2 * min;
randExp.randInt = (a, b) => Math.floor((a + b) / 2);

return randExp.gen();
return this.adjustMaxLength(randExp.gen(), max);
}

private checkLength(
Expand Down
11 changes: 11 additions & 0 deletions packages/openapi-sampler/tests/string.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import { sample } from '../src';


describe('StringSampler', () => {
[
{
input: {
maxLength: 55,
minLength: 0,
format: 'pattern',
pattern: '^[A-Za-z0-9._%-]+@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{1,4}$',
type: 'string'
},
expected: "[email protected]"
},
{
input: {
type: 'string',
Expand Down

0 comments on commit c610687

Please sign in to comment.