From 690f49d00ced063b49ab084ec81090817c138dc7 Mon Sep 17 00:00:00 2001 From: "Michael (SPG) Weng" Date: Tue, 29 Oct 2024 10:53:26 -0400 Subject: [PATCH 1/4] Add integration tests for build commands - Validate the workflow of user calling the Swift: Run Build/Clean Build/Debug Build commands. - Ensure Swift: Run Build will not get blocked by pre-set breakpoint. - Ensure Swift: Clean Build will result in a cleaned up .build folder. - Ensure Swift: Debug Build will stop on a breakpoint and resume. Issue: #1184 --- src/commands.ts | 12 ++- src/commands/build.ts | 8 +- src/debugger/launch.ts | 6 +- test/integration-tests/commands/build.test.ts | 78 +++++++++++++++++++ 4 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 test/integration-tests/commands/build.test.ts diff --git a/src/commands.ts b/src/commands.ts index bd366549c..28e33560b 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -64,6 +64,12 @@ export function registerToolchainCommands( ]; } +export enum Commands { + RUN = "swift.run", + DEBUG = "swift.debug", + CLEAN_BUILD = "swift.cleanBuild", +} + /** * Registers this extension's commands in the given {@link vscode.ExtensionContext context}. */ @@ -74,9 +80,9 @@ export function register(ctx: WorkspaceContext): vscode.Disposable[] { resolveDependencies(ctx) ), vscode.commands.registerCommand("swift.updateDependencies", () => updateDependencies(ctx)), - vscode.commands.registerCommand("swift.run", () => runBuild(ctx)), - vscode.commands.registerCommand("swift.debug", () => debugBuild(ctx)), - vscode.commands.registerCommand("swift.cleanBuild", () => cleanBuild(ctx)), + vscode.commands.registerCommand(Commands.RUN, () => runBuild(ctx)), + vscode.commands.registerCommand(Commands.DEBUG, () => debugBuild(ctx)), + vscode.commands.registerCommand(Commands.CLEAN_BUILD, () => cleanBuild(ctx)), vscode.commands.registerCommand("swift.runTestsMultipleTimes", item => { if (ctx.currentFolder) { return runTestMultipleTimes(ctx.currentFolder, item, false); diff --git a/src/commands/build.ts b/src/commands/build.ts index 6a36b521c..b6decb5a1 100644 --- a/src/commands/build.ts +++ b/src/commands/build.ts @@ -23,14 +23,14 @@ import { FolderContext } from "../FolderContext"; * Executes a {@link vscode.Task task} to run swift target. */ export async function runBuild(ctx: WorkspaceContext) { - await debugBuildWithOptions(ctx, { noDebug: true }); + return await debugBuildWithOptions(ctx, { noDebug: true }); } /** * Executes a {@link vscode.Task task} to debug swift target. */ export async function debugBuild(ctx: WorkspaceContext) { - await debugBuildWithOptions(ctx, {}); + return await debugBuildWithOptions(ctx, {}); } /** @@ -41,7 +41,7 @@ export async function cleanBuild(ctx: WorkspaceContext) { if (!current) { return; } - await folderCleanBuild(current); + return await folderCleanBuild(current); } /** @@ -62,7 +62,7 @@ export async function folderCleanBuild(folderContext: FolderContext) { folderContext.workspaceContext.toolchain ); - await executeTaskWithUI(task, "Clean Build", folderContext); + return await executeTaskWithUI(task, "Clean Build", folderContext); } /** diff --git a/src/debugger/launch.ts b/src/debugger/launch.ts index e96c42023..acb417b6a 100644 --- a/src/debugger/launch.ts +++ b/src/debugger/launch.ts @@ -178,15 +178,17 @@ export async function debugLaunchConfig( config: vscode.DebugConfiguration, options: vscode.DebugSessionOptions = {} ) { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { vscode.debug.startDebugging(workspaceFolder, config, options).then( started => { if (started) { const terminateSession = vscode.debug.onDidTerminateDebugSession(async () => { // dispose terminate debug handler terminateSession.dispose(); - resolve(); + resolve(true); }); + } else { + resolve(false); } }, reason => { diff --git a/test/integration-tests/commands/build.test.ts b/test/integration-tests/commands/build.test.ts new file mode 100644 index 000000000..9fc0ae98a --- /dev/null +++ b/test/integration-tests/commands/build.test.ts @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the VS Code Swift open source project +// +// Copyright (c) 2024 the VS Code Swift project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of VS Code Swift project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import * as vscode from "vscode"; +import * as fs from "fs"; +import * as path from "path"; +import { expect } from "chai"; +import { folderContextPromise, globalWorkspaceContextPromise } from "../extension.test"; +import { waitForNoRunningTasks } from "../../utilities"; +import { testAssetUri } from "../../fixtures"; +import { FolderContext } from "../../../src/FolderContext"; +import { WorkspaceContext } from "../../../src/WorkspaceContext"; +import { Commands } from "../../../src/commands"; +import { makeDebugConfigurations } from "../../../src/debugger/launch"; + +suite("Build Commands", function () { + let folderContext: FolderContext; + let workspaceContext: WorkspaceContext; + const uri = testAssetUri("defaultPackage/Sources/PackageExe/main.swift"); + const breakpoints = [ + new vscode.SourceBreakpoint(new vscode.Location(uri, new vscode.Position(2, 0))), + ]; + + suiteSetup(async function () { + workspaceContext = await globalWorkspaceContextPromise; + await waitForNoRunningTasks(); + folderContext = await folderContextPromise("defaultPackage"); + await workspaceContext.focusFolder(folderContext); + await vscode.window.showTextDocument(uri); + makeDebugConfigurations(folderContext, undefined, true); + }); + + suiteTeardown(async () => { + await vscode.commands.executeCommand("workbench.action.closeAllEditors"); + }); + + test("Swift: Run Build", async () => { + // A breakpoint will have not effect on the Run command. + vscode.debug.addBreakpoints(breakpoints); + + const result = await vscode.commands.executeCommand(Commands.RUN); + expect(result).to.be.true; + + vscode.debug.removeBreakpoints(breakpoints); + }); + + test("Swift: Clean Build", async () => { + const buildPath = path.join(folderContext.folder.fsPath, ".build"); + const beforeItemCount = fs.readdirSync(buildPath).length; + + const result = await vscode.commands.executeCommand(Commands.CLEAN_BUILD); + expect(result).to.be.true; + + const afterItemCount = fs.readdirSync(buildPath).length; + expect(afterItemCount).to.be.lessThan(beforeItemCount); + }); + + test("Swift: Debug Build", async () => { + vscode.debug.addBreakpoints(breakpoints); + + const result = vscode.commands.executeCommand(Commands.DEBUG); + expect(result).to.eventually.be.true; + + await vscode.commands.executeCommand("workbench.action.debug.continue"); + vscode.debug.removeBreakpoints(breakpoints); + }); +}); From 64763077f8ff5aa14bd0366d6aa5495e1e74c9a4 Mon Sep 17 00:00:00 2001 From: "Michael (SPG) Weng" Date: Thu, 31 Oct 2024 14:39:28 -0400 Subject: [PATCH 2/4] - Added module enum for workbench commands string constant - Added comments for clarification - Added utilities to listen for dap message, this is useful for test synchronization. Code takes inspiration from https://github.com/swiftlang/vscode-swift/pull/1126 --- src/ui/ReloadExtension.ts | 3 +- src/utilities/command.ts | 19 +++++ .../BackgroundCompilation.test.ts | 3 +- .../DiagnosticsManager.test.ts | 3 +- test/integration-tests/commands/build.test.ts | 19 ++++- .../editor/CommentCompletion.test.ts | 3 +- test/unit-tests/ui/ReloadExtension.test.ts | 3 +- test/utilities/debug.ts | 78 +++++++++++++++++++ 8 files changed, 123 insertions(+), 8 deletions(-) create mode 100644 src/utilities/command.ts create mode 100644 test/utilities/debug.ts diff --git a/src/ui/ReloadExtension.ts b/src/ui/ReloadExtension.ts index 2ae9f2c8d..47b623cb9 100644 --- a/src/ui/ReloadExtension.ts +++ b/src/ui/ReloadExtension.ts @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// import * as vscode from "vscode"; +import { Workbench } from "../utilities/command"; /** * Prompts the user to reload the extension in cases where we are unable to do @@ -29,7 +30,7 @@ export async function showReloadExtensionNotification( const buttons: ("Reload Extensions" | T)[] = ["Reload Extensions", ...items]; const selected = await vscode.window.showWarningMessage(message, ...buttons); if (selected === "Reload Extensions") { - await vscode.commands.executeCommand("workbench.action.reloadWindow"); + await vscode.commands.executeCommand(Workbench.ACTION_RELOADWINDOW); } return selected; } diff --git a/src/utilities/command.ts b/src/utilities/command.ts new file mode 100644 index 000000000..54d0c724a --- /dev/null +++ b/src/utilities/command.ts @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the VS Code Swift open source project +// +// Copyright (c) 2024 the VS Code Swift project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of VS Code Swift project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +// +export enum Workbench { + ACTION_DEBUG_CONTINUE = "workbench.action.debug.continue", + ACTION_CLOSEALLEDITORS = "workbench.action.closeAllEditors", + ACTION_RELOADWINDOW = "workbench.action.reloadWindow", +} diff --git a/test/integration-tests/BackgroundCompilation.test.ts b/test/integration-tests/BackgroundCompilation.test.ts index 08b14961a..7332697dc 100644 --- a/test/integration-tests/BackgroundCompilation.test.ts +++ b/test/integration-tests/BackgroundCompilation.test.ts @@ -18,6 +18,7 @@ import { WorkspaceContext } from "../../src/WorkspaceContext"; import { globalWorkspaceContextPromise } from "./extension.test"; import { testAssetUri } from "../fixtures"; import { waitForNoRunningTasks } from "../utilities"; +import { Workbench } from "../../src/utilities/command"; suite("BackgroundCompilation Test Suite", () => { let workspaceContext: WorkspaceContext; @@ -31,7 +32,7 @@ suite("BackgroundCompilation Test Suite", () => { suiteTeardown(async () => { await vscode.workspace.getConfiguration("swift").update("backgroundCompilation", undefined); - await vscode.commands.executeCommand("workbench.action.closeActiveEditor"); + await vscode.commands.executeCommand(Workbench.ACTION_CLOSEALLEDITORS); }); test("build all on save @slow", async () => { diff --git a/test/integration-tests/DiagnosticsManager.test.ts b/test/integration-tests/DiagnosticsManager.test.ts index 28acdd340..4e22f94da 100644 --- a/test/integration-tests/DiagnosticsManager.test.ts +++ b/test/integration-tests/DiagnosticsManager.test.ts @@ -23,6 +23,7 @@ import { DiagnosticsManager } from "../../src/DiagnosticsManager"; import { FolderContext } from "../../src/FolderContext"; import { Version } from "../../src/utilities/version"; import { folderContextPromise, globalWorkspaceContextPromise } from "./extension.test"; +import { Workbench } from "../../src/utilities/command"; const waitForDiagnostics = (uris: vscode.Uri[], allowEmpty: boolean = true) => new Promise(res => @@ -907,7 +908,7 @@ suite("DiagnosticsManager Test Suite", async function () { }); teardown(async () => { - await vscode.commands.executeCommand("workbench.action.closeAllEditors"); + await vscode.commands.executeCommand(Workbench.ACTION_CLOSEALLEDITORS); }); test("Provides swift diagnostics", async () => { diff --git a/test/integration-tests/commands/build.test.ts b/test/integration-tests/commands/build.test.ts index 9fc0ae98a..83b2c4c66 100644 --- a/test/integration-tests/commands/build.test.ts +++ b/test/integration-tests/commands/build.test.ts @@ -23,6 +23,8 @@ import { FolderContext } from "../../../src/FolderContext"; import { WorkspaceContext } from "../../../src/WorkspaceContext"; import { Commands } from "../../../src/commands"; import { makeDebugConfigurations } from "../../../src/debugger/launch"; +import { Workbench } from "../../../src/utilities/command"; +import { continueSession, waitForDebugAdapterCommand } from "../../utilities/debug"; suite("Build Commands", function () { let folderContext: FolderContext; @@ -42,7 +44,7 @@ suite("Build Commands", function () { }); suiteTeardown(async () => { - await vscode.commands.executeCommand("workbench.action.closeAllEditors"); + await vscode.commands.executeCommand(Workbench.ACTION_CLOSEALLEDITORS); }); test("Swift: Run Build", async () => { @@ -63,16 +65,27 @@ suite("Build Commands", function () { expect(result).to.be.true; const afterItemCount = fs.readdirSync(buildPath).length; + // This test will run in order after the Swift: Run Build test, + // where .build folder is going to be filled with built artifacts. + // After executing the clean command the build directory is guranteed to have less entry. expect(afterItemCount).to.be.lessThan(beforeItemCount); }); - test("Swift: Debug Build", async () => { + test("Swift: Debug Build @slow", async () => { vscode.debug.addBreakpoints(breakpoints); + // Promise used to indicate we hit the break point. + // NB: "stopped" is the exact command when debuggee has stopped due to break point, + // but "stackTrace" is the deterministic sync point we will use to make sure we can execute continue + const bpPromise = waitForDebugAdapterCommand( + "Debug PackageExe (defaultPackage)", + "stackTrace", + workspaceContext + ); const result = vscode.commands.executeCommand(Commands.DEBUG); expect(result).to.eventually.be.true; - await vscode.commands.executeCommand("workbench.action.debug.continue"); + await bpPromise.then(() => continueSession()); vscode.debug.removeBreakpoints(breakpoints); }); }); diff --git a/test/integration-tests/editor/CommentCompletion.test.ts b/test/integration-tests/editor/CommentCompletion.test.ts index 9f8655a91..13611f418 100644 --- a/test/integration-tests/editor/CommentCompletion.test.ts +++ b/test/integration-tests/editor/CommentCompletion.test.ts @@ -15,6 +15,7 @@ import * as assert from "assert"; import * as vscode from "vscode"; import { CommentCompletionProviders } from "../../../src/editor/CommentCompletion"; +import { Workbench } from "../../../src/utilities/command"; suite("CommentCompletion Test Suite", () => { let document: vscode.TextDocument | undefined; @@ -31,7 +32,7 @@ suite("CommentCompletion Test Suite", () => { if (editor && document) { await vscode.window.showTextDocument(document, editor.viewColumn); - await vscode.commands.executeCommand("workbench.action.closeActiveEditor"); + await vscode.commands.executeCommand(Workbench.ACTION_CLOSEALLEDITORS); } provider.dispose(); diff --git a/test/unit-tests/ui/ReloadExtension.test.ts b/test/unit-tests/ui/ReloadExtension.test.ts index 2c3b3052f..d7cb731f4 100644 --- a/test/unit-tests/ui/ReloadExtension.test.ts +++ b/test/unit-tests/ui/ReloadExtension.test.ts @@ -15,6 +15,7 @@ import { expect } from "chai"; import { mockGlobalObject } from "../../MockUtils"; import * as vscode from "vscode"; import { showReloadExtensionNotification } from "../../../src/ui/ReloadExtension"; +import { Workbench } from "../../../src/utilities/command"; suite("showReloadExtensionNotification()", async function () { const mockedVSCodeWindow = mockGlobalObject(vscode, "window"); @@ -38,7 +39,7 @@ suite("showReloadExtensionNotification()", async function () { await showReloadExtensionNotification("Want to reload?"); expect(mockedVSCodeCommands.executeCommand).to.have.been.calledOnceWithExactly( - "workbench.action.reloadWindow" + Workbench.ACTION_RELOADWINDOW ); }); diff --git a/test/utilities/debug.ts b/test/utilities/debug.ts new file mode 100644 index 000000000..3f929efc5 --- /dev/null +++ b/test/utilities/debug.ts @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the VS Code Swift open source project +// +// Copyright (c) 2024 the VS Code Swift project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of VS Code Swift project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +import * as vscode from "vscode"; +import { Workbench } from "../../src/utilities/command"; +import { DebugAdapter } from "../../src/debugger/debugAdapter"; +import { WorkspaceContext } from "../../src/WorkspaceContext"; + +export async function continueSession(): Promise { + await vscode.commands.executeCommand(Workbench.ACTION_DEBUG_CONTINUE); +} + +/** + * Waits for a specific message from the debug adapter. + * + * @param name The name of the debug session to wait for. + * @param matches A function to match the desired message. + * @param workspaceContext The workspace context containing toolchain information. + * @returns A promise that resolves with the matching message. + */ +export async function waitForDebugAdapterMessage( + name: string, + matches: (message: any) => boolean, + workspaceContext: WorkspaceContext +): Promise { + return await new Promise(res => { + const disposable = vscode.debug.registerDebugAdapterTrackerFactory( + DebugAdapter.getLaunchConfigType(workspaceContext.toolchain.swiftVersion), + { + createDebugAdapterTracker: function ( + session: vscode.DebugSession + ): vscode.ProviderResult { + if (session.name !== name) { + return; + } + return { + onDidSendMessage(message) { + if (matches(message)) { + disposable.dispose(); + res(message); + } + }, + }; + }, + } + ); + }); +} + +/** + * Waits for a specific command to be sent by the debug adapter. + * + * @param name The name of the debug session to wait for. + * @param command The command to wait for. + * @param workspaceContext The workspace context containing toolchain information. + * @returns A promise that resolves with the matching command message. + */ +export async function waitForDebugAdapterCommand( + name: string, + command: string, + workspaceContext: WorkspaceContext +): Promise { + return await waitForDebugAdapterMessage( + name, + (m: any) => m.command === command, + workspaceContext + ); +} From 240dc390b7274d1a0656521ca43f692374382c33 Mon Sep 17 00:00:00 2001 From: "Michael (SPG) Weng" Date: Thu, 31 Oct 2024 15:04:25 -0400 Subject: [PATCH 3/4] - Rename from utilies/command.ts to utilies/commands.ts - Minor cosmetic change to utilies/commands.ts --- src/ui/ReloadExtension.ts | 2 +- src/utilities/{command.ts => commands.ts} | 2 +- test/integration-tests/BackgroundCompilation.test.ts | 2 +- test/integration-tests/DiagnosticsManager.test.ts | 2 +- test/integration-tests/commands/build.test.ts | 2 +- test/integration-tests/editor/CommentCompletion.test.ts | 2 +- test/unit-tests/ui/ReloadExtension.test.ts | 2 +- test/utilities/debug.ts | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) rename src/utilities/{command.ts => commands.ts} (99%) diff --git a/src/ui/ReloadExtension.ts b/src/ui/ReloadExtension.ts index 47b623cb9..b8d201589 100644 --- a/src/ui/ReloadExtension.ts +++ b/src/ui/ReloadExtension.ts @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import * as vscode from "vscode"; -import { Workbench } from "../utilities/command"; +import { Workbench } from "../utilities/commands"; /** * Prompts the user to reload the extension in cases where we are unable to do diff --git a/src/utilities/command.ts b/src/utilities/commands.ts similarity index 99% rename from src/utilities/command.ts rename to src/utilities/commands.ts index 54d0c724a..cc994f76c 100644 --- a/src/utilities/command.ts +++ b/src/utilities/commands.ts @@ -11,7 +11,7 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// -// + export enum Workbench { ACTION_DEBUG_CONTINUE = "workbench.action.debug.continue", ACTION_CLOSEALLEDITORS = "workbench.action.closeAllEditors", diff --git a/test/integration-tests/BackgroundCompilation.test.ts b/test/integration-tests/BackgroundCompilation.test.ts index 7332697dc..e39ecd3f7 100644 --- a/test/integration-tests/BackgroundCompilation.test.ts +++ b/test/integration-tests/BackgroundCompilation.test.ts @@ -18,7 +18,7 @@ import { WorkspaceContext } from "../../src/WorkspaceContext"; import { globalWorkspaceContextPromise } from "./extension.test"; import { testAssetUri } from "../fixtures"; import { waitForNoRunningTasks } from "../utilities"; -import { Workbench } from "../../src/utilities/command"; +import { Workbench } from "../../src/utilities/commands"; suite("BackgroundCompilation Test Suite", () => { let workspaceContext: WorkspaceContext; diff --git a/test/integration-tests/DiagnosticsManager.test.ts b/test/integration-tests/DiagnosticsManager.test.ts index 4e22f94da..e84d2d18c 100644 --- a/test/integration-tests/DiagnosticsManager.test.ts +++ b/test/integration-tests/DiagnosticsManager.test.ts @@ -23,7 +23,7 @@ import { DiagnosticsManager } from "../../src/DiagnosticsManager"; import { FolderContext } from "../../src/FolderContext"; import { Version } from "../../src/utilities/version"; import { folderContextPromise, globalWorkspaceContextPromise } from "./extension.test"; -import { Workbench } from "../../src/utilities/command"; +import { Workbench } from "../../src/utilities/commands"; const waitForDiagnostics = (uris: vscode.Uri[], allowEmpty: boolean = true) => new Promise(res => diff --git a/test/integration-tests/commands/build.test.ts b/test/integration-tests/commands/build.test.ts index 83b2c4c66..fc0f3f988 100644 --- a/test/integration-tests/commands/build.test.ts +++ b/test/integration-tests/commands/build.test.ts @@ -23,7 +23,7 @@ import { FolderContext } from "../../../src/FolderContext"; import { WorkspaceContext } from "../../../src/WorkspaceContext"; import { Commands } from "../../../src/commands"; import { makeDebugConfigurations } from "../../../src/debugger/launch"; -import { Workbench } from "../../../src/utilities/command"; +import { Workbench } from "../../../src/utilities/commands"; import { continueSession, waitForDebugAdapterCommand } from "../../utilities/debug"; suite("Build Commands", function () { diff --git a/test/integration-tests/editor/CommentCompletion.test.ts b/test/integration-tests/editor/CommentCompletion.test.ts index 13611f418..0d4f9ecb8 100644 --- a/test/integration-tests/editor/CommentCompletion.test.ts +++ b/test/integration-tests/editor/CommentCompletion.test.ts @@ -15,7 +15,7 @@ import * as assert from "assert"; import * as vscode from "vscode"; import { CommentCompletionProviders } from "../../../src/editor/CommentCompletion"; -import { Workbench } from "../../../src/utilities/command"; +import { Workbench } from "../../../src/utilities/commands"; suite("CommentCompletion Test Suite", () => { let document: vscode.TextDocument | undefined; diff --git a/test/unit-tests/ui/ReloadExtension.test.ts b/test/unit-tests/ui/ReloadExtension.test.ts index d7cb731f4..422bfce23 100644 --- a/test/unit-tests/ui/ReloadExtension.test.ts +++ b/test/unit-tests/ui/ReloadExtension.test.ts @@ -15,7 +15,7 @@ import { expect } from "chai"; import { mockGlobalObject } from "../../MockUtils"; import * as vscode from "vscode"; import { showReloadExtensionNotification } from "../../../src/ui/ReloadExtension"; -import { Workbench } from "../../../src/utilities/command"; +import { Workbench } from "../../../src/utilities/commands"; suite("showReloadExtensionNotification()", async function () { const mockedVSCodeWindow = mockGlobalObject(vscode, "window"); diff --git a/test/utilities/debug.ts b/test/utilities/debug.ts index 3f929efc5..083438ab2 100644 --- a/test/utilities/debug.ts +++ b/test/utilities/debug.ts @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// import * as vscode from "vscode"; -import { Workbench } from "../../src/utilities/command"; +import { Workbench } from "../../src/utilities/commands"; import { DebugAdapter } from "../../src/debugger/debugAdapter"; import { WorkspaceContext } from "../../src/WorkspaceContext"; From da75453705ab234560aa512ca1d0957208cbf465 Mon Sep 17 00:00:00 2001 From: "Michael (SPG) Weng" Date: Tue, 5 Nov 2024 17:04:12 -0500 Subject: [PATCH 4/4] - Fix a bug in updateSettings where promise is not being exlicitly returned, causing restore of setting being not awaitable - Make makeDebugConfigurations to be awaitable - Change launch to also update the key for ASLR disable settings - Make the test properly set up and reset the settings that update the launch config --- src/debugger/launch.ts | 11 +++++++++-- test/integration-tests/commands/build.test.ts | 8 +++++++- .../testexplorer/TestExplorerIntegration.test.ts | 3 ++- test/integration-tests/testexplorer/utilities.ts | 6 ++---- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/debugger/launch.ts b/src/debugger/launch.ts index acb417b6a..87bf04edf 100644 --- a/src/debugger/launch.ts +++ b/src/debugger/launch.ts @@ -29,9 +29,13 @@ import { CI_DISABLE_ASLR } from "./lldb"; * @param ctx folder context to create launch configurations for * @param yes automatically answer yes to dialogs */ -export async function makeDebugConfigurations(ctx: FolderContext, message?: string, yes = false) { +export async function makeDebugConfigurations( + ctx: FolderContext, + message?: string, + yes = false +): Promise { if (!configuration.folder(ctx.workspaceFolder).autoGenerateLaunchConfigurations) { - return; + return false; } const wsLaunchSection = vscode.workspace.getConfiguration("launch", ctx.folder); const launchConfigs = wsLaunchSection.get("configurations") || []; @@ -41,6 +45,8 @@ export async function makeDebugConfigurations(ctx: FolderContext, message?: stri "cwd", "preLaunchTask", "type", + "disableASLR", + "initCommands", `env.${swiftLibraryPathKey()}`, ]; const configUpdates: { index: number; config: vscode.DebugConfiguration }[] = []; @@ -96,6 +102,7 @@ export async function makeDebugConfigurations(ctx: FolderContext, message?: stri vscode.ConfigurationTarget.WorkspaceFolder ); } + return true; } // Return debug launch configuration for an executable in the given folder diff --git a/test/integration-tests/commands/build.test.ts b/test/integration-tests/commands/build.test.ts index fc0f3f988..9d59656a5 100644 --- a/test/integration-tests/commands/build.test.ts +++ b/test/integration-tests/commands/build.test.ts @@ -25,10 +25,12 @@ import { Commands } from "../../../src/commands"; import { makeDebugConfigurations } from "../../../src/debugger/launch"; import { Workbench } from "../../../src/utilities/commands"; import { continueSession, waitForDebugAdapterCommand } from "../../utilities/debug"; +import { SettingsMap, updateSettings } from "../testexplorer/utilities"; suite("Build Commands", function () { let folderContext: FolderContext; let workspaceContext: WorkspaceContext; + let settingsTeardown: () => Promise; const uri = testAssetUri("defaultPackage/Sources/PackageExe/main.swift"); const breakpoints = [ new vscode.SourceBreakpoint(new vscode.Location(uri, new vscode.Position(2, 0))), @@ -40,10 +42,14 @@ suite("Build Commands", function () { folderContext = await folderContextPromise("defaultPackage"); await workspaceContext.focusFolder(folderContext); await vscode.window.showTextDocument(uri); - makeDebugConfigurations(folderContext, undefined, true); + settingsTeardown = await updateSettings({ + "swift.autoGenerateLaunchConfigurations": true, + }); + await makeDebugConfigurations(folderContext, undefined, true); }); suiteTeardown(async () => { + await settingsTeardown(); await vscode.commands.executeCommand(Workbench.ACTION_CLOSEALLEDITORS); }); diff --git a/test/integration-tests/testexplorer/TestExplorerIntegration.test.ts b/test/integration-tests/testexplorer/TestExplorerIntegration.test.ts index cdd9533a4..02bd97b60 100644 --- a/test/integration-tests/testexplorer/TestExplorerIntegration.test.ts +++ b/test/integration-tests/testexplorer/TestExplorerIntegration.test.ts @@ -24,6 +24,7 @@ import { eventPromise, gatherTests, runTest, + SettingsMap, setupTestExplorerTest, waitForTestExplorerReady, } from "./utilities"; @@ -51,7 +52,7 @@ suite("Test Explorer Suite", function () { let testExplorer: TestExplorer; suite("Debugging", function () { - let settingsTeardown: () => void; + let settingsTeardown: () => Promise; async function runXCTest() { const suiteId = "PackageTests.PassingXCTestSuite"; diff --git a/test/integration-tests/testexplorer/utilities.ts b/test/integration-tests/testexplorer/utilities.ts index 4f7a9b52b..ec310067d 100644 --- a/test/integration-tests/testexplorer/utilities.ts +++ b/test/integration-tests/testexplorer/utilities.ts @@ -188,7 +188,7 @@ export type SettingsMap = { [key: string]: unknown }; * "section.name" format, and the value is the new setting value. * @returns A function that, when called, resets the settings back to their original values. */ -export async function updateSettings(settings: SettingsMap): Promise<() => Promise> { +export async function updateSettings(settings: SettingsMap): Promise<() => Promise> { const applySettings = async (settings: SettingsMap) => { const savedOriginalSettings: SettingsMap = {}; Object.keys(settings).forEach(async setting => { @@ -224,9 +224,7 @@ export async function updateSettings(settings: SettingsMap): Promise<() => Promi const savedOriginalSettings = await applySettings(settings); // Clients call the callback to reset updated settings to their original value - return async () => { - await applySettings(savedOriginalSettings); - }; + return async () => await applySettings(savedOriginalSettings); } /**