/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable node/no-unsupported-features/node-builtins */
/* eslint-disable no-async-promise-executor */
/* eslint-disable node/no-unpublished-import */
import assert from 'assert';
import * as cp from 'child_process';
import * as fs from 'fs';
import * as readline from 'readline';
import * as http from 'http';
import { tmpdir } from 'os';
import * as net from 'net';
import * as path from 'path';
import * as sinon from 'sinon';
import * as proxy from '../../src/goDebugFactory';
import * as vscode from 'vscode';
import { DebugConfiguration, DebugProtocolMessage } from 'vscode';
import { DebugClient } from 'vscode-debugadapter-testsupport';
import { ILocation } from 'vscode-debugadapter-testsupport/lib/debugClient';
import { DebugProtocol } from 'vscode-debugprotocol';
import {
	Delve,
	escapeGoModPath,
	GoDebugSession,
	PackageBuildInfo,
	RemoteSourcesAndPackages
} from '../../src/debugAdapter/goDebug';
import * as extConfig from '../../src/config';
import { GoDebugConfigurationProvider, parseDebugProgramArgSync } from '../../src/goDebugConfiguration';
import { getBinPath, rmdirRecursive } from '../../src/util';
import { killProcessTree, killProcess } from '../../src/utils/processUtils';
import getPort = require('get-port');
import util = require('util');
import { TimestampedLogger } from '../../src/goLogging';

// For debugging test and streaming the trace instead of buffering, set this.
const PRINT_TO_CONSOLE = false;

suite('Path Manipulation Tests', () => {
	test('escapeGoModPath works', () => {
		assert.strictEqual(escapeGoModPath('BurnSushi/test.go'), '!burn!sushi/test.go');
	});
});

suite('GoDebugSession Tests', async () => {
	const workspaceFolder = '/usr/workspacefolder';
	const delve: Delve = {} as Delve;
	let goDebugSession: GoDebugSession;
	let remoteSourcesAndPackages: RemoteSourcesAndPackages;
	let fileSystem: typeof fs;

	let previousEnv: any;

	setup(() => {
		previousEnv = Object.assign({}, process.env);

		process.env.GOPATH = '/usr/gopath';
		process.env.GOROOT = '/usr/goroot';
		remoteSourcesAndPackages = new RemoteSourcesAndPackages();
		// eslint-disable-next-line prettier/prettier
		fileSystem = ({ existsSync: () => false } as unknown) as typeof fs;
		delve.program = workspaceFolder;
		delve.isApiV1 = false;
		goDebugSession = new GoDebugSession(true, false, fileSystem);
		goDebugSession['delve'] = delve;
		goDebugSession['remoteSourcesAndPackages'] = remoteSourcesAndPackages;
	});

	teardown(() => {
		process.env = previousEnv;
		sinon.restore();
	});

	test('inferRemotePathFromLocalPath works', () => {
		const sourceFileMapping = new Map<string, string[]>();
		sourceFileMapping.set('main.go', ['/app/hello-world/main.go', '/app/main.go']);
		sourceFileMapping.set('blah.go', ['/app/blah.go']);

		remoteSourcesAndPackages.remoteSourceFilesNameGrouping = sourceFileMapping;

		const inferredPath = goDebugSession['inferRemotePathFromLocalPath'](
			'C:\\Users\\Documents\\src\\hello-world\\main.go'
		);
		assert.strictEqual(inferredPath, '/app/hello-world/main.go');
	});

	test('inferRemotePathFromLocalPath does not crash due to non-existing files', () => {
		const sourceFileMapping = new Map<string, string[]>();
		sourceFileMapping.set('main.go', ['/app/hello-world/main.go', '/app/main.go']);

		remoteSourcesAndPackages.remoteSourceFilesNameGrouping = sourceFileMapping;

		// Non-existing file.
		const inferredPath = goDebugSession['inferRemotePathFromLocalPath'](
			'C:\\Users\\Documents\\src\\hello-world\\main-copy.go'
		);
		assert.strictEqual(inferredPath, undefined);
	});

	test('inferLocalPathFromRemoteGoPackage works for package in workspaceFolder', () => {
		const remotePath = '/src/hello-world/morestrings/morestrings.go';
		const helloPackage: PackageBuildInfo = {
			ImportPath: 'hello-world/morestrings',
			DirectoryPath: '/src/hello-world/morestrings',
			Files: ['/src/hello-world/morestrings/lessstrings.go', '/src/hello-world/morestrings/morestrings.go']
		};

		const testPackage: PackageBuildInfo = {
			ImportPath: 'FooBar/test',
			DirectoryPath: 'remote/pkg/mod/!foo!bar/test@v1.0.2',
			Files: ['remote/pkg/mod/!foo!bar/test@v1.0.2/test.go']
		};

		const localPath = path.join(workspaceFolder, 'hello-world/morestrings/morestrings.go');
		const existsSyncStub = sinon.stub(fileSystem, 'existsSync');
		existsSyncStub.withArgs(localPath).returns(true);

		remoteSourcesAndPackages.remotePackagesBuildInfo = [helloPackage, testPackage];

		goDebugSession['localPathSeparator'] = '/';
		const inferredLocalPath = goDebugSession['inferLocalPathFromRemoteGoPackage'](remotePath);
		assert.strictEqual(inferredLocalPath, localPath);
	});

	test('inferLocalPathFromRemoteGoPackage works for package in GOPATH/pkg/mod', () => {
		const remotePath = 'remote/pkg/mod/!foo!bar/test@v1.0.2/test.go';
		const helloPackage: PackageBuildInfo = {
			ImportPath: 'hello-world',
			DirectoryPath: '/src/hello-world',
			Files: ['src/hello-world/hello.go', 'src/hello-world/world.go']
		};

		const testPackage: PackageBuildInfo = {
			ImportPath: 'FooBar/test',
			DirectoryPath: 'remote/pkg/mod/!foo!bar/test@v1.0.2',
			Files: ['remote/pkg/mod/!foo!bar/test@v1.0.2/test.go']
		};

		const localPath = path.join(process.env.GOPATH ?? '', 'pkg/mod/!foo!bar/test@v1.0.2/test.go');
		const existsSyncStub = sinon.stub(fileSystem, 'existsSync');
		existsSyncStub.withArgs(localPath).returns(true);

		remoteSourcesAndPackages.remotePackagesBuildInfo = [helloPackage, testPackage];

		goDebugSession['localPathSeparator'] = '/';
		const inferredLocalPath = goDebugSession['inferLocalPathFromRemoteGoPackage'](remotePath);
		assert.strictEqual(inferredLocalPath, localPath);
	});

	test('inferLocalPathFromRemoteGoPackage works for package in GOPATH/pkg/mod with relative path', () => {
		const remotePath = '!foo!bar/test@v1.0.2/test.go';
		const helloPackage: PackageBuildInfo = {
			ImportPath: 'hello-world',
			DirectoryPath: '/src/hello-world',
			Files: ['src/hello-world/hello.go', 'src/hello-world/world.go']
		};

		const testPackage: PackageBuildInfo = {
			ImportPath: 'FooBar/test',
			DirectoryPath: '!foo!bar/test@v1.0.2',
			Files: ['!foo!bar/test@v1.0.2/test.go']
		};

		const localPath = path.join(process.env.GOPATH ?? '', 'pkg/mod/!foo!bar/test@v1.0.2/test.go');
		const existsSyncStub = sinon.stub(fileSystem, 'existsSync');
		existsSyncStub.withArgs(localPath).returns(true);

		remoteSourcesAndPackages.remotePackagesBuildInfo = [helloPackage, testPackage];

		goDebugSession['localPathSeparator'] = '/';
		const inferredLocalPath = goDebugSession['inferLocalPathFromRemoteGoPackage'](remotePath);
		assert.strictEqual(inferredLocalPath, localPath);
	});

	test('inferLocalPathFromRemoteGoPackage works for package in GOPATH/src', () => {
		const remotePath = 'remote/gopath/src/foobar/test@v1.0.2-abcde-34/test.go';
		const helloPackage: PackageBuildInfo = {
			ImportPath: 'hello-world',
			DirectoryPath: '/src/hello-world',
			Files: ['src/hello-world/hello.go', 'src/hello-world/world.go']
		};

		const testPackage: PackageBuildInfo = {
			ImportPath: 'foobar/test',
			DirectoryPath: 'remote/gopath/src/foobar/test@v1.0.2-abcde-34',
			Files: ['remote/gopath/src/foobar/test@v1.0.2-abcde-34/test.go']
		};

		const localPath = path.join(process.env.GOPATH ?? '', 'src', 'foobar/test@v1.0.2-abcde-34/test.go');
		const existsSyncStub = sinon.stub(fileSystem, 'existsSync');
		existsSyncStub.withArgs(localPath).returns(true);

		remoteSourcesAndPackages.remotePackagesBuildInfo = [helloPackage, testPackage];

		goDebugSession['localPathSeparator'] = '/';
		const inferredLocalPath = goDebugSession['inferLocalPathFromRemoteGoPackage'](remotePath);
		assert.strictEqual(inferredLocalPath, localPath);
	});

	test('inferLocalPathFromRemoteGoPackage works for package in GOPATH/src with relative path', () => {
		const remotePath = 'foobar/test@v1.0.2/test.go';
		const helloPackage: PackageBuildInfo = {
			ImportPath: 'hello-world',
			DirectoryPath: '/src/hello-world',
			Files: ['src/hello-world/hello.go', 'src/hello-world/world.go']
		};

		const testPackage: PackageBuildInfo = {
			ImportPath: 'foobar/test',
			DirectoryPath: 'foobar/test@v1.0.2',
			Files: ['foobar/test@v1.0.2/test.go']
		};

		const localPath = path.join(process.env.GOPATH ?? '', 'src', 'foobar/test@v1.0.2/test.go');
		const existsSyncStub = sinon.stub(fileSystem, 'existsSync');
		existsSyncStub.withArgs(localPath).returns(true);

		remoteSourcesAndPackages.remotePackagesBuildInfo = [helloPackage, testPackage];

		goDebugSession['localPathSeparator'] = '/';
		const inferredLocalPath = goDebugSession['inferLocalPathFromRemoteGoPackage'](remotePath);
		assert.strictEqual(inferredLocalPath, localPath);
	});

	test('inferLocalPathFromRemoteGoPackage works for package in GOROOT/src', () => {
		const remotePath = 'remote/goroot/src/foobar/test@v1.0.2/test.go';
		const helloPackage: PackageBuildInfo = {
			ImportPath: 'hello-world',
			DirectoryPath: '/src/hello-world',
			Files: ['src/hello-world/hello.go', 'src/hello-world/world.go']
		};

		const testPackage: PackageBuildInfo = {
			ImportPath: 'foobar/test',
			DirectoryPath: 'remote/goroot/src/foobar/test@v1.0.2',
			Files: ['remote/goroot/src/foobar/test@v1.0.2/test.go']
		};

		const localPath = path.join(process.env.GOROOT ?? '', 'src', 'foobar/test@v1.0.2/test.go');
		const existsSyncStub = sinon.stub(fileSystem, 'existsSync');
		existsSyncStub.withArgs(localPath).returns(true);

		remoteSourcesAndPackages.remotePackagesBuildInfo = [helloPackage, testPackage];

		goDebugSession['localPathSeparator'] = '/';
		const inferredLocalPath = goDebugSession['inferLocalPathFromRemoteGoPackage'](remotePath);
		assert.strictEqual(inferredLocalPath, localPath);
	});

	test('inferLocalPathFromRemoteGoPackage works for package in GOROOT/src with relative path', () => {
		const remotePath = 'foobar/test@v1.0.2/test.go';
		const helloPackage: PackageBuildInfo = {
			ImportPath: 'hello-world',
			DirectoryPath: '/src/hello-world',
			Files: ['src/hello-world/hello.go', 'src/hello-world/world.go']
		};

		const testPackage: PackageBuildInfo = {
			ImportPath: 'foobar/test',
			DirectoryPath: 'foobar/test@v1.0.2',
			Files: ['foobar/test@v1.0.2/test.go']
		};

		const localPath = path.join(process.env.GOROOT ?? '', 'src', 'foobar/test@v1.0.2/test.go');
		const existsSyncStub = sinon.stub(fileSystem, 'existsSync');
		existsSyncStub.withArgs(localPath).returns(true);

		remoteSourcesAndPackages.remotePackagesBuildInfo = [helloPackage, testPackage];

		goDebugSession['localPathSeparator'] = '/';
		const inferredLocalPath = goDebugSession['inferLocalPathFromRemoteGoPackage'](remotePath);
		assert.strictEqual(inferredLocalPath, localPath);
	});
});

suite('RemoteSourcesAndPackages Tests', () => {
	const helloPackage: PackageBuildInfo = {
		ImportPath: 'hello-world',
		DirectoryPath: '/src/hello-world',
		Files: ['src/hello-world/hello.go', 'src/hello-world/world.go']
	};
	const testPackage: PackageBuildInfo = {
		ImportPath: 'test',
		DirectoryPath: '/src/test',
		Files: ['src/test/test.go']
	};
	const sources = ['src/hello-world/hello.go', 'src/hello-world/world.go', 'src/test/test.go'];
	let remoteSourcesAndPackages: RemoteSourcesAndPackages;
	let delve: Delve;
	setup(() => {
		// eslint-disable-next-line prettier/prettier
		delve = ({ callPromise: () => ({}), isApiV1: false } as unknown) as Delve;
		remoteSourcesAndPackages = new RemoteSourcesAndPackages();
	});

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

	test('initializeRemotePackagesAndSources retrieves remote packages and sources', async () => {
		const stub = sinon.stub(delve, 'callPromise');
		stub.withArgs('ListPackagesBuildInfo', [{ IncludeFiles: true }]).returns(
			Promise.resolve({ List: [helloPackage, testPackage] })
		);
		stub.withArgs('ListSources', [{}]).returns(Promise.resolve({ Sources: sources }));

		await remoteSourcesAndPackages.initializeRemotePackagesAndSources(delve);
		assert.deepEqual(remoteSourcesAndPackages.remoteSourceFiles, sources);
		assert.deepEqual(remoteSourcesAndPackages.remotePackagesBuildInfo, [helloPackage, testPackage]);
	});
});

// Test suite adapted from:
// https://github.com/microsoft/vscode-mock-debug/blob/master/src/tests/adapter.test.ts
const testAll = (ctx: Mocha.Context, isDlvDap: boolean, withConsole?: string) => {
	const debugConfigProvider = new GoDebugConfigurationProvider();
	const DEBUG_ADAPTER = path.join('.', 'out', 'src', 'debugAdapter', 'goDebug.js');

	const PROJECT_ROOT = path.normalize(path.join(__dirname, '..', '..', '..'));
	const DATA_ROOT = path.join(PROJECT_ROOT, 'test', 'testdata');

	const remoteAttachConfig = {
		name: 'Attach',
		type: 'go',
		request: 'attach',
		mode: 'remote', // This implies debugAdapter = legacy.
		host: '127.0.0.1',
		port: 3456
	};

	let dc: DebugClient;
	let dlvDapAdapter: DelveDAPDebugAdapterOnSocket | null;
	let dapTraced = false;

	setup(async () => {
		dapTraced = false;

		if (isDlvDap) {
			dc = new DebugClient('dlv', 'dap', 'go');
			// dc.start will be called in initializeDebugConfig call,
			// which creates a thin adapter for delve dap mode,
			// runs it on a network port, and gets wired with this dc.

			// Launching delve may take longer than the default timeout of 5000.
			dc.defaultTimeout = 20_000;
			return;
		}

		dc = new DebugClient('node', path.join(PROJECT_ROOT, DEBUG_ADAPTER), 'go', undefined, true);
		// Launching delve may take longer than the default timeout of 5000.
		dc.defaultTimeout = 20_000;
		// To connect to a running debug server for debugging the tests, specify PORT.
		await dc.start();
	});

	teardown(async () => {
		if (dlvDapAdapter) {
			const d = dlvDapAdapter;
			dlvDapAdapter = null;
			if (ctx.currentTest?.state === 'failed') {
				console.log(`${ctx.currentTest?.title} FAILED: DAP Trace`);
				d.printLog();
			}
			d.dispose();
		} else {
			if (ctx.currentTest?.state === 'failed' && dapTraced) {
				console.log(`${ctx.currentTest?.title} FAILED: Debug Adapter Trace`);
				try {
					await new Promise<void>((resolve) => {
						const rl = readline.createInterface({
							input: fs.createReadStream(path.join(tmpdir(), 'vscode-go-debug.txt')),
							crlfDelay: Infinity
						});
						rl.on('line', (line) => console.log(line));
						rl.on('close', () => resolve());
					});
				} catch (e) {
					console.log(`Failed to read trace: ${e}`);
				}
			}
			dc?.stop();
		}
		sinon.restore();
	});

	/**
	 * This function sets up a server that returns helloworld on serverPort.
	 * The server will be started as a Delve remote headless instance
	 * that will listen on the specified dlvPort.
	 * We are using a server as opposed to a long-running program
	 * because we can use responses to better test when the program is
	 * running vs stopped/killed.
	 */
	async function setUpRemoteProgram(
		dlvPort: number,
		serverPort: number,
		acceptMultiClient = true,
		continueOnStart = true
	): Promise<cp.ChildProcess> {
		const serverFolder = path.join(DATA_ROOT, 'helloWorldServer');
		const toolPath = getBinPath('dlv');
		const args = [
			'debug',
			'--check-go-version=false',
			'--api-version=2',
			'--headless',
			`--listen=127.0.0.1:${dlvPort}`
		];
		if (acceptMultiClient) {
			args.push('--accept-multiclient');
		}
		if (continueOnStart) {
			args.push('--continue');
		}
		const childProcess = cp.spawn(toolPath, args, {
			cwd: serverFolder,
			env: { PORT: `${serverPort}`, ...process.env }
		});

		// Give dlv a few seconds to start.
		await new Promise((resolve) => setTimeout(resolve, 10_000));
		return childProcess;
	}

	/**
	 * Helper function to set up remote attach configuration.
	 * This will issue an initializeRequest, followed by attachRequest.
	 * It will then wait for an initializedEvent before sending a breakpointRequest
	 * if breakpoints are provided. Lastly the configurationDoneRequest will be sent.
	 * NOTE: For simplicity, this function assumes the breakpoints are in the same file.
	 */
	async function setUpRemoteAttach(config: DebugConfiguration, breakpoints: ILocation[] = []): Promise<void> {
		const debugConfig = await initializeDebugConfig(config);
		const initializedResult = await dc.initializeRequest();
		assert.ok(initializedResult.success);

		// When the attach request is completed successfully, we should get
		// an initialized event.
		await Promise.all([
			new Promise<void>(async (resolve) => {
				console.log(`Setting up attach request for ${JSON.stringify(debugConfig)}.`);
				const attachResult = await dc.attachRequest(debugConfig as DebugProtocol.AttachRequestArguments);
				assert.ok(attachResult.success);
				resolve();
			}),
			dc.waitForEvent('initialized')
		]);

		if (breakpoints.length) {
			console.log('Sending set breakpoints request for remote attach setup.');
			const breakpointsResult = await dc.setBreakpointsRequest({
				source: { path: breakpoints[0].path },
				breakpoints
			});
			assert.ok(breakpointsResult.success && breakpointsResult.body.breakpoints.length === breakpoints.length);
			// Verify that there are no non-verified breakpoints.
			breakpointsResult.body.breakpoints.forEach((breakpoint) => {
				assert.ok(breakpoint.verified);
			});
		}
		console.log('Sending configuration done request for remote attach setup.');
		const configurationDoneResult = await dc.configurationDoneRequest();
		assert.ok(configurationDoneResult.success);
	}

	/**
	 * Helper function to retrieve a stopped event for a breakpoint.
	 * This function will keep calling action() until we receive a stoppedEvent.
	 * Will return undefined if the result of repeatedly calling action does not
	 * induce a stoppedEvent.
	 */
	async function waitForBreakpoint(action: () => void, breakpoint: ILocation): Promise<void> {
		const assertStoppedLocation = dc.assertStoppedLocation('breakpoint', breakpoint);
		await new Promise((res) => setTimeout(res, 1_000));
		action();
		await assertStoppedLocation;
	}

	/**
	 * Helper function to assert that a variable has a particular value.
	 * This should be called when the program is stopped.
	 *
	 * The following requests are issued by this function to determine the
	 * value of the variable:
	 *  1. threadsRequest
	 *  2. stackTraceRequest
	 *  3. scopesRequest
	 *  4. variablesRequest
	 */
	async function assertLocalVariableValue(name: string, val: string): Promise<void> {
		const threadsResponse = await dc.threadsRequest();
		assert(threadsResponse.success);
		const stackTraceResponse = await dc.stackTraceRequest({ threadId: threadsResponse.body.threads[0].id });
		assert(stackTraceResponse.success);
		const scopesResponse = await dc.scopesRequest({ frameId: stackTraceResponse.body.stackFrames[0].id });
		assert(scopesResponse.success);
		const localScopeIndex = scopesResponse.body.scopes.findIndex((v) => v.name === 'Local' || v.name === 'Locals');
		assert(localScopeIndex >= 0, "no scope named 'Local':");
		const variablesResponse = await dc.variablesRequest({
			variablesReference: scopesResponse.body.scopes[localScopeIndex].variablesReference
		});
		assert(variablesResponse.success);
		// Locate the variable with the matching name.
		const i = variablesResponse.body.variables.findIndex((v) => v.name === name);
		assert(i >= 0, `no variable in scope named ${name}`);
		// Check that the value of name is val.
		assert.strictEqual(variablesResponse.body.variables[i].value, val);
	}

	suite('basic', () => {
		test('unknown request should produce error', async () => {
			// fake config that will be used to initialize fixtures.
			const config = { name: 'Launch', type: 'go', request: 'launch', program: DATA_ROOT };
			await initializeDebugConfig(config);

			try {
				await dc.send('illegal_request');
			} catch {
				return;
			}
			throw new Error('does not report error on unknown request');
		});
	});

	suite('initialize', () => {
		test('should return supported features', async () => {
			const config = { name: 'Launch', type: 'go', request: 'launch', program: DATA_ROOT };
			await initializeDebugConfig(config);
			await dc.initializeRequest().then((response) => {
				response.body = response.body || {};
				assert.strictEqual(response.body.supportsConditionalBreakpoints, true);
				assert.strictEqual(response.body.supportsConfigurationDoneRequest, true);
				if (!isDlvDap) {
					// not supported in dlv-dap
					assert.strictEqual(response.body.supportsSetVariable, true);
				}
			});
		});

		test("should produce error for invalid 'pathFormat'", async () => {
			const config = { name: 'Launch', type: 'go', request: 'launch', program: DATA_ROOT };
			await initializeDebugConfig(config);
			try {
				await dc.initializeRequest({
					adapterID: 'mock',
					linesStartAt1: true,
					columnsStartAt1: true,
					pathFormat: 'url'
				});
			} catch (err) {
				return; // want error
			}
			throw new Error("does not report error on invalid 'pathFormat' attribute");
		});
	});

	suite('env', () => {
		let sandbox: sinon.SinonSandbox;

		setup(() => {
			sandbox = sinon.createSandbox();
		});
		teardown(async () => sandbox.restore());

		test('env var from go.toolsEnvVars is respected', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'envTest');
			const FILE = path.join(PROGRAM, 'main.go');
			const BREAKPOINT_LINE = 10;

			const goConfig = Object.create(vscode.workspace.getConfiguration('go'), {
				toolsEnvVars: {
					value: { FOO: 'BAR' }
				}
			});
			const configStub = sandbox.stub(extConfig, 'getGoConfig').returns(goConfig);

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				args: ['FOO']
			};
			const debugConfig = await initializeDebugConfig(config);
			await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE));
			await assertLocalVariableValue('v', '"BAR"');

			await dc.continueRequest({ threadId: 1 }); // continue until completion for cleanup.
		});

		test('env var from launch config is respected', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'envTest');
			const FILE = path.join(PROGRAM, 'main.go');
			const BREAKPOINT_LINE = 10;

			const goConfig = Object.create(vscode.workspace.getConfiguration('go'), {
				toolsEnvVars: {
					value: { FOO: 'BAR' }
				}
			});
			const configStub = sandbox.stub(extConfig, 'getGoConfig').returns(goConfig);

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				args: ['FOO'],
				env: { FOO: 'BAZ' }
			};
			const debugConfig = await initializeDebugConfig(config);
			await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE));
			await assertLocalVariableValue('v', '"BAZ"');

			await dc.continueRequest({ threadId: 1 }); // continue until completion for cleanup.
		});
	});

	suite('launch', () => {
		test('should run program to the end', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'baseTest');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM
			};
			const debugConfig = await initializeDebugConfig(config);
			await Promise.all([dc.configurationSequence(), dc.launch(debugConfig), dc.waitForEvent('terminated')]);
		});

		test('should stop on entry', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'baseTest');
			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				stopOnEntry: true
			};
			const debugConfig = await initializeDebugConfig(config);
			await Promise.all([
				dc.configurationSequence(),
				dc.launch(debugConfig),
				// The debug adapter does not support a stack trace request
				// when there are no goroutines running. Which is true when it is stopped
				// on entry. Therefore we would need another method from dc.assertStoppedLocation
				// to check the debugger is stopped on entry.
				dc.waitForEvent('stopped').then((event) => {
					const stevent = event as DebugProtocol.StoppedEvent;
					assert.strictEqual(stevent.body.reason, 'entry');
				})
			]);
		});

		test('should debug a file', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'baseTest', 'test.go');
			const config = {
				name: 'Launch file',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM
			};

			const debugConfig = await initializeDebugConfig(config);
			await Promise.all([dc.configurationSequence(), dc.launch(debugConfig), dc.waitForEvent('terminated')]);
		});

		test('should debug a single test', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'baseTest');
			const config = {
				name: 'Launch file',
				type: 'go',
				request: 'launch',
				mode: 'test',
				program: PROGRAM,
				args: ['-test.run', 'TestMe']
			};

			const debugConfig = await initializeDebugConfig(config);
			await Promise.all([dc.configurationSequence(), dc.launch(debugConfig), dc.waitForEvent('terminated')]);
		});

		test('should debug a test package', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'baseTest');
			const config = {
				name: 'Launch file',
				type: 'go',
				request: 'launch',
				mode: 'test',
				program: PROGRAM
			};

			const debugConfig = await initializeDebugConfig(config);
			await Promise.all([dc.configurationSequence(), dc.launch(debugConfig), dc.waitForEvent('terminated')]);
		});

		test('invalid flags are passed to dlv but should be caught by dlv (legacy)', async function () {
			if (isDlvDap) {
				this.skip();
			}

			const PROGRAM = path.join(DATA_ROOT, 'baseTest');
			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				dlvFlags: ['--invalid']
			};
			const debugConfig = await initializeDebugConfig(config);
			await Promise.all([
				dc.assertOutput('stderr', 'Error: unknown flag: --invalid\n', 5000),
				dc.waitForEvent('terminated'),
				dc.initializeRequest().then((response) => {
					// The current debug adapter does not respond to launch request but,
					// instead, sends error messages and TerminatedEvent as delve is closed.
					// The promise from dc.launchRequest resolves when the launch response
					// is received, so the promise will never get resolved.
					dc.launchRequest(debugConfig as any);
				})
			]);
		});

		test('invalid flags are passed to dlv but should be caught by dlv', async function () {
			if (!isDlvDap) {
				this.skip(); // not working in dlv-dap.
			}

			// TODO(hyangah): why does it take 30sec?
			const PROGRAM = path.join(DATA_ROOT, 'baseTest');
			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				dlvFlags: ['--invalid']
			};
			try {
				await initializeDebugConfig(config);
				await dc.initializeRequest();
			} catch (err) {
				return;
			}
			throw new Error('does not report error on invalid delve flag');
		});

		test('should run program with showLog=false and logOutput specified', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'baseTest');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				showLog: false,
				logOutput: 'dap'
			};
			const debugConfig = await initializeDebugConfig(config, true);
			await Promise.all([dc.configurationSequence(), dc.launch(debugConfig), dc.waitForEvent('terminated')]);
		});

		test('should handle threads request after initialization', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'baseTest');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM
			};
			const debugConfig = await initializeDebugConfig(config);
			await Promise.all([
				dc.configurationSequence().then(() => {
					dc.threadsRequest().then((response) => {
						assert.ok(response.success);
					});
				}),
				dc.launch(debugConfig),
				dc.waitForEvent('terminated')
			]);
		});

		test('should handle delayed initial threads request', async () => {
			// If the program exits very quickly, the initial threadsRequest
			// will complete after it has exited.
			const PROGRAM = path.join(DATA_ROOT, 'baseTest');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM
			};
			const debugConfig = await initializeDebugConfig(config);
			await Promise.all([dc.configurationSequence(), dc.launch(debugConfig), dc.waitForEvent('terminated')]);

			const response = await dc.threadsRequest();
			assert.ok(response.success);
		});

		test('user-specified --listen flag should be ignored', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'baseTest');
			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				dlvFlags: ['--listen=127.0.0.1:80']
			};
			const debugConfig = await initializeDebugConfig(config);

			await Promise.all([dc.configurationSequence(), dc.launch(debugConfig), dc.waitForEvent('terminated')]);
		});
	});

	suite('set current working directory', () => {
		test('should debug program with cwd set', async () => {
			const WD = path.join(DATA_ROOT, 'cwdTest');
			const PROGRAM = path.join(WD, 'cwdTest');
			const FILE = path.join(PROGRAM, 'main.go');
			const BREAKPOINT_LINE = 11;

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				cwd: WD
			};
			const debugConfig = await initializeDebugConfig(config);
			await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE));

			await assertLocalVariableValue('strdat', '"Hello, World!"');
		});

		test('should debug program without cwd set', async () => {
			const WD = path.join(DATA_ROOT, 'cwdTest');
			const PROGRAM = path.join(WD, 'cwdTest');
			const FILE = path.join(PROGRAM, 'main.go');
			const BREAKPOINT_LINE = 11;

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM
			};
			const debugConfig = await initializeDebugConfig(config);
			await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE));

			await assertLocalVariableValue('strdat', '"Goodbye, World."');
		});

		test('should debug file program with cwd set', async () => {
			const WD = path.join(DATA_ROOT, 'cwdTest');
			const PROGRAM = path.join(WD, 'cwdTest', 'main.go');
			const FILE = PROGRAM;
			const BREAKPOINT_LINE = 11;

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				cwd: WD
			};
			const debugConfig = await initializeDebugConfig(config);
			await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE));

			await assertLocalVariableValue('strdat', '"Hello, World!"');
		});

		test('should debug file program without cwd set', async () => {
			const WD = path.join(DATA_ROOT, 'cwdTest');
			const PROGRAM = path.join(WD, 'cwdTest', 'main.go');
			const FILE = PROGRAM;
			const BREAKPOINT_LINE = 11;

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM
			};
			const debugConfig = await initializeDebugConfig(config);

			await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE));

			await assertLocalVariableValue('strdat', '"Goodbye, World."');
		});

		async function waitForHelloGoodbyeOutput(dc: DebugClient): Promise<DebugProtocol.Event> {
			return await new Promise<DebugProtocol.Event>((resolve, reject) => {
				dc.on('output', (event) => {
					if (event.body.output === 'Hello, World!\n' || event.body.output === 'Goodbye, World.\n') {
						// Resolve when we have found the event that we want.
						resolve(event);
						return;
					}
				});
			});
		}

		test('should run program with cwd set (noDebug)', async () => {
			const WD = path.join(DATA_ROOT, 'cwdTest');
			const PROGRAM = path.join(WD, 'cwdTest');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				cwd: WD,
				noDebug: true
			};
			const debugConfig = await initializeDebugConfig(config);
			dc.launch(debugConfig);
			const event = await waitForHelloGoodbyeOutput(dc);
			assert.strictEqual(event.body.output, 'Hello, World!\n');
		});

		test('should run program without cwd set (noDebug)', async () => {
			const WD = path.join(DATA_ROOT, 'cwdTest');
			const PROGRAM = path.join(WD, 'cwdTest');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				noDebug: true
			};
			const debugConfig = await initializeDebugConfig(config);
			dc.launch(debugConfig);
			const event = await waitForHelloGoodbyeOutput(dc);
			assert.strictEqual(event.body.output, 'Goodbye, World.\n');
		});

		test('should run file program with cwd set (noDebug)', async () => {
			const WD = path.join(DATA_ROOT, 'cwdTest');
			const PROGRAM = path.join(WD, 'cwdTest', 'main.go');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				cwd: WD,
				noDebug: true
			};
			const debugConfig = await initializeDebugConfig(config);
			dc.launch(debugConfig);
			const event = await waitForHelloGoodbyeOutput(dc);
			assert.strictEqual(event.body.output, 'Hello, World!\n');
		});
		test('should run file program without cwd set (noDebug)', async () => {
			const WD = path.join(DATA_ROOT, 'cwdTest');
			const PROGRAM = path.join(WD, 'cwdTest', 'main.go');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				noDebug: true
			};
			const debugConfig = await initializeDebugConfig(config);
			dc.launch(debugConfig);
			const event = await waitForHelloGoodbyeOutput(dc);
			assert.strictEqual(event.body.output, 'Goodbye, World.\n');
		});
	});

	suite('remote attach', () => {
		let childProcess: cp.ChildProcess;
		let server: number;
		let debugConfig: DebugConfiguration;

		setup(async () => {
			server = await getPort();
			remoteAttachConfig.port = await getPort();
			debugConfig = remoteAttachConfig;
		});

		teardown(async () => {
			await dc.stop();
			await killProcessTree(childProcess);
			// Wait 2 seconds for the process to be killed.
			await new Promise((resolve) => setTimeout(resolve, 2_000));
		});

		test('can connect and initialize using external dlv --headless --accept-multiclient=true --continue=true', async () => {
			childProcess = await setUpRemoteProgram(remoteAttachConfig.port, server, true, true);

			await setUpRemoteAttach(debugConfig);
		});

		test('can connect and initialize using external dlv --headless --accept-multiclient=false --continue=false', async () => {
			childProcess = await setUpRemoteProgram(remoteAttachConfig.port, server, false, false);

			await setUpRemoteAttach(debugConfig);
		});

		test('can connect and initialize using external dlv --headless --accept-multiclient=true --continue=false', async () => {
			childProcess = await setUpRemoteProgram(remoteAttachConfig.port, server, true, false);

			await setUpRemoteAttach(debugConfig);
		});

		test('connection to remote is terminated when external dlv process exits', async function () {
			if (isDlvDap) {
				this.skip(); // this test does not apply for dlv-dap.
			}

			const childProcess = await setUpRemoteProgram(remoteAttachConfig.port, server, true, false);

			await setUpRemoteAttach(remoteAttachConfig);

			killProcess(childProcess);

			await dc.waitForEvent('terminated');
		});
	});

	// The file paths returned from delve use '/' not the native path
	// separator, so we can replace any instances of '\' with '/', which
	// allows the hitBreakpoint check to match.
	const getBreakpointLocation = (FILE: string, LINE: number) => {
		return { path: FILE.replace(/\\/g, '/'), line: LINE };
	};

	suite('setBreakpoints', () => {
		let server: number;
		let remoteAttachDebugConfig: DebugConfiguration;
		setup(async () => {
			server = await getPort();
			remoteAttachConfig.port = await getPort();
			remoteAttachDebugConfig = remoteAttachConfig;
		});

		test('should stop on a breakpoint', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'baseTest');

			const FILE = path.join(DATA_ROOT, 'baseTest', 'test.go');
			const BREAKPOINT_LINE = 11;

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM
			};
			const debugConfig = await initializeDebugConfig(config);
			await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE));
		});

		test('should stop on a breakpoint in test file', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'baseTest');

			const FILE = path.join(DATA_ROOT, 'baseTest', 'sample_test.go');
			const BREAKPOINT_LINE = 15;

			const config = {
				name: 'Launch file',
				type: 'go',
				request: 'launch',
				mode: 'test',
				program: PROGRAM
			};
			const debugConfig = await initializeDebugConfig(config);
			await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE));
		});

		test('stopped for a breakpoint set during initialization (remote attach)', async () => {
			const FILE = path.join(DATA_ROOT, 'helloWorldServer', 'main.go');
			const BREAKPOINT_LINE = 29;
			const remoteProgram = await setUpRemoteProgram(remoteAttachConfig.port, server);

			const breakpointLocation = getBreakpointLocation(FILE, BREAKPOINT_LINE);

			// Setup attach with a breakpoint.
			await setUpRemoteAttach(remoteAttachDebugConfig, [breakpointLocation]);

			// Calls the helloworld server to make the breakpoint hit.
			await waitForBreakpoint(
				() => http.get(`http://localhost:${server}`).on('error', (data) => console.log(data)),
				breakpointLocation
			);

			await dc.disconnectRequest({ restart: false });
			await killProcessTree(remoteProgram);
			await new Promise((resolve) => setTimeout(resolve, 2_000));
		});

		test('stopped for a breakpoint set after initialization (remote attach)', async () => {
			const FILE = path.join(DATA_ROOT, 'helloWorldServer', 'main.go');
			const BREAKPOINT_LINE = 29;
			const remoteProgram = await setUpRemoteProgram(remoteAttachConfig.port, server);

			// Setup attach without a breakpoint.
			await setUpRemoteAttach(remoteAttachDebugConfig);

			// Now sets a breakpoint.
			const breakpointLocation = getBreakpointLocation(FILE, BREAKPOINT_LINE);
			const breakpointsResult = await dc.setBreakpointsRequest({
				source: { path: breakpointLocation.path },
				breakpoints: [breakpointLocation]
			});
			assert.ok(breakpointsResult.success && breakpointsResult.body.breakpoints[0].verified);

			// Calls the helloworld server to make the breakpoint hit.
			await waitForBreakpoint(
				() => http.get(`http://localhost:${server}`).on('error', (data) => console.log(data)),
				breakpointLocation
			);

			await dc.disconnectRequest({ restart: false });
			await killProcessTree(remoteProgram);
			await new Promise((resolve) => setTimeout(resolve, 2_000));
		});

		test('should set breakpoints during continue', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'sleep');

			const FILE = path.join(DATA_ROOT, 'sleep', 'sleep.go');
			const HELLO_LINE = 10;
			const helloLocation = getBreakpointLocation(FILE, HELLO_LINE);

			const config = {
				name: 'Launch file',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM
			};
			const debugConfig = await initializeDebugConfig(config);
			await Promise.all([dc.configurationSequence(), dc.launch(debugConfig)]);

			await Promise.all([
				dc.setBreakpointsRequest({
					lines: [helloLocation.line],
					breakpoints: [{ line: helloLocation.line, column: 0 }],
					source: { path: helloLocation.path }
				}),
				dc.assertStoppedLocation('breakpoint', helloLocation)
			]);
		});

		async function setBreakpointsWhileRunningStep(resumeFunc: () => Promise<void>) {
			const PROGRAM = path.join(DATA_ROOT, 'sleep');

			const FILE = path.join(DATA_ROOT, 'sleep', 'sleep.go');
			const SLEEP_LINE = 11;
			const setupBreakpoint = getBreakpointLocation(FILE, SLEEP_LINE);

			const HELLO_LINE = 10;
			const resumeBreakpoint = getBreakpointLocation(FILE, HELLO_LINE);

			const config = {
				name: 'Launch file',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM
			};
			const debugConfig = await initializeDebugConfig(config);
			await dc.hitBreakpoint(debugConfig, setupBreakpoint);

			// The program is now stopped at the line containing time.Sleep().
			// Issue a next request, followed by a setBreakpointsRequest.
			await resumeFunc();

			// Assert that the program completes the step request.
			await Promise.all([
				dc.setBreakpointsRequest({
					lines: [resumeBreakpoint.line],
					breakpoints: [{ line: resumeBreakpoint.line, column: 0 }],
					source: { path: resumeBreakpoint.path }
				}),
				dc.assertStoppedLocation('step', {})
			]);

			// Once the 'step' has completed, continue the program and
			// make sure the breakpoint set while the program was nexting
			// is succesfully hit.
			await Promise.all([
				dc.continueRequest({ threadId: 1 }),
				dc.assertStoppedLocation('breakpoint', resumeBreakpoint)
			]);
		}

		test('should set breakpoints during next', async function () {
			if (!isDlvDap) {
				this.skip();
			}
			await setBreakpointsWhileRunningStep(async () => {
				const nextResponse = await dc.nextRequest({ threadId: 1 });
				assert.ok(nextResponse.success);
			});
		});

		test('should set breakpoints during step out', async function () {
			if (!isDlvDap) {
				this.skip();
			}

			await setBreakpointsWhileRunningStep(async () => {
				await Promise.all([dc.stepInRequest({ threadId: 1 }), dc.assertStoppedLocation('step', {})]);

				const stepOutResponse = await dc.stepOutRequest({ threadId: 1 });
				assert.ok(stepOutResponse.success);
			});
		});

		async function setBreakpointsDuringStep(nextFunc: () => void) {
			const PROGRAM = path.join(DATA_ROOT, 'sleep');

			const FILE = path.join(DATA_ROOT, 'sleep', 'sleep.go');
			const SLEEP_LINE = 11;
			const setupBreakpoint = getBreakpointLocation(FILE, SLEEP_LINE);

			const HELLO_LINE = 10;
			const onNextBreakpoint = getBreakpointLocation(FILE, HELLO_LINE);

			const config = {
				name: 'Launch file',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM
			};
			const debugConfig = await initializeDebugConfig(config);
			await dc.hitBreakpoint(debugConfig, setupBreakpoint);

			// The program is now stopped at the line containing time.Sleep().
			// Issue a next request, followed by a setBreakpointsRequest.
			nextFunc();

			// Note: the current behavior of setting a breakpoint during a next
			// request will cause the step to be interrupted, so it may not be
			// stopped on the next line.
			await Promise.all([
				dc.setBreakpointsRequest({
					lines: [onNextBreakpoint.line],
					breakpoints: [{ line: onNextBreakpoint.line, column: 0 }],
					source: { path: onNextBreakpoint.path }
				}),
				dc.assertStoppedLocation('next cancelled', {})
			]);

			// Once the 'step' has completed, continue the program and
			// make sure the breakpoint set while the program was nexting
			// is succesfully hit.
			await Promise.all([
				dc.continueRequest({ threadId: 1 }),
				dc.assertStoppedLocation('breakpoint', onNextBreakpoint)
			]);
		}

		test('should set breakpoints during next (legacy)', async function () {
			if (isDlvDap) {
				this.skip();
			}
			await setBreakpointsDuringStep(async () => {
				const nextResponse = await dc.nextRequest({ threadId: 1 });
				assert.ok(nextResponse.success);
			});
		});

		test('should set breakpoints during step out (legacy)', async function () {
			if (isDlvDap) {
				this.skip();
			}

			await setBreakpointsDuringStep(async () => {
				const stepOutResponse = await dc.stepOutRequest({ threadId: 1 });
				assert.ok(stepOutResponse.success);
			});
		});
	});

	suite('conditionalBreakpoints', () => {
		test('should stop on conditional breakpoint', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'condbp');
			const FILE = path.join(DATA_ROOT, 'condbp', 'condbp.go');
			const BREAKPOINT_LINE = 7;
			const location = getBreakpointLocation(FILE, BREAKPOINT_LINE);

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM
			};
			const debugConfig = await initializeDebugConfig(config);
			await Promise.all([
				dc
					.waitForEvent('initialized')
					.then(() => {
						return dc.setBreakpointsRequest({
							lines: [location.line],
							breakpoints: [{ line: location.line, condition: 'i == 2' }],
							source: { path: location.path }
						});
					})
					.then(() => {
						return dc.configurationDoneRequest();
					}),
				dc.launch(debugConfig),

				dc.assertStoppedLocation('breakpoint', location)
			]).then(() =>
				// The program is stopped at the breakpoint, check to make sure 'i == 1'.
				assertLocalVariableValue('i', '2')
			);
		});

		test('should add breakpoint condition', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'condbp');
			const FILE = path.join(DATA_ROOT, 'condbp', 'condbp.go');
			const BREAKPOINT_LINE = 7;
			const location = getBreakpointLocation(FILE, BREAKPOINT_LINE);

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM
			};
			const debugConfig = await initializeDebugConfig(config);
			await dc
				.hitBreakpoint(debugConfig, location)
				.then(() =>
					// The program is stopped at the breakpoint, check to make sure 'i == 0'.
					assertLocalVariableValue('i', '0')
				)
				.then(() =>
					// Add a condition to the breakpoint, and make sure it runs until 'i == 2'.
					dc
						.setBreakpointsRequest({
							lines: [location.line],
							breakpoints: [{ line: location.line, condition: 'i == 2' }],
							source: { path: location.path }
						})
						.then(() =>
							Promise.all([
								dc.continueRequest({ threadId: 1 }),
								dc.assertStoppedLocation('breakpoint', location)
							]).then(() =>
								// The program is stopped at the breakpoint, check to make sure 'i == 2'.
								assertLocalVariableValue('i', '2')
							)
						)
				);
		});

		test('should remove breakpoint condition', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'condbp');
			const FILE = path.join(DATA_ROOT, 'condbp', 'condbp.go');
			const BREAKPOINT_LINE = 7;
			const location = getBreakpointLocation(FILE, BREAKPOINT_LINE);

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM
			};
			const debugConfig = await initializeDebugConfig(config);
			await Promise.all([
				dc
					.waitForEvent('initialized')
					.then(async () => {
						return dc.setBreakpointsRequest({
							lines: [location.line],
							breakpoints: [{ line: location.line, condition: 'i == 2' }],
							source: { path: location.path }
						});
					})
					.then(() => {
						return dc.configurationDoneRequest();
					}),

				dc.launch(debugConfig),

				dc.assertStoppedLocation('breakpoint', location)
			])
				.then(() =>
					// The program is stopped at the breakpoint, check to make sure 'i == 2'.
					assertLocalVariableValue('i', '2')
				)
				.then(() =>
					// Remove the breakpoint condition, and make sure the program runs until 'i == 3'.
					dc
						.setBreakpointsRequest({
							lines: [location.line],
							breakpoints: [{ line: location.line }],
							source: { path: location.path }
						})
						.then(() =>
							Promise.all([
								dc.continueRequest({ threadId: 1 }),
								dc.assertStoppedLocation('breakpoint', location)
							]).then(() =>
								// The program is stopped at the breakpoint, check to make sure 'i == 3'.
								assertLocalVariableValue('i', '3')
							)
						)
				);
		});
	});

	suite('panicBreakpoints', () => {
		test('should stop on panic', async () => {
			const PROGRAM_WITH_EXCEPTION = path.join(DATA_ROOT, 'panic');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM_WITH_EXCEPTION
			};
			const debugConfig = await initializeDebugConfig(config);
			await Promise.all([
				dc.configurationSequence(),
				dc.launch(debugConfig),
				dc.waitForEvent('stopped').then((event) => {
					assert(
						event.body.reason === 'runtime error' ||
							event.body.reason === 'panic' ||
							event.body.reason === 'exception'
					);
				})
			]);
		});

		test('should stop on runtime error during continue', async function () {
			if (!isDlvDap) {
				// Not implemented in the legacy adapter.
				this.skip();
			}

			const PROGRAM_WITH_EXCEPTION = path.join(DATA_ROOT, 'runtimeError');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM_WITH_EXCEPTION
			};
			const debugConfig = await initializeDebugConfig(config);
			await Promise.all([
				dc.configurationSequence(),
				dc.launch(debugConfig),
				dc.waitForEvent('stopped').then((event) => {
					assert(
						event.body.reason === 'runtime error' ||
							event.body.reason === 'panic' ||
							event.body.reason === 'exception'
					);
				})
			]);
		});

		test('should stop on runtime error during next', async function () {
			if (!isDlvDap) {
				// Not implemented in the legacy adapter.
				this.skip();
			}

			const PROGRAM_WITH_EXCEPTION = path.join(DATA_ROOT, 'runtimeError');
			const FILE = path.join(PROGRAM_WITH_EXCEPTION, 'oops.go');
			const BREAKPOINT_LINE = 5;

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM_WITH_EXCEPTION
			};
			const debugConfig = await initializeDebugConfig(config);

			await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE));
			await Promise.all([
				dc.nextRequest({ threadId: 1 }),
				dc.waitForEvent('stopped').then((event) => {
					assert(
						event.body.reason === 'runtime error' ||
							event.body.reason === 'panic' ||
							event.body.reason === 'exception'
					);
				})
			]);
		});
	});

	suite('disconnect', () => {
		// The teardown code for the Go Debug Adapter test suite issues a disconnectRequest.
		// In order for these tests to pass, the debug adapter must not fail if a
		// disconnectRequest is sent after it has already disconnected.

		test('disconnect should work for remote attach', async () => {
			const server = await getPort();
			remoteAttachConfig.port = await getPort();
			const remoteProgram = await setUpRemoteProgram(remoteAttachConfig.port, server);

			// Setup attach.
			await setUpRemoteAttach(remoteAttachConfig);

			// Calls the helloworld server to get a response.
			let response = '';
			await new Promise<void>((resolve) => {
				http.get(`http://localhost:${server}`, (res) => {
					res.on('data', (data) => (response += data));
					res.on('end', () => resolve());
				});
			});

			await dc.disconnectRequest();
			// Checks that after the disconnect, the helloworld server still works.
			let secondResponse = '';
			await new Promise<void>((resolve) => {
				http.get(`http://localhost:${server}`, (res) => {
					res.on('data', (data) => (secondResponse += data));
					res.on('end', () => resolve());
				});
			});
			assert.strictEqual(response, 'Hello, world!');
			assert.strictEqual(response, secondResponse);
			await killProcessTree(remoteProgram);
			await new Promise((resolve) => setTimeout(resolve, 2_000));
		});

		test('should disconnect while continuing on entry', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'loop');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				stopOnEntry: false
			};
			const debugConfig = await initializeDebugConfig(config);
			await Promise.all([dc.configurationSequence(), dc.launch(debugConfig)]);

			await Promise.all([dc.disconnectRequest({ restart: false }), dc.waitForEvent('terminated')]);
		});

		// FIXIT: disabled due to https://github.com/golang/vscode-go/issues/1995
		test.skip('should disconnect with multiple disconnectRequests', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'loop');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				stopOnEntry: false
			};
			const debugConfig = await initializeDebugConfig(config);

			await Promise.all([dc.configurationSequence(), dc.launch(debugConfig)]);

			await Promise.all([
				new Promise<void>((resolve) => {
					dc.disconnectRequest({ restart: false });
					dc.disconnectRequest({ restart: false });
					resolve();
				}),
				dc.waitForEvent('terminated')
			]);
		});

		test('should disconnect after continue', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'loop');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				stopOnEntry: true
			};
			const debugConfig = await initializeDebugConfig(config);
			await Promise.all([dc.configurationSequence(), dc.launch(debugConfig)]);

			const continueResponse = await dc.continueRequest({ threadId: 1 });
			assert.ok(continueResponse.success);

			await Promise.all([dc.disconnectRequest({ restart: false }), dc.waitForEvent('terminated')]);
		});

		test('should disconnect while nexting', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'sleep');
			const FILE = path.join(DATA_ROOT, 'sleep', 'sleep.go');
			const BREAKPOINT_LINE = 11;
			const location = getBreakpointLocation(FILE, BREAKPOINT_LINE);

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				stopOnEntry: false
			};
			const debugConfig = await initializeDebugConfig(config);
			await dc.hitBreakpoint(debugConfig, location);

			const nextResponse = await dc.nextRequest({ threadId: 1 });
			assert.ok(nextResponse.success);

			await Promise.all([dc.disconnectRequest({ restart: false }), dc.waitForEvent('terminated')]);
		});

		test('should disconnect while paused on pause', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'loop');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM
			};
			const debugConfig = await initializeDebugConfig(config);

			await Promise.all([dc.configurationSequence(), dc.launch(debugConfig)]);

			const pauseResponse = await dc.pauseRequest({ threadId: 1 });
			assert.ok(pauseResponse.success);

			await Promise.all([dc.disconnectRequest({ restart: false }), dc.waitForEvent('terminated')]);
		});

		test('should disconnect while paused on breakpoint', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'loop');
			const FILE = path.join(PROGRAM, 'loop.go');
			const BREAKPOINT_LINE = 5;

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM
			};
			const debugConfig = await initializeDebugConfig(config);

			await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE));

			await Promise.all([dc.disconnectRequest({ restart: false }), dc.waitForEvent('terminated')]);
		});

		test('should disconnect while paused on entry', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'loop');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				stopOnEntry: true
			};
			const debugConfig = await initializeDebugConfig(config);

			await Promise.all([dc.configurationSequence(), dc.launch(debugConfig)]);

			await Promise.all([dc.disconnectRequest({ restart: false }), dc.waitForEvent('terminated')]);
		});

		test('should disconnect while paused on next', async () => {
			const PROGRAM = path.join(DATA_ROOT, 'loop');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				stopOnEntry: true
			};
			const debugConfig = await initializeDebugConfig(config);

			await Promise.all([dc.configurationSequence(), dc.launch(debugConfig)]);

			const nextResponse = await dc.nextRequest({ threadId: 1 });
			assert.ok(nextResponse.success);

			await Promise.all([dc.disconnectRequest({ restart: false }), dc.waitForEvent('terminated')]);
		});

		// This test is flaky. It has been updated to run stat multiple
		// times to decrease the likelihood of stat occuring before delve
		// has a chance to clean up.
		// BUG(https://github.com/golang/vscode-go/issues/1993)
		test('should cleanup when stopped', async function () {
			if (!isDlvDap) {
				this.skip();
			}
			const PROGRAM = path.join(DATA_ROOT, 'loop');
			const OUTPUT = path.join(PROGRAM, '_loop_output');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				stopOnEntry: false,
				output: OUTPUT
			};
			const debugConfig = await initializeDebugConfig(config);

			await Promise.all([dc.configurationSequence(), dc.launch(debugConfig)]);

			try {
				const fsstat = util.promisify(fs.stat);
				await fsstat(OUTPUT);
			} catch (e) {
				assert.fail(`debug output ${OUTPUT} wasn't built: ${e}`);
			}

			// Skip the proper disconnect sequence started with a disconnect request.
			await dlvDapAdapter?.dispose(1);
			dc = undefined!;
			let stat: fs.Stats | null = null;
			try {
				const fsstat = util.promisify(fs.stat);
				const maxAttempts = 2;
				for (let i = 0; i < maxAttempts; i++) {
					await sleep(1000); // allow dlv to respond and finish cleanup.
					stat = await fsstat(OUTPUT);
					// Don't need to try again if stat result is null.
					if (stat === null) {
						break;
					}
				}
				fs.unlinkSync(OUTPUT);
			} catch (e) {
				console.log(`output was cleaned ${OUTPUT} ${e}`);
			}
			assert.strictEqual(stat, null, `debug output ${OUTPUT} wasn't cleaned up. ${JSON.stringify(stat)}`);
			console.log('finished');
		});
	});

	suite('switch goroutine', () => {
		async function continueAndFindParkedGoroutine(file: string): Promise<number> {
			// Find a goroutine that is stopped in parked.
			const bp = getBreakpointLocation(file, 8);
			await dc.setBreakpointsRequest({ source: { path: bp.path }, breakpoints: [bp] });

			let parkedGoid = -1;
			while (parkedGoid < 0) {
				const res = await Promise.all([
					dc.continueRequest({ threadId: 1 }),
					Promise.race([
						dc.waitForEvent('stopped'),
						// It is very unlikely to happen. But in theory if all sayhi
						// goroutines are run serially, there will never be a second parked
						// sayhi goroutine when another breaks and we will keep trying
						// until process termination. If the process terminates, mark the test
						// as done.
						dc.waitForEvent('terminated')
					])
				]);
				const event = res[1];
				if (res[1].event === 'terminated') {
					break;
				}
				const threads = await dc.threadsRequest();

				// Search for a parked goroutine that we know for sure will have to be
				// resumed before the program can exit. This is a goroutine that:
				// 1. is executing main.hi
				// 2. hasn't called wg.Done yet
				// 3. is not the currently selected goroutine
				for (let i = 0; i < threads.body.threads.length; i++) {
					const g = threads.body.threads[i];
					if (g.id === event.body.threadId) {
						continue;
					}
					const st = await dc.stackTraceRequest({ threadId: g.id, startFrame: 0, levels: 5 });
					for (let j = 0; j < st.body.stackFrames.length; j++) {
						const frame = st.body.stackFrames[j];
						if (frame.name === 'main.hi') {
							parkedGoid = g.id;
							break;
						}
					}
					if (parkedGoid >= 0) {
						break;
					}
				}
			}

			// Clear all breakpoints
			await dc.setBreakpointsRequest({ source: { path: bp.path }, breakpoints: [] });
			return parkedGoid;
		}

		async function runSwitchGoroutineTest(stepFunction: string) {
			const PROGRAM = path.join(DATA_ROOT, 'goroutineTest');
			const FILE = path.join(PROGRAM, 'main.go');

			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				stopOnEntry: true
			};
			const debugConfig = await initializeDebugConfig(config);

			await Promise.all([dc.configurationSequence(), dc.launch(debugConfig), dc.waitForEvent('stopped')]);

			const parkedGoid = await continueAndFindParkedGoroutine(FILE);

			// runStepFunction runs the necessary step function and resolves if it succeeded.
			async function runStepFunction(
				args: { threadId: number },
				resolve: (value: void | PromiseLike<void>) => void,
				reject: (reason?: any) => void
			) {
				const callback = (resp: any) => {
					assert.ok(resp.success);
					resolve();
				};
				switch (stepFunction) {
					case 'next':
						callback(await dc.nextRequest(args));
						break;
					case 'step in':
						callback(await dc.stepInRequest(args));
						break;
					case 'step out':
						callback(await dc.stepOutRequest(args));
						break;
					default:
						reject(new Error(`not a valid step function ${stepFunction}`));
				}
			}

			if (parkedGoid > 0) {
				// Next on the parkedGoid.
				await Promise.all([
					new Promise<void>((resolve, reject) => {
						const args = { threadId: parkedGoid };
						return runStepFunction(args, resolve, reject);
					}),
					dc.waitForEvent('stopped').then((event) => {
						assert.strictEqual(event.body.reason, 'step');
						assert.strictEqual(event.body.threadId, parkedGoid);
					})
				]);
			} else {
				console.log('Unable to find a goroutine to step.');
			}
		}

		test('next', async function () {
			if (!isDlvDap) {
				// Not implemented in the legacy adapter.
				this.skip();
			}
			await runSwitchGoroutineTest('next');
		});

		test('step in', async function () {
			if (!isDlvDap) {
				// Not implemented in the legacy adapter.
				this.skip();
			}
			await runSwitchGoroutineTest('step in');
		});

		test('step out', async function () {
			if (!isDlvDap) {
				// Not implemented in the legacy adapter.
				this.skip();
			}
			await runSwitchGoroutineTest('step in');
		});
	});

	suite('logDest attribute tests', () => {
		const PROGRAM = path.join(DATA_ROOT, 'baseTest');

		let tmpDir: string;
		suiteSetup(() => {
			tmpDir = fs.mkdtempSync(path.join(tmpdir(), 'logDestTest'));
		});
		suiteTeardown(() => {
			rmdirRecursive(tmpDir);
		});

		test('logs are written to logDest file', async function () {
			if (!isDlvDap || process.platform === 'win32') {
				this.skip();
			}
			const DELVE_LOG = path.join(tmpDir, 'delve.log');
			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				logDest: DELVE_LOG
			};

			const debugConfig = await initializeDebugConfig(config);
			await Promise.all([dc.configurationSequence(), dc.launch(debugConfig), dc.waitForEvent('terminated')]);
			await dc.stop();
			dc = undefined!;
			const dapLog = fs.readFileSync(DELVE_LOG)?.toString();
			const preamble =
				debugConfig?.console === 'integratedTerminal' || debugConfig?.console === 'externalTerminal'
					? 'DAP server for a predetermined client'
					: 'DAP server listening at';
			assert(
				dapLog.includes(preamble) &&
					dapLog.includes('"command":"initialize"') &&
					dapLog.includes('"event":"terminated"'),
				dapLog
			);
		});

		async function testWithInvalidLogDest(logDest: any, wantedErrorMessage: string) {
			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				logDest
			};

			await initializeDebugConfig(config);
			try {
				await dc.initializeRequest();
				assert.fail('dlv dap started normally, wanted the invalid logDest to cause failure');
			} catch (error) {
				assert((error as Error)?.message.includes(wantedErrorMessage), `unexpected error: ${error}`);
			}
		}
		test('relative path as logDest triggers an error', async function () {
			if (!isDlvDap || withConsole || process.platform === 'win32') this.skip();
			await testWithInvalidLogDest('delve.log', 'relative path');
		});

		test('number as logDest triggers an error', async function () {
			if (!isDlvDap || withConsole || process.platform === 'win32') this.skip();
			await testWithInvalidLogDest(3, 'file descriptor');
		});
	});

	suite('substitute path', () => {
		// TODO(suzmue): add unit tests for substitutePath.
		let tmpDir: string;

		suiteSetup(() => {
			tmpDir = fs.mkdtempSync(path.join(DATA_ROOT, 'substitutePathTest'));
		});

		suiteTeardown(() => {
			rmdirRecursive(tmpDir);
		});

		function copyDirectory(name: string) {
			const from = path.join(DATA_ROOT, name);
			const to = path.join(tmpDir, name);
			fs.mkdirSync(to);
			fs.readdirSync(from).forEach((file) => {
				fs.copyFileSync(path.join(from, file), path.join(to, file));
			});
			return to;
		}

		async function buildGoProgram(cwd: string, outputFile: string): Promise<string> {
			const goRuntimePath = getBinPath('go');
			const execFile = util.promisify(cp.execFile);
			const child = await execFile(goRuntimePath, ['build', '-o', outputFile, "--gcflags='all=-N -l'", '.'], {
				cwd
			});
			if (child.stderr.length > 0) {
				throw Error(child.stderr);
			}
			return outputFile;
		}

		suite('substitutePath with missing files', () => {
			let goBuildOutput: string;
			suiteSetup(() => {
				goBuildOutput = fs.mkdtempSync(path.join(tmpdir(), 'output'));
			});

			suiteTeardown(() => {
				rmdirRecursive(goBuildOutput);
			});

			async function copyBuildDelete(program: string): Promise<{ program: string; output: string }> {
				const wd = copyDirectory(program);
				const output = await buildGoProgram(wd, path.join(goBuildOutput, program));
				rmdirRecursive(wd);
				return { program: wd, output };
			}

			test('should stop on a breakpoint set in file with substituted path', async () => {
				const { program, output } = await copyBuildDelete('baseTest');
				const FILE = path.join(DATA_ROOT, 'baseTest', 'test.go');
				const BREAKPOINT_LINE = 11;

				const config = {
					name: 'Launch',
					type: 'go',
					request: 'launch',
					mode: 'exec',
					program: output,
					substitutePath: [
						{
							from: path.join(DATA_ROOT, 'baseTest'),
							to: program
						}
					]
				};
				const debugConfig = await initializeDebugConfig(config);

				await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE));
			});
		});

		suite('substitutePath with remote program', () => {
			let server: number;
			let remoteAttachDebugConfig: DebugConfiguration;
			let helloWorldLocal: string;
			let helloWorldRemote: string;
			setup(async () => {
				server = await getPort();
				remoteAttachConfig.port = await getPort();
				remoteAttachDebugConfig = remoteAttachConfig;
			});

			suiteSetup(() => {
				helloWorldLocal = copyDirectory('helloWorldServer');
				helloWorldRemote = path.join(DATA_ROOT, 'helloWorldServer');
			});

			suiteTeardown(() => {
				rmdirRecursive(helloWorldLocal);
			});

			test('stopped for a breakpoint set during initialization using substitutePath (remote attach)', async () => {
				const FILE = path.join(helloWorldLocal, 'main.go');
				const BREAKPOINT_LINE = 29;
				const remoteProgram = await setUpRemoteProgram(remoteAttachConfig.port, server);

				const breakpointLocation = getBreakpointLocation(FILE, BREAKPOINT_LINE);
				// Setup attach with a breakpoint.
				remoteAttachDebugConfig.cwd = tmpDir;
				remoteAttachDebugConfig.remotePath = '';
				remoteAttachDebugConfig.substitutePath = [{ from: helloWorldLocal, to: helloWorldRemote }];
				await setUpRemoteAttach(remoteAttachDebugConfig, [breakpointLocation]);

				// Calls the helloworld server to make the breakpoint hit.
				await waitForBreakpoint(
					() => http.get(`http://localhost:${server}`).on('error', (data) => console.log(data)),
					breakpointLocation
				);

				await dc.disconnectRequest({ restart: false });
				await killProcessTree(remoteProgram);
				await new Promise((resolve) => setTimeout(resolve, 2_000));
			});

			// Skip because it times out in nightly release workflow.
			// BUG(https://github.com/golang/vscode-go/issues/1043)
			test.skip('stopped for a breakpoint set during initialization using remotePath (remote attach)', async function () {
				if (isDlvDap) {
					this.skip(); // remotePath is not used in dlv-dap
				}

				const FILE = path.join(helloWorldLocal, 'main.go');
				const BREAKPOINT_LINE = 29;
				const remoteProgram = await setUpRemoteProgram(remoteAttachConfig.port, server);

				const breakpointLocation = getBreakpointLocation(FILE, BREAKPOINT_LINE);
				// Setup attach with a breakpoint.
				remoteAttachDebugConfig.cwd = helloWorldLocal;
				remoteAttachDebugConfig.remotePath = helloWorldRemote;
				// This is a bad mapping, make sure that the remotePath config is used first.
				remoteAttachDebugConfig.substitutePath = [{ from: helloWorldLocal, to: helloWorldLocal }];
				await setUpRemoteAttach(remoteAttachDebugConfig, [breakpointLocation]);

				// Calls the helloworld server to make the breakpoint hit.
				await waitForBreakpoint(
					() => http.get(`http://localhost:${server}`).on('error', (data) => console.log(data)),
					breakpointLocation
				);

				await dc.disconnectRequest({ restart: false });
				await killProcessTree(remoteProgram);
				await new Promise((resolve) => setTimeout(resolve, 2_000));
			});
		});

		suite('substitutePath with symlink', () => {
			let realPath: string;
			let symlinkPath: string;

			suiteSetup(() => {
				realPath = copyDirectory('baseTest');
				symlinkPath = path.join(tmpDir, 'symlinked');
				fs.symlinkSync(realPath, symlinkPath, 'dir');
			});
			suiteTeardown(() => {
				fs.unlinkSync(symlinkPath);
				rmdirRecursive(realPath);
			});
			test('should stop on a breakpoint', async function () {
				if (!isDlvDap) this.skip(); // BUG: the legacy adapter fails with 'breakpoint verification mismatch' error.
				const FILE = path.join(symlinkPath, 'test.go');
				const BREAKPOINT_LINE = 11;
				const config = {
					name: 'Launch',
					type: 'go',
					request: 'launch',
					mode: 'debug',
					program: FILE,
					substitutePath: [
						{
							from: symlinkPath,
							to: realPath
						}
					]
				};
				const debugConfig = await initializeDebugConfig(config);
				await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE));
			});
		});
	});

	let testNumber = 0;
	async function initializeDebugConfig(config: DebugConfiguration, keepUserLogSettings?: boolean) {
		// be explicit and prevent resolveDebugConfiguration from picking
		// a default debugAdapter for us.
		config['debugAdapter'] = isDlvDap ? 'dlv-dap' : 'legacy';
		if (withConsole) {
			config['console'] = withConsole;
		}

		if (!keepUserLogSettings) {
			dapTraced = true;

			// Log the output for easier test debugging.
			config['logOutput'] = isDlvDap ? 'dap,debugger' : 'rpc,debugger';
			config['showLog'] = true;
			config['trace'] = 'verbose';
		}

		// disable version check (like in dlv-dap).
		if (!isDlvDap) {
			const dlvFlags = config['dlvFlags'] || [];
			config['dlvFlags'] = ['--check-go-version=false'].concat(dlvFlags);
		}
		// Give each test a distinct debug binary. If a previous test
		// and a new test use the same binary location, it is possible
		// that the second test could build the binary, and then the
		// first test could delete that binary during cleanup before the
		// second test has a chance to run it.
		if (!config['output'] && ['debug', 'auto', 'test'].includes(config['mode'])) {
			const dir = parseDebugProgramArgSync(config['program']).dirname;
			config['output'] = path.join(dir, `__debug_bin_${testNumber}`);
		}
		testNumber++;

		let debugConfig: DebugConfiguration | null | undefined = await debugConfigProvider.resolveDebugConfiguration(
			undefined,
			config
		);
		debugConfig = await debugConfigProvider.resolveDebugConfigurationWithSubstitutedVariables(
			undefined,
			debugConfig!
		);

		if (isDlvDap) {
			dlvDapAdapter = await DelveDAPDebugAdapterOnSocket.create(debugConfig!);
			const port = await dlvDapAdapter.serve();
			await dc.start(port); // This will connect to the adapter's port.
		}
		return debugConfig;
	}
};

suite('Go Debug Adapter Tests (legacy)', function () {
	this.timeout(60_000);
	testAll(this.ctx, false);
});

suite('Go Debug Adapter Tests (dlv-dap)', function () {
	this.timeout(60_000);
	testAll(this.ctx, true);
});

suite('Go Debug Adapter Tests (dlv-dap, console=integratedTerminal)', function () {
	this.timeout(60_000);
	testAll(this.ctx, true, 'integratedTerminal');
});

// DelveDAPDebugAdapterOnSocket runs a DelveDAPOutputAdapter
// over a network socket. This allows tests to instantiate
// the thin adapter for Delve DAP and the debug test support's
// DebugClient to communicate with the adapter over a network socket.
class DelveDAPDebugAdapterOnSocket extends proxy.DelveDAPOutputAdapter {
	static async create(config: DebugConfiguration) {
		const d = new DelveDAPDebugAdapterOnSocket(config);
		return d;
	}

	private constructor(config: DebugConfiguration) {
		super(config, new TimestampedLogger('error', undefined, PRINT_TO_CONSOLE));
	}

	private static TWO_CRLF = '\r\n\r\n';
	private _rawData?: Buffer;
	private _contentLength?: number;
	private _writableStream?: NodeJS.WritableStream;
	private _server?: net.Server;
	private _port?: number; // port for the thin adapter.

	public serve(): Promise<number | undefined> {
		return new Promise(async (resolve, reject) => {
			this._port = await getPort();
			this._server = net.createServer((c) => {
				this.log('>> accepted connection from client');
				c.on('end', () => {
					this.log('>> client disconnected');
					this.dispose();
				});
				this.run(c, c);
			});
			this._server.on('error', (err) => reject(err));
			this._server.listen(this._port, () => resolve(this._port));
		});
	}

	private run(inStream: NodeJS.ReadableStream, outStream: NodeJS.WritableStream): void {
		this._writableStream = outStream;
		this._rawData = Buffer.alloc(0);

		// forward to DelveDAPDebugAdapter, which will forward to dlv dap.
		inStream.on('data', (data: Buffer) => this._handleData(data));
		// DebugClient silently drops reverse requests. Handle runInTerminal request here.
		this.onDidSendMessage((m) => {
			if (this.handleRunInTerminal(m)) {
				return;
			}
			this._send(m);
		});

		inStream.resume();
	}

	// handleRunInTerminal spawns the requested command and simulates RunInTerminal
	// handler implementation inside an editor.
	private _dlvInTerminal: cp.ChildProcess | undefined;
	private handleRunInTerminal(m: vscode.DebugProtocolMessage) {
		const m0 = m as any;
		if (m0['type'] !== 'request' || m0['command'] !== 'runInTerminal') {
			return false;
		}
		const json = JSON.stringify(m0);
		this.log(`<- server: ${json}`);

		const resp = {
			seq: 0,
			type: 'response',
			success: false,
			request_seq: m0['seq'],
			command: m0['command'],
			body: {}
		};

		if (!this._dlvInTerminal && m0['arguments']?.args?.length > 0) {
			const args = m0['arguments'].args as string[];
			const env = m0['arguments'].env ? Object.assign({}, process.env, m0['arguments'].env) : undefined;
			const p = cp.spawn(args[0], args.slice(1), {
				cwd: m0['arguments'].cwd,
				env
			});
			// stdout/stderr are supposed to appear in the terminal, but
			// some of noDebug tests depend on access to stdout/stderr.
			// For those tests, let's pump the output as OutputEvent.
			p.stdout.on('data', (chunk) => {
				this.outputEvent('stdout', chunk.toString());
			});
			p.stderr.on('data', (chunk) => {
				this.outputEvent('stderr', chunk.toString());
			});
			resp.success = true;
			resp.body = { processId: p.pid };
			this._dlvInTerminal = p;
		}

		this.log(`-> server: ${JSON.stringify(resp)}`);
		this.handleMessage(resp);

		return true;
	}

	private _disposed = false;
	public async dispose(timeoutMS?: number) {
		if (this._disposed) {
			return;
		}
		this._disposed = true;
		this.log('adapter disposing');
		await this._server?.close();
		await super.dispose(timeoutMS);
		this.log('adapter disposed');
	}

	// Code from
	// https://github.com/microsoft/vscode-debugadapter-node/blob/2235a2227d1a439372be578cd3f55e15211851b7/testSupport/src/protocolClient.ts#L96-L97
	private _send(message: DebugProtocolMessage): void {
		if (this._writableStream) {
			const json = JSON.stringify(message);
			this.log(`<- server: ${json}`);
			if (!this._writableStream.writable) {
				this.log('socket closed already');
				return;
			}
			this._writableStream.write(
				`Content-Length: ${Buffer.byteLength(json, 'utf8')}${DelveDAPDebugAdapterOnSocket.TWO_CRLF}${json}`,
				'utf8'
			);
		}
	}

	// Code from
	// https://github.com/microsoft/vscode-debugadapter-node/blob/2235a2227d1a439372be578cd3f55e15211851b7/testSupport/src/protocolClient.ts#L100-L132
	private _handleData(data: Buffer): void {
		this._rawData = Buffer.concat([this._rawData!, data]);

		// eslint-disable-next-line no-constant-condition
		while (true) {
			if (this._contentLength! >= 0) {
				if (this._rawData.length >= this._contentLength!) {
					const message = this._rawData.toString('utf8', 0, this._contentLength);
					this._rawData = this._rawData.slice(this._contentLength);
					this._contentLength = -1;
					if (message.length > 0) {
						try {
							this.log(`-> server: ${message}`);
							const msg: DebugProtocol.ProtocolMessage = JSON.parse(message);
							this.handleMessage(msg);
						} catch (e) {
							throw new Error('Error handling data: ' + (e && (e as Error).message));
						}
					}
					continue; // there may be more complete messages to process
				}
			} else {
				const idx = this._rawData.indexOf(DelveDAPDebugAdapterOnSocket.TWO_CRLF);
				if (idx !== -1) {
					const header = this._rawData.toString('utf8', 0, idx);
					const lines = header.split('\r\n');
					for (let i = 0; i < lines.length; i++) {
						const pair = lines[i].split(/: +/);
						if (pair[0] === 'Content-Length') {
							this._contentLength = +pair[1];
						}
					}
					this._rawData = this._rawData.slice(idx + DelveDAPDebugAdapterOnSocket.TWO_CRLF.length);
					continue;
				}
			}
			break;
		}
	}
	/* --- accumulate log messages so we can output when the test fails --- */
	private _log = [] as string[];
	private log(msg: string) {
		this._log.push(msg);
		if (PRINT_TO_CONSOLE) {
			console.log(msg);
		}
	}
	public printLog() {
		this._log.forEach((msg) => console.log(msg));
	}
}

function sleep(ms: number) {
	return new Promise((resolve) => setTimeout(resolve, ms));
}
