Skip to content

Commit ebb7bef

Browse files
Speedup tests by ~15% by moving some stripIgnoredCharacters tests to fuzzing (#3584)
1 parent 6a04b49 commit ebb7bef

File tree

2 files changed

+248
-224
lines changed

2 files changed

+248
-224
lines changed

src/utilities/__tests__/stripIgnoredCharacters-fuzz.ts

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,50 @@ import { Source } from '../../language/source';
1010

1111
import { stripIgnoredCharacters } from '../stripIgnoredCharacters';
1212

13+
const ignoredTokens = [
14+
// UnicodeBOM ::
15+
'\uFEFF', // Byte Order Mark (U+FEFF)
16+
17+
// WhiteSpace ::
18+
'\t', // Horizontal Tab (U+0009)
19+
' ', // Space (U+0020)
20+
21+
// LineTerminator ::
22+
'\n', // "New Line (U+000A)"
23+
'\r', // "Carriage Return (U+000D)" [ lookahead ! "New Line (U+000A)" ]
24+
'\r\n', // "Carriage Return (U+000D)" "New Line (U+000A)"
25+
26+
// Comment ::
27+
'# "Comment" string\n', // `#` CommentChar*
28+
29+
// Comma ::
30+
',', // ,
31+
];
32+
33+
const punctuatorTokens = [
34+
'!',
35+
'$',
36+
'(',
37+
')',
38+
'...',
39+
':',
40+
'=',
41+
'@',
42+
'[',
43+
']',
44+
'{',
45+
'|',
46+
'}',
47+
];
48+
49+
const nonPunctuatorTokens = [
50+
'name_token', // Name
51+
'1', // IntValue
52+
'3.14', // FloatValue
53+
'"some string value"', // StringValue
54+
'"""block\nstring\nvalue"""', // StringValue(BlockString)
55+
];
56+
1357
function lexValue(str: string) {
1458
const lexer = new Lexer(new Source(str));
1559
const value = lexer.advance().value;
@@ -18,7 +62,208 @@ function lexValue(str: string) {
1862
return value;
1963
}
2064

65+
function expectStripped(docString: string) {
66+
return {
67+
toEqual(expected: string): void {
68+
const stripped = stripIgnoredCharacters(docString);
69+
70+
assert(
71+
stripped === expected,
72+
dedent`
73+
Expected stripIgnoredCharacters(${inspectStr(docString)})
74+
to equal ${inspectStr(expected)}
75+
but got ${inspectStr(stripped)}
76+
`,
77+
);
78+
79+
const strippedTwice = stripIgnoredCharacters(stripped);
80+
81+
assert(
82+
stripped === strippedTwice,
83+
dedent`
84+
Expected stripIgnoredCharacters(${inspectStr(stripped)})
85+
to equal ${inspectStr(stripped)}
86+
but got ${inspectStr(strippedTwice)}
87+
`,
88+
);
89+
},
90+
toStayTheSame(): void {
91+
this.toEqual(docString);
92+
},
93+
};
94+
}
95+
2196
describe('stripIgnoredCharacters', () => {
97+
it('strips documents with random combination of ignored characters', () => {
98+
for (const ignored of ignoredTokens) {
99+
expectStripped(ignored).toEqual('');
100+
101+
for (const anotherIgnored of ignoredTokens) {
102+
expectStripped(ignored + anotherIgnored).toEqual('');
103+
}
104+
}
105+
expectStripped(ignoredTokens.join('')).toEqual('');
106+
});
107+
108+
it('strips random leading and trailing ignored tokens', () => {
109+
for (const token of [...punctuatorTokens, ...nonPunctuatorTokens]) {
110+
for (const ignored of ignoredTokens) {
111+
expectStripped(ignored + token).toEqual(token);
112+
expectStripped(token + ignored).toEqual(token);
113+
114+
for (const anotherIgnored of ignoredTokens) {
115+
expectStripped(token + ignored + ignored).toEqual(token);
116+
expectStripped(ignored + anotherIgnored + token).toEqual(token);
117+
}
118+
}
119+
120+
expectStripped(ignoredTokens.join('') + token).toEqual(token);
121+
expectStripped(token + ignoredTokens.join('')).toEqual(token);
122+
}
123+
});
124+
125+
it('strips random ignored tokens between punctuator tokens', () => {
126+
for (const left of punctuatorTokens) {
127+
for (const right of punctuatorTokens) {
128+
for (const ignored of ignoredTokens) {
129+
expectStripped(left + ignored + right).toEqual(left + right);
130+
131+
for (const anotherIgnored of ignoredTokens) {
132+
expectStripped(left + ignored + anotherIgnored + right).toEqual(
133+
left + right,
134+
);
135+
}
136+
}
137+
138+
expectStripped(left + ignoredTokens.join('') + right).toEqual(
139+
left + right,
140+
);
141+
}
142+
}
143+
});
144+
145+
it('strips random ignored tokens between punctuator and non-punctuator tokens', () => {
146+
for (const nonPunctuator of nonPunctuatorTokens) {
147+
for (const punctuator of punctuatorTokens) {
148+
for (const ignored of ignoredTokens) {
149+
expectStripped(punctuator + ignored + nonPunctuator).toEqual(
150+
punctuator + nonPunctuator,
151+
);
152+
153+
for (const anotherIgnored of ignoredTokens) {
154+
expectStripped(
155+
punctuator + ignored + anotherIgnored + nonPunctuator,
156+
).toEqual(punctuator + nonPunctuator);
157+
}
158+
}
159+
160+
expectStripped(
161+
punctuator + ignoredTokens.join('') + nonPunctuator,
162+
).toEqual(punctuator + nonPunctuator);
163+
}
164+
}
165+
});
166+
167+
it('strips random ignored tokens between non-punctuator and punctuator tokens', () => {
168+
for (const nonPunctuator of nonPunctuatorTokens) {
169+
for (const punctuator of punctuatorTokens) {
170+
// Special case for that is handled in the below test
171+
if (punctuator === '...') {
172+
continue;
173+
}
174+
175+
for (const ignored of ignoredTokens) {
176+
expectStripped(nonPunctuator + ignored + punctuator).toEqual(
177+
nonPunctuator + punctuator,
178+
);
179+
180+
for (const anotherIgnored of ignoredTokens) {
181+
expectStripped(
182+
nonPunctuator + ignored + anotherIgnored + punctuator,
183+
).toEqual(nonPunctuator + punctuator);
184+
}
185+
}
186+
187+
expectStripped(
188+
nonPunctuator + ignoredTokens.join('') + punctuator,
189+
).toEqual(nonPunctuator + punctuator);
190+
}
191+
}
192+
});
193+
194+
it('replace random ignored tokens between non-punctuator tokens and spread with space', () => {
195+
for (const nonPunctuator of nonPunctuatorTokens) {
196+
for (const ignored of ignoredTokens) {
197+
expectStripped(nonPunctuator + ignored + '...').toEqual(
198+
nonPunctuator + ' ...',
199+
);
200+
201+
for (const anotherIgnored of ignoredTokens) {
202+
expectStripped(
203+
nonPunctuator + ignored + anotherIgnored + ' ...',
204+
).toEqual(nonPunctuator + ' ...');
205+
}
206+
}
207+
208+
expectStripped(nonPunctuator + ignoredTokens.join('') + '...').toEqual(
209+
nonPunctuator + ' ...',
210+
);
211+
}
212+
});
213+
214+
it('replace random ignored tokens between non-punctuator tokens with space', () => {
215+
for (const left of nonPunctuatorTokens) {
216+
for (const right of nonPunctuatorTokens) {
217+
for (const ignored of ignoredTokens) {
218+
expectStripped(left + ignored + right).toEqual(left + ' ' + right);
219+
220+
for (const anotherIgnored of ignoredTokens) {
221+
expectStripped(left + ignored + anotherIgnored + right).toEqual(
222+
left + ' ' + right,
223+
);
224+
}
225+
}
226+
227+
expectStripped(left + ignoredTokens.join('') + right).toEqual(
228+
left + ' ' + right,
229+
);
230+
}
231+
}
232+
});
233+
234+
it('does not strip random ignored tokens embedded in the string', () => {
235+
for (const ignored of ignoredTokens) {
236+
expectStripped(JSON.stringify(ignored)).toStayTheSame();
237+
238+
for (const anotherIgnored of ignoredTokens) {
239+
expectStripped(
240+
JSON.stringify(ignored + anotherIgnored),
241+
).toStayTheSame();
242+
}
243+
}
244+
245+
expectStripped(JSON.stringify(ignoredTokens.join(''))).toStayTheSame();
246+
});
247+
248+
it('does not strip random ignored tokens embedded in the block string', () => {
249+
const ignoredTokensWithoutFormatting = ignoredTokens.filter(
250+
(token) => !['\n', '\r', '\r\n', '\t', ' '].includes(token),
251+
);
252+
for (const ignored of ignoredTokensWithoutFormatting) {
253+
expectStripped('"""|' + ignored + '|"""').toStayTheSame();
254+
255+
for (const anotherIgnored of ignoredTokensWithoutFormatting) {
256+
expectStripped(
257+
'"""|' + ignored + anotherIgnored + '|"""',
258+
).toStayTheSame();
259+
}
260+
}
261+
262+
expectStripped(
263+
'"""|' + ignoredTokensWithoutFormatting.join('') + '|"""',
264+
).toStayTheSame();
265+
});
266+
22267
it('strips ignored characters inside random block strings', () => {
23268
// Testing with length >7 is taking exponentially more time. However it is
24269
// highly recommended to test with increased limit if you make any change.

0 commit comments

Comments
 (0)