| /* eslint-disable @typescript-eslint/no-explicit-any */ |
| /*--------------------------------------------------------- |
| * Copyright 2020 The Go Authors. All rights reserved. |
| * Licensed under the MIT License. See LICENSE in the project root for license information. |
| *--------------------------------------------------------*/ |
| |
| 'use strict'; |
| |
| import assert from 'assert'; |
| import { getGoConfig } from '../../src/config'; |
| import { computeTestCommand, getTestFlags, goTest } from '../../src/testUtils'; |
| import { rmdirRecursive } from '../../src/util'; |
| import fs = require('fs-extra'); |
| import os = require('os'); |
| import path = require('path'); |
| import sinon = require('sinon'); |
| import vscode = require('vscode'); |
| |
| suite('Test Go Test Args', () => { |
| function runTest(param: { |
| expectedArgs: string; |
| expectedOutArgs: string; |
| flags?: string[]; |
| functions?: string[]; |
| isBenchmark?: boolean; |
| }) { |
| const { args, outArgs } = computeTestCommand( |
| { |
| dir: '', |
| goConfig: getGoConfig(), |
| flags: param.flags || [], |
| functions: param.functions || [], |
| isBenchmark: param.isBenchmark || false, |
| applyCodeCoverage: false |
| }, |
| ['./...'] |
| ); |
| |
| assert.strictEqual(args.join(' '), param.expectedArgs, 'actual command'); |
| assert.strictEqual(outArgs.join(' '), param.expectedOutArgs, 'displayed command'); |
| } |
| |
| test('default config', () => { |
| runTest({ |
| expectedArgs: 'test -timeout 30s ./...', |
| expectedOutArgs: 'test -timeout 30s ./...' |
| }); |
| }); |
| test('user flag [-v] enables -json flag', () => { |
| runTest({ |
| expectedArgs: 'test -timeout 30s -json ./... -v', |
| expectedOutArgs: 'test -timeout 30s ./... -v', |
| flags: ['-v'] |
| }); |
| }); |
| test('user flag [-json -v] prevents -json flag addition', () => { |
| runTest({ |
| expectedArgs: 'test -timeout 30s ./... -json -v', |
| expectedOutArgs: 'test -timeout 30s ./... -json -v', |
| flags: ['-json', '-v'] |
| }); |
| }); |
| test('user flag [-args] does not crash', () => { |
| runTest({ |
| expectedArgs: 'test -timeout 30s ./... -args', |
| expectedOutArgs: 'test -timeout 30s ./... -args', |
| flags: ['-args'] |
| }); |
| }); |
| test('user flag [-args -v] does not enable -json flag', () => { |
| runTest({ |
| expectedArgs: 'test -timeout 30s ./... -args -v', |
| expectedOutArgs: 'test -timeout 30s ./... -args -v', |
| flags: ['-args', '-v'] |
| }); |
| }); |
| test('specifying functions adds -run flags', () => { |
| runTest({ |
| expectedArgs: 'test -timeout 30s -run ^(TestA|TestB)$ ./...', |
| expectedOutArgs: 'test -timeout 30s -run ^(TestA|TestB)$ ./...', |
| functions: ['TestA', 'TestB'] |
| }); |
| }); |
| test('functions & benchmark adds -bench flags and skips timeout', () => { |
| runTest({ |
| expectedArgs: 'test -benchmem -run=^$ -bench ^(TestA|TestB)$ ./...', |
| expectedOutArgs: 'test -benchmem -run=^$ -bench ^(TestA|TestB)$ ./...', |
| functions: ['TestA', 'TestB'], |
| isBenchmark: true |
| }); |
| }); |
| test('user -run flag is ignored when functions are provided', () => { |
| runTest({ |
| expectedArgs: 'test -timeout 30s -run ^(TestA|TestB)$ ./...', |
| expectedOutArgs: 'test -timeout 30s -run ^(TestA|TestB)$ ./...', |
| functions: ['TestA', 'TestB'], |
| flags: ['-run', 'TestC'] |
| }); |
| }); |
| }); |
| |
| suite('Test Go Test', function () { |
| this.timeout(50000); |
| |
| const sourcePath = path.join(__dirname, '..', '..', '..', 'test', 'testdata', 'goTestTest'); |
| |
| let tmpGopath: string; |
| let repoPath: string; |
| |
| let previousEnv: any; |
| |
| setup(() => { |
| previousEnv = Object.assign({}, process.env); |
| }); |
| |
| teardown(async () => { |
| process.env = previousEnv; |
| rmdirRecursive(tmpGopath); |
| }); |
| |
| function setupRepo(isModuleMode: boolean) { |
| tmpGopath = fs.mkdtempSync(path.join(os.tmpdir(), 'go-test-test')); |
| fs.mkdirSync(path.join(tmpGopath, 'src')); |
| repoPath = path.join(tmpGopath, 'src', 'goTestTest'); |
| fs.copySync(sourcePath, repoPath, { |
| recursive: true, |
| filter: (src: string): boolean => { |
| if (isModuleMode) { |
| return true; |
| } |
| return path.basename(src) !== 'go.mod'; // skip go.mod file. |
| } |
| }); |
| process.env.GOPATH = tmpGopath; |
| process.env.GO111MODULE = isModuleMode ? 'on' : 'off'; |
| } |
| |
| async function runTest( |
| input: { isMod: boolean; includeSubDirectories: boolean; testFlags?: string[]; applyCodeCoverage?: boolean }, |
| wantFiles: string[] |
| ) { |
| const config = Object.create(getGoConfig()); |
| const outputChannel = new FakeOutputChannel(); |
| |
| const testConfig = { |
| goConfig: config, |
| outputChannel, |
| dir: repoPath, |
| flags: input.testFlags ? input.testFlags : getTestFlags(config), |
| isMod: input.isMod, |
| includeSubDirectories: input.includeSubDirectories, |
| applyCodeCoverage: input.applyCodeCoverage |
| }; |
| try { |
| // TODO: instead of calling goTest, consider to test |
| // testCurrentPackage, testCurrentWorkspace, testCurrentFile |
| // which are closer to the features exposed to users. |
| const result = await goTest(testConfig); |
| assert.equal(result, false); // we expect tests to fail. |
| } catch (e) { |
| console.log('exception: ${e}'); |
| } |
| |
| const testOutput = outputChannel.toString(); |
| for (const want of wantFiles) { |
| assert.ok(testOutput.includes(want), `\nFully resolved file path "${want}" not found in \n${testOutput}`); |
| } |
| } |
| |
| test('resolves file names in logs (modules)', async () => { |
| setupRepo(true); |
| await runTest({ isMod: true, includeSubDirectories: true }, [ |
| path.join(repoPath, 'a_test.go'), |
| path.join(repoPath, 'b', 'b_test.go') |
| ]); |
| await runTest({ isMod: true, includeSubDirectories: false }, [path.join(repoPath, 'a_test.go')]); |
| await runTest({ isMod: true, includeSubDirectories: true, testFlags: ['-v'] }, [ |
| path.join(repoPath, 'a_test.go'), |
| path.join(repoPath, 'b', 'b_test.go') |
| ]); |
| await runTest({ isMod: true, includeSubDirectories: true, testFlags: ['-race'], applyCodeCoverage: true }, [ |
| path.join(repoPath, 'a_test.go'), |
| path.join(repoPath, 'b', 'b_test.go') |
| ]); |
| await runTest({ isMod: true, includeSubDirectories: false, testFlags: ['-v'] }, [ |
| path.join(repoPath, 'a_test.go') |
| ]); |
| }); |
| |
| test('resolves file names in logs (GOPATH)', async () => { |
| setupRepo(false); |
| await runTest({ isMod: false, includeSubDirectories: true }, [ |
| path.join(repoPath, 'a_test.go'), |
| path.join(repoPath, 'b', 'b_test.go') |
| ]); |
| await runTest({ isMod: false, includeSubDirectories: false }, [path.join(repoPath, 'a_test.go')]); |
| await runTest({ isMod: false, includeSubDirectories: true, testFlags: ['-v'] }, [ |
| path.join(repoPath, 'a_test.go'), |
| path.join(repoPath, 'b', 'b_test.go') |
| ]); |
| await runTest({ isMod: false, includeSubDirectories: true, testFlags: ['-race'], applyCodeCoverage: true }, [ |
| path.join(repoPath, 'a_test.go'), |
| path.join(repoPath, 'b', 'b_test.go') |
| ]); |
| await runTest({ isMod: false, includeSubDirectories: false, testFlags: ['-v'] }, [ |
| path.join(repoPath, 'a_test.go') |
| ]); |
| }); |
| }); |
| |
| // FakeOutputChannel is a fake output channel used to buffer |
| // the output of the tested language client in an in-memory |
| // string array until cleared. |
| class FakeOutputChannel implements vscode.OutputChannel { |
| public name = 'FakeOutputChannel'; |
| public show = sinon.fake(); // no-empty |
| public hide = sinon.fake(); // no-empty |
| public dispose = sinon.fake(); // no-empty |
| |
| private buf = [] as string[]; |
| |
| public append = (v: string) => this.enqueue(v); |
| public appendLine = (v: string) => this.enqueue(v); |
| public clear = () => { |
| this.buf = []; |
| }; |
| public toString = () => { |
| return this.buf.join('\n'); |
| }; |
| |
| private enqueue = (v: string) => { |
| if (this.buf.length > 1024) { |
| this.buf.shift(); |
| } |
| this.buf.push(v.trim()); |
| }; |
| } |