From bec9cf3fa2c4306217ba1d79c6c476b0b3909fe7 Mon Sep 17 00:00:00 2001 From: "Hana (Hyang-Ah) Kim" Date: Wed, 5 Aug 2020 11:44:24 -0400 Subject: [PATCH] src/testUtil.ts: switch to -json mode only if -v is set CL/242540 made runTest uses -json mode to ease streaming test output processing. However, it turned out -json makes the test output more verbose than the standard test output. (golang/go#40588) Verbose output by default is not ideal especially when running tests on many packages. This change brings back the old test output processing logic when users do not use the `-v` flag. The `go test` command will stream test output only if the `-v` flag is specified, so the original issue CL/242540 remains addressed. Fixes golang/vscode-go#471 Updates golang/vscode-go#316 Updates golang/go#40588 Change-Id: I29d6d1319acccab2457300c118216ceebb4c4033 Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/246918 Run-TryBot: Hyang-Ah Hana Kim TryBot-Result: kokoro Reviewed-by: Rebecca Stambler --- src/testUtils.ts | 90 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 25 deletions(-) diff --git a/src/testUtils.ts b/src/testUtils.ts index aafe4270d1..cd00956e90 100644 --- a/src/testUtils.ts +++ b/src/testUtils.ts @@ -21,7 +21,7 @@ import { resolvePath } from './util'; import { envPath, getCurrentGoRoot, getCurrentGoWorkspaceFromGOPATH, parseEnvFile } from './utils/goPath'; -import {killProcessTree} from './utils/processUtils'; +import { killProcessTree } from './utils/processUtils'; const testOutputChannel = vscode.window.createOutputChannel('Go Tests'); const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); @@ -326,8 +326,11 @@ export async function goTest(testconfig: TestConfig): Promise { outTargets.push(...targets); } + if (args.includes('-v') && !args.includes('-json')) { + args.push('-json'); + } + args.push(...targets); - args.push('-json'); // ensure that user provided flags are appended last (allow use of -args ...) // ignore user provided -run flag if we are already using it @@ -345,29 +348,9 @@ export async function goTest(testconfig: TestConfig): Promise { const errBuf = new LineBuffer(); const testResultLines: string[] = []; - const processTestResultLine = (line: string) => { - try { - const m = (JSON.parse(line)); - if (m.Action !== 'output' || !m.Output) { - return; - } - const out = m.Output; - const pkg = m.Package; - if (pkg && (pkgMap.has(pkg) || currentGoWorkspace)) { - const pkgNameArr = pkg.split('/'); - const baseDir = pkgMap.get(pkg) || path.join(currentGoWorkspace, ...pkgNameArr); - // go test emits test results on stdout, which contain file names relative to the package under test - outputChannel.appendLine(expandFilePathInOutput(out, baseDir).trimRight()); - } else { - outputChannel.appendLine(out.trimRight()); - } - } catch (e) { - // TODO: disable this log if it becomes too spammy. - console.log(`failed to parse JSON: ${e}: ${line}`); - // Build failures or other messages come in non-JSON format. So, output as they are. - outputChannel.appendLine(line); - } - }; + const processTestResultLine = args.includes('-json') ? + processTestResultLineInJSONMode(pkgMap, currentGoWorkspace, outputChannel) : + processTestResultLineInStandardMode(pkgMap, currentGoWorkspace, testResultLines, outputChannel); outBuf.onLine((line) => processTestResultLine(line)); outBuf.onDone((last) => { @@ -421,6 +404,63 @@ export async function goTest(testconfig: TestConfig): Promise { return testResult; } +function processTestResultLineInJSONMode( + pkgMap: Map, + currentGoWorkspace: string, + outputChannel: vscode.OutputChannel) { + return (line: string) => { + try { + const m = (JSON.parse(line)); + if (m.Action !== 'output' || !m.Output) { + return; + } + const out = m.Output; + const pkg = m.Package; + if (pkg && (pkgMap.has(pkg) || currentGoWorkspace)) { + const pkgNameArr = pkg.split('/'); + const baseDir = pkgMap.get(pkg) || path.join(currentGoWorkspace, ...pkgNameArr); + // go test emits test results on stdout, which contain file names relative to the package under test + outputChannel.appendLine(expandFilePathInOutput(out, baseDir).trimRight()); + } else { + outputChannel.appendLine(out.trimRight()); + } + } catch (e) { + // TODO: disable this log if it becomes too spammy. + console.log(`failed to parse JSON: ${e}: ${line}`); + // Build failures or other messages come in non-JSON format. So, output as they are. + outputChannel.appendLine(line); + } + }; +} + +function processTestResultLineInStandardMode( + pkgMap: Map, + currentGoWorkspace: string, + testResultLines: string[], + outputChannel: vscode.OutputChannel) { + // 1=ok/FAIL, 2=package, 3=time/(cached) + const packageResultLineRE = /^(ok|FAIL)\s+(\S+)\s+([0-9\.]+s|\(cached\))/; + const lineWithErrorRE = /^(\t|\s\s\s\s)\S/; + + return (line: string) => { + testResultLines.push(line); + const result = line.match(packageResultLineRE); + if (result && (pkgMap.has(result[2]) || currentGoWorkspace)) { + const hasTestFailed = line.startsWith('FAIL'); + const packageNameArr = result[2].split('/'); + const baseDir = pkgMap.get(result[2]) || path.join(currentGoWorkspace, ...packageNameArr); + testResultLines.forEach((testResultLine) => { + if (hasTestFailed && lineWithErrorRE.test(testResultLine)) { + outputChannel.appendLine(expandFilePathInOutput(testResultLine, baseDir)); + } else { + outputChannel.appendLine(testResultLine); + } + }); + testResultLines.splice(0); + } + }; +} + /** * Reveals the output channel in the UI. */