Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for the Swift snippets workflows #1126

Merged
merged 13 commits into from
Dec 11, 2024
5 changes: 5 additions & 0 deletions assets/test/defaultPackage/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
5 changes: 5 additions & 0 deletions assets/test/defaultPackage/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
3 changes: 3 additions & 0 deletions assets/test/defaultPackage/Snippets/hello.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import PackageLib

print("hello \(a)")
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
13 changes: 7 additions & 6 deletions src/SwiftSnippets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<boolean | undefined> {
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<boolean | undefined> {
return await debugSnippetWithOptions(ctx, {});
}

export async function debugSnippetWithOptions(
ctx: WorkspaceContext,
options: vscode.DebugSessionOptions
) {
): Promise<boolean | undefined> {
const folderContext = ctx.currentFolder;
if (!ctx.currentDocument || !folderContext) {
return;
Expand All @@ -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) {
Expand All @@ -106,5 +106,6 @@ export async function debugSnippetWithOptions(
});
} catch {
// ignore error if task failed to run
return;
}
}
2 changes: 1 addition & 1 deletion test/integration-tests/BackgroundCompilation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down
2 changes: 1 addition & 1 deletion test/integration-tests/DiagnosticsManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
102 changes: 102 additions & 0 deletions test/integration-tests/SwiftSnippet.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//===----------------------------------------------------------------------===//
//
// 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 { testAssetPath, testAssetUri } from "../fixtures";
import { waitForNoRunningTasks } from "../utilities/tasks";
import { expect } from "chai";
import {
continueSession,
waitForDebugAdapterRequest,
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.endsWith(".exe") ? path : path + ".exe";
path = path.replace(/\//g, "\\");
}
return path.toLocaleLowerCase(); // Windows may use d:\ or D:\
}

suite("SwiftSnippet Test Suite @slow", 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))),
];
let workspaceContext: WorkspaceContext;

activateExtensionForSuite({
async setup(ctx) {
workspaceContext = ctx;

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 () => {
closeAllEditors();
vscode.debug.removeBreakpoints(breakpoints);
});

test("Run `Swift: Run Swift Snippet` command for snippet file", async () => {
award999 marked this conversation as resolved.
Show resolved Hide resolved
const sessionPromise = waitUntilDebugSessionTerminates("Run hello");

const succeeded = await vscode.commands.executeCommand("swift.runSnippet");

expect(succeeded).to.be.true;
const session = await sessionPromise;
expect(normalizePath(session.configuration.program)).to.equal(
normalizePath(testAssetPath("defaultPackage"), ".build", "debug", "hello")
);
expect(session.configuration).to.have.property("noDebug", true);
});

test("Run `Swift: Debug Swift Snippet` command for snippet file", async () => {
award999 marked this conversation as resolved.
Show resolved Hide resolved
const bpPromise = waitForDebugAdapterRequest("Run hello", "stackTrace");
const sessionPromise = waitUntilDebugSessionTerminates("Run hello");

const succeeded = vscode.commands.executeCommand("swift.debugSnippet");

// Once bp is hit, continue
await bpPromise.then(() => continueSession());

await expect(succeeded).to.eventually.be.true;

const session = await sessionPromise;
expect(normalizePath(session.configuration.program)).to.equal(
normalizePath(testAssetPath("defaultPackage"), ".build", "debug", "hello")
);
expect(session.configuration).to.not.have.property("noDebug");
});
});
9 changes: 4 additions & 5 deletions test/integration-tests/commands/build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ 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";
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,
Expand Down Expand Up @@ -97,10 +97,9 @@ 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",
workspaceContext
"stackTrace"
);

const result = vscode.commands.executeCommand(Commands.DEBUG);
Expand Down
2 changes: 1 addition & 1 deletion test/integration-tests/commands/dependency.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
2 changes: 1 addition & 1 deletion test/integration-tests/language/macro.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
2 changes: 1 addition & 1 deletion test/integration-tests/tasks/SwiftExecution.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import { activateExtensionForSuite, folderInRootWorkspace } from "../utilities/t
import {
cleanOutput,
executeTaskAndWaitForResult,
mutable,
waitForEndTaskProcess,
} from "../../utilities";
} from "../../utilities/tasks";
import { mutable } from "../../utilities/types";

suite("SwiftPluginTaskProvider Test Suite", () => {
let workspaceContext: WorkspaceContext;
Expand Down
2 changes: 1 addition & 1 deletion test/integration-tests/tasks/SwiftPseudoterminal.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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", () => {
Expand Down
2 changes: 1 addition & 1 deletion test/integration-tests/tasks/SwiftTaskProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
2 changes: 1 addition & 1 deletion test/integration-tests/tasks/TaskManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion test/integration-tests/tasks/TaskQueue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
5 changes: 3 additions & 2 deletions test/integration-tests/utilities/testutilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ 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";
import { closeAllEditors } from "../../utilities/commands";

function getRootWorkspaceFolder(): vscode.WorkspaceFolder {
const result = vscode.workspace.workspaceFolders?.at(0);
Expand Down Expand Up @@ -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();
Expand Down
20 changes: 20 additions & 0 deletions test/utilities/commands.ts
Original file line number Diff line number Diff line change
@@ -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);
}
Loading
Loading