|  | /* eslint-disable @typescript-eslint/no-explicit-any */ | 
|  | /* eslint-disable @typescript-eslint/no-unused-vars */ | 
|  | /* eslint-disable eqeqeq */ | 
|  | /* eslint-disable node/no-unpublished-import */ | 
|  | /*--------------------------------------------------------- | 
|  | * Copyright (C) Microsoft Corporation. All rights reserved. | 
|  | * Licensed under the MIT License. See LICENSE in the project root for license information. | 
|  | *--------------------------------------------------------*/ | 
|  |  | 
|  | import assert from 'assert'; | 
|  | import * as fs from 'fs-extra'; | 
|  | import * as path from 'path'; | 
|  | import * as sinon from 'sinon'; | 
|  | import * as vscode from 'vscode'; | 
|  | import { getGoConfig, getGoplsConfig } from '../../src/config'; | 
|  | import { FilePatch, getEdits, getEditsFromUnifiedDiffStr } from '../../src/diffUtils'; | 
|  | import { check } from '../../src/goCheck'; | 
|  | import { | 
|  | generateTestCurrentFile, | 
|  | generateTestCurrentFunction, | 
|  | generateTestCurrentPackage | 
|  | } from '../../src/goGenerateTests'; | 
|  | import { updateGoVarsFromConfig } from '../../src/goInstallTools'; | 
|  | import { buildLanguageServerConfig } from '../../src/language/goLanguageServer'; | 
|  | import { goLint } from '../../src/goLint'; | 
|  | import { goPlay } from '../../src/goPlayground'; | 
|  | import { testCurrentFile } from '../../src/commands'; | 
|  | import { | 
|  | getBinPath, | 
|  | getCurrentGoPath, | 
|  | getGoVersion, | 
|  | getImportPath, | 
|  | GoVersion, | 
|  | handleDiagnosticErrors, | 
|  | ICheckResult | 
|  | } from '../../src/util'; | 
|  | import cp = require('child_process'); | 
|  | import os = require('os'); | 
|  | import { MockExtensionContext } from '../mocks/MockContext'; | 
|  |  | 
|  | const testAll = (isModuleMode: boolean) => { | 
|  | const dummyCancellationSource = new vscode.CancellationTokenSource(); | 
|  |  | 
|  | // suiteSetup will initialize the following vars. | 
|  | let gopath: string; | 
|  | let repoPath: string; | 
|  | let fixturePath: string; | 
|  | let fixtureSourcePath: string; | 
|  | let generateTestsSourcePath: string; | 
|  | let generateFunctionTestSourcePath: string; | 
|  | let generatePackageTestSourcePath: string; | 
|  | let previousEnv: any; | 
|  | let goVersion: GoVersion; | 
|  |  | 
|  | suiteSetup(async () => { | 
|  | previousEnv = Object.assign({}, process.env); | 
|  | process.env.GO111MODULE = isModuleMode ? 'on' : 'off'; | 
|  |  | 
|  | await updateGoVarsFromConfig({}); | 
|  |  | 
|  | gopath = getCurrentGoPath(); | 
|  | if (!gopath) { | 
|  | assert.ok(gopath, 'Cannot run tests if GOPATH is not set as environment variable'); | 
|  | return; | 
|  | } | 
|  | goVersion = await getGoVersion(); | 
|  |  | 
|  | console.log(`Using GOPATH: ${gopath}`); | 
|  |  | 
|  | repoPath = isModuleMode ? fs.mkdtempSync(path.join(os.tmpdir(), 'legacy')) : path.join(gopath, 'src', 'test'); | 
|  | fixturePath = path.join(repoPath, 'testfixture'); | 
|  | fixtureSourcePath = path.join(__dirname, '..', '..', '..', 'test', 'testdata'); | 
|  | generateTestsSourcePath = path.join(repoPath, 'generatetests'); | 
|  | generateFunctionTestSourcePath = path.join(repoPath, 'generatefunctiontest'); | 
|  | generatePackageTestSourcePath = path.join(repoPath, 'generatePackagetest'); | 
|  |  | 
|  | fs.removeSync(repoPath); | 
|  | fs.copySync(fixtureSourcePath, fixturePath, { | 
|  | recursive: true | 
|  | // TODO(hyangah): should we enable GOPATH mode | 
|  | }); | 
|  | fs.copySync( | 
|  | path.join(fixtureSourcePath, 'generatetests', 'generatetests.go'), | 
|  | path.join(generateTestsSourcePath, 'generatetests.go') | 
|  | ); | 
|  | fs.copySync( | 
|  | path.join(fixtureSourcePath, 'generatetests', 'generatetests.go'), | 
|  | path.join(generateFunctionTestSourcePath, 'generatetests.go') | 
|  | ); | 
|  | fs.copySync( | 
|  | path.join(fixtureSourcePath, 'generatetests', 'generatetests.go'), | 
|  | path.join(generatePackageTestSourcePath, 'generatetests.go') | 
|  | ); | 
|  | fs.copySync( | 
|  | path.join(fixtureSourcePath, 'diffTestData', 'file1.go'), | 
|  | path.join(fixturePath, 'diffTest1Data', 'file1.go') | 
|  | ); | 
|  | fs.copySync( | 
|  | path.join(fixtureSourcePath, 'diffTestData', 'file2.go'), | 
|  | path.join(fixturePath, 'diffTest1Data', 'file2.go') | 
|  | ); | 
|  | fs.copySync( | 
|  | path.join(fixtureSourcePath, 'diffTestData', 'file1.go'), | 
|  | path.join(fixturePath, 'diffTest2Data', 'file1.go') | 
|  | ); | 
|  | fs.copySync( | 
|  | path.join(fixtureSourcePath, 'diffTestData', 'file2.go'), | 
|  | path.join(fixturePath, 'diffTest2Data', 'file2.go') | 
|  | ); | 
|  | }); | 
|  |  | 
|  | suiteTeardown(() => { | 
|  | fs.removeSync(repoPath); | 
|  | process.env = previousEnv; | 
|  | }); | 
|  |  | 
|  | teardown(() => { | 
|  | sinon.restore(); | 
|  | }); | 
|  |  | 
|  | test('Linting - concurrent process cancelation', async () => { | 
|  | const util = require('../../src/util'); | 
|  | const processutil = require('../../src/utils/processUtils'); | 
|  | sinon.spy(util, 'runTool'); | 
|  | sinon.spy(processutil, 'killProcessTree'); | 
|  |  | 
|  | const config = Object.create(getGoConfig(), { | 
|  | vetOnSave: { value: 'package' }, | 
|  | vetFlags: { value: ['-all'] }, | 
|  | buildOnSave: { value: 'package' }, | 
|  | lintOnSave: { value: 'package' }, | 
|  | // simulate a long running lint process by sleeping for a couple seconds | 
|  | lintTool: { value: process.platform !== 'win32' ? 'sleep' : 'timeout' }, | 
|  | lintFlags: { value: process.platform !== 'win32' ? ['2'] : ['/t', '2'] } | 
|  | }); | 
|  | const goplsConfig = Object.create(getGoplsConfig(), {}); | 
|  |  | 
|  | const results = await Promise.all([ | 
|  | goLint(vscode.Uri.file(path.join(fixturePath, 'linterTest', 'linter_1.go')), config, goplsConfig), | 
|  | goLint(vscode.Uri.file(path.join(fixturePath, 'linterTest', 'linter_2.go')), config, goplsConfig) | 
|  | ]); | 
|  | assert.equal(util.runTool.callCount, 2, 'should have launched 2 lint jobs'); | 
|  | assert.equal( | 
|  | processutil.killProcessTree.callCount, | 
|  | 1, | 
|  | 'should have killed 1 lint job before launching the next' | 
|  | ); | 
|  | }); | 
|  |  | 
|  | test('Linting - lint errors with multiple open files', async () => { | 
|  | try { | 
|  | // handleDiagnosticErrors may adjust the lint errors' ranges to make the error more visible. | 
|  | // This adjustment applies only to the text documents known to vscode. This test checks | 
|  | // the adjustment is made consistently across multiple open text documents. | 
|  | const file1 = await vscode.workspace.openTextDocument( | 
|  | vscode.Uri.file(path.join(fixturePath, 'linterTest', 'linter_1.go')) | 
|  | ); | 
|  | const file2 = await vscode.workspace.openTextDocument( | 
|  | vscode.Uri.file(path.join(fixturePath, 'linterTest', 'linter_2.go')) | 
|  | ); | 
|  | console.log('start linting'); | 
|  | const warnings = await goLint( | 
|  | file2.uri, | 
|  | Object.create(getGoConfig(), { | 
|  | lintTool: { value: 'staticcheck' }, | 
|  | lintFlags: { value: ['-checks', 'all,-ST1000,-ST1016'] } | 
|  | // staticcheck skips debatable checks such as ST1003 by default, | 
|  | // but this test depends on ST1003 (MixedCaps package name) presented in both files | 
|  | // in the same package. So, enable that. | 
|  | }), | 
|  | Object.create(getGoplsConfig(), {}), | 
|  | 'package' | 
|  | ); | 
|  |  | 
|  | const diagnosticCollection = vscode.languages.createDiagnosticCollection('linttest'); | 
|  | handleDiagnosticErrors({}, file2, warnings, diagnosticCollection); | 
|  |  | 
|  | // The first diagnostic message for each file should be about the use of MixedCaps in package name. | 
|  | // Both files belong to the same package name, and we want them to be identical. | 
|  | const file1Diagnostics = diagnosticCollection.get(file1.uri); | 
|  | const file2Diagnostics = diagnosticCollection.get(file2.uri); | 
|  | assert(file1Diagnostics); | 
|  | assert(file2Diagnostics); | 
|  | assert(file1Diagnostics.length > 0); | 
|  | assert(file2Diagnostics.length > 0); | 
|  | assert.deepStrictEqual(file1Diagnostics[0], file2Diagnostics[0]); | 
|  | } catch (e) { | 
|  | assert.fail(`failed to lint: ${e}`); | 
|  | } | 
|  | }); | 
|  |  | 
|  | test('Error checking', async () => { | 
|  | const config = Object.create(getGoConfig(), { | 
|  | vetOnSave: { value: 'package' }, | 
|  | vetFlags: { value: ['-all'] }, | 
|  | lintOnSave: { value: 'package' }, | 
|  | lintTool: { value: 'staticcheck' }, | 
|  | lintFlags: { value: [] }, | 
|  | buildOnSave: { value: 'package' } | 
|  | }); | 
|  | const expectedLintErrors = [ | 
|  | // Unlike golint, staticcheck will report only those compile errors, | 
|  | // but not lint errors when the program is broken. | 
|  | { | 
|  | line: 11, | 
|  | severity: 'warning', | 
|  | // From v0.4.0, staticcheck uses 'undefined:' as the prefix of this error. | 
|  | msg: /(?:undeclared name|undefined): prin \(compile\)/ | 
|  | } | 
|  | ]; | 
|  | // If a user has enabled diagnostics via a language server, | 
|  | // then we disable running build or vet to avoid duplicate errors and warnings. | 
|  | const lspConfig = await buildLanguageServerConfig(getGoConfig()); | 
|  | const expectedBuildVetErrors = lspConfig.enabled | 
|  | ? [] | 
|  | : [{ line: 11, severity: 'error', msg: 'undefined: prin' }]; | 
|  |  | 
|  | // `check` itself doesn't run deDupeDiagnostics, so we expect all vet/lint errors. | 
|  | const expected = [...expectedLintErrors, ...expectedBuildVetErrors]; | 
|  | const diagnostics = await check( | 
|  | { | 
|  | buildDiagnosticCollection: vscode.languages.createDiagnosticCollection('buildtest'), | 
|  | lintDiagnosticCollection: vscode.languages.createDiagnosticCollection('linttest'), | 
|  | vetDiagnosticCollection: vscode.languages.createDiagnosticCollection('vettest') | 
|  | }, | 
|  | vscode.Uri.file(path.join(fixturePath, 'errorsTest', 'errors.go')), | 
|  | config | 
|  | ); | 
|  | const sortedDiagnostics = ([] as ICheckResult[]).concat | 
|  | .apply( | 
|  | [], | 
|  | diagnostics.map((x) => x.errors) | 
|  | ) | 
|  | .sort((a: any, b: any) => a.line - b.line); | 
|  | assert.equal(sortedDiagnostics.length > 0, true, 'Failed to get linter results'); | 
|  |  | 
|  | const matchCount = expected.filter((expectedItem) => { | 
|  | return sortedDiagnostics.some((diag: any) => { | 
|  | return ( | 
|  | expectedItem.line === diag.line && | 
|  | expectedItem.severity === diag.severity && | 
|  | diag.msg.match(expectedItem.msg) | 
|  | ); | 
|  | }); | 
|  | }); | 
|  | assert.equal( | 
|  | matchCount.length >= expected.length, | 
|  | true, | 
|  | `Failed to match expected errors \n${JSON.stringify(sortedDiagnostics)} \n VS\n ${JSON.stringify(expected)}` | 
|  | ); | 
|  | }); | 
|  |  | 
|  | test('Test Generate unit tests skeleton for file', async () => { | 
|  | const uri = vscode.Uri.file(path.join(generateTestsSourcePath, 'generatetests.go')); | 
|  | const document = await vscode.workspace.openTextDocument(uri); | 
|  | await vscode.window.showTextDocument(document); | 
|  | const ctx = new MockExtensionContext() as any; | 
|  | await generateTestCurrentFile(ctx, {})(); | 
|  |  | 
|  | const testFileGenerated = fs.existsSync(path.join(generateTestsSourcePath, 'generatetests_test.go')); | 
|  | assert.equal(testFileGenerated, true, 'Test file not generated.'); | 
|  | }); | 
|  |  | 
|  | test('Test Generate unit tests skeleton for a function', async () => { | 
|  | const uri = vscode.Uri.file(path.join(generateFunctionTestSourcePath, 'generatetests.go')); | 
|  | const document = await vscode.workspace.openTextDocument(uri); | 
|  | const editor = await vscode.window.showTextDocument(document); | 
|  | editor.selection = new vscode.Selection(5, 0, 6, 0); | 
|  | const ctx = new MockExtensionContext() as any; | 
|  | await generateTestCurrentFunction(ctx, {})(); | 
|  |  | 
|  | const testFileGenerated = fs.existsSync(path.join(generateTestsSourcePath, 'generatetests_test.go')); | 
|  | assert.equal(testFileGenerated, true, 'Test file not generated.'); | 
|  | }); | 
|  |  | 
|  | test('Test Generate unit tests skeleton for package', async () => { | 
|  | const uri = vscode.Uri.file(path.join(generatePackageTestSourcePath, 'generatetests.go')); | 
|  | const document = await vscode.workspace.openTextDocument(uri); | 
|  | await vscode.window.showTextDocument(document); | 
|  | const ctx = new MockExtensionContext() as any; | 
|  | await generateTestCurrentPackage(ctx, {})(); | 
|  |  | 
|  | const testFileGenerated = fs.existsSync(path.join(generateTestsSourcePath, 'generatetests_test.go')); | 
|  | assert.equal(testFileGenerated, true, 'Test file not generated.'); | 
|  | }); | 
|  |  | 
|  | test('Test diffUtils.getEditsFromUnifiedDiffStr', async function () { | 
|  | // Run this test only in module mode. | 
|  | if (!isModuleMode) { | 
|  | this.skip(); | 
|  | } | 
|  |  | 
|  | if (process.platform === 'win32') { | 
|  | // This test requires diff tool that's not available on windows | 
|  | this.skip(); | 
|  | } | 
|  |  | 
|  | const file1path = path.join(fixturePath, 'diffTest1Data', 'file1.go'); | 
|  | const file2path = path.join(fixturePath, 'diffTest1Data', 'file2.go'); | 
|  | const file1uri = vscode.Uri.file(file1path); | 
|  | const file2contents = fs.readFileSync(file2path, 'utf8'); | 
|  |  | 
|  | const fileEditPatches: any | FilePatch[] = await new Promise((resolve) => { | 
|  | cp.exec(`diff -u ${file1path} ${file2path}`, (err, stdout, stderr) => { | 
|  | const filePatches: FilePatch[] = getEditsFromUnifiedDiffStr(stdout); | 
|  |  | 
|  | if (!filePatches || filePatches.length !== 1) { | 
|  | assert.fail(null, null, 'Failed to get patches for the test file', ''); | 
|  | } | 
|  |  | 
|  | if (!filePatches[0].fileName) { | 
|  | assert.fail(null, null, 'Failed to parse the file path from the diff output', ''); | 
|  | } | 
|  |  | 
|  | if (!filePatches[0].edits) { | 
|  | assert.fail(null, null, 'Failed to parse edits from the diff output', ''); | 
|  | } | 
|  | resolve(filePatches); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | const textDocument = await vscode.workspace.openTextDocument(file1uri); | 
|  | const editor = await vscode.window.showTextDocument(textDocument); | 
|  | await editor.edit((editBuilder) => { | 
|  | fileEditPatches[0].edits.forEach((edit: any) => { | 
|  | edit.applyUsingTextEditorEdit(editBuilder); | 
|  | }); | 
|  | }); | 
|  | assert.equal(editor.document.getText(), file2contents); | 
|  | }); | 
|  |  | 
|  | test('Test diffUtils.getEdits', async function () { | 
|  | if (!isModuleMode) { | 
|  | this.skip(); | 
|  | } // Run this test only in module mode. | 
|  |  | 
|  | const file1path = path.join(fixturePath, 'diffTest2Data', 'file1.go'); | 
|  | const file2path = path.join(fixturePath, 'diffTest2Data', 'file2.go'); | 
|  | const file1uri = vscode.Uri.file(file1path); | 
|  | const file1contents = fs.readFileSync(file1path, 'utf8'); | 
|  | const file2contents = fs.readFileSync(file2path, 'utf8'); | 
|  |  | 
|  | const fileEdits = getEdits(file1path, file1contents, file2contents); | 
|  |  | 
|  | if (!fileEdits) { | 
|  | assert.fail(null, null, 'Failed to get patches for the test file', ''); | 
|  | } | 
|  |  | 
|  | if (!fileEdits.fileName) { | 
|  | assert.fail(null, null, 'Failed to parse the file path from the diff output', ''); | 
|  | } | 
|  |  | 
|  | if (!fileEdits.edits) { | 
|  | assert.fail(null, null, 'Failed to parse edits from the diff output', ''); | 
|  | } | 
|  |  | 
|  | const textDocument = await vscode.workspace.openTextDocument(file1uri); | 
|  | const editor = await vscode.window.showTextDocument(textDocument); | 
|  | await editor.edit((editBuilder) => { | 
|  | fileEdits.edits.forEach((edit) => { | 
|  | edit.applyUsingTextEditorEdit(editBuilder); | 
|  | }); | 
|  | }); | 
|  | assert.equal(editor.document.getText(), file2contents); | 
|  | }); | 
|  |  | 
|  | test('Test Env Variables are passed to Tests', async () => { | 
|  | const config = Object.create(getGoConfig(), { | 
|  | testEnvVars: { value: { dummyEnvVar: 'dummyEnvValue', dummyNonString: 1 } } | 
|  | }); | 
|  | const uri = vscode.Uri.file(path.join(fixturePath, 'baseTest', 'sample_test.go')); | 
|  | const document = await vscode.workspace.openTextDocument(uri); | 
|  | await vscode.window.showTextDocument(document); | 
|  | const ctx = new MockExtensionContext() as any; | 
|  | const result = await testCurrentFile(false, () => config)(ctx, {})([]); | 
|  | assert.equal(result, true); | 
|  | }); | 
|  |  | 
|  | test('getImportPath()', () => { | 
|  | const testCases: [string, string][] = [ | 
|  | ['import "github.com/sirupsen/logrus"', 'github.com/sirupsen/logrus'], | 
|  | ['import "net/http"', 'net/http'], | 
|  | ['"github.com/sirupsen/logrus"', 'github.com/sirupsen/logrus'], | 
|  | ['', ''], | 
|  | ['func foo(bar int) (int, error) {', ''], | 
|  | ['// This is a comment, complete with punctuation.', ''] | 
|  | ]; | 
|  |  | 
|  | testCases.forEach((run) => { | 
|  | assert.equal(run[1], getImportPath(run[0])); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test('goPlay - success run', async () => { | 
|  | const goplayPath = getBinPath('goplay'); | 
|  | if (goplayPath === 'goplay') { | 
|  | // goplay is not installed, so skip the test | 
|  | return; | 
|  | } | 
|  |  | 
|  | const validCode = ` | 
|  | package main | 
|  | import ( | 
|  | "fmt" | 
|  | ) | 
|  | func main() { | 
|  | for i := 1; i < 4; i++ { | 
|  | fmt.Printf("%v ", i) | 
|  | } | 
|  | fmt.Print("Go!") | 
|  | }`; | 
|  | const goConfig = Object.create(getGoConfig(), { | 
|  | playground: { value: { run: true, openbrowser: false, share: false } } | 
|  | }); | 
|  |  | 
|  | await goPlay(validCode, goConfig['playground']).then( | 
|  | (result) => { | 
|  | assert(result.includes('1 2 3 Go!')); | 
|  | }, | 
|  | (e) => { | 
|  | assert.ifError(e); | 
|  | } | 
|  | ); | 
|  | }); | 
|  |  | 
|  | test('goPlay - success run & share', async () => { | 
|  | const goplayPath = getBinPath('goplay'); | 
|  | if (goplayPath === 'goplay') { | 
|  | // goplay is not installed, so skip the test | 
|  | return; | 
|  | } | 
|  |  | 
|  | const validCode = ` | 
|  | package main | 
|  | import ( | 
|  | "fmt" | 
|  | ) | 
|  | func main() { | 
|  | for i := 1; i < 4; i++ { | 
|  | fmt.Printf("%v ", i) | 
|  | } | 
|  | fmt.Print("Go!") | 
|  | }`; | 
|  | const goConfig = Object.create(getGoConfig(), { | 
|  | playground: { value: { run: true, openbrowser: false, share: true } } | 
|  | }); | 
|  |  | 
|  | await goPlay(validCode, goConfig['playground']).then( | 
|  | (result) => { | 
|  | assert(result.includes('1 2 3 Go!')); | 
|  | assert(result.includes('https://play.golang.org/')); | 
|  | }, | 
|  | (e) => { | 
|  | assert.ifError(e); | 
|  | } | 
|  | ); | 
|  | }); | 
|  |  | 
|  | test('goPlay - fail', async () => { | 
|  | const goplayPath = getBinPath('goplay'); | 
|  | if (goplayPath === 'goplay') { | 
|  | // goplay is not installed, so skip the test | 
|  | return; | 
|  | } | 
|  |  | 
|  | const invalidCode = ` | 
|  | package main | 
|  | import ( | 
|  | "fmt" | 
|  | ) | 
|  | func fantasy() { | 
|  | fmt.Print("not a main package, sorry") | 
|  | }`; | 
|  | const goConfig = Object.create(getGoConfig(), { | 
|  | playground: { value: { run: true, openbrowser: false, share: false } } | 
|  | }); | 
|  |  | 
|  | await goPlay(invalidCode, goConfig['playground']).then( | 
|  | (result) => { | 
|  | assert.ifError(result); | 
|  | }, | 
|  | (e) => { | 
|  | assert.ok(e); | 
|  | } | 
|  | ); | 
|  | }); | 
|  |  | 
|  | test('Build Tags checking', async () => { | 
|  | const goplsConfig = await buildLanguageServerConfig(getGoConfig()); | 
|  | if (goplsConfig.enabled) { | 
|  | // Skip this test if gopls is enabled. Build/Vet checks this test depend on are | 
|  | // disabled when the language server is enabled, and gopls is not handling tags yet. | 
|  | return; | 
|  | } | 
|  | // Note: The following checks can't be parallelized because the underlying go build command | 
|  | // runner (goBuild) will cancel any outstanding go build commands. | 
|  |  | 
|  | const checkWithTags = async (tags: string) => { | 
|  | const fileUri = vscode.Uri.file(path.join(fixturePath, 'buildTags', 'hello.go')); | 
|  | const defaultGoCfg = getGoConfig(fileUri); | 
|  | const cfg = Object.create(defaultGoCfg, { | 
|  | vetOnSave: { value: 'off' }, | 
|  | lintOnSave: { value: 'off' }, | 
|  | buildOnSave: { value: 'package' }, | 
|  | buildTags: { value: tags } | 
|  | }) as vscode.WorkspaceConfiguration; | 
|  |  | 
|  | const diagnostics = await check({}, fileUri, cfg); | 
|  | return ([] as string[]).concat( | 
|  | ...diagnostics.map<string[]>((d) => { | 
|  | return d.errors.map((e) => e.msg) as string[]; | 
|  | }) | 
|  | ); | 
|  | }; | 
|  |  | 
|  | const errors1 = await checkWithTags('randomtag'); | 
|  | assert.deepEqual( | 
|  | errors1, | 
|  | ['undefined: fmt.Prinln'], | 
|  | 'check with buildtag "randomtag" failed. Unexpected errors found.' | 
|  | ); | 
|  |  | 
|  | // TODO(hyangah): after go1.13, -tags expects a comma-separated tag list. | 
|  | // For backwards compatibility, space-separated tag lists are still recognized, | 
|  | // but change to a space-separated list once we stop testing with go1.12. | 
|  | const errors2 = await checkWithTags('randomtag other'); | 
|  | assert.deepEqual( | 
|  | errors2, | 
|  | ['undefined: fmt.Prinln'], | 
|  | 'check with multiple buildtags "randomtag,other" failed. Unexpected errors found.' | 
|  | ); | 
|  |  | 
|  | const errors3 = await checkWithTags(''); | 
|  | assert.equal( | 
|  | errors3.length, | 
|  | 1, | 
|  | 'check without buildtag failed. Unexpected number of errors found' + JSON.stringify(errors3) | 
|  | ); | 
|  | const errMsg = errors3[0]; | 
|  | assert.ok( | 
|  | errMsg.includes("can't load package: package test/testfixture/buildTags") || | 
|  | errMsg.includes('build constraints exclude all Go files'), | 
|  | `check without buildtags failed. Go files not excluded. ${errMsg}` | 
|  | ); | 
|  | }); | 
|  |  | 
|  | test('Test Tags checking', async () => { | 
|  | const config1 = Object.create(getGoConfig(), { | 
|  | vetOnSave: { value: 'off' }, | 
|  | lintOnSave: { value: 'off' }, | 
|  | buildOnSave: { value: 'package' }, | 
|  | testTags: { value: null }, | 
|  | buildTags: { value: 'randomtag' } | 
|  | }); | 
|  |  | 
|  | const config2 = Object.create(getGoConfig(), { | 
|  | vetOnSave: { value: 'off' }, | 
|  | lintOnSave: { value: 'off' }, | 
|  | buildOnSave: { value: 'package' }, | 
|  | testTags: { value: 'randomtag' } | 
|  | }); | 
|  |  | 
|  | const config3 = Object.create(getGoConfig(), { | 
|  | vetOnSave: { value: 'off' }, | 
|  | lintOnSave: { value: 'off' }, | 
|  | buildOnSave: { value: 'package' }, | 
|  | testTags: { value: 'randomtag othertag' } | 
|  | }); | 
|  |  | 
|  | const config4 = Object.create(getGoConfig(), { | 
|  | vetOnSave: { value: 'off' }, | 
|  | lintOnSave: { value: 'off' }, | 
|  | buildOnSave: { value: 'package' }, | 
|  | testTags: { value: '' } | 
|  | }); | 
|  |  | 
|  | const uri = vscode.Uri.file(path.join(fixturePath, 'testTags', 'hello_test.go')); | 
|  | const document = await vscode.workspace.openTextDocument(uri); | 
|  | await vscode.window.showTextDocument(document); | 
|  | const ctx = new MockExtensionContext() as any; | 
|  |  | 
|  | const result1 = await testCurrentFile(false, () => config1)(ctx, {})([]); | 
|  | assert.equal(result1, true); | 
|  |  | 
|  | const result2 = await testCurrentFile(false, () => config2)(ctx, {})([]); | 
|  | assert.equal(result2, true); | 
|  |  | 
|  | const result3 = await testCurrentFile(false, () => config3)(ctx, {})([]); | 
|  | assert.equal(result3, true); | 
|  |  | 
|  | const result4 = await testCurrentFile(false, () => config4)(ctx, {})([]); | 
|  | assert.equal(result4, false); | 
|  | }); | 
|  | }; | 
|  |  | 
|  | suite('Go Extension Tests (GOPATH mode)', function () { | 
|  | this.timeout(20000); | 
|  | testAll(false); | 
|  | }); | 
|  |  | 
|  | suite('Go Extension Tests (Module mode)', function () { | 
|  | this.timeout(20000); | 
|  | testAll(true); | 
|  | }); |