|
1 | | -import path from "node:path"; |
2 | | -import createEsmUtils from "esm-utils"; |
3 | | -import { BOM, FULL_TEST } from "./constants.js"; |
4 | | -import * as failedTests from "./failed-format-tests.js"; |
5 | | -import { format, parse } from "./run-prettier.js"; |
| 1 | +import { FULL_TEST } from "./constants.js"; |
| 2 | +import { format } from "./run-prettier.js"; |
6 | 3 | import consistentEndOfLine from "./utils/consistent-end-of-line.js"; |
7 | 4 | import createSnapshot from "./utils/create-snapshot.js"; |
8 | 5 | import visualizeEndOfLine from "./utils/visualize-end-of-line.js"; |
| 6 | +import * as testAstCompare from "./test-ast-compare.js"; |
| 7 | +import * as testBom from "./test-bom.js"; |
| 8 | +import * as testEndOfLine from "./test-end-of-line.js"; |
| 9 | +import * as testSecondFormat from "./test-second-format.js"; |
| 10 | +import * as testBytecodeCompare from "./test-bytecode-compare.js"; |
| 11 | +import * as testAntlrFormat from "./test-antlr-format.js"; |
| 12 | +import * as testVariantCoverage from "./test-variant-coverage.js"; |
9 | 13 | import { shouldThrowOnFormat } from "./utilities.js"; |
10 | | -import getPrettier from "./get-prettier.js"; |
11 | | -import getCreateParser from "./get-create-parser.js"; |
12 | | -import getVariantCoverage from "./get-variant-coverage.js"; |
13 | | -import getPlugins from "./get-plugins.js"; |
14 | | -import compileContract from "./utils/compile-contract.js"; |
15 | | - |
16 | | -const { __dirname } = createEsmUtils(import.meta); |
17 | | - |
18 | | -const testsWithAstChanges = new Map( |
19 | | - [ |
20 | | - "Parentheses/AddNoParentheses.sol", |
21 | | - "Parentheses/SubNoParentheses.sol", |
22 | | - "Parentheses/MulNoParentheses.sol", |
23 | | - "Parentheses/DivNoParentheses.sol", |
24 | | - "Parentheses/ModNoParentheses.sol", |
25 | | - "Parentheses/ExpNoParentheses.sol", |
26 | | - "Parentheses/ShiftLNoParentheses.sol", |
27 | | - "Parentheses/ShiftRNoParentheses.sol", |
28 | | - "Parentheses/BitAndNoParentheses.sol", |
29 | | - "Parentheses/BitOrNoParentheses.sol", |
30 | | - "Parentheses/BitXorNoParentheses.sol", |
31 | | - "Parentheses/LogicNoParentheses.sol", |
32 | | - "HexLiteral/HexLiteral.sol", |
33 | | - "ModifierInvocations/ModifierInvocations.sol", |
34 | | - ].map((fixture) => { |
35 | | - const [file, compareBytecode = () => true] = Array.isArray(fixture) |
36 | | - ? fixture |
37 | | - : [fixture]; |
38 | | - return [path.join(__dirname, "../format/", file), compareBytecode]; |
39 | | - }), |
40 | | -); |
41 | | - |
42 | | -const shouldCompareBytecode = (filename, options) => { |
43 | | - const testFunction = testsWithAstChanges.get(filename); |
44 | | - |
45 | | - if (!testFunction) { |
46 | | - return false; |
47 | | - } |
48 | | - |
49 | | - return testFunction(options); |
50 | | -}; |
51 | 14 |
|
52 | 15 | async function runTest({ |
53 | 16 | parsers, |
@@ -101,114 +64,22 @@ async function runTest({ |
101 | 64 | if (!FULL_TEST) { |
102 | 65 | return; |
103 | 66 | } |
104 | | - |
105 | | - if (formatOptions.parser === "slang") { |
106 | | - const createParser = await getCreateParser(); |
107 | | - const variantCoverage = await getVariantCoverage(); |
108 | | - const { parser, parseOutput } = createParser(code, formatOptions); |
109 | | - |
110 | | - // Check coverage |
111 | | - variantCoverage(parseOutput.tree.asNonterminalNode()); |
112 | | - |
113 | | - if (!failedTests.isAntlrMismatch(filename, formatOptions)) { |
114 | | - // Compare with ANTLR's format |
115 | | - const prettier = await getPrettier(); |
116 | | - const { formatted: antlrOutput } = await prettier.formatWithCursor(code, { |
117 | | - ...formatOptions, |
118 | | - // Since Slang forces us to decide on a compiler version, we need to do the |
119 | | - // same for ANTLR unless it was already given as an option. |
120 | | - compiler: formatOptions.compiler || parser.languageVersion, |
121 | | - parser: "antlr", |
122 | | - plugins: await getPlugins(), |
123 | | - }); |
124 | | - expect(antlrOutput).toEqual(formatResult.output); |
125 | | - } |
126 | | - } |
127 | | - |
128 | | - const isUnstableTest = failedTests.isUnstable(filename, formatOptions); |
129 | | - if ( |
130 | | - (formatResult.changed || isUnstableTest) && |
131 | | - // No range and cursor |
132 | | - formatResult.input === code |
133 | | - ) { |
134 | | - const { eolVisualizedOutput: firstOutput, output } = formatResult; |
135 | | - const { eolVisualizedOutput: secondOutput } = await format( |
136 | | - output, |
137 | | - formatOptions, |
138 | | - ); |
139 | | - if (isUnstableTest) { |
140 | | - // To keep eye on failed tests, this assert never supposed to pass, |
141 | | - // if it fails, just remove the file from `unstableTests` |
142 | | - expect(secondOutput).not.toEqual(firstOutput); |
143 | | - } else { |
144 | | - expect(secondOutput).toEqual(firstOutput); |
145 | | - } |
146 | | - } |
147 | | - |
148 | | - const isAstUnstableTest = failedTests.isAstUnstable(filename, formatOptions); |
149 | | - // Some parsers skip parsing empty files |
150 | | - if (formatResult.changed && code.trim()) { |
151 | | - const { input, output } = formatResult; |
152 | | - const originalAst = await parse(input, formatOptions); |
153 | | - const formattedAst = await parse(output, formatOptions); |
154 | | - if (isAstUnstableTest) { |
155 | | - expect(formattedAst).not.toEqual(originalAst); |
156 | | - } else { |
157 | | - expect(formattedAst).toEqual(originalAst); |
158 | | - } |
159 | | - } |
160 | | - |
161 | | - if (!shouldSkipEolTest(code, formatResult.options)) { |
162 | | - for (const eol of ["\r\n", "\r"]) { |
163 | | - const { eolVisualizedOutput: output } = await format( |
164 | | - code.replace(/\n/gu, eol), |
165 | | - formatOptions, |
166 | | - ); |
167 | | - // Only if `endOfLine: "auto"` the result will be different |
168 | | - const expected = |
169 | | - formatOptions.endOfLine === "auto" |
170 | | - ? visualizeEndOfLine( |
171 | | - // All `code` use `LF`, so the `eol` of result is always `LF` |
172 | | - formatResult.outputWithCursor.replace(/\n/gu, eol), |
173 | | - ) |
174 | | - : formatResult.eolVisualizedOutput; |
175 | | - expect(output).toEqual(expected); |
176 | | - } |
177 | | - } |
178 | | - |
179 | | - if (code.charAt(0) !== BOM) { |
180 | | - const { eolVisualizedOutput: output } = await format( |
181 | | - BOM + code, |
182 | | - formatOptions, |
183 | | - ); |
184 | | - const expected = BOM + formatResult.eolVisualizedOutput; |
185 | | - expect(output).toEqual(expected); |
186 | | - } |
187 | | - |
188 | | - if (shouldCompareBytecode(filename, formatOptions)) { |
189 | | - const output = compileContract(filename, formatResult.output); |
190 | | - const expected = compileContract(filename, formatResult.input); |
191 | | - expect(output).toEqual(expected); |
192 | | - } |
193 | | -} |
194 | | - |
195 | | -function shouldSkipEolTest(code, options) { |
196 | | - if (code.includes("\r")) { |
197 | | - return true; |
198 | | - } |
199 | | - const { requirePragma, rangeStart, rangeEnd } = options; |
200 | | - if (requirePragma) { |
201 | | - return true; |
202 | | - } |
203 | | - |
204 | | - if ( |
205 | | - typeof rangeStart === "number" && |
206 | | - typeof rangeEnd === "number" && |
207 | | - rangeStart >= rangeEnd |
208 | | - ) { |
209 | | - return true; |
210 | | - } |
211 | | - return false; |
| 67 | + await Promise.all( |
| 68 | + [ |
| 69 | + testAntlrFormat.run, |
| 70 | + testVariantCoverage.run, |
| 71 | + testSecondFormat.run, |
| 72 | + testAstCompare.run, |
| 73 | + testBom.run, |
| 74 | + testBytecodeCompare.run, |
| 75 | + ] |
| 76 | + .map((run) => run(code, formatResult, filename, formatOptions)) |
| 77 | + .join( |
| 78 | + ["\r\n", "\r"].map((eol) => |
| 79 | + testEndOfLine.run(code, formatResult, filename, formatOptions, eol), |
| 80 | + ), |
| 81 | + ), |
| 82 | + ); |
212 | 83 | } |
213 | 84 |
|
214 | 85 | export { runTest }; |
0 commit comments