export async function goTest()

in src/testUtils.ts [275:383]


export async function goTest(testconfig: TestConfig): Promise<boolean> {
	let outputChannel = testOutputChannel;
	if (testconfig.outputChannel) {
		outputChannel = testconfig.outputChannel;
	}

	const goRuntimePath = getBinPath('go');
	if (!goRuntimePath) {
		vscode.window.showErrorMessage(
			`Failed to run "go test" as the "go" binary cannot be found in either GOROOT(${getCurrentGoRoot()}) or PATH(${getEnvPath()})`
		);
		return Promise.resolve(false);
	}

	// We do not want to clear it if tests are already running, as that could
	// lose valuable output.
	if (runningTestProcesses.length < 1) {
		outputChannel.clear();
	}

	if (testconfig.goConfig['disableConcurrentTests']) {
		await cancelRunningTests();
	}

	if (!testconfig.background) {
		outputChannel.show(true);
	}

	const testType: string = testconfig.isBenchmark ? 'Benchmarks' : 'Tests';

	// compute test target package
	const { targets, pkgMap, currentGoWorkspace } = await getTestTargetPackages(testconfig, outputChannel);

	// generate full test args.
	const { args, outArgs, tmpCoverPath, addJSONFlag } = computeTestCommand(testconfig, targets);

	outputChannel.appendLine(['Running tool:', goRuntimePath, ...outArgs].join(' '));
	outputChannel.appendLine('');

	let testResult = false;
	try {
		testResult = await new Promise<boolean>(async (resolve, reject) => {
			const testEnvVars = getTestEnvVars(testconfig.goConfig);
			const tp = cp.spawn(goRuntimePath, args, { env: testEnvVars, cwd: testconfig.dir });
			const outBuf = new LineBuffer();
			const errBuf = new LineBuffer();

			testconfig.cancel?.onCancellationRequested(() => killProcessTree(tp));

			const testResultLines: string[] = [];
			const processTestResultLine = addJSONFlag
				? processTestResultLineInJSONMode(
						pkgMap,
						currentGoWorkspace,
						outputChannel,
						testconfig.goTestOutputConsumer
				  )
				: processTestResultLineInStandardMode(pkgMap, currentGoWorkspace, testResultLines, outputChannel);

			outBuf.onLine((line) => processTestResultLine(line));
			outBuf.onDone((last) => {
				if (last) {
					processTestResultLine(last);
				}

				// If there are any remaining test result lines, emit them to the output channel.
				if (testResultLines.length > 0) {
					testResultLines.forEach((line) => outputChannel.appendLine(line));
				}
			});

			// go test emits build errors on stderr, which contain paths relative to the cwd
			errBuf.onLine((line) => outputChannel.appendLine(expandFilePathInOutput(line, testconfig.dir)));
			errBuf.onDone((last) => last && outputChannel.appendLine(expandFilePathInOutput(last, testconfig.dir)));

			tp.stdout.on('data', (chunk) => outBuf.append(chunk.toString()));
			tp.stderr.on('data', (chunk) => errBuf.append(chunk.toString()));

			statusBarItem.show();

			tp.on('close', (code, signal) => {
				outBuf.done();
				errBuf.done();

				const index = runningTestProcesses.indexOf(tp, 0);
				if (index > -1) {
					runningTestProcesses.splice(index, 1);
				}

				if (!runningTestProcesses.length) {
					statusBarItem.hide();
				}

				resolve(code === 0);
			});

			runningTestProcesses.push(tp);
		});
	} catch (err) {
		outputChannel.appendLine(`Error: ${testType} failed.`);
		if (err instanceof Error) {
			outputChannel.appendLine((err as Error).message);
		}
	}
	if (tmpCoverPath) {
		await applyCodeCoverageToAllEditors(tmpCoverPath, testconfig.dir);
	}
	return testResult;
}