From df7b15715c1a0c0f95d301be338269b028bb0d0a Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Thu, 3 Oct 2024 15:31:01 -0400 Subject: [PATCH 01/13] Add test snippet source --- assets/test/defaultPackage/Package.swift | 5 +++++ assets/test/defaultPackage/Package@swift-6.0.swift | 5 +++++ assets/test/defaultPackage/Snippets/hello.swift | 3 +++ 3 files changed, 13 insertions(+) create mode 100644 assets/test/defaultPackage/Snippets/hello.swift diff --git a/assets/test/defaultPackage/Package.swift b/assets/test/defaultPackage/Package.swift index 277eda1df..6ea1984f1 100644 --- a/assets/test/defaultPackage/Package.swift +++ b/assets/test/defaultPackage/Package.swift @@ -5,6 +5,11 @@ import PackageDescription let package = Package( name: "defaultPackage", + products: [ + .library( + name: "PackageLib", + targets: ["PackageLib"]), + ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. // Targets can depend on other targets in this package, and on products in packages this package depends on. diff --git a/assets/test/defaultPackage/Package@swift-6.0.swift b/assets/test/defaultPackage/Package@swift-6.0.swift index e855e5e3e..838242e8c 100644 --- a/assets/test/defaultPackage/Package@swift-6.0.swift +++ b/assets/test/defaultPackage/Package@swift-6.0.swift @@ -8,6 +8,11 @@ let package = Package( platforms: [ .macOS(.v13) ], + products: [ + .library( + name: "PackageLib", + targets: ["PackageLib"]), + ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. // Targets can depend on other targets in this package, and on products in packages this package depends on. diff --git a/assets/test/defaultPackage/Snippets/hello.swift b/assets/test/defaultPackage/Snippets/hello.swift new file mode 100644 index 000000000..98cb0a220 --- /dev/null +++ b/assets/test/defaultPackage/Snippets/hello.swift @@ -0,0 +1,3 @@ +import PackageLib + +print("hello \(a)") \ No newline at end of file From b56e2c5d0ea6c087aaf553711b379650b0f3b358 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Mon, 7 Oct 2024 11:24:26 -0400 Subject: [PATCH 02/13] Add tests for the Swift snippets workflows * Created some common utilities for dealing with debug sessions * Add integration test for run command and debug variant, big difference being whether the breakpoint is hit or not Issue: #1125 --- .../BackgroundCompilation.test.ts | 2 +- .../DiagnosticsManager.test.ts | 2 +- test/integration-tests/SwiftSnippet.test.ts | 87 +++++++++++++++++++ .../tasks/SwiftExecution.test.ts | 2 +- .../tasks/SwiftPluginTaskProvider.test.ts | 8 +- .../tasks/SwiftPseudoterminal.test.ts | 2 +- .../tasks/SwiftTaskProvider.test.ts | 2 +- .../tasks/TaskManager.test.ts | 2 +- .../integration-tests/tasks/TaskQueue.test.ts | 2 +- test/utilities/debug.ts | 53 ++++++++--- test/{utilities.ts => utilities/tasks.ts} | 4 +- test/utilities/types.ts | 21 +++++ 12 files changed, 160 insertions(+), 27 deletions(-) create mode 100644 test/integration-tests/SwiftSnippet.test.ts rename test/{utilities.ts => utilities/tasks.ts} (97%) create mode 100644 test/utilities/types.ts diff --git a/test/integration-tests/BackgroundCompilation.test.ts b/test/integration-tests/BackgroundCompilation.test.ts index 54f4d4456..90c8660a4 100644 --- a/test/integration-tests/BackgroundCompilation.test.ts +++ b/test/integration-tests/BackgroundCompilation.test.ts @@ -16,7 +16,7 @@ import * as assert from "assert"; import * as vscode from "vscode"; import { WorkspaceContext } from "../../src/WorkspaceContext"; import { testAssetUri } from "../fixtures"; -import { waitForNoRunningTasks } from "../utilities"; +import { waitForNoRunningTasks } from "../utilities/tasks"; import { Workbench } from "../../src/utilities/commands"; import { activateExtensionForTest, updateSettings } from "./utilities/testutilities"; diff --git a/test/integration-tests/DiagnosticsManager.test.ts b/test/integration-tests/DiagnosticsManager.test.ts index 03f1e82f6..a075e421c 100644 --- a/test/integration-tests/DiagnosticsManager.test.ts +++ b/test/integration-tests/DiagnosticsManager.test.ts @@ -15,7 +15,7 @@ import * as assert from "assert"; import * as vscode from "vscode"; import { SwiftToolchain } from "../../src/toolchain/toolchain"; -import { executeTaskAndWaitForResult, waitForNoRunningTasks } from "../utilities"; +import { executeTaskAndWaitForResult, waitForNoRunningTasks } from "../utilities/tasks"; import { WorkspaceContext } from "../../src/WorkspaceContext"; import { testAssetWorkspaceFolder, testSwiftTask } from "../fixtures"; import { createBuildAllTask } from "../../src/tasks/SwiftTaskProvider"; diff --git a/test/integration-tests/SwiftSnippet.test.ts b/test/integration-tests/SwiftSnippet.test.ts new file mode 100644 index 000000000..e94f69eb7 --- /dev/null +++ b/test/integration-tests/SwiftSnippet.test.ts @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// 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 { folderContextPromise } from "./extension.test"; +import { testAssetPath, testAssetUri } from "../fixtures"; +import { waitForNoRunningTasks } from "../utilities/tasks"; +import { expect } from "chai"; +import { + continueSession, + waitForDebugAdapterCommand, + waitForDebugAdapterExit, + waitUntilDebugSessionTerminates, +} from "../utilities/debug"; + +suite("SwiftSnippet Test Suite", () => { + const uri = testAssetUri("defaultPackage/Snippets/hello.swift"); + const breakpoints = [ + new vscode.SourceBreakpoint(new vscode.Location(uri, new vscode.Position(2, 0))), + ]; + + suiteSetup(async () => { + await folderContextPromise("defaultPackage"); + await waitForNoRunningTasks(); + + // File needs to be open for command to be enabled + const doc = await vscode.workspace.openTextDocument(uri.fsPath); + await vscode.window.showTextDocument(doc); + + // Set a breakpoint + vscode.debug.addBreakpoints(breakpoints); + }); + + suiteTeardown(async () => { + await vscode.commands.executeCommand("workbench.action.closeAllEditors"); + vscode.debug.removeBreakpoints(breakpoints); + }); + + test("Run `Swift: Run Swift Snippet` command for snippet file", async () => { + const sessionPromise = waitUntilDebugSessionTerminates("Run hello"); + const exitPromise = waitForDebugAdapterExit("Run hello"); + + await vscode.commands.executeCommand("swift.runSnippet"); + + const exitCode = await exitPromise; + expect(exitCode).to.equal(0); + + const session = await sessionPromise; + expect(session.configuration).to.have.property( + "program", + `${testAssetPath("defaultPackage")}/.build/debug/hello` + ); + expect(session.configuration).to.have.property("noDebug", true); + }).timeout(120000); + + test("Run `Swift: Debug Swift Snippet` command for snippet file", async () => { + const bpPromise = waitForDebugAdapterCommand("Run hello", "stackTrace"); + const sessionPromise = waitUntilDebugSessionTerminates("Run hello"); + const exitPromise = waitForDebugAdapterExit("Run hello"); + + vscode.commands.executeCommand("swift.debugSnippet"); + + // Once bp is hit, continue + await bpPromise.then(() => continueSession()); + + const exitCode = await exitPromise; + expect(exitCode).to.equal(0); + + const session = await sessionPromise; + expect(session.configuration).to.have.property( + "program", + `${testAssetPath("defaultPackage")}/.build/debug/hello` + ); + expect(session.configuration).to.not.have.property("noDebug"); + }).timeout(120000); +}); diff --git a/test/integration-tests/tasks/SwiftExecution.test.ts b/test/integration-tests/tasks/SwiftExecution.test.ts index 7558a8912..a4d7867e2 100644 --- a/test/integration-tests/tasks/SwiftExecution.test.ts +++ b/test/integration-tests/tasks/SwiftExecution.test.ts @@ -16,7 +16,7 @@ import * as vscode from "vscode"; import * as assert from "assert"; import { testSwiftTask } from "../../fixtures"; import { WorkspaceContext } from "../../../src/WorkspaceContext"; -import { executeTaskAndWaitForResult, waitForNoRunningTasks } from "../../utilities"; +import { executeTaskAndWaitForResult, waitForNoRunningTasks } from "../../utilities/tasks"; import { SwiftToolchain } from "../../../src/toolchain/toolchain"; import { activateExtensionForSuite } from "../utilities/testutilities"; diff --git a/test/integration-tests/tasks/SwiftPluginTaskProvider.test.ts b/test/integration-tests/tasks/SwiftPluginTaskProvider.test.ts index 23dc46d67..b1eba333b 100644 --- a/test/integration-tests/tasks/SwiftPluginTaskProvider.test.ts +++ b/test/integration-tests/tasks/SwiftPluginTaskProvider.test.ts @@ -19,12 +19,8 @@ import { WorkspaceContext } from "../../../src/WorkspaceContext"; import { SwiftPluginTaskProvider } from "../../../src/tasks/SwiftPluginTaskProvider"; import { FolderContext } from "../../../src/FolderContext"; import { activateExtensionForSuite, folderInRootWorkspace } from "../utilities/testutilities"; -import { - cleanOutput, - executeTaskAndWaitForResult, - mutable, - waitForEndTaskProcess, -} from "../../utilities"; +import { cleanOutput, executeTaskAndWaitForResult, waitForEndTaskProcess } from "../../utilities/tasks"; +import { mutable } from "../../utilities/types"; suite("SwiftPluginTaskProvider Test Suite", () => { let workspaceContext: WorkspaceContext; diff --git a/test/integration-tests/tasks/SwiftPseudoterminal.test.ts b/test/integration-tests/tasks/SwiftPseudoterminal.test.ts index a88863ffe..92f5a6ea9 100644 --- a/test/integration-tests/tasks/SwiftPseudoterminal.test.ts +++ b/test/integration-tests/tasks/SwiftPseudoterminal.test.ts @@ -15,7 +15,7 @@ import * as assert from "assert"; import * as vscode from "vscode"; import { TestSwiftProcess } from "../../fixtures"; -import { waitForClose, waitForWrite } from "../../utilities"; +import { waitForClose, waitForWrite } from "../../utilities/tasks"; import { SwiftPseudoterminal } from "../../../src/tasks/SwiftPseudoterminal"; suite("SwiftPseudoterminal Tests Suite", () => { diff --git a/test/integration-tests/tasks/SwiftTaskProvider.test.ts b/test/integration-tests/tasks/SwiftTaskProvider.test.ts index 291ebbefe..d28657fac 100644 --- a/test/integration-tests/tasks/SwiftTaskProvider.test.ts +++ b/test/integration-tests/tasks/SwiftTaskProvider.test.ts @@ -27,7 +27,7 @@ import { executeTaskAndWaitForResult, waitForEndTaskProcess, waitForNoRunningTasks, -} from "../../utilities"; +} from "../../utilities/tasks"; import { Version } from "../../../src/utilities/version"; import { FolderContext } from "../../../src/FolderContext"; import { mockGlobalObject } from "../../MockUtils"; diff --git a/test/integration-tests/tasks/TaskManager.test.ts b/test/integration-tests/tasks/TaskManager.test.ts index 9f6cae9b1..bb05883e7 100644 --- a/test/integration-tests/tasks/TaskManager.test.ts +++ b/test/integration-tests/tasks/TaskManager.test.ts @@ -16,8 +16,8 @@ import * as vscode from "vscode"; import * as assert from "assert"; import { TaskManager } from "../../../src/tasks/TaskManager"; import { WorkspaceContext } from "../../../src/WorkspaceContext"; -import { waitForNoRunningTasks } from "../../utilities"; import { activateExtensionForSuite } from "../utilities/testutilities"; +import { waitForNoRunningTasks } from "../../utilities/tasks"; suite("TaskManager Test Suite", () => { let workspaceContext: WorkspaceContext; diff --git a/test/integration-tests/tasks/TaskQueue.test.ts b/test/integration-tests/tasks/TaskQueue.test.ts index b80c28af6..113d3ce7a 100644 --- a/test/integration-tests/tasks/TaskQueue.test.ts +++ b/test/integration-tests/tasks/TaskQueue.test.ts @@ -17,7 +17,7 @@ import * as assert from "assert"; import { testAssetPath } from "../../fixtures"; import { WorkspaceContext } from "../../../src/WorkspaceContext"; import { SwiftExecOperation, TaskOperation, TaskQueue } from "../../../src/tasks/TaskQueue"; -import { waitForNoRunningTasks } from "../../utilities"; +import { waitForNoRunningTasks } from "../../utilities/tasks"; import { activateExtensionForSuite } from "../utilities/testutilities"; suite("TaskQueue Test Suite", () => { diff --git a/test/utilities/debug.ts b/test/utilities/debug.ts index 083438ab2..09c6bd713 100644 --- a/test/utilities/debug.ts +++ b/test/utilities/debug.ts @@ -31,11 +31,10 @@ export async function continueSession(): Promise { 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), + "swift-lldb", { createDebugAdapterTracker: function ( session: vscode.DebugSession @@ -57,6 +56,22 @@ export async function waitForDebugAdapterMessage( }); } +/** + * Waits for a specific debug session to terminate. + * + * @param name The name of the debug session to wait for. + * @returns the terminated DebugSession + */ +export async function waitUntilDebugSessionTerminates(name: string): Promise { + return await new Promise(res => + vscode.debug.onDidTerminateDebugSession(e => { + if (e.name === name) { + res(e); + } + }) + ); +} + /** * Waits for a specific command to be sent by the debug adapter. * @@ -65,14 +80,28 @@ export async function waitForDebugAdapterMessage( * @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 - ); +export async function waitForDebugAdapterCommand(name: string, command: string): Promise { + return await waitForDebugAdapterMessage(name, (m: any) => m.command === command); +} + +/** + * Waits for a specific event 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 event. + */ +export async function waitForDebugAdapterEvent(name: string, event: string): Promise { + return await waitForDebugAdapterMessage(name, (m: any) => m.event === event); +} + +/** + * Waits for a debug adapter for the specified DebugSession name to terminate. + * + * @param name The name of the debug session to wait for. + * @returns exit code of the DAP + */ +export async function waitForDebugAdapterExit(name: string): Promise { + return await waitForDebugAdapterEvent(name, "exited").then(m => m.body.exitCode); } diff --git a/test/utilities.ts b/test/utilities/tasks.ts similarity index 97% rename from test/utilities.ts rename to test/utilities/tasks.ts index 92ade71a4..ecdaa8cc0 100644 --- a/test/utilities.ts +++ b/test/utilities/tasks.ts @@ -15,8 +15,8 @@ import * as vscode from "vscode"; // eslint-disable-next-line @typescript-eslint/no-require-imports import stripAnsi = require("strip-ansi"); -import { SwiftTaskFixture } from "./fixtures"; -import { SwiftTask } from "../src/tasks/SwiftTaskProvider"; +import { SwiftTaskFixture } from "../fixtures"; +import { SwiftTask } from "../../src/tasks/SwiftTaskProvider"; export type Mutable = { -readonly [K in keyof T]: T[K]; diff --git a/test/utilities/types.ts b/test/utilities/types.ts new file mode 100644 index 000000000..f2547ee7c --- /dev/null +++ b/test/utilities/types.ts @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// 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 type Mutable = { + -readonly [K in keyof T]: T[K]; +}; + +export function mutable(target: T): Mutable { + return target; +} From 57be6b0e40da6ce2514138b228961910bb343dbf Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Mon, 7 Oct 2024 11:40:44 -0400 Subject: [PATCH 03/13] Fix build error after rebase --- test/integration-tests/ui/PackageDependencyProvider.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration-tests/ui/PackageDependencyProvider.test.ts b/test/integration-tests/ui/PackageDependencyProvider.test.ts index bec1e9903..6eb79235b 100644 --- a/test/integration-tests/ui/PackageDependencyProvider.test.ts +++ b/test/integration-tests/ui/PackageDependencyProvider.test.ts @@ -19,7 +19,7 @@ import { PackageDependenciesProvider, PackageNode, } from "../../../src/ui/PackageDependencyProvider"; -import { executeTaskAndWaitForResult, waitForNoRunningTasks } from "../../utilities"; +import { executeTaskAndWaitForResult, waitForNoRunningTasks } from "../../utilities/tasks"; import { getBuildAllTask, SwiftTask } from "../../../src/tasks/SwiftTaskProvider"; import { testAssetPath } from "../../fixtures"; import { activateExtensionForSuite, folderInRootWorkspace } from "../utilities/testutilities"; From 1a97dd6364f615f7377a489319295ced30647f9f Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Wed, 9 Oct 2024 14:46:56 -0400 Subject: [PATCH 04/13] Only run these test on 6.0+ toolchain CodeLLDB is not working with older toolchains so need to use lldb-dap --- test/integration-tests/SwiftSnippet.test.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/integration-tests/SwiftSnippet.test.ts b/test/integration-tests/SwiftSnippet.test.ts index e94f69eb7..bfb9afa91 100644 --- a/test/integration-tests/SwiftSnippet.test.ts +++ b/test/integration-tests/SwiftSnippet.test.ts @@ -23,6 +23,7 @@ import { waitForDebugAdapterExit, waitUntilDebugSessionTerminates, } from "../utilities/debug"; +import { Version } from "../../src/utilities/version"; suite("SwiftSnippet Test Suite", () => { const uri = testAssetUri("defaultPackage/Snippets/hello.swift"); @@ -30,8 +31,11 @@ suite("SwiftSnippet Test Suite", () => { new vscode.SourceBreakpoint(new vscode.Location(uri, new vscode.Position(2, 0))), ]; - suiteSetup(async () => { - await folderContextPromise("defaultPackage"); + suiteSetup(async function () { + const folder = await folderContextPromise("defaultPackage"); + if (folder.workspaceContext.toolchain.swiftVersion.isLessThan(new Version(6, 0, 0))) { + this.skip(); + } await waitForNoRunningTasks(); // File needs to be open for command to be enabled From cdf5d54edae07ee967c8abdaecb0c4d3dc0aa722 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Tue, 10 Dec 2024 11:12:43 -0500 Subject: [PATCH 05/13] Fix errors after rebase --- test/integration-tests/SwiftSnippet.test.ts | 32 +++++++++++-------- test/integration-tests/commands/build.test.ts | 3 +- .../commands/dependency.test.ts | 2 +- test/integration-tests/language/macro.test.ts | 2 +- .../utilities/testutilities.ts | 2 +- 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/test/integration-tests/SwiftSnippet.test.ts b/test/integration-tests/SwiftSnippet.test.ts index bfb9afa91..3c89c64e6 100644 --- a/test/integration-tests/SwiftSnippet.test.ts +++ b/test/integration-tests/SwiftSnippet.test.ts @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// import * as vscode from "vscode"; -import { folderContextPromise } from "./extension.test"; import { testAssetPath, testAssetUri } from "../fixtures"; import { waitForNoRunningTasks } from "../utilities/tasks"; import { expect } from "chai"; @@ -24,26 +23,33 @@ import { waitUntilDebugSessionTerminates, } from "../utilities/debug"; import { Version } from "../../src/utilities/version"; +import { activateExtensionForSuite, folderInRootWorkspace } from "./utilities/testutilities"; +import { WorkspaceContext } from "../../src/WorkspaceContext"; suite("SwiftSnippet Test Suite", () => { const uri = testAssetUri("defaultPackage/Snippets/hello.swift"); const breakpoints = [ new vscode.SourceBreakpoint(new vscode.Location(uri, new vscode.Position(2, 0))), ]; + let workspaceContext: WorkspaceContext; - suiteSetup(async function () { - const folder = await folderContextPromise("defaultPackage"); - if (folder.workspaceContext.toolchain.swiftVersion.isLessThan(new Version(6, 0, 0))) { - this.skip(); - } - await waitForNoRunningTasks(); + activateExtensionForSuite({ + async setup(ctx) { + workspaceContext = ctx; - // File needs to be open for command to be enabled - const doc = await vscode.workspace.openTextDocument(uri.fsPath); - await vscode.window.showTextDocument(doc); - - // Set a breakpoint - vscode.debug.addBreakpoints(breakpoints); + const folder = await folderInRootWorkspace("defaultPackage", workspaceContext); + if (folder.workspaceContext.toolchain.swiftVersion.isLessThan(new Version(6, 0, 0))) { + this.skip(); + } + await waitForNoRunningTasks(); + + // File needs to be open for command to be enabled + const doc = await vscode.workspace.openTextDocument(uri.fsPath); + await vscode.window.showTextDocument(doc); + + // Set a breakpoint + vscode.debug.addBreakpoints(breakpoints); + }, }); suiteTeardown(async () => { diff --git a/test/integration-tests/commands/build.test.ts b/test/integration-tests/commands/build.test.ts index 00d45f8b1..443b46075 100644 --- a/test/integration-tests/commands/build.test.ts +++ b/test/integration-tests/commands/build.test.ts @@ -16,7 +16,7 @@ import * as vscode from "vscode"; import * as fs from "fs/promises"; import * as path from "path"; import { expect } from "chai"; -import { waitForNoRunningTasks } from "../../utilities"; +import { waitForNoRunningTasks } from "../../utilities/tasks"; import { testAssetUri } from "../../fixtures"; import { FolderContext } from "../../../src/FolderContext"; import { WorkspaceContext } from "../../../src/WorkspaceContext"; @@ -100,7 +100,6 @@ suite("Build Commands", function () { const bpPromise = waitForDebugAdapterCommand( "Debug PackageExe (defaultPackage)", "stackTrace", - workspaceContext ); const result = vscode.commands.executeCommand(Commands.DEBUG); diff --git a/test/integration-tests/commands/dependency.test.ts b/test/integration-tests/commands/dependency.test.ts index b5b9ec2d3..ec8c312f2 100644 --- a/test/integration-tests/commands/dependency.test.ts +++ b/test/integration-tests/commands/dependency.test.ts @@ -18,7 +18,7 @@ import { PackageDependenciesProvider, PackageNode, } from "../../../src/ui/PackageDependencyProvider"; -import { executeTaskAndWaitForResult, waitForNoRunningTasks } from "../../utilities"; +import { executeTaskAndWaitForResult, waitForNoRunningTasks } from "../../utilities/tasks"; import { getBuildAllTask, SwiftTask } from "../../../src/tasks/SwiftTaskProvider"; import { testAssetUri } from "../../fixtures"; import { FolderContext } from "../../../src/FolderContext"; diff --git a/test/integration-tests/language/macro.test.ts b/test/integration-tests/language/macro.test.ts index ae2a47cbe..9defec831 100644 --- a/test/integration-tests/language/macro.test.ts +++ b/test/integration-tests/language/macro.test.ts @@ -19,7 +19,7 @@ import { LanguageClientManager } from "../../../src/sourcekit-lsp/LanguageClient import { WorkspaceContext } from "../../../src/WorkspaceContext"; import { testAssetUri } from "../../fixtures"; import { FolderContext } from "../../../src/FolderContext"; -import { executeTaskAndWaitForResult, waitForNoRunningTasks } from "../../utilities"; +import { executeTaskAndWaitForResult, waitForNoRunningTasks } from "../../utilities/tasks"; import { getBuildAllTask, SwiftTask } from "../../../src/tasks/SwiftTaskProvider"; import { Version } from "../../../src/utilities/version"; import { activateExtensionForSuite, folderInRootWorkspace } from "../utilities/testutilities"; diff --git a/test/integration-tests/utilities/testutilities.ts b/test/integration-tests/utilities/testutilities.ts index 7dbd044f1..aa51784a1 100644 --- a/test/integration-tests/utilities/testutilities.ts +++ b/test/integration-tests/utilities/testutilities.ts @@ -19,7 +19,7 @@ import { Api } from "../../../src/extension"; import { testAssetUri } from "../../fixtures"; import { WorkspaceContext } from "../../../src/WorkspaceContext"; import { FolderContext } from "../../../src/FolderContext"; -import { waitForNoRunningTasks } from "../../utilities"; +import { waitForNoRunningTasks } from "../../utilities/tasks"; function getRootWorkspaceFolder(): vscode.WorkspaceFolder { const result = vscode.workspace.workspaceFolders?.at(0); From bef3498c3180d485676ab04c9d39ad1bcf3e2c54 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Tue, 10 Dec 2024 11:39:44 -0500 Subject: [PATCH 06/13] Fix format errors --- test/integration-tests/SwiftSnippet.test.ts | 4 +- test/integration-tests/commands/build.test.ts | 2 +- .../tasks/SwiftPluginTaskProvider.test.ts | 6 ++- test/utilities/debug.ts | 41 ++++++++----------- 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/test/integration-tests/SwiftSnippet.test.ts b/test/integration-tests/SwiftSnippet.test.ts index 3c89c64e6..5830df739 100644 --- a/test/integration-tests/SwiftSnippet.test.ts +++ b/test/integration-tests/SwiftSnippet.test.ts @@ -42,11 +42,11 @@ suite("SwiftSnippet Test Suite", () => { this.skip(); } await waitForNoRunningTasks(); - + // File needs to be open for command to be enabled const doc = await vscode.workspace.openTextDocument(uri.fsPath); await vscode.window.showTextDocument(doc); - + // Set a breakpoint vscode.debug.addBreakpoints(breakpoints); }, diff --git a/test/integration-tests/commands/build.test.ts b/test/integration-tests/commands/build.test.ts index 443b46075..e516a554d 100644 --- a/test/integration-tests/commands/build.test.ts +++ b/test/integration-tests/commands/build.test.ts @@ -99,7 +99,7 @@ suite("Build Commands", function () { // but "stackTrace" is the deterministic sync point we will use to make sure we can execute continue const bpPromise = waitForDebugAdapterCommand( "Debug PackageExe (defaultPackage)", - "stackTrace", + "stackTrace" ); const result = vscode.commands.executeCommand(Commands.DEBUG); diff --git a/test/integration-tests/tasks/SwiftPluginTaskProvider.test.ts b/test/integration-tests/tasks/SwiftPluginTaskProvider.test.ts index b1eba333b..38f2ef637 100644 --- a/test/integration-tests/tasks/SwiftPluginTaskProvider.test.ts +++ b/test/integration-tests/tasks/SwiftPluginTaskProvider.test.ts @@ -19,7 +19,11 @@ import { WorkspaceContext } from "../../../src/WorkspaceContext"; import { SwiftPluginTaskProvider } from "../../../src/tasks/SwiftPluginTaskProvider"; import { FolderContext } from "../../../src/FolderContext"; import { activateExtensionForSuite, folderInRootWorkspace } from "../utilities/testutilities"; -import { cleanOutput, executeTaskAndWaitForResult, waitForEndTaskProcess } from "../../utilities/tasks"; +import { + cleanOutput, + executeTaskAndWaitForResult, + waitForEndTaskProcess, +} from "../../utilities/tasks"; import { mutable } from "../../utilities/types"; suite("SwiftPluginTaskProvider Test Suite", () => { diff --git a/test/utilities/debug.ts b/test/utilities/debug.ts index 09c6bd713..42de9ab6c 100644 --- a/test/utilities/debug.ts +++ b/test/utilities/debug.ts @@ -13,8 +13,6 @@ //===----------------------------------------------------------------------===// import * as vscode from "vscode"; import { Workbench } from "../../src/utilities/commands"; -import { DebugAdapter } from "../../src/debugger/debugAdapter"; -import { WorkspaceContext } from "../../src/WorkspaceContext"; export async function continueSession(): Promise { await vscode.commands.executeCommand(Workbench.ACTION_DEBUG_CONTINUE); @@ -30,29 +28,26 @@ export async function continueSession(): Promise { */ export async function waitForDebugAdapterMessage( name: string, - matches: (message: any) => boolean, + matches: (message: any) => boolean ): Promise { return await new Promise(res => { - const disposable = vscode.debug.registerDebugAdapterTrackerFactory( - "swift-lldb", - { - createDebugAdapterTracker: function ( - session: vscode.DebugSession - ): vscode.ProviderResult { - if (session.name !== name) { - return; - } - return { - onDidSendMessage(message) { - if (matches(message)) { - disposable.dispose(); - res(message); - } - }, - }; - }, - } - ); + const disposable = vscode.debug.registerDebugAdapterTrackerFactory("swift-lldb", { + createDebugAdapterTracker: function ( + session: vscode.DebugSession + ): vscode.ProviderResult { + if (session.name !== name) { + return; + } + return { + onDidSendMessage(message) { + if (matches(message)) { + disposable.dispose(); + res(message); + } + }, + }; + }, + }); }); } From 01adc2c9993a7aff7e4623dbcd81c4a5472bfd44 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Tue, 10 Dec 2024 12:49:31 -0500 Subject: [PATCH 07/13] Fix review comment --- package-lock.json | 13 ++++++++++ package.json | 1 + test/integration-tests/SwiftSnippet.test.ts | 12 +++++---- test/integration-tests/commands/build.test.ts | 4 +-- test/utilities/debug.ts | 26 +++++++++++++------ 5 files changed, 41 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 76a3ee88e..b14850f46 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "@types/xml2js": "^0.4.14", "@typescript-eslint/eslint-plugin": "^8.16.0", "@typescript-eslint/parser": "^8.16.0", + "@vscode/debugprotocol": "^1.68.0", "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", "@vscode/vsce": "^2.32.0", @@ -1359,6 +1360,12 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "node_modules/@vscode/debugprotocol": { + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@vscode/debugprotocol/-/debugprotocol-1.68.0.tgz", + "integrity": "sha512-2J27dysaXmvnfuhFGhfeuxfHRXunqNPxtBoR3koiTOA9rdxWNDTa1zIFLCFMSHJ9MPTPKFcBeblsyaCJCIlQxg==", + "dev": true + }, "node_modules/@vscode/test-cli": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/@vscode/test-cli/-/test-cli-0.0.10.tgz", @@ -6828,6 +6835,12 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "@vscode/debugprotocol": { + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@vscode/debugprotocol/-/debugprotocol-1.68.0.tgz", + "integrity": "sha512-2J27dysaXmvnfuhFGhfeuxfHRXunqNPxtBoR3koiTOA9rdxWNDTa1zIFLCFMSHJ9MPTPKFcBeblsyaCJCIlQxg==", + "dev": true + }, "@vscode/test-cli": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/@vscode/test-cli/-/test-cli-0.0.10.tgz", diff --git a/package.json b/package.json index 54f7e7936..0f996e748 100644 --- a/package.json +++ b/package.json @@ -1311,6 +1311,7 @@ "@types/xml2js": "^0.4.14", "@typescript-eslint/eslint-plugin": "^8.16.0", "@typescript-eslint/parser": "^8.16.0", + "@vscode/debugprotocol": "^1.68.0", "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", "@vscode/vsce": "^2.32.0", diff --git a/test/integration-tests/SwiftSnippet.test.ts b/test/integration-tests/SwiftSnippet.test.ts index 5830df739..2aec6bfe8 100644 --- a/test/integration-tests/SwiftSnippet.test.ts +++ b/test/integration-tests/SwiftSnippet.test.ts @@ -18,7 +18,7 @@ import { waitForNoRunningTasks } from "../utilities/tasks"; import { expect } from "chai"; import { continueSession, - waitForDebugAdapterCommand, + waitForDebugAdapterRequest, waitForDebugAdapterExit, waitUntilDebugSessionTerminates, } from "../utilities/debug"; @@ -26,7 +26,9 @@ import { Version } from "../../src/utilities/version"; import { activateExtensionForSuite, folderInRootWorkspace } from "./utilities/testutilities"; import { WorkspaceContext } from "../../src/WorkspaceContext"; -suite("SwiftSnippet Test Suite", () => { +suite("SwiftSnippet Test Suite", function () { + this.timeout(120000); + const uri = testAssetUri("defaultPackage/Snippets/hello.swift"); const breakpoints = [ new vscode.SourceBreakpoint(new vscode.Location(uri, new vscode.Position(2, 0))), @@ -72,10 +74,10 @@ suite("SwiftSnippet Test Suite", () => { `${testAssetPath("defaultPackage")}/.build/debug/hello` ); expect(session.configuration).to.have.property("noDebug", true); - }).timeout(120000); + }); test("Run `Swift: Debug Swift Snippet` command for snippet file", async () => { - const bpPromise = waitForDebugAdapterCommand("Run hello", "stackTrace"); + const bpPromise = waitForDebugAdapterRequest("Run hello", "stackTrace"); const sessionPromise = waitUntilDebugSessionTerminates("Run hello"); const exitPromise = waitForDebugAdapterExit("Run hello"); @@ -93,5 +95,5 @@ suite("SwiftSnippet Test Suite", () => { `${testAssetPath("defaultPackage")}/.build/debug/hello` ); expect(session.configuration).to.not.have.property("noDebug"); - }).timeout(120000); + }); }); diff --git a/test/integration-tests/commands/build.test.ts b/test/integration-tests/commands/build.test.ts index e516a554d..77c47540e 100644 --- a/test/integration-tests/commands/build.test.ts +++ b/test/integration-tests/commands/build.test.ts @@ -23,7 +23,7 @@ import { WorkspaceContext } from "../../../src/WorkspaceContext"; import { Commands } from "../../../src/commands"; import { makeDebugConfigurations } from "../../../src/debugger/launch"; import { Workbench } from "../../../src/utilities/commands"; -import { continueSession, waitForDebugAdapterCommand } from "../../utilities/debug"; +import { continueSession, waitForDebugAdapterRequest } from "../../utilities/debug"; import { activateExtensionForSuite, folderInRootWorkspace, @@ -97,7 +97,7 @@ suite("Build Commands", function () { // 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( + const bpPromise = waitForDebugAdapterRequest( "Debug PackageExe (defaultPackage)", "stackTrace" ); diff --git a/test/utilities/debug.ts b/test/utilities/debug.ts index 42de9ab6c..fb122e8cd 100644 --- a/test/utilities/debug.ts +++ b/test/utilities/debug.ts @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// import * as vscode from "vscode"; +import { DebugProtocol } from "@vscode/debugprotocol"; import { Workbench } from "../../src/utilities/commands"; export async function continueSession(): Promise { @@ -26,11 +27,11 @@ export async function continueSession(): Promise { * @param workspaceContext The workspace context containing toolchain information. * @returns A promise that resolves with the matching message. */ -export async function waitForDebugAdapterMessage( +export async function waitForDebugAdapterMessage( name: string, - matches: (message: any) => boolean -): Promise { - return await new Promise(res => { + matches: (message: T) => boolean +): Promise { + return await new Promise(res => { const disposable = vscode.debug.registerDebugAdapterTrackerFactory("swift-lldb", { createDebugAdapterTracker: function ( session: vscode.DebugSession @@ -75,8 +76,14 @@ export async function waitUntilDebugSessionTerminates(name: string): Promise { - return await waitForDebugAdapterMessage(name, (m: any) => m.command === command); +export async function waitForDebugAdapterRequest( + name: string, + command: string +): Promise { + return await waitForDebugAdapterMessage( + name, + (m: DebugProtocol.Request) => m.command === command + ); } /** @@ -87,8 +94,11 @@ export async function waitForDebugAdapterCommand(name: string, command: string): * @param workspaceContext The workspace context containing toolchain information. * @returns A promise that resolves with the matching command event. */ -export async function waitForDebugAdapterEvent(name: string, event: string): Promise { - return await waitForDebugAdapterMessage(name, (m: any) => m.event === event); +export async function waitForDebugAdapterEvent( + name: string, + event: string +): Promise { + return await waitForDebugAdapterMessage(name, (m: DebugProtocol.Event) => m.event === event); } /** From 81de1039156378adff3c608535db454997b2dc43 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Tue, 10 Dec 2024 12:52:10 -0500 Subject: [PATCH 08/13] Fix test failing on windows --- test/integration-tests/SwiftSnippet.test.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/test/integration-tests/SwiftSnippet.test.ts b/test/integration-tests/SwiftSnippet.test.ts index 2aec6bfe8..504f037bd 100644 --- a/test/integration-tests/SwiftSnippet.test.ts +++ b/test/integration-tests/SwiftSnippet.test.ts @@ -69,9 +69,8 @@ suite("SwiftSnippet Test Suite", function () { expect(exitCode).to.equal(0); const session = await sessionPromise; - expect(session.configuration).to.have.property( - "program", - `${testAssetPath("defaultPackage")}/.build/debug/hello` + expect(session.configuration.program?.toLowerCase()).to.equal( + `${testAssetPath("defaultPackage")}/.build/debug/hello`.toLocaleLowerCase() // Windows may use d:\ or D:\ ); expect(session.configuration).to.have.property("noDebug", true); }); @@ -90,9 +89,8 @@ suite("SwiftSnippet Test Suite", function () { expect(exitCode).to.equal(0); const session = await sessionPromise; - expect(session.configuration).to.have.property( - "program", - `${testAssetPath("defaultPackage")}/.build/debug/hello` + expect(session.configuration.program?.toLowerCase()).to.equal( + `${testAssetPath("defaultPackage")}/.build/debug/hello`.toLocaleLowerCase() // Windows may use d:\ or D:\ ); expect(session.configuration).to.not.have.property("noDebug"); }); From 2610da2593cfe9f124817654e589b1cf00ecfb94 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Tue, 10 Dec 2024 12:53:43 -0500 Subject: [PATCH 09/13] Fix review comment --- test/utilities/debug.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/utilities/debug.ts b/test/utilities/debug.ts index fb122e8cd..a1a5304b7 100644 --- a/test/utilities/debug.ts +++ b/test/utilities/debug.ts @@ -108,5 +108,6 @@ export async function waitForDebugAdapterEvent( * @returns exit code of the DAP */ export async function waitForDebugAdapterExit(name: string): Promise { - return await waitForDebugAdapterEvent(name, "exited").then(m => m.body.exitCode); + const message = await waitForDebugAdapterEvent(name, "exited"); + return message.body.exitCode; } From d4d3dfbe2874809cff409c74a504a193f773ebe6 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Tue, 10 Dec 2024 13:32:50 -0500 Subject: [PATCH 10/13] Add .exe to expected path for windows --- test/integration-tests/SwiftSnippet.test.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/integration-tests/SwiftSnippet.test.ts b/test/integration-tests/SwiftSnippet.test.ts index 504f037bd..999ef4480 100644 --- a/test/integration-tests/SwiftSnippet.test.ts +++ b/test/integration-tests/SwiftSnippet.test.ts @@ -25,6 +25,7 @@ import { import { Version } from "../../src/utilities/version"; import { activateExtensionForSuite, folderInRootWorkspace } from "./utilities/testutilities"; import { WorkspaceContext } from "../../src/WorkspaceContext"; +import { join } from "path"; suite("SwiftSnippet Test Suite", function () { this.timeout(120000); @@ -69,8 +70,12 @@ suite("SwiftSnippet Test Suite", function () { expect(exitCode).to.equal(0); const session = await sessionPromise; + let path = join(testAssetPath("defaultPackage"), ".build", "debug", "hello"); + if (process.platform === "win32") { + path = path + ".exe"; + } expect(session.configuration.program?.toLowerCase()).to.equal( - `${testAssetPath("defaultPackage")}/.build/debug/hello`.toLocaleLowerCase() // Windows may use d:\ or D:\ + path.toLocaleLowerCase() // Windows may use d:\ or D:\ ); expect(session.configuration).to.have.property("noDebug", true); }); @@ -89,8 +94,12 @@ suite("SwiftSnippet Test Suite", function () { expect(exitCode).to.equal(0); const session = await sessionPromise; + let path = join(testAssetPath("defaultPackage"), ".build", "debug", "hello"); + if (process.platform === "win32") { + path = path + ".exe"; + } expect(session.configuration.program?.toLowerCase()).to.equal( - `${testAssetPath("defaultPackage")}/.build/debug/hello`.toLocaleLowerCase() // Windows may use d:\ or D:\ + path.toLocaleLowerCase() // Windows may use d:\ or D:\ ); expect(session.configuration).to.not.have.property("noDebug"); }); From ce73bd3acd9fc76952211579ee4b703699ff467b Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Tue, 10 Dec 2024 15:57:02 -0500 Subject: [PATCH 11/13] Some clean up --- src/SwiftSnippets.ts | 13 +++--- test/integration-tests/SwiftSnippet.test.ts | 42 +++++++++---------- .../utilities/testutilities.ts | 3 +- test/utilities/commands.ts | 20 +++++++++ 4 files changed, 48 insertions(+), 30 deletions(-) create mode 100644 test/utilities/commands.ts diff --git a/src/SwiftSnippets.ts b/src/SwiftSnippets.ts index 0685fc434..511283c40 100644 --- a/src/SwiftSnippets.ts +++ b/src/SwiftSnippets.ts @@ -49,22 +49,22 @@ export function setSnippetContextKey(ctx: WorkspaceContext) { * If current file is a Swift Snippet run it * @param ctx Workspace Context */ -export async function runSnippet(ctx: WorkspaceContext) { - await debugSnippetWithOptions(ctx, { noDebug: true }); +export async function runSnippet(ctx: WorkspaceContext): Promise { + return await debugSnippetWithOptions(ctx, { noDebug: true }); } /** * If current file is a Swift Snippet run it in the debugger * @param ctx Workspace Context */ -export async function debugSnippet(ctx: WorkspaceContext) { - await debugSnippetWithOptions(ctx, {}); +export async function debugSnippet(ctx: WorkspaceContext): Promise { + return await debugSnippetWithOptions(ctx, {}); } export async function debugSnippetWithOptions( ctx: WorkspaceContext, options: vscode.DebugSessionOptions -) { +): Promise { const folderContext = ctx.currentFolder; if (!ctx.currentDocument || !folderContext) { return; @@ -89,7 +89,7 @@ export async function debugSnippetWithOptions( try { // queue build task and when it is complete run executable in the debugger - await folderContext.taskQueue + return await folderContext.taskQueue .queueOperation(new TaskOperation(snippetBuildTask)) .then(result => { if (result === 0) { @@ -106,5 +106,6 @@ export async function debugSnippetWithOptions( }); } catch { // ignore error if task failed to run + return; } } diff --git a/test/integration-tests/SwiftSnippet.test.ts b/test/integration-tests/SwiftSnippet.test.ts index 999ef4480..1a27ed278 100644 --- a/test/integration-tests/SwiftSnippet.test.ts +++ b/test/integration-tests/SwiftSnippet.test.ts @@ -19,13 +19,22 @@ import { expect } from "chai"; import { continueSession, waitForDebugAdapterRequest, - waitForDebugAdapterExit, waitUntilDebugSessionTerminates, } from "../utilities/debug"; import { Version } from "../../src/utilities/version"; import { activateExtensionForSuite, folderInRootWorkspace } from "./utilities/testutilities"; import { WorkspaceContext } from "../../src/WorkspaceContext"; import { join } from "path"; +import { closeAllEditors } from "../utilities/commands"; + +function normalizePath(...segments: string[]): string { + let path = join(...segments); + if (process.platform === "win32") { + path = path + ".exe"; + path = path.replace(/\//g, "\\"); + } + return path.toLocaleLowerCase(); // Windows may use d:\ or D:\ +} suite("SwiftSnippet Test Suite", function () { this.timeout(120000); @@ -56,26 +65,19 @@ suite("SwiftSnippet Test Suite", function () { }); suiteTeardown(async () => { - await vscode.commands.executeCommand("workbench.action.closeAllEditors"); + closeAllEditors(); vscode.debug.removeBreakpoints(breakpoints); }); test("Run `Swift: Run Swift Snippet` command for snippet file", async () => { const sessionPromise = waitUntilDebugSessionTerminates("Run hello"); - const exitPromise = waitForDebugAdapterExit("Run hello"); - - await vscode.commands.executeCommand("swift.runSnippet"); - const exitCode = await exitPromise; - expect(exitCode).to.equal(0); + const succeeded = await vscode.commands.executeCommand("swift.runSnippet"); + expect(succeeded).to.be.true; const session = await sessionPromise; - let path = join(testAssetPath("defaultPackage"), ".build", "debug", "hello"); - if (process.platform === "win32") { - path = path + ".exe"; - } - expect(session.configuration.program?.toLowerCase()).to.equal( - path.toLocaleLowerCase() // Windows may use d:\ or D:\ + expect(normalizePath(session.configuration.program)).to.equal( + normalizePath(testAssetPath("defaultPackage"), ".build", "debug", "hello") ); expect(session.configuration).to.have.property("noDebug", true); }); @@ -83,23 +85,17 @@ suite("SwiftSnippet Test Suite", function () { test("Run `Swift: Debug Swift Snippet` command for snippet file", async () => { const bpPromise = waitForDebugAdapterRequest("Run hello", "stackTrace"); const sessionPromise = waitUntilDebugSessionTerminates("Run hello"); - const exitPromise = waitForDebugAdapterExit("Run hello"); - vscode.commands.executeCommand("swift.debugSnippet"); + const succeeded = vscode.commands.executeCommand("swift.debugSnippet"); // Once bp is hit, continue await bpPromise.then(() => continueSession()); - const exitCode = await exitPromise; - expect(exitCode).to.equal(0); + await expect(succeeded).to.eventually.be.true; const session = await sessionPromise; - let path = join(testAssetPath("defaultPackage"), ".build", "debug", "hello"); - if (process.platform === "win32") { - path = path + ".exe"; - } - expect(session.configuration.program?.toLowerCase()).to.equal( - path.toLocaleLowerCase() // Windows may use d:\ or D:\ + expect(normalizePath(session.configuration.program)).to.equal( + normalizePath(testAssetPath("defaultPackage"), ".build", "debug", "hello") ); expect(session.configuration).to.not.have.property("noDebug"); }); diff --git a/test/integration-tests/utilities/testutilities.ts b/test/integration-tests/utilities/testutilities.ts index aa51784a1..39b19fd16 100644 --- a/test/integration-tests/utilities/testutilities.ts +++ b/test/integration-tests/utilities/testutilities.ts @@ -20,6 +20,7 @@ import { testAssetUri } from "../../fixtures"; import { WorkspaceContext } from "../../../src/WorkspaceContext"; import { FolderContext } from "../../../src/FolderContext"; import { waitForNoRunningTasks } from "../../utilities/tasks"; +import { closeAllEditors } from "../../utilities/commands"; function getRootWorkspaceFolder(): vscode.WorkspaceFolder { const result = vscode.workspace.workspaceFolders?.at(0); @@ -175,7 +176,7 @@ const extensionBootstrapper = (() => { await waitForNoRunningTasks({ timeout: 10000 }); // Close all editors before deactivating the extension. - await vscode.commands.executeCommand("workbench.action.closeAllEditors"); + closeAllEditors(); await activatedAPI.workspaceContext?.removeWorkspaceFolder(getRootWorkspaceFolder()); await activatedAPI.deactivate(); diff --git a/test/utilities/commands.ts b/test/utilities/commands.ts new file mode 100644 index 000000000..0b52378d4 --- /dev/null +++ b/test/utilities/commands.ts @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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/commands"; + +export async function closeAllEditors() { + await vscode.commands.executeCommand(Workbench.ACTION_CLOSEALLEDITORS); +} From 9cf13afa12fc6d4e58fea98d85b557684e577742 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Wed, 11 Dec 2024 07:50:31 -0500 Subject: [PATCH 12/13] Fix failure --- test/integration-tests/SwiftSnippet.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration-tests/SwiftSnippet.test.ts b/test/integration-tests/SwiftSnippet.test.ts index 1a27ed278..dd689ef05 100644 --- a/test/integration-tests/SwiftSnippet.test.ts +++ b/test/integration-tests/SwiftSnippet.test.ts @@ -30,7 +30,7 @@ import { closeAllEditors } from "../utilities/commands"; function normalizePath(...segments: string[]): string { let path = join(...segments); if (process.platform === "win32") { - path = path + ".exe"; + path = path.endsWith(".exe") ? path : path + ".exe"; path = path.replace(/\//g, "\\"); } return path.toLocaleLowerCase(); // Windows may use d:\ or D:\ From e669c4030183c17e140456eb5c9ff596874eac47 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Wed, 11 Dec 2024 08:25:06 -0500 Subject: [PATCH 13/13] Don't run snippets tests in CI --- test/integration-tests/SwiftSnippet.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration-tests/SwiftSnippet.test.ts b/test/integration-tests/SwiftSnippet.test.ts index dd689ef05..9cfbbed25 100644 --- a/test/integration-tests/SwiftSnippet.test.ts +++ b/test/integration-tests/SwiftSnippet.test.ts @@ -36,7 +36,7 @@ function normalizePath(...segments: string[]): string { return path.toLocaleLowerCase(); // Windows may use d:\ or D:\ } -suite("SwiftSnippet Test Suite", function () { +suite("SwiftSnippet Test Suite @slow", function () { this.timeout(120000); const uri = testAssetUri("defaultPackage/Snippets/hello.swift");