Skip to content

Commit 8a0346f

Browse files
Move fuzzing tests into separate files (#2575)
1 parent 541a449 commit 8a0346f

File tree

7 files changed

+150
-92
lines changed

7 files changed

+150
-92
lines changed

.github/workflows/ci.yml

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,32 @@ jobs:
4848
- name: Build package
4949
run: npm run build
5050

51+
fuzz:
52+
name: Run fuzzing tests on Node v${{ matrix.node_version }}
53+
runs-on: ubuntu-latest
54+
steps:
55+
- name: Checkout repo
56+
uses: actions/checkout@v2
57+
58+
- name: Setup Node.js v${{ matrix.node_version }}
59+
uses: actions/setup-node@v1
60+
with:
61+
node-version: ${{ matrix.node_version }}
62+
63+
- name: Cache Node.js modules
64+
uses: actions/cache@v1
65+
with:
66+
path: ~/.npm
67+
key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}
68+
restore-keys: |
69+
${{ runner.OS }}-node-
70+
71+
- name: Install Dependencies
72+
run: npm ci
73+
74+
- name: Run Tests
75+
run: npm run fuzzonly
76+
5177
coverage:
5278
name: Measure test coverage
5379
runs-on: ubuntu-latest
@@ -114,7 +140,7 @@ jobs:
114140
github.event_name == 'push' &&
115141
github.repository == 'graphql/graphql-js' &&
116142
github.ref == 'refs/heads/master'
117-
needs: [test, lint]
143+
needs: [test, fuzz, lint]
118144
steps:
119145
- name: Checkout repo
120146
uses: actions/checkout@v2

.nycrc.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ include:
33
- 'src/'
44
exclude:
55
- 'src/polyfills'
6+
- '**/*-fuzz.js'
67
- '**/*-benchmark.js'
78
- '**/*.d.ts'
89
- 'src/validation/rules/ExecutableDefinitions.js'

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"scripts": {
2828
"test": "npm run prettier:check && npm run lint && npm run check && npm run testonly && npm run check:ts && npm run check:spelling",
2929
"test:ci": "npm run prettier:check && npm run lint -- --no-cache && npm run check && npm run testonly:cover && npm run check:ts && npm run check:spelling && npm run build",
30+
"fuzzonly": "mocha --full-trace src/**/__tests__/**/*-fuzz.js",
3031
"testonly": "mocha --full-trace src/**/__tests__/**/*-test.js",
3132
"testonly:cover": "nyc npm run testonly",
3233
"lint": "eslint --cache --ext .js,.ts src resources",
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// @flow strict
2+
3+
import { describe, it } from 'mocha';
4+
5+
import dedent from '../../__testUtils__/dedent';
6+
import inspectStr from '../../__testUtils__/inspectStr';
7+
import genFuzzStrings from '../../__testUtils__/genFuzzStrings';
8+
9+
import invariant from '../../jsutils/invariant';
10+
11+
import { Lexer } from '../lexer';
12+
import { Source } from '../source';
13+
import { printBlockString } from '../blockString';
14+
15+
function lexValue(str) {
16+
const lexer = new Lexer(new Source(str));
17+
const value = lexer.advance().value;
18+
19+
invariant(lexer.advance().kind === '<EOF>', 'Expected EOF');
20+
return value;
21+
}
22+
23+
describe('printBlockString', () => {
24+
it('correctly print random strings', () => {
25+
// Testing with length >7 is taking exponentially more time. However it is
26+
// highly recommended to test with increased limit if you make any change.
27+
for (const fuzzStr of genFuzzStrings({
28+
allowedChars: ['\n', '\t', ' ', '"', 'a', '\\'],
29+
maxLength: 7,
30+
})) {
31+
const testStr = '"""' + fuzzStr + '"""';
32+
33+
let testValue;
34+
try {
35+
testValue = lexValue(testStr);
36+
} catch (e) {
37+
continue; // skip invalid values
38+
}
39+
invariant(typeof testValue === 'string');
40+
41+
const printedValue = lexValue(printBlockString(testValue));
42+
43+
invariant(
44+
testValue === printedValue,
45+
dedent`
46+
Expected lexValue(printBlockString(${inspectStr(testValue)}))
47+
to equal ${inspectStr(testValue)}
48+
but got ${inspectStr(printedValue)}
49+
`,
50+
);
51+
52+
const printedMultilineString = lexValue(
53+
printBlockString(testValue, ' ', true),
54+
);
55+
56+
invariant(
57+
testValue === printedMultilineString,
58+
dedent`
59+
Expected lexValue(printBlockString(${inspectStr(
60+
testValue,
61+
)}, ' ', true))
62+
to equal ${inspectStr(testValue)}
63+
but got ${inspectStr(printedMultilineString)}
64+
`,
65+
);
66+
}
67+
}).timeout(20000);
68+
});

src/language/__tests__/blockString-test.js

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,6 @@
33
import { expect } from 'chai';
44
import { describe, it } from 'mocha';
55

6-
import dedent from '../../__testUtils__/dedent';
7-
import inspectStr from '../../__testUtils__/inspectStr';
8-
import genFuzzStrings from '../../__testUtils__/genFuzzStrings';
9-
10-
import invariant from '../../jsutils/invariant';
11-
12-
import { Lexer } from '../lexer';
13-
import { Source } from '../source';
146
import {
157
dedentBlockStringValue,
168
getBlockStringIndentation,
@@ -189,57 +181,4 @@ describe('printBlockString', () => {
189181
),
190182
);
191183
});
192-
193-
it('correctly print random strings', () => {
194-
// Testing with length >5 is taking exponentially more time. However it is
195-
// highly recommended to test with increased limit if you make any change.
196-
for (const fuzzStr of genFuzzStrings({
197-
allowedChars: ['\n', '\t', ' ', '"', 'a', '\\'],
198-
maxLength: 5,
199-
})) {
200-
const testStr = '"""' + fuzzStr + '"""';
201-
202-
let testValue;
203-
try {
204-
testValue = lexValue(testStr);
205-
} catch (e) {
206-
continue; // skip invalid values
207-
}
208-
invariant(typeof testValue === 'string');
209-
210-
const printedValue = lexValue(printBlockString(testValue));
211-
212-
invariant(
213-
testValue === printedValue,
214-
dedent`
215-
Expected lexValue(printBlockString(${inspectStr(testValue)}))
216-
to equal ${inspectStr(testValue)}
217-
but got ${inspectStr(printedValue)}
218-
`,
219-
);
220-
221-
const printedMultilineString = lexValue(
222-
printBlockString(testValue, ' ', true),
223-
);
224-
225-
invariant(
226-
testValue === printedMultilineString,
227-
dedent`
228-
Expected lexValue(printBlockString(${inspectStr(
229-
testValue,
230-
)}, ' ', true))
231-
to equal ${inspectStr(testValue)}
232-
but got ${inspectStr(printedMultilineString)}
233-
`,
234-
);
235-
}
236-
237-
function lexValue(str) {
238-
const lexer = new Lexer(new Source(str));
239-
const value = lexer.advance().value;
240-
241-
invariant(lexer.advance().kind === '<EOF>', 'Expected EOF');
242-
return value;
243-
}
244-
});
245184
});
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// @flow strict
2+
3+
import { describe, it } from 'mocha';
4+
5+
import dedent from '../../__testUtils__/dedent';
6+
import inspectStr from '../../__testUtils__/inspectStr';
7+
import genFuzzStrings from '../../__testUtils__/genFuzzStrings';
8+
9+
import invariant from '../../jsutils/invariant';
10+
11+
import { Lexer } from '../../language/lexer';
12+
import { Source } from '../../language/source';
13+
14+
import { stripIgnoredCharacters } from '../stripIgnoredCharacters';
15+
16+
function lexValue(str) {
17+
const lexer = new Lexer(new Source(str));
18+
const value = lexer.advance().value;
19+
20+
invariant(lexer.advance().kind === '<EOF>', 'Expected EOF');
21+
return value;
22+
}
23+
24+
describe('stripIgnoredCharacters', () => {
25+
it('strips ignored characters inside random block strings', () => {
26+
// Testing with length >7 is taking exponentially more time. However it is
27+
// highly recommended to test with increased limit if you make any change.
28+
for (const fuzzStr of genFuzzStrings({
29+
allowedChars: ['\n', '\t', ' ', '"', 'a', '\\'],
30+
maxLength: 7,
31+
})) {
32+
const testStr = '"""' + fuzzStr + '"""';
33+
34+
let testValue;
35+
try {
36+
testValue = lexValue(testStr);
37+
} catch (e) {
38+
continue; // skip invalid values
39+
}
40+
41+
const strippedValue = lexValue(stripIgnoredCharacters(testStr));
42+
43+
invariant(
44+
testValue === strippedValue,
45+
dedent`
46+
Expected lexValue(stripIgnoredCharacters(${inspectStr(testStr)}))
47+
to equal ${inspectStr(testValue)}
48+
but got ${inspectStr(strippedValue)}
49+
`,
50+
);
51+
}
52+
}).timeout(20000);
53+
});

src/utilities/__tests__/stripIgnoredCharacters-test.js

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { describe, it } from 'mocha';
55

66
import dedent from '../../__testUtils__/dedent';
77
import inspectStr from '../../__testUtils__/inspectStr';
8-
import genFuzzStrings from '../../__testUtils__/genFuzzStrings';
98

109
import invariant from '../../jsutils/invariant';
1110

@@ -438,35 +437,6 @@ describe('stripIgnoredCharacters', () => {
438437
expectStrippedString('"""\na\n b\nc"""').toEqual('"""a\n b\nc"""');
439438
});
440439

441-
it('strips ignored characters inside random block strings', () => {
442-
// Testing with length >5 is taking exponentially more time. However it is
443-
// highly recommended to test with increased limit if you make any change.
444-
for (const fuzzStr of genFuzzStrings({
445-
allowedChars: ['\n', '\t', ' ', '"', 'a', '\\'],
446-
maxLength: 5,
447-
})) {
448-
const testStr = '"""' + fuzzStr + '"""';
449-
450-
let testValue;
451-
try {
452-
testValue = lexValue(testStr);
453-
} catch (e) {
454-
continue; // skip invalid values
455-
}
456-
457-
const strippedValue = lexValue(stripIgnoredCharacters(testStr));
458-
459-
invariant(
460-
testValue === strippedValue,
461-
dedent`
462-
Expected lexValue(stripIgnoredCharacters(${inspectStr(testStr)}))
463-
to equal ${inspectStr(testValue)}
464-
but got ${inspectStr(strippedValue)}
465-
`,
466-
);
467-
}
468-
});
469-
470440
it('strips kitchen sink query but maintains the exact same AST', () => {
471441
const strippedQuery = stripIgnoredCharacters(kitchenSinkQuery);
472442
expect(stripIgnoredCharacters(strippedQuery)).to.equal(strippedQuery);

0 commit comments

Comments
 (0)