/* 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
	public replace = 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());
	};
}
