Skip to content

Commit e3ade90

Browse files
authored
Add tests for the Swift snippets workflows (#1126)
* Add test snippet source * 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
1 parent cf37af5 commit e3ade90

24 files changed

+266
-60
lines changed

assets/test/defaultPackage/Package.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ import PackageDescription
55

66
let package = Package(
77
name: "defaultPackage",
8+
products: [
9+
.library(
10+
name: "PackageLib",
11+
targets: ["PackageLib"]),
12+
],
813
targets: [
914
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
1015
// Targets can depend on other targets in this package, and on products in packages this package depends on.

assets/test/defaultPackage/[email protected]

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ let package = Package(
88
platforms: [
99
.macOS(.v13)
1010
],
11+
products: [
12+
.library(
13+
name: "PackageLib",
14+
targets: ["PackageLib"]),
15+
],
1116
targets: [
1217
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
1318
// Targets can depend on other targets in this package, and on products in packages this package depends on.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import PackageLib
2+
3+
print("hello \(a)")

package-lock.json

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,6 +1311,7 @@
13111311
"@types/xml2js": "^0.4.14",
13121312
"@typescript-eslint/eslint-plugin": "^8.16.0",
13131313
"@typescript-eslint/parser": "^8.16.0",
1314+
"@vscode/debugprotocol": "^1.68.0",
13141315
"@vscode/test-cli": "^0.0.10",
13151316
"@vscode/test-electron": "^2.4.1",
13161317
"@vscode/vsce": "^2.32.0",

src/SwiftSnippets.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,22 @@ export function setSnippetContextKey(ctx: WorkspaceContext) {
4949
* If current file is a Swift Snippet run it
5050
* @param ctx Workspace Context
5151
*/
52-
export async function runSnippet(ctx: WorkspaceContext) {
53-
await debugSnippetWithOptions(ctx, { noDebug: true });
52+
export async function runSnippet(ctx: WorkspaceContext): Promise<boolean | undefined> {
53+
return await debugSnippetWithOptions(ctx, { noDebug: true });
5454
}
5555

5656
/**
5757
* If current file is a Swift Snippet run it in the debugger
5858
* @param ctx Workspace Context
5959
*/
60-
export async function debugSnippet(ctx: WorkspaceContext) {
61-
await debugSnippetWithOptions(ctx, {});
60+
export async function debugSnippet(ctx: WorkspaceContext): Promise<boolean | undefined> {
61+
return await debugSnippetWithOptions(ctx, {});
6262
}
6363

6464
export async function debugSnippetWithOptions(
6565
ctx: WorkspaceContext,
6666
options: vscode.DebugSessionOptions
67-
) {
67+
): Promise<boolean | undefined> {
6868
const folderContext = ctx.currentFolder;
6969
if (!ctx.currentDocument || !folderContext) {
7070
return;
@@ -89,7 +89,7 @@ export async function debugSnippetWithOptions(
8989

9090
try {
9191
// queue build task and when it is complete run executable in the debugger
92-
await folderContext.taskQueue
92+
return await folderContext.taskQueue
9393
.queueOperation(new TaskOperation(snippetBuildTask))
9494
.then(result => {
9595
if (result === 0) {
@@ -106,5 +106,6 @@ export async function debugSnippetWithOptions(
106106
});
107107
} catch {
108108
// ignore error if task failed to run
109+
return;
109110
}
110111
}

test/integration-tests/BackgroundCompilation.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import * as assert from "assert";
1616
import * as vscode from "vscode";
1717
import { WorkspaceContext } from "../../src/WorkspaceContext";
1818
import { testAssetUri } from "../fixtures";
19-
import { waitForNoRunningTasks } from "../utilities";
19+
import { waitForNoRunningTasks } from "../utilities/tasks";
2020
import { Workbench } from "../../src/utilities/commands";
2121
import { activateExtensionForTest, updateSettings } from "./utilities/testutilities";
2222

test/integration-tests/DiagnosticsManager.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import * as assert from "assert";
1616
import * as vscode from "vscode";
1717
import { SwiftToolchain } from "../../src/toolchain/toolchain";
18-
import { executeTaskAndWaitForResult, waitForNoRunningTasks } from "../utilities";
18+
import { executeTaskAndWaitForResult, waitForNoRunningTasks } from "../utilities/tasks";
1919
import { WorkspaceContext } from "../../src/WorkspaceContext";
2020
import { testAssetWorkspaceFolder, testSwiftTask } from "../fixtures";
2121
import { createBuildAllTask } from "../../src/tasks/SwiftTaskProvider";
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the VS Code Swift open source project
4+
//
5+
// Copyright (c) 2024 the VS Code Swift project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of VS Code Swift project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import * as vscode from "vscode";
16+
import { testAssetPath, testAssetUri } from "../fixtures";
17+
import { waitForNoRunningTasks } from "../utilities/tasks";
18+
import { expect } from "chai";
19+
import {
20+
continueSession,
21+
waitForDebugAdapterRequest,
22+
waitUntilDebugSessionTerminates,
23+
} from "../utilities/debug";
24+
import { Version } from "../../src/utilities/version";
25+
import { activateExtensionForSuite, folderInRootWorkspace } from "./utilities/testutilities";
26+
import { WorkspaceContext } from "../../src/WorkspaceContext";
27+
import { join } from "path";
28+
import { closeAllEditors } from "../utilities/commands";
29+
30+
function normalizePath(...segments: string[]): string {
31+
let path = join(...segments);
32+
if (process.platform === "win32") {
33+
path = path.endsWith(".exe") ? path : path + ".exe";
34+
path = path.replace(/\//g, "\\");
35+
}
36+
return path.toLocaleLowerCase(); // Windows may use d:\ or D:\
37+
}
38+
39+
suite("SwiftSnippet Test Suite @slow", function () {
40+
this.timeout(120000);
41+
42+
const uri = testAssetUri("defaultPackage/Snippets/hello.swift");
43+
const breakpoints = [
44+
new vscode.SourceBreakpoint(new vscode.Location(uri, new vscode.Position(2, 0))),
45+
];
46+
let workspaceContext: WorkspaceContext;
47+
48+
activateExtensionForSuite({
49+
async setup(ctx) {
50+
workspaceContext = ctx;
51+
52+
const folder = await folderInRootWorkspace("defaultPackage", workspaceContext);
53+
if (folder.workspaceContext.toolchain.swiftVersion.isLessThan(new Version(6, 0, 0))) {
54+
this.skip();
55+
}
56+
await waitForNoRunningTasks();
57+
58+
// File needs to be open for command to be enabled
59+
const doc = await vscode.workspace.openTextDocument(uri.fsPath);
60+
await vscode.window.showTextDocument(doc);
61+
62+
// Set a breakpoint
63+
vscode.debug.addBreakpoints(breakpoints);
64+
},
65+
});
66+
67+
suiteTeardown(async () => {
68+
closeAllEditors();
69+
vscode.debug.removeBreakpoints(breakpoints);
70+
});
71+
72+
test("Run `Swift: Run Swift Snippet` command for snippet file", async () => {
73+
const sessionPromise = waitUntilDebugSessionTerminates("Run hello");
74+
75+
const succeeded = await vscode.commands.executeCommand("swift.runSnippet");
76+
77+
expect(succeeded).to.be.true;
78+
const session = await sessionPromise;
79+
expect(normalizePath(session.configuration.program)).to.equal(
80+
normalizePath(testAssetPath("defaultPackage"), ".build", "debug", "hello")
81+
);
82+
expect(session.configuration).to.have.property("noDebug", true);
83+
});
84+
85+
test("Run `Swift: Debug Swift Snippet` command for snippet file", async () => {
86+
const bpPromise = waitForDebugAdapterRequest("Run hello", "stackTrace");
87+
const sessionPromise = waitUntilDebugSessionTerminates("Run hello");
88+
89+
const succeeded = vscode.commands.executeCommand("swift.debugSnippet");
90+
91+
// Once bp is hit, continue
92+
await bpPromise.then(() => continueSession());
93+
94+
await expect(succeeded).to.eventually.be.true;
95+
96+
const session = await sessionPromise;
97+
expect(normalizePath(session.configuration.program)).to.equal(
98+
normalizePath(testAssetPath("defaultPackage"), ".build", "debug", "hello")
99+
);
100+
expect(session.configuration).to.not.have.property("noDebug");
101+
});
102+
});

test/integration-tests/commands/build.test.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ import * as vscode from "vscode";
1616
import * as fs from "fs/promises";
1717
import * as path from "path";
1818
import { expect } from "chai";
19-
import { waitForNoRunningTasks } from "../../utilities";
19+
import { waitForNoRunningTasks } from "../../utilities/tasks";
2020
import { testAssetUri } from "../../fixtures";
2121
import { FolderContext } from "../../../src/FolderContext";
2222
import { WorkspaceContext } from "../../../src/WorkspaceContext";
2323
import { Commands } from "../../../src/commands";
2424
import { makeDebugConfigurations } from "../../../src/debugger/launch";
2525
import { Workbench } from "../../../src/utilities/commands";
26-
import { continueSession, waitForDebugAdapterCommand } from "../../utilities/debug";
26+
import { continueSession, waitForDebugAdapterRequest } from "../../utilities/debug";
2727
import {
2828
activateExtensionForSuite,
2929
folderInRootWorkspace,
@@ -97,10 +97,9 @@ suite("Build Commands", function () {
9797
// Promise used to indicate we hit the break point.
9898
// NB: "stopped" is the exact command when debuggee has stopped due to break point,
9999
// but "stackTrace" is the deterministic sync point we will use to make sure we can execute continue
100-
const bpPromise = waitForDebugAdapterCommand(
100+
const bpPromise = waitForDebugAdapterRequest(
101101
"Debug PackageExe (defaultPackage)",
102-
"stackTrace",
103-
workspaceContext
102+
"stackTrace"
104103
);
105104

106105
const result = vscode.commands.executeCommand(Commands.DEBUG);

0 commit comments

Comments
 (0)