/*---------------------------------------------------------
 * Copyright (C) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 *--------------------------------------------------------*/

import * as assert from 'assert';
import cp = require('child_process');
import * as fs from 'fs-extra';
import * as path from 'path';
import * as sinon from 'sinon';
import * as vscode from 'vscode';
import { FilePatch, getEdits, getEditsFromUnifiedDiffStr } from '../../src/diffUtils';
import { check } from '../../src/goCheck';
import { GoDefinitionProvider } from '../../src/goDeclaration';
import { GoHoverProvider } from '../../src/goExtraInfo';
import { runFillStruct } from '../../src/goFillStruct';
import {
	generateTestCurrentFile,
	generateTestCurrentFunction,
	generateTestCurrentPackage
} from '../../src/goGenerateTests';
import { getTextEditForAddImport, listPackages } from '../../src/goImport';
import { updateGoVarsFromConfig } from '../../src/goInstallTools';
import { buildLanguageServerConfig } from '../../src/goLanguageServer';
import { goLint } from '../../src/goLint';
import { documentSymbols, GoDocumentSymbolProvider, GoOutlineImportsOptions } from '../../src/goOutline';
import { getAllPackages } from '../../src/goPackages';
import { goPlay } from '../../src/goPlayground';
import { GoSignatureHelpProvider } from '../../src/goSignature';
import { GoCompletionItemProvider } from '../../src/goSuggest';
import { getWorkspaceSymbols } from '../../src/goSymbol';
import { testCurrentFile } from '../../src/goTest';
import {
	getBinPath,
	getCurrentGoPath,
	getGoConfig,
	getImportPath,
	getToolsGopath,
	handleDiagnosticErrors,
	ICheckResult,
	isVendorSupported
} from '../../src/util';

suite('Go Extension Tests', function () {
	this.timeout(15000);

	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 toolsGopath: string;

	suiteSetup(async () => {
		await updateGoVarsFromConfig();

		gopath = getCurrentGoPath();
		if (!gopath) {
			assert.ok(gopath, 'Cannot run tests if GOPATH is not set as environment variable');
			return;
		}
		console.log(`Using GOPATH: ${gopath}`);

		repoPath = 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');
		toolsGopath = getToolsGopath() || gopath;

		fs.removeSync(repoPath);
		fs.copySync(fixtureSourcePath, fixturePath, {
			recursive: true,
			// All of the tests run in GOPATH mode for now.
			// TODO(rstambler): Run tests in GOPATH and module mode.
			filter: (src: string): boolean => {
				if (path.basename(src) === 'go.mod') {
					return false;
				}
				return true;
			},
		});
		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);
	});

	teardown(() => {
		sinon.restore();
	});

	async function testDefinitionProvider(goConfig: vscode.WorkspaceConfiguration): Promise<any> {
		const provider = new GoDefinitionProvider(goConfig);
		const uri = vscode.Uri.file(path.join(fixturePath, 'baseTest', 'test.go'));
		const position = new vscode.Position(10, 3);
		const textDocument = await vscode.workspace.openTextDocument(uri);
		const definitionInfo = await provider.provideDefinition(textDocument, position, dummyCancellationSource.token);

		assert.equal(
			definitionInfo.uri.path.toLowerCase(),
			uri.path.toLowerCase(),
			`${definitionInfo.uri.path} is not the same as ${uri.path}`
		);
		assert.equal(definitionInfo.range.start.line, 6);
		assert.equal(definitionInfo.range.start.character, 5);
	}

	async function testSignatureHelpProvider(
		goConfig: vscode.WorkspaceConfiguration,
		testCases: [vscode.Position, string, string, string[]][]
	): Promise<any> {
		const provider = new GoSignatureHelpProvider(goConfig);
		const uri = vscode.Uri.file(path.join(fixturePath, 'gogetdocTestData', 'test.go'));
		const textDocument = await vscode.workspace.openTextDocument(uri);

		const promises = testCases.map(([position, expected, expectedDoc, expectedParams]) =>
			provider.provideSignatureHelp(textDocument, position, dummyCancellationSource.token).then((sigHelp) => {
				assert.ok(
					sigHelp,
					`No signature for gogetdocTestData/test.go:${position.line + 1}:${position.character + 1}`
				);
				assert.equal(sigHelp.signatures.length, 1, 'unexpected number of overloads');
				assert.equal(sigHelp.signatures[0].label, expected);
				assert.equal(sigHelp.signatures[0].documentation, expectedDoc);
				assert.equal(sigHelp.signatures[0].parameters.length, expectedParams.length);
				for (let i = 0; i < expectedParams.length; i++) {
					assert.equal(sigHelp.signatures[0].parameters[i].label, expectedParams[i]);
				}
			})
		);
		return Promise.all(promises);
	}

	async function testHoverProvider(
		goConfig: vscode.WorkspaceConfiguration,
		testCases: [vscode.Position, string | null, string | null][]
	): Promise<any> {
		const provider = new GoHoverProvider(goConfig);
		const uri = vscode.Uri.file(path.join(fixturePath, 'gogetdocTestData', 'test.go'));
		const textDocument = await vscode.workspace.openTextDocument(uri);

		const promises = testCases.map(([position, expectedSignature, expectedDocumentation]) =>
			provider.provideHover(textDocument, position, dummyCancellationSource.token).then((res) => {
				if (expectedSignature === null && expectedDocumentation === null) {
					assert.equal(res, null);
					return;
				}
				let expectedHover = '\n```go\n' + expectedSignature + '\n```\n';
				if (expectedDocumentation != null) {
					expectedHover += expectedDocumentation;
				}
				assert.equal(res.contents.length, 1);
				assert.equal((<vscode.MarkdownString>res.contents[0]).value, expectedHover);
			})
		);
		return Promise.all(promises);
	}

	test('Test Definition Provider using godoc', async () => {
		const config = Object.create(vscode.workspace.getConfiguration('go'), {
			docsTool: { value: 'godoc' }
		});
		await testDefinitionProvider(config);
	});

	test('Test Definition Provider using gogetdoc', async () => {
		const gogetdocPath = getBinPath('gogetdoc');
		if (gogetdocPath === 'gogetdoc') {
			// gogetdoc is not installed, so skip the test
			return;
		}
		const config = Object.create(vscode.workspace.getConfiguration('go'), {
			docsTool: { value: 'gogetdoc' }
		});
		await testDefinitionProvider(config);
	});

	test('Test SignatureHelp Provider using godoc', async () => {
		const printlnDoc = `Println formats using the default formats for its operands and writes to
standard output. Spaces are always added between operands and a newline is
appended. It returns the number of bytes written and any write error
encountered.
`;

		const testCases: [vscode.Position, string, string, string[]][] = [
			[
				new vscode.Position(19, 13),
				'Println(a ...interface{}) (n int, err error)',
				printlnDoc,
				['a ...interface{}']
			],
			[
				new vscode.Position(23, 7),
				'print(txt string)',
				`This is an unexported function so couldn't get this comment on hover :( Not\nanymore!!\n`,
				['txt string']
			],
			[
				new vscode.Position(41, 19),
				'Hello(s string, exclaim bool) string',
				'Hello is a method on the struct ABC. Will signature help understand this\ncorrectly\n',
				['s string', 'exclaim bool']
			],
			[
				new vscode.Position(41, 47),
				'EmptyLine(s string) string',
				'EmptyLine has docs\n\nwith a blank line in the middle\n',
				['s string']
			]
		];
		const config = Object.create(vscode.workspace.getConfiguration('go'), {
			docsTool: { value: 'godoc' }
		});
		await testSignatureHelpProvider(config, testCases);
	});

	test('Test SignatureHelp Provider using gogetdoc', async () => {
		const gogetdocPath = getBinPath('gogetdoc');
		if (gogetdocPath === 'gogetdoc') {
			// gogetdoc is not installed, so skip the test
			return;
		}

		const printlnDoc = `Println formats using the default formats for its operands and writes to standard output.
Spaces are always added between operands and a newline is appended.
It returns the number of bytes written and any write error encountered.
`;
		const testCases: [vscode.Position, string, string, string[]][] = [
			[
				new vscode.Position(19, 13),
				'Println(a ...interface{}) (n int, err error)',
				printlnDoc,
				['a ...interface{}']
			],
			[
				new vscode.Position(23, 7),
				'print(txt string)',
				`This is an unexported function so couldn't get this comment on hover :(\nNot anymore!!\n`,
				['txt string']
			],
			[
				new vscode.Position(41, 19),
				'Hello(s string, exclaim bool) string',
				'Hello is a method on the struct ABC. Will signature help understand this correctly\n',
				['s string', 'exclaim bool']
			],
			[
				new vscode.Position(41, 47),
				'EmptyLine(s string) string',
				'EmptyLine has docs\n\nwith a blank line in the middle\n',
				['s string']
			]
		];
		const config = Object.create(vscode.workspace.getConfiguration('go'), {
			docsTool: { value: 'gogetdoc' }
		});
		await testSignatureHelpProvider(config, testCases);
	});

	test('Test Hover Provider using godoc', async () => {
		const printlnDoc = `Println formats using the default formats for its operands and writes to
standard output. Spaces are always added between operands and a newline is
appended. It returns the number of bytes written and any write error
encountered.
`;
		const testCases: [vscode.Position, string | null, string | null][] = [
			// [new vscode.Position(3,3), '/usr/local/go/src/fmt'],
			[new vscode.Position(0, 3), null, null], // keyword
			[new vscode.Position(23, 14), null, null], // inside a string
			[new vscode.Position(20, 0), null, null], // just a }
			[new vscode.Position(28, 16), null, null], // inside a number
			[new vscode.Position(22, 5), 'main func()', '\n'],
			[new vscode.Position(40, 23), 'import (math "math")', null],
			[new vscode.Position(19, 6), 'Println func(a ...interface{}) (n int, err error)', printlnDoc],
			[
				new vscode.Position(23, 4),
				'print func(txt string)',
				`This is an unexported function so couldn't get this comment on hover :( Not\nanymore!!\n`
			]
		];
		const config = Object.create(vscode.workspace.getConfiguration('go'), {
			docsTool: { value: 'godoc' }
		});
		await testHoverProvider(config, testCases);
	});

	test('Test Hover Provider using gogetdoc', async () => {
		const gogetdocPath = getBinPath('gogetdoc');
		if (gogetdocPath === 'gogetdoc') {
			// gogetdoc is not installed, so skip the test
			return;
		}

		const printlnDoc = `Println formats using the default formats for its operands and writes to standard output.
Spaces are always added between operands and a newline is appended.
It returns the number of bytes written and any write error encountered.
`;
		const testCases: [vscode.Position, string | null, string | null][] = [
			[new vscode.Position(0, 3), null, null], // keyword
			[new vscode.Position(23, 11), null, null], // inside a string
			[new vscode.Position(20, 0), null, null], // just a }
			[new vscode.Position(28, 16), null, null], // inside a number
			[new vscode.Position(22, 5), 'func main()', ''],
			[
				new vscode.Position(23, 4),
				'func print(txt string)',
				`This is an unexported function so couldn't get this comment on hover :(\nNot anymore!!\n`
			],
			[
				new vscode.Position(40, 23),
				'package math',
				'Package math provides basic constants and mathematical functions.\n\nThis package does not guarantee bit-identical results across architectures.\n'
			],
			[new vscode.Position(19, 6), 'func Println(a ...interface{}) (n int, err error)', printlnDoc],
			[
				new vscode.Position(27, 14),
				'type ABC struct {\n    a int\n    b int\n    c int\n}',
				`ABC is a struct, you coudn't use Goto Definition or Hover info on this before\nNow you can due to gogetdoc and go doc\n`
			],
			[
				new vscode.Position(28, 6),
				'func IPv4Mask(a, b, c, d byte) IPMask',
				'IPv4Mask returns the IP mask (in 4-byte form) of the\nIPv4 mask a.b.c.d.\n'
			]
		];
		const config = Object.create(vscode.workspace.getConfiguration('go'), {
			docsTool: { value: 'gogetdoc' }
		});
		await testHoverProvider(config, testCases);
	});

	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(vscode.workspace.getConfiguration('go'), {
			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 results = await Promise.all([
			goLint(vscode.Uri.file(path.join(fixturePath, 'linterTest', 'linter_1.go')), config),
			goLint(vscode.Uri.file(path.join(fixturePath, 'linterTest', 'linter_2.go')), config)
		]);
		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 () => {
		// 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')));
		const warnings = await goLint(file2.uri, Object.create(vscode.workspace.getConfiguration('go'), {
			lintTool: { value: 'golint' },
			lintFlags: { value: [] }
		}), '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.length > 0);
		assert(file2Diagnostics.length > 0);
		assert.deepStrictEqual(file1Diagnostics[0], file2Diagnostics[0]);
	});

	test('Error checking', async () => {
		const config = Object.create(vscode.workspace.getConfiguration('go'), {
			vetOnSave: { value: 'package' },
			vetFlags: { value: ['-all'] },
			lintOnSave: { value: 'package' },
			lintTool: { value: 'golint' },
			lintFlags: { value: [] },
			buildOnSave: { value: 'package' }
		});
		const expectedLintErrors = [
			{
				line: 7,
				severity: 'warning',
				msg: 'exported function Print2 should have comment or be unexported'
			},
		];
		// 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 = buildLanguageServerConfig(getGoConfig());
		const expectedBuildVetErrors = lspConfig.enabled ? [] : [{ line: 11, severity: 'error', msg: 'undefined: prin' }];

		const expected = [...expectedLintErrors, ...expectedBuildVetErrors];
		const diagnostics = await check(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 &&
					expectedItem.msg === diag.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 gotestsPath = getBinPath('gotests');
		if (gotestsPath === 'gotests') {
			// gotests is not installed, so skip the test
			return;
		}

		const uri = vscode.Uri.file(path.join(generateTestsSourcePath, 'generatetests.go'));
		const document = await vscode.workspace.openTextDocument(uri);
		await vscode.window.showTextDocument(document);
		await generateTestCurrentFile();

		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 gotestsPath = getBinPath('gotests');
		if (gotestsPath === 'gotests') {
			// gotests is not installed, so skip the test
			return;
		}

		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);
		await generateTestCurrentFunction();

		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 gotestsPath = getBinPath('gotests');
		if (gotestsPath === 'gotests') {
			// gotests is not installed, so skip the test
			return;
		}

		const uri = vscode.Uri.file(path.join(generatePackageTestSourcePath, 'generatetests.go'));
		const document = await vscode.workspace.openTextDocument(uri);
		await vscode.window.showTextDocument(document);
		await generateTestCurrentPackage();

		const testFileGenerated = fs.existsSync(path.join(generateTestsSourcePath, 'generatetests_test.go'));
		assert.equal(testFileGenerated, true, 'Test file not generated.');
	});

	test('Test diffUtils.getEditsFromUnifiedDiffStr', async function () {
		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 () => {
		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(vscode.workspace.getConfiguration('go'), {
			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 result = await testCurrentFile(config, false, []);
		assert.equal(result, true);
	});

	test('Test Outline', async () => {
		const uri = vscode.Uri.file(path.join(fixturePath, 'outlineTest', 'test.go'));
		const document = await vscode.workspace.openTextDocument(uri);
		const options = {
			document,
			fileName: document.fileName,
			importsOption: GoOutlineImportsOptions.Include
		};

		const outlines = await documentSymbols(options, dummyCancellationSource.token);
		const packageSymbols = outlines.filter((x: any) => x.kind === vscode.SymbolKind.Package);
		const imports = outlines[0].children.filter((x: any) => x.kind === vscode.SymbolKind.Namespace);
		const functions = outlines[0].children.filter((x: any) => x.kind === vscode.SymbolKind.Function);

		assert.equal(packageSymbols.length, 1);
		assert.equal(packageSymbols[0].name, 'main');
		assert.equal(imports.length, 1);
		assert.equal(imports[0].name, '"fmt"');
		assert.equal(functions.length, 2);
		assert.equal(functions[0].name, 'print');
		assert.equal(functions[1].name, 'main');
	});

	test('Test Outline imports only', async () => {
		const uri = vscode.Uri.file(path.join(fixturePath, 'outlineTest', 'test.go'));
		const document = await vscode.workspace.openTextDocument(uri);
		const options = {
			document,
			fileName: document.fileName,
			importsOption: GoOutlineImportsOptions.Only
		};

		const outlines = await documentSymbols(options, dummyCancellationSource.token);
		const packageSymbols = outlines.filter((x) => x.kind === vscode.SymbolKind.Package);
		const imports = outlines[0].children.filter((x: any) => x.kind === vscode.SymbolKind.Namespace);
		const functions = outlines[0].children.filter((x: any) => x.kind === vscode.SymbolKind.Function);

		assert.equal(packageSymbols.length, 1);
		assert.equal(packageSymbols[0].name, 'main');
		assert.equal(imports.length, 1);
		assert.equal(imports[0].name, '"fmt"');
		assert.equal(functions.length, 0);
	});

	test('Test Outline document symbols', async () => {
		const uri = vscode.Uri.file(path.join(fixturePath, 'outlineTest', 'test.go'));
		const document = await vscode.workspace.openTextDocument(uri);
		const symbolProvider = new GoDocumentSymbolProvider();

		const outlines = await symbolProvider.provideDocumentSymbols(document, dummyCancellationSource.token);
		const packages = outlines.filter((x) => x.kind === vscode.SymbolKind.Package);
		const variables = outlines[0].children.filter((x: any) => x.kind === vscode.SymbolKind.Variable);
		const functions = outlines[0].children.filter((x: any) => x.kind === vscode.SymbolKind.Function);
		const structs = outlines[0].children.filter((x: any) => x.kind === vscode.SymbolKind.Struct);
		const interfaces = outlines[0].children.filter((x: any) => x.kind === vscode.SymbolKind.Interface);

		assert.equal(packages[0].name, 'main');
		assert.equal(variables.length, 0);
		assert.equal(functions[0].name, 'print');
		assert.equal(functions[1].name, 'main');
		assert.equal(structs.length, 1);
		assert.equal(structs[0].name, 'foo');
		assert.equal(interfaces.length, 1);
		assert.equal(interfaces[0].name, 'circle');
	});

	test('Test listPackages', async () => {
		const uri = vscode.Uri.file(path.join(fixturePath, 'baseTest', 'test.go'));
		const document = await vscode.workspace.openTextDocument(uri);
		await vscode.window.showTextDocument(document);

		const includeImportedPkgs = await listPackages(false);
		const excludeImportedPkgs = await listPackages(true);
		assert.equal(includeImportedPkgs.indexOf('fmt') > -1, true);
		assert.equal(excludeImportedPkgs.indexOf('fmt') > -1, false);
	});

	test('Replace vendor packages with relative path', async () => {
		const vendorSupport = await isVendorSupported();
		const filePath = path.join(fixturePath, 'vendoring', 'main.go');
		const workDir = path.dirname(filePath);
		const vendorPkgsFullPath = [
			'test/testfixture/vendoring/vendor/example.com/vendorpls',
		];
		const vendorPkgsRelativePath = ['example.com/vendorpls'];

		const gopkgsPromise = getAllPackages(workDir).then((pkgMap) => {
			const pkgs = Array.from(pkgMap.keys()).filter((p) => {
				const pkg = pkgMap.get(p);
				return pkg && pkg.name !== 'main';
			});
			if (vendorSupport) {
				vendorPkgsFullPath.forEach((pkg) => {
					assert.equal(pkgs.indexOf(pkg) > -1, true, `Package not found by goPkgs: ${pkg}`);
				});
				vendorPkgsRelativePath.forEach((pkg) => {
					assert.equal(
						pkgs.indexOf(pkg),
						-1,
						`Relative path to vendor package ${pkg} should not be returned by gopkgs command`
					);
				});
			}
			return pkgs;
		});

		const listPkgPromise: Thenable<string[]> = vscode.workspace
			.openTextDocument(vscode.Uri.file(filePath))
			.then(async (document) => {
				await vscode.window.showTextDocument(document);
				const pkgs = await listPackages();
				if (vendorSupport) {
					vendorPkgsRelativePath.forEach((pkg) => {
						assert.equal(pkgs.indexOf(pkg) > -1, true, `Relative path for vendor package ${pkg} not found`);
					});
					vendorPkgsFullPath.forEach((pkg) => {
						assert.equal(
							pkgs.indexOf(pkg),
							-1,
							`Full path for vendor package ${pkg} should be shown by listPackages method`
						);
					});
				}
				return pkgs;
			});

		const values = await Promise.all<string[]>([gopkgsPromise, listPkgPromise]);
		if (!vendorSupport) {
			const originalPkgs = values[0].sort();
			const updatedPkgs = values[1].sort();
			assert.equal(originalPkgs.length, updatedPkgs.length);
			for (let index = 0; index < originalPkgs.length; index++) {
				assert.equal(updatedPkgs[index], originalPkgs[index]);
			}
		}
	});

	test('Vendor pkgs from other projects should not be allowed to import', async () => {
		const vendorSupport = await isVendorSupported();
		const filePath = path.join(fixturePath, 'baseTest', 'test.go');
		const vendorPkgs = [
			'test/testfixture/vendoring/vendor/example.com/vendorpls',
		];

		const gopkgsPromise = new Promise<void>((resolve, reject) => {
			const cmd = cp.spawn(getBinPath('gopkgs'), ['-format', '{{.ImportPath}}'], {
				env: process.env
			});
			const chunks: any[] = [];
			cmd.stdout.on('data', (d) => chunks.push(d));
			cmd.on('close', () => {
				const pkgs = chunks
					.join('')
					.split('\n')
					.filter((pkg) => pkg)
					.sort();
				if (vendorSupport) {
					vendorPkgs.forEach((pkg) => {
						assert.equal(pkgs.indexOf(pkg) > -1, true, `Package not found by goPkgs: ${pkg}`);
					});
				}
				return resolve();
			});
		});

		const listPkgPromise: Thenable<void> = vscode.workspace
			.openTextDocument(vscode.Uri.file(filePath))
			.then(async (document) => {
				await vscode.window.showTextDocument(document);
				const pkgs = await listPackages();
				if (vendorSupport) {
					vendorPkgs.forEach((pkg) => {
						assert.equal(
							pkgs.indexOf(pkg),
							-1,
							`Vendor package ${pkg} should not be shown by listPackages method`
						);
					});
				}
			});

		return Promise.all<void>([gopkgsPromise, listPkgPromise]);
	});

	test('Workspace Symbols', () => {
		const workspacePath = path.join(fixturePath, 'vendoring');
		const configWithoutIgnoringFolders = Object.create(vscode.workspace.getConfiguration('go'), {
			gotoSymbol: {
				value: {
					ignoreFolders: []
				}
			}
		});
		const configWithIgnoringFolders = Object.create(vscode.workspace.getConfiguration('go'), {
			gotoSymbol: {
				value: {
					ignoreFolders: ['vendor']
				}
			}
		});
		const configWithIncludeGoroot = Object.create(vscode.workspace.getConfiguration('go'), {
			gotoSymbol: {
				value: {
					includeGoroot: true
				}
			}
		});
		const configWithoutIncludeGoroot = Object.create(vscode.workspace.getConfiguration('go'), {
			gotoSymbol: {
				value: {
					includeGoroot: false
				}
			}
		});

		const withoutIgnoringFolders = getWorkspaceSymbols(
			workspacePath,
			'SomethingStr',
			dummyCancellationSource.token,
			configWithoutIgnoringFolders
		).then((results) => {
			assert.equal(results[0].name, 'SomethingStrange');
			assert.equal(results[0].path, path.join(workspacePath, 'vendor/example.com/vendorpls/lib.go'));
		});
		const withIgnoringFolders = getWorkspaceSymbols(
			workspacePath,
			'SomethingStr',
			dummyCancellationSource.token,
			configWithIgnoringFolders
		).then((results) => {
			assert.equal(results.length, 0);
		});
		const withoutIncludingGoroot = getWorkspaceSymbols(
			workspacePath,
			'Mutex',
			dummyCancellationSource.token,
			configWithoutIncludeGoroot
		).then((results) => {
			assert.equal(results.length, 0);
		});
		const withIncludingGoroot = getWorkspaceSymbols(
			workspacePath,
			'Mutex',
			dummyCancellationSource.token,
			configWithIncludeGoroot
		).then((results) => {
			assert(results.some((result) => result.name === 'Mutex'));
		});

		return Promise.all([withIgnoringFolders, withoutIgnoringFolders, withIncludingGoroot, withoutIncludingGoroot]);
	});

	test('Test Completion', async () => {
		const printlnDoc = `Println formats using the default formats for its operands and writes to
standard output. Spaces are always added between operands and a newline is
appended. It returns the number of bytes written and any write error
encountered.
`;
		const provider = new GoCompletionItemProvider();
		const testCases: [vscode.Position, string, string | null, string | null][] = [
			[new vscode.Position(7, 4), 'fmt', 'fmt', null],
			[new vscode.Position(7, 6), 'Println', 'func(a ...interface{}) (n int, err error)', printlnDoc]
		];
		const uri = vscode.Uri.file(path.join(fixturePath, 'baseTest', 'test.go'));
		const textDocument = await vscode.workspace.openTextDocument(uri);
		const editor = await vscode.window.showTextDocument(textDocument);

		const promises = testCases.map(([position, expectedLabel, expectedDetail, expectedDoc]) =>
			provider
				.provideCompletionItems(editor.document, position, dummyCancellationSource.token)
				.then(async (items) => {
					const item = items.items.find((x) => x.label === expectedLabel);
					if (!item) {
						assert.fail('missing expected item in completion list');
					}
					assert.equal(item.detail, expectedDetail);
					const resolvedItemResult: vscode.ProviderResult<vscode.CompletionItem> = provider.resolveCompletionItem(
						item,
						dummyCancellationSource.token
					);
					if (!resolvedItemResult) {
						return;
					}
					if (resolvedItemResult instanceof vscode.CompletionItem) {
						if (resolvedItemResult.documentation) {
							assert.equal((<vscode.MarkdownString>resolvedItemResult.documentation).value, expectedDoc);
						}
						return;
					}
					const resolvedItem = await resolvedItemResult;
					if (resolvedItem) {
						assert.equal((<vscode.MarkdownString>resolvedItem.documentation).value, expectedDoc);
					}
				})
		);
		await Promise.all(promises);
	});

	test('Test Completion Snippets For Functions', async () => {
		const provider = new GoCompletionItemProvider();
		const uri = vscode.Uri.file(path.join(fixturePath, 'completions', 'snippets.go'));
		const baseConfig = vscode.workspace.getConfiguration('go');
		const textDocument = await vscode.workspace.openTextDocument(uri);
		const editor = await vscode.window.showTextDocument(textDocument);

		const noFunctionSnippet = provider
			.provideCompletionItemsInternal(
				editor.document,
				new vscode.Position(9, 6),
				dummyCancellationSource.token,
				Object.create(baseConfig, {
					useCodeSnippetsOnFunctionSuggest: { value: false }
				})
			)
			.then((items) => {
				items = items instanceof vscode.CompletionList ? items.items : items;
				const item = items.find((x) => x.label === 'Print');
				if (!item) {
					assert.fail('Suggestion with label "Print" not found in test case noFunctionSnippet.');
				}
				assert.equal(!item.insertText, true);
			});
		const withFunctionSnippet = provider
			.provideCompletionItemsInternal(
				editor.document,
				new vscode.Position(9, 6),
				dummyCancellationSource.token,
				Object.create(baseConfig, {
					useCodeSnippetsOnFunctionSuggest: { value: true }
				})
			)
			.then((items1) => {
				items1 = items1 instanceof vscode.CompletionList ? items1.items : items1;
				const item1 = items1.find((x) => x.label === 'Print');
				if (!item1) {
					assert.fail('Suggestion with label "Print" not found in test case withFunctionSnippet.');
				}
				assert.equal((<vscode.SnippetString>item1.insertText).value, 'Print(${1:a ...interface{\\}})');
			});
		const withFunctionSnippetNotype = provider
			.provideCompletionItemsInternal(
				editor.document,
				new vscode.Position(9, 6),
				dummyCancellationSource.token,
				Object.create(baseConfig, {
					useCodeSnippetsOnFunctionSuggestWithoutType: { value: true }
				})
			)
			.then((items2) => {
				items2 = items2 instanceof vscode.CompletionList ? items2.items : items2;
				const item2 = items2.find((x) => x.label === 'Print');
				if (!item2) {
					assert.fail('Suggestion with label "Print" not found in test case withFunctionSnippetNotype.');
				}
				assert.equal((<vscode.SnippetString>item2.insertText).value, 'Print(${1:a})');
			});
		const noFunctionAsVarSnippet = provider
			.provideCompletionItemsInternal(
				editor.document,
				new vscode.Position(11, 3),
				dummyCancellationSource.token,
				Object.create(baseConfig, {
					useCodeSnippetsOnFunctionSuggest: { value: false }
				})
			)
			.then((items3) => {
				items3 = items3 instanceof vscode.CompletionList ? items3.items : items3;
				const item3 = items3.find((x) => x.label === 'funcAsVariable');
				if (!item3) {
					assert.fail('Suggestion with label "Print" not found in test case noFunctionAsVarSnippet.');
				}
				assert.equal(!item3.insertText, true);
			});
		const withFunctionAsVarSnippet = provider
			.provideCompletionItemsInternal(
				editor.document,
				new vscode.Position(11, 3),
				dummyCancellationSource.token,
				Object.create(baseConfig, {
					useCodeSnippetsOnFunctionSuggest: { value: true }
				})
			)
			.then((items4) => {
				items4 = items4 instanceof vscode.CompletionList ? items4.items : items4;
				const item4 = items4.find((x) => x.label === 'funcAsVariable');
				if (!item4) {
					assert.fail('Suggestion with label "Print" not found in test case withFunctionAsVarSnippet.');
				}
				assert.equal((<vscode.SnippetString>item4.insertText).value, 'funcAsVariable(${1:k string})');
			});
		const withFunctionAsVarSnippetNoType = provider
			.provideCompletionItemsInternal(
				editor.document,
				new vscode.Position(11, 3),
				dummyCancellationSource.token,
				Object.create(baseConfig, {
					useCodeSnippetsOnFunctionSuggestWithoutType: { value: true }
				})
			)
			.then((items5) => {
				items5 = items5 instanceof vscode.CompletionList ? items5.items : items5;
				const item5 = items5.find((x) => x.label === 'funcAsVariable');
				if (!item5) {
					assert.fail('Suggestion with label "Print" not found in test case withFunctionAsVarSnippetNoType.');
				}
				assert.equal((<vscode.SnippetString>item5.insertText).value, 'funcAsVariable(${1:k})');
			});
		const noFunctionAsTypeSnippet = provider
			.provideCompletionItemsInternal(
				editor.document,
				new vscode.Position(14, 0),
				dummyCancellationSource.token,
				Object.create(baseConfig, {
					useCodeSnippetsOnFunctionSuggest: { value: false }
				})
			)
			.then((items6) => {
				items6 = items6 instanceof vscode.CompletionList ? items6.items : items6;
				const item1 = items6.find((x) => x.label === 'HandlerFunc');
				const item2 = items6.find((x) => x.label === 'HandlerFuncWithArgNames');
				const item3 = items6.find((x) => x.label === 'HandlerFuncNoReturnType');
				if (!item1) {
					assert.fail('Suggestion with label "HandlerFunc" not found in test case noFunctionAsTypeSnippet.');
				}
				assert.equal(!item1.insertText, true);
				if (!item2) {
					assert.fail(
						'Suggestion with label "HandlerFuncWithArgNames" not found in test case noFunctionAsTypeSnippet.'
					);
				}
				assert.equal(!item2.insertText, true);
				if (!item3) {
					assert.fail(
						'Suggestion with label "HandlerFuncNoReturnType" not found in test case noFunctionAsTypeSnippet.'
					);
				}
				assert.equal(!item3.insertText, true);
			});
		const withFunctionAsTypeSnippet = provider
			.provideCompletionItemsInternal(
				editor.document,
				new vscode.Position(14, 0),
				dummyCancellationSource.token,
				Object.create(baseConfig, {
					useCodeSnippetsOnFunctionSuggest: { value: true }
				})
			)
			.then((items7) => {
				items7 = items7 instanceof vscode.CompletionList ? items7.items : items7;
				const item11 = items7.find((x) => x.label === 'HandlerFunc');
				const item21 = items7.find((x) => x.label === 'HandlerFuncWithArgNames');
				const item31 = items7.find((x) => x.label === 'HandlerFuncNoReturnType');
				if (!item11) {
					assert.fail(
						'Suggestion with label "HandlerFunc" not found in test case withFunctionAsTypeSnippet.'
					);
				}
				assert.equal(
					(<vscode.SnippetString>item11.insertText).value,
					'HandlerFunc(func(${1:arg1} string, ${2:arg2} string) {\n\t$3\n}) (string, string)'
				);
				if (!item21) {
					assert.fail(
						'Suggestion with label "HandlerFuncWithArgNames" not found in test case withFunctionAsTypeSnippet.'
					);
				}
				assert.equal(
					(<vscode.SnippetString>item21.insertText).value,
					'HandlerFuncWithArgNames(func(${1:w} string, ${2:r} string) {\n\t$3\n}) int'
				);
				if (!item31) {
					assert.fail(
						'Suggestion with label "HandlerFuncNoReturnType" not found in test case withFunctionAsTypeSnippet.'
					);
				}
				assert.equal(
					(<vscode.SnippetString>item31.insertText).value,
					'HandlerFuncNoReturnType(func(${1:arg1} string, ${2:arg2} string) {\n\t$3\n})'
				);
			});
		await Promise.all([
			noFunctionSnippet,
			withFunctionSnippet,
			withFunctionSnippetNotype,
			noFunctionAsVarSnippet,
			withFunctionAsVarSnippet,
			withFunctionAsVarSnippetNoType,
			noFunctionAsTypeSnippet,
			withFunctionAsTypeSnippet
		]);
	});

	test('Test No Completion Snippets For Functions', async () => {
		const provider = new GoCompletionItemProvider();
		const uri = vscode.Uri.file(path.join(fixturePath, 'completions', 'nosnippets.go'));
		const baseConfig = vscode.workspace.getConfiguration('go');
		const textDocument = await vscode.workspace.openTextDocument(uri);
		const editor = await vscode.window.showTextDocument(textDocument);

		const symbolFollowedByBrackets = provider
			.provideCompletionItemsInternal(
				editor.document,
				new vscode.Position(5, 10),
				dummyCancellationSource.token,
				Object.create(baseConfig, {
					useCodeSnippetsOnFunctionSuggest: { value: true }
				})
			)
			.then((items) => {
				items = items instanceof vscode.CompletionList ? items.items : items;
				const item = items.find((x) => x.label === 'Print');
				if (!item) {
					assert.fail('Suggestion with label "Print" not found in test case symbolFollowedByBrackets.');
				}
				assert.equal(!item.insertText, true, 'Unexpected snippet when symbol is followed by ().');
			});
		const symbolAsLastParameter = provider
			.provideCompletionItemsInternal(
				editor.document,
				new vscode.Position(7, 13),
				dummyCancellationSource.token,
				Object.create(baseConfig, {
					useCodeSnippetsOnFunctionSuggest: { value: true }
				})
			)
			.then((items1) => {
				items1 = items1 instanceof vscode.CompletionList ? items1.items : items1;
				const item1 = items1.find((x) => x.label === 'funcAsVariable');
				if (!item1) {
					assert.fail('Suggestion with label "funcAsVariable" not found in test case symbolAsLastParameter.');
				}
				assert.equal(!item1.insertText, true, 'Unexpected snippet when symbol is a parameter inside func call');
			});
		const symbolsAsNonLastParameter = provider
			.provideCompletionItemsInternal(
				editor.document,
				new vscode.Position(8, 11),
				dummyCancellationSource.token,
				Object.create(baseConfig, {
					useCodeSnippetsOnFunctionSuggest: { value: true }
				})
			)
			.then((items2) => {
				items2 = items2 instanceof vscode.CompletionList ? items2.items : items2;
				const item2 = items2.find((x) => x.label === 'funcAsVariable');
				if (!item2) {
					assert.fail(
						'Suggestion with label "funcAsVariable" not found in test case symbolsAsNonLastParameter.'
					);
				}
				assert.equal(
					!item2.insertText,
					true,
					'Unexpected snippet when symbol is one of the parameters inside func call.'
				);
			});
		await Promise.all([symbolFollowedByBrackets, symbolAsLastParameter, symbolsAsNonLastParameter]);
	});

	test('Test Completion on unimported packages', async () => {
		const config = Object.create(vscode.workspace.getConfiguration('go'), {
			autocompleteUnimportedPackages: { value: true }
		});
		const provider = new GoCompletionItemProvider();
		const testCases: [vscode.Position, string[]][] = [
			[new vscode.Position(10, 3), ['bytes']],
			[new vscode.Position(11, 6), ['Abs', 'Acos', 'Asin']]
		];
		const uri = vscode.Uri.file(path.join(fixturePath, 'completions', 'unimportedPkgs.go'));
		const textDocument = await vscode.workspace.openTextDocument(uri);
		const editor = await vscode.window.showTextDocument(textDocument);

		const promises = testCases.map(([position, expected]) =>
			provider
				.provideCompletionItemsInternal(editor.document, position, dummyCancellationSource.token, config)
				.then((items) => {
					items = items instanceof vscode.CompletionList ? items.items : items;
					const labels = items.map((x) => x.label);
					for (const entry of expected) {
						assert.equal(
							labels.indexOf(entry) > -1,
							true,
							`missing expected item in completion list: ${entry} Actual: ${labels}`
						);
					}
				})
		);
		await Promise.all(promises);
	});

	test('Test Completion on unimported packages (multiple)', async () => {
		const config = Object.create(vscode.workspace.getConfiguration('go'), {
			gocodeFlags: { value: ['-builtin'] }
		});
		const provider = new GoCompletionItemProvider();
		const position = new vscode.Position(3, 14);
		const expectedItems = [
			{
				label: 'template (html/template)',
				import: '\nimport (\n\t"html/template"\n)\n'
			},
			{
				label: 'template (text/template)',
				import: '\nimport (\n\t"text/template"\n)\n'
			}
		];
		const uri = vscode.Uri.file(path.join(fixturePath, 'completions', 'unimportedMultiplePkgs.go'));
		const textDocument = await vscode.workspace.openTextDocument(uri);
		const editor = await vscode.window.showTextDocument(textDocument);

		const completionResult = await provider.provideCompletionItemsInternal(
			editor.document,
			position,
			dummyCancellationSource.token,
			config
		);
		const items = completionResult instanceof vscode.CompletionList ? completionResult.items : completionResult;
		const labels = items.map((x) => x.label);
		expectedItems.forEach((expectedItem) => {
			const actualItem: vscode.CompletionItem = items.filter((item) => item.label === expectedItem.label)[0];
			if (!actualItem) {
				assert.fail(
					actualItem,
					expectedItem,
					`Missing expected item in completion list: ${expectedItem.label} Actual: ${labels}`
				);
			}
			if (!actualItem.additionalTextEdits) {
				assert.fail(`Missing additionalTextEdits on suggestion for ${actualItem}`);
			}
			assert.equal(actualItem.additionalTextEdits.length, 1);
			assert.equal(actualItem.additionalTextEdits[0].newText, expectedItem.import);
		});
	});

	test('Test Completion on Comments for Exported Members', async () => {
		const provider = new GoCompletionItemProvider();
		const testCases: [vscode.Position, string[]][] = [
			[new vscode.Position(6, 4), ['Language']],
			[new vscode.Position(9, 4), ['GreetingText']],
			// checking for comment completions with begining of comment without space
			[new vscode.Position(12, 2), []],
			// cursor between /$/ this should not trigger any completion
			[new vscode.Position(12, 1), []],
			[new vscode.Position(12, 4), ['SayHello']],
			[new vscode.Position(17, 5), ['HelloParams']],
			[new vscode.Position(26, 5), ['Abs']]
		];
		const uri = vscode.Uri.file(path.join(fixturePath, 'completions', 'exportedMemberDocs.go'));

		const textDocument = await vscode.workspace.openTextDocument(uri);
		const editor = await vscode.window.showTextDocument(textDocument);

		const promises = testCases.map(([position, expected]) =>
			provider.provideCompletionItems(editor.document, position, dummyCancellationSource.token).then((items) => {
				const labels = items.items.map((x) => x.label);
				assert.equal(
					expected.length,
					labels.length,
					`expected number of completions: ${expected.length} Actual: ${labels.length} at position(${position.line + 1
					},${position.character + 1}) ${labels}`
				);
				expected.forEach((entry, index) => {
					assert.equal(
						entry,
						labels[index],
						`mismatch in comment completion list Expected: ${entry} Actual: ${labels[index]}`
					);
				});
			})
		);
		await Promise.all(promises);
	});

	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(vscode.workspace.getConfiguration('go'), {
			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(vscode.workspace.getConfiguration('go'), {
			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(vscode.workspace.getConfiguration('go'), {
			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 = 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(vscode.workspace.getConfiguration('go'), {
			vetOnSave: { value: 'off' },
			lintOnSave: { value: 'off' },
			buildOnSave: { value: 'package' },
			testTags: { value: null },
			buildTags: { value: 'randomtag' }
		});

		const config2 = Object.create(vscode.workspace.getConfiguration('go'), {
			vetOnSave: { value: 'off' },
			lintOnSave: { value: 'off' },
			buildOnSave: { value: 'package' },
			testTags: { value: 'randomtag' }
		});

		const config3 = Object.create(vscode.workspace.getConfiguration('go'), {
			vetOnSave: { value: 'off' },
			lintOnSave: { value: 'off' },
			buildOnSave: { value: 'package' },
			testTags: { value: 'randomtag othertag' }
		});

		const config4 = Object.create(vscode.workspace.getConfiguration('go'), {
			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 result1 = await testCurrentFile(config1, false, []);
		assert.equal(result1, true);

		const result2 = await testCurrentFile(config2, false, []);
		assert.equal(result2, true);

		const result3 = await testCurrentFile(config3, false, []);
		assert.equal(result3, true);

		const result4 = await testCurrentFile(config4, false, []);
		assert.equal(result4, false);
	});

	function fixEOL(eol: vscode.EndOfLine, strWithLF: string): string {
		if (eol === vscode.EndOfLine.LF) {
			return strWithLF;
		}
		return strWithLF.split('\n').join('\r\n');  // replaceAll.
	}

	test('Add imports when no imports', async () => {
		const uri = vscode.Uri.file(path.join(fixturePath, 'importTest', 'noimports.go'));
		const document = await vscode.workspace.openTextDocument(uri);
		await vscode.window.showTextDocument(document);

		const expectedText = document.getText() + fixEOL(document.eol, '\n' + 'import (\n\t"bytes"\n)\n');
		const edits = getTextEditForAddImport('bytes');
		const edit = new vscode.WorkspaceEdit();
		edit.set(document.uri, edits);
		return vscode.workspace.applyEdit(edit).then(() => {
			assert.equal(
				vscode.window.activeTextEditor && vscode.window.activeTextEditor.document.getText(),
				expectedText
			);
			return Promise.resolve();
		});
	});

	test('Add imports to an import block', async () => {
		const uri = vscode.Uri.file(path.join(fixturePath, 'importTest', 'groupImports.go'));
		const document = await vscode.workspace.openTextDocument(uri);
		await vscode.window.showTextDocument(document);
		const eol = document.eol;

		const expectedText = document.getText().replace(
			fixEOL(eol, '\t"fmt"\n\t"math"'),
			fixEOL(eol, '\t"bytes"\n\t"fmt"\n\t"math"'));
		const edits = getTextEditForAddImport('bytes');
		const edit = new vscode.WorkspaceEdit();
		edit.set(document.uri, edits);
		await vscode.workspace.applyEdit(edit);
		assert.equal(vscode.window.activeTextEditor && vscode.window.activeTextEditor.document.getText(), expectedText);
	});

	test('Add imports and collapse single imports to an import block', async () => {
		const uri = vscode.Uri.file(path.join(fixturePath, 'importTest', 'singleImports.go'));
		const document = await vscode.workspace.openTextDocument(uri);
		await vscode.window.showTextDocument(document);
		const eol = document.eol;

		const expectedText = document
			.getText()
			.replace(
				fixEOL(eol, 'import "fmt"\nimport . "math" // comment'),
				fixEOL(eol, 'import (\n\t"bytes"\n\t"fmt"\n\t. "math" // comment\n)')
			);
		const edits = getTextEditForAddImport('bytes');
		const edit = new vscode.WorkspaceEdit();
		edit.set(document.uri, edits);
		await vscode.workspace.applyEdit(edit);
		assert.equal(vscode.window.activeTextEditor && vscode.window.activeTextEditor.document.getText(), expectedText);
	});

	test('Add imports and avoid pseudo package imports for cgo', async () => {
		const uri = vscode.Uri.file(path.join(fixturePath, 'importTest', 'cgoImports.go'));
		const document = await vscode.workspace.openTextDocument(uri);
		await vscode.window.showTextDocument(document);
		const eol = document.eol;

		const expectedText = document
			.getText()
			.replace(
				fixEOL(eol, 'import "math"'),
				fixEOL(eol, 'import (\n\t"bytes"\n\t"math"\n)')
			);
		const edits = getTextEditForAddImport('bytes');
		const edit = new vscode.WorkspaceEdit();
		edit.set(document.uri, edits);
		await vscode.workspace.applyEdit(edit);
		assert.equal(vscode.window.activeTextEditor && vscode.window.activeTextEditor.document.getText(), expectedText);
	});

	test('Fill struct', async () => {
		const uri = vscode.Uri.file(path.join(fixturePath, 'fillStruct', 'input_1.go'));
		const golden = fs.readFileSync(path.join(fixturePath, 'fillStruct', 'golden_1.go'), 'utf-8');

		const textDocument = await vscode.workspace.openTextDocument(uri);
		await vscode.window.showTextDocument(textDocument);

		const editor = await vscode.window.showTextDocument(textDocument);
		const selection = new vscode.Selection(12, 15, 12, 15);
		editor.selection = selection;
		await runFillStruct(editor);
		assert.equal(vscode.window.activeTextEditor && vscode.window.activeTextEditor.document.getText(), golden);
	});

	test('Fill struct - select line', async () => {
		const uri = vscode.Uri.file(path.join(fixturePath, 'fillStruct', 'input_2.go'));
		const golden = fs.readFileSync(path.join(fixturePath, 'fillStruct', 'golden_2.go'), 'utf-8');

		const textDocument = await vscode.workspace.openTextDocument(uri);
		const editor = await vscode.window.showTextDocument(textDocument);

		const selection = new vscode.Selection(7, 0, 7, 10);
		editor.selection = selection;
		await runFillStruct(editor);
		assert.equal(vscode.window.activeTextEditor && vscode.window.activeTextEditor.document.getText(), golden);
	});
});
