1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
import * as fs from 'fs';
import { ICompilerResult, LLParse } from 'llparse';
import { Dot } from 'llparse-dot';
import {
Fixture, FixtureResult, IFixtureBuildOptions,
} from 'llparse-test-fixture';
import * as path from 'path';
import * as llhttp from '../../src/llhttp';
export { FixtureResult };
export type TestType = 'request' | 'response' | 'request-finish' | 'response-finish' |
'request-lenient-all' | 'response-lenient-all' |
'request-lenient-headers' | 'response-lenient-headers' |
'request-lenient-chunked-length' | 'request-lenient-transfer-encoding' |
'request-lenient-keep-alive' | 'response-lenient-keep-alive' |
'request-lenient-version' | 'response-lenient-version' |
'request-lenient-data-after-close' | 'response-lenient-data-after-close' |
'request-lenient-optional-lf-after-cr' | 'response-lenient-optional-lf-after-cr' |
'request-lenient-optional-cr-before-lf' | 'response-lenient-optional-cr-before-lf' |
'request-lenient-optional-crlf-after-chunk' | 'response-lenient-optional-crlf-after-chunk' |
'request-lenient-spaces-after-chunk-size' | 'response-lenient-spaces-after-chunk-size' |
'none' | 'url';
export const allowedTypes: TestType[] = [
'request',
'response',
'request-finish',
'response-finish',
'request-lenient-all',
'response-lenient-all',
'request-lenient-headers',
'response-lenient-headers',
'request-lenient-keep-alive',
'response-lenient-keep-alive',
'request-lenient-chunked-length',
'request-lenient-transfer-encoding',
'request-lenient-version',
'response-lenient-version',
'request-lenient-data-after-close',
'response-lenient-data-after-close',
'request-lenient-optional-lf-after-cr',
'response-lenient-optional-lf-after-cr',
'request-lenient-optional-cr-before-lf',
'response-lenient-optional-cr-before-lf',
'request-lenient-optional-crlf-after-chunk',
'response-lenient-optional-crlf-after-chunk',
'request-lenient-spaces-after-chunk-size',
'response-lenient-spaces-after-chunk-size',
];
const BUILD_DIR = path.join(__dirname, '..', 'tmp');
const CHEADERS_FILE = path.join(BUILD_DIR, 'cheaders.h');
const cheaders = new llhttp.CHeaders().build();
try {
fs.mkdirSync(BUILD_DIR);
} catch (e) {
// no-op
}
fs.writeFileSync(CHEADERS_FILE, cheaders);
const fixtures = new Fixture({
buildDir: path.join(__dirname, '..', 'tmp'),
extra: [
'-msse4.2',
'-DLLHTTP__TEST',
'-DLLPARSE__ERROR_PAUSE=' + llhttp.constants.ERROR.PAUSED,
'-include', CHEADERS_FILE,
path.join(__dirname, 'extra.c'),
],
maxParallel: process.env.LLPARSE_DEBUG ? 1 : undefined,
});
const cache: Map<any, ICompilerResult> = new Map();
export async function build(
llparse: LLParse, node: any, outFile: string,
options: IFixtureBuildOptions = {},
ty: TestType = 'none'): Promise<FixtureResult> {
const dot = new Dot();
fs.writeFileSync(path.join(BUILD_DIR, outFile + '.dot'),
dot.build(node));
let artifacts: ICompilerResult;
if (cache.has(node)) {
artifacts = cache.get(node)!;
} else {
artifacts = llparse.build(node, {
c: { header: outFile },
debug: process.env.LLPARSE_DEBUG ? 'llparse__debug' : undefined,
});
cache.set(node, artifacts);
}
const extra = options.extra === undefined ? [] : options.extra.slice();
if (allowedTypes.includes(ty)) {
extra.push(
`-DLLPARSE__TEST_INIT=llhttp__test_init_${ty.replace(/-/g, '_')}`);
}
if (ty === 'request-finish' || ty === 'response-finish') {
if (ty === 'request-finish') {
extra.push('-DLLPARSE__TEST_INIT=llhttp__test_init_request');
} else {
extra.push('-DLLPARSE__TEST_INIT=llhttp__test_init_response');
}
extra.push('-DLLPARSE__TEST_FINISH=llhttp__test_finish');
}
return await fixtures.build(artifacts, outFile, Object.assign(options, {
extra,
}));
}
|