(output)
| 166 | } |
| 167 | |
| 168 | function parseGoTest(output) { |
| 169 | const result = { passed: 0, failed: 0, errors: 0, skipped: 0, failures: [] }; |
| 170 | |
| 171 | // "--- PASS: TestName (0.00s)" and "--- FAIL: TestName (0.00s)" |
| 172 | const passRe = /^--- PASS:/mg; |
| 173 | const failRe = /^--- FAIL:\s+(\S+)/mg; |
| 174 | const skipRe = /^--- SKIP:/mg; |
| 175 | |
| 176 | let m; |
| 177 | while ((m = passRe.exec(output)) !== null) result.passed++; |
| 178 | while ((m = skipRe.exec(output)) !== null) result.skipped++; |
| 179 | while ((m = failRe.exec(output)) !== null) { |
| 180 | result.failed++; |
| 181 | // Collect indented lines after FAIL as message |
| 182 | const rest = output.slice(m.index + m[0].length); |
| 183 | const msgLines = []; |
| 184 | for (const line of rest.split('\n').slice(1)) { |
| 185 | if (!line.startsWith('\t') && !line.startsWith(' ')) break; |
| 186 | msgLines.push(line.trim()); |
| 187 | if (msgLines.length >= 5) break; |
| 188 | } |
| 189 | result.failures.push({ name: m[1], message: msgLines.join(' ').slice(0, 200) }); |
| 190 | } |
| 191 | |
| 192 | // "FAIL\t<package>" line indicates build/compile failure |
| 193 | if (result.passed === 0 && result.failed === 0 && /^FAIL\t/m.test(output)) { |
| 194 | result.errors = 1; |
| 195 | result.failures.push({ name: '(build failure)', message: output.split('\n').find(l => l.startsWith('#')) || 'build failed' }); |
| 196 | } |
| 197 | |
| 198 | return result; |
| 199 | } |
| 200 | |
| 201 | function parseCargoTest(output) { |
| 202 | const result = { passed: 0, failed: 0, errors: 0, skipped: 0, failures: [] }; |
no outgoing calls
no test coverage detected