/* eslint-disable no-async-promise-executor */
/*---------------------------------------------------------
 * Copyright 2026 The Go Authors. All rights reserved.
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 *--------------------------------------------------------*/

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 * as extConfig from '../../src/config';
import { GoDebugConfigurationProvider, parseDebugProgramArgSync } from '../../src/goDebugConfiguration';
import { getBinPath, rmdirRecursive } from '../../src/util';
import { killProcessTree } from '../../src/utils/processUtils';
import getPort = require('get-port');
import util = require('util');
import { affectedByIssue832 } from './testutils';

// For debugging test and streaming the trace instead of buffering, set this.
const DEBUG = process.env['DEBUG'] === '1';
function debugLog(msg: string) {
	if (DEBUG) console.log(msg);
}

// 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();
			}
			void 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}`);
				}
			}
			void 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 promise = new Promise<cp.ChildProcess>((resolve, reject) => {
			const p = cp.spawn(toolPath, args, {
				cwd: serverFolder,
				env: { PORT: `${serverPort}`, ...process.env }
			});

			let started = false;
			const timeoutToken: NodeJS.Timer = setTimeout(() => {
				console.log(`dlv debug server (PID: ${p.pid}) is not responding`);
				reject(new Error('timed out while waiting for DAP server to start'));
			}, 30_000);

			const stopWaitingForServerToStart = () => {
				clearTimeout(timeoutToken);
				started = true;
				resolve(p);
			};

			if (continueOnStart) {
				// wait till helloWorldServer starts and prints its log message to STDERR.
				p.stderr.on('data', (chunk) => {
					const msg = chunk.toString();
					if (!started && msg.includes('helloWorldServer starting to listen on')) {
						stopWaitingForServerToStart();
					}
					console.log(msg);
				});
			} else {
				p.stdout.on('data', (chunk) => {
					const msg = chunk.toString();
					if (!started && msg.includes('listening at:')) {
						stopWaitingForServerToStart();
					}
					console.log(msg);
				});
			}
		});
		return promise;
	}

	/**
	 * 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) => {
				const debugConfigCopy = Object.assign({}, debugConfig);
				delete debugConfigCopy.env;
				debugLog(`Setting up attach request for ${JSON.stringify(debugConfigCopy)}.`);
				const attachResult = await dc.attachRequest(debugConfig as DebugProtocol.AttachRequestArguments);
				assert.ok(attachResult.success);
				resolve();
			}),
			dc.waitForEvent('initialized')
		]);

		if (breakpoints.length) {
			debugLog('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);
			});
		}
		debugLog('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 create a promise that's resolved when
	 * output event with any of the provided strings is observed.
	 */
	async function waitForOutputMessage(dc: DebugClient, ...patterns: string[]): Promise<DebugProtocol.Event> {
		return await new Promise<DebugProtocol.Event>((resolve) => {
			dc.on('output', (event) => {
				for (const pattern of patterns) {
					if (event.body.output.includes(pattern)) {
						// Resolve when we have found the event that we want.
						resolve(event);
						return;
					}
				}
			});
		});
	}

	/**
	 * 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 {
				return; // want error
			}
			throw new Error("does not report error on invalid 'pathFormat' attribute");
		});
	});

	suite('env', () => {
		if (!isDlvDap) {
			return;
		}

		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' }
				}
			});
			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' }
				}
			});
			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', () => {
		if (!isDlvDap) {
			return;
		}
		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(() => {
					// 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.
					void 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.
			}

			const PROGRAM = path.join(DATA_ROOT, 'baseTest');
			const config = {
				name: 'Launch',
				type: 'go',
				request: 'launch',
				mode: 'debug',
				program: PROGRAM,
				dlvFlags: ['--invalid']
			};

			await initializeDebugConfig(config);

			await Promise.race([
				// send an initialize request, which triggers launchDelveDAP
				// from the thin adapter. We expect no response.
				dc.initializeRequest().then(() => Promise.reject('unexpected initialization success')),
				// we expect the useful error message.
				waitForOutputMessage(dc, 'Error: unknown flag: --invalid')
			]);
		});

		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(() => {
					void 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', () => {
		if (!isDlvDap) {
			return;
		}
		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 waitForOutputMessage(dc, 'Hello, World!\n', 'Goodbye, World.\n');
		}

		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);
			void 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);
			void 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);
			void 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);
			void dc.launch(debugConfig);
			const event = await waitForHelloGoodbyeOutput(dc);
			assert.strictEqual(event.body.output, 'Goodbye, World.\n');
		});
	});

	suite('remote attach', () => {
		if (withConsole) {
			return;
		}
		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));
		});

		// stop here for integrated terminal test mode.
		if (withConsole) {
			return;
		}

		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)
			]);
		}

		// Skip this test because it is flaky.
		test.skip('should set breakpoints during next', async () => {
			await setBreakpointsWhileRunningStep(async () => {
				const nextResponse = await dc.nextRequest({ threadId: 1 });
				assert.ok(nextResponse.success);
			});
		});

		// Skip this test because it is flaky.
		test.skip('should set breakpoints during step out', async () => {
			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', () => {
		if (withConsole) {
			return;
		}
		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', () => {
		if (withConsole) {
			return;
		}
		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', () => {
		if (withConsole) {
			return;
		}
		// 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) => {
					void dc.disconnectRequest({ restart: false });
					void 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 || affectedByIssue832()) {
				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', () => {
		if (withConsole) {
			return;
		}
		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', () => {
		if (!isDlvDap) {
			return;
		}
		const PROGRAM = path.join(DATA_ROOT, 'baseTest');

		let tmpDir: string;
		suiteSetup(() => {
			tmpDir = fs.mkdtempSync(path.join(tmpdir(), 'logDestTest'));
		});
		suiteTeardown(() => {
			tryRmdirRecursive(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', () => {
		if (withConsole || affectedByIssue832()) {
			return;
		}
		// TODO(suzmue): add unit tests for substitutePath.
		let tmpDir: string;

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

		suiteTeardown(() => {
			tryRmdirRecursive(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(() => {
				tryRmdirRecursive(goBuildOutput);
			});

			async function copyBuildDelete(program: string): Promise<{ program: string; output: string }> {
				const wd = copyDirectory(program);
				const output = await buildGoProgram(wd, path.join(goBuildOutput, program));
				tryRmdirRecursive(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(() => {
				tryRmdirRecursive(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);
				tryRmdirRecursive(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));
			});
		});
	});

	suite('hideSystemGoroutines', () => {
		if (!isDlvDap) {
			return;
		}
		test('should toggle hiding system goroutines', 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,
				hideSystemGoroutines: false
			};
			const debugConfig = await initializeDebugConfig(config);
			await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE));
			let threadsResponse = await dc.threadsRequest();
			assert.ok(threadsResponse.success);
			assert.ok(threadsResponse.body.threads.length > 1);

			const toggle = () =>
				Promise.all([
					proxy.toggleHideSystemGoroutinesCustomRequest(async (command: string, args?: any) => {
						return dc.customRequest(command, args).then((rsp) => {
							return rsp.body;
						});
					}),
					dc.waitForEvent('invalidated').then((event) => {
						assert.strictEqual(event.body.areas.length, 1);
						assert.strictEqual(event.body.areas[0], 'threads');
					})
				]);
			// Toggle so only the main goroutine is shown.
			await toggle();
			threadsResponse = await dc.threadsRequest();
			assert.ok(threadsResponse.success);
			assert.strictEqual(threadsResponse.body.threads.length, 1);
			// Toggle so all goroutines are shown again.
			await toggle();
			threadsResponse = await dc.threadsRequest();
			assert.ok(threadsResponse.success);
			assert.ok(threadsResponse.body.threads.length > 1);
		});
	});

	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.
			//
			// Disable "rpc" logging in "legacy" mode to prevent vscode-go test
			// timeouts caused by oversized stacktrace outputs.
			config['logOutput'] = isDlvDap ? 'dap,debugger' : '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;
			if (!dir) throw new Error('Debug configuration does not define an output directory');
			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 () {
	if (affectedByIssue832()) {
		return;
	}
	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) {
		const log = (msg: string) => {
			debugLog(msg);
		};
		super(config, { trace: log, debug: log, info: log, error: log });
	}

	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');
					void 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)}`);
		void 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]);

		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);
							void 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 (DEBUG) {
			console.log(msg);
		}
	}
	public printLog() {
		this._log.forEach((msg) => console.log(msg));
	}
}

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

function tryRmdirRecursive(dir: string) {
	try {
		rmdirRecursive(dir);
	} catch (e) {
		console.log(`failed to delete ${dir}: ${e}`);
	}
}

// Kill a process.
function killProcess(p: cp.ChildProcess) {
	if (p && p.pid && p.exitCode === null) {
		try {
			p.kill();
		} catch (e) {
			console.log(`Error killing process ${p.pid}: ${e}`);
		}
	}
}
