Skip to content

Commit

Permalink
[release] src/testUtil.ts: switch to -json mode only if -v is set
Browse files Browse the repository at this point in the history
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 #471
Updates #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 <[email protected]>
TryBot-Result: kokoro <[email protected]>
Reviewed-by: Rebecca Stambler <[email protected]>
(cherry picked from commit bec9cf3)
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/247017
Reviewed-by: Hyang-Ah Hana Kim <[email protected]>
  • Loading branch information
hyangah committed Aug 5, 2020
1 parent c469d69 commit 307c949
Showing 1 changed file with 65 additions and 25 deletions.
90 changes: 65 additions & 25 deletions src/testUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -326,8 +326,11 @@ export async function goTest(testconfig: TestConfig): Promise<boolean> {
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
Expand All @@ -345,29 +348,9 @@ export async function goTest(testconfig: TestConfig): Promise<boolean> {
const errBuf = new LineBuffer();

const testResultLines: string[] = [];
const processTestResultLine = (line: string) => {
try {
const m = <GoTestOutput>(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) => {
Expand Down Expand Up @@ -421,6 +404,63 @@ export async function goTest(testconfig: TestConfig): Promise<boolean> {
return testResult;
}

function processTestResultLineInJSONMode(
pkgMap: Map<string, string>,
currentGoWorkspace: string,
outputChannel: vscode.OutputChannel) {
return (line: string) => {
try {
const m = <GoTestOutput>(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<string, string>,
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.
*/
Expand Down

0 comments on commit 307c949

Please sign in to comment.