Skip to content

Commit

Permalink
Allow disabling SwiftPM sandboxing
Browse files Browse the repository at this point in the history
To get our tests to run in a sandbox, we need to disable sandboxing
because you cannot create a new sandbox when you're already running
under a sandbox

- Add new `swift.disableSandbox` setting
- Disable sandboxing for tasks and commands run by the extension
- Disable hardware acceleration since ci.swift.org will run on x64
- Fix failing xcode watcher unit test
- Increase some timeouts as build times seem slower on these nodes
- Skip any LSP dependent tests for 6.0 or earlier. The LSP will
  only allow disabling sandboxing in 6.1+
- Disable debugging tests since need shareport permission
  • Loading branch information
award999 committed Feb 13, 2025
1 parent 39fb686 commit ff19a00
Show file tree
Hide file tree
Showing 31 changed files with 309 additions and 96 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ default.profraw
assets/documentation-webview
assets/test/**/Package.resolved
assets/swift-docc-render
ud
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ node_modules/
/coverage/
/dist/
/snippets/

# macOS CI
/ud/
31 changes: 18 additions & 13 deletions .vscode-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,36 @@ const path = require("path");
const isCIBuild = process.env["CI"] === "1";
const isFastTestRun = process.env["FAST_TEST_RUN"] === "1";

const dataDir = process.env["VSCODE_DATA_DIR"];

// "env" in launch.json doesn't seem to work with vscode-test
const isDebugRun = !(process.env["_"] ?? "").endsWith("node_modules/.bin/vscode-test");

// so tests don't timeout when a breakpoint is hit
const timeout = isDebugRun ? Number.MAX_SAFE_INTEGER : 3000;

const launchArgs = [
"--disable-updates",
"--disable-crash-reporter",
"--disable-workspace-trust",
"--disable-telemetry",
];
if (dataDir) {
launchArgs.push("--user-data-dir", dataDir);
}
// GPU hardware acceleration not working on Darwin for intel
if (process.platform === "darwin" && process.arch === "x64") {
launchArgs.push("--disable-gpu");
}

module.exports = defineConfig({
tests: [
{
label: "integrationTests",
files: ["dist/test/common.js", "dist/test/integration-tests/**/*.test.js"],
version: process.env["VSCODE_VERSION"] ?? "stable",
workspaceFolder: "./assets/test",
launchArgs: [
"--disable-updates",
"--disable-crash-reporter",
"--disable-workspace-trust",
"--disable-telemetry",
],
launchArgs,
mocha: {
ui: "tdd",
color: true,
Expand All @@ -59,13 +70,7 @@ module.exports = defineConfig({
label: "unitTests",
files: ["dist/test/common.js", "dist/test/unit-tests/**/*.test.js"],
version: process.env["VSCODE_VERSION"] ?? "stable",
launchArgs: [
"--disable-extensions",
"--disable-updates",
"--disable-crash-reporter",
"--disable-workspace-trust",
"--disable-telemetry",
],
launchArgs: launchArgs.concat("--disable-extensions"),
mocha: {
ui: "tdd",
color: true,
Expand Down
1 change: 1 addition & 0 deletions assets/test/.vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"command": "command_plugin",
"args": ["--foo"],
"cwd": "command-plugin",
"disableSandbox": true,
"problemMatcher": [
"$swiftc"
],
Expand Down
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,12 @@
"swift.swiftSDK": {
"type": "string",
"default": "",
"markdownDescription": "The [Swift SDK](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0387-cross-compilation-destinations.md) to compile against (`--swift-sdk` parameter).",
"markdownDescription": "The [Swift SDK](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0387-cross-compilation-destinations.md) to compile against (`--swift-sdk` parameter)."
},
"swift.disableSandox": {
"type": "boolean",
"default": false,
"markdownDescription": "Disable sandboxing when running SwiftPM commands. In most cases you should keep the sandbox enabled and leave this setting set to `false`",
"order": 4
},
"swift.diagnostics": {
Expand Down
7 changes: 6 additions & 1 deletion src/commands/dependencies/unedit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@ async function uneditFolderDependency(
) {
try {
const uneditOperation = new SwiftExecOperation(
["package", "unedit", ...args, identifier],
ctx.toolchain.buildFlags.withAdditionalFlags([
"package",
"unedit",
...args,
identifier,
]),
folder,
`Finish editing ${identifier}`,
{ showStatusItem: true, checkAlreadyRunning: false, log: "Unedit" },
Expand Down
8 changes: 7 additions & 1 deletion src/commands/dependencies/useLocal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,13 @@ export async function useLocalDependency(
folder = folders[0];
}
const task = createSwiftTask(
["package", "edit", "--path", folder.fsPath, identifier],
ctx.toolchain.buildFlags.withAdditionalFlags([
"package",
"edit",
"--path",
folder.fsPath,
identifier,
]),
"Edit Package Dependency",
{
scope: currentFolder.workspaceFolder,
Expand Down
5 changes: 4 additions & 1 deletion src/commands/resetPackage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ export async function resetPackage(ctx: WorkspaceContext) {
*/
export async function folderResetPackage(folderContext: FolderContext) {
const task = createSwiftTask(
["package", "reset"],
folderContext.workspaceContext.toolchain.buildFlags.withAdditionalFlags([
"package",
"reset",
]),
"Reset Package Dependencies",
{
cwd: folderContext.folder,
Expand Down
11 changes: 11 additions & 0 deletions src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ export interface DebuggerConfiguration {
readonly debugAdapter: DebugAdapters;
/** Return path to debug adapter */
readonly customDebugAdapterPath: string;
/** Whether or not to disable setting up the debugger */
readonly disable: boolean;
}

/** workspace folder configuration */
Expand Down Expand Up @@ -212,6 +214,11 @@ const configuration = {
get customDebugAdapterPath(): string {
return vscode.workspace.getConfiguration("swift.debugger").get<string>("path", "");
},
get disable(): boolean {
return vscode.workspace
.getConfiguration("swift.debugger")
.get<boolean>("disable", false);
},
};
},
/** Files and directories to exclude from the code coverage. */
Expand Down Expand Up @@ -375,6 +382,10 @@ const configuration = {
.getConfiguration("swift")
.get<boolean>("enableTerminalEnvironment", true);
},
/** Whether or not to disable SwiftPM sandboxing */
get disableSandbox(): boolean {
return vscode.workspace.getConfiguration("swift").get<boolean>("disableSandbox", false);
},
};

export default configuration;
2 changes: 1 addition & 1 deletion src/debugger/buildConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ export class TestingConfigurationFactory {
}

const swiftTestingArgs = [
...args,
...this.ctx.workspaceContext.toolchain.buildFlags.withAdditionalFlags(args),
"--enable-swift-testing",
"--event-stream-version",
"0",
Expand Down
4 changes: 3 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ export async function activate(context: vscode.ExtensionContext): Promise<Api> {
const workspaceContext = await WorkspaceContext.create(context, outputChannel, toolchain);
context.subscriptions.push(...commands.register(workspaceContext));
context.subscriptions.push(workspaceContext);
context.subscriptions.push(registerDebugger(workspaceContext));
if (!configuration.debugger.disable) {
context.subscriptions.push(registerDebugger(workspaceContext));
}
context.subscriptions.push(new SelectedXcodeWatcher(outputChannel));

// listen for workspace folder changes and active text editor changes
Expand Down
4 changes: 2 additions & 2 deletions src/tasks/SwiftPluginTaskProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export class SwiftPluginTaskProvider implements vscode.TaskProvider {
task.definition.command,
...task.definition.args,
];
swiftArgs = this.workspaceContext.toolchain.buildFlags.withSwiftSDKFlags(swiftArgs);
swiftArgs = this.workspaceContext.toolchain.buildFlags.withAdditionalFlags(swiftArgs);

const cwd = resolveTaskCwd(task, task.definition.cwd);
const newTask = new vscode.Task(
Expand Down Expand Up @@ -122,7 +122,7 @@ export class SwiftPluginTaskProvider implements vscode.TaskProvider {
plugin.command,
...definition.args,
];
swiftArgs = this.workspaceContext.toolchain.buildFlags.withSwiftSDKFlags(swiftArgs);
swiftArgs = this.workspaceContext.toolchain.buildFlags.withAdditionalFlags(swiftArgs);

const presentation = config?.presentationOptions ?? {};
const task = new vscode.Task(
Expand Down
5 changes: 3 additions & 2 deletions src/tasks/SwiftTaskProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ export function createSwiftTask(
cmdEnv: { [key: string]: string } = {}
): SwiftTask {
const swift = toolchain.getToolchainExecutable("swift");
args = toolchain.buildFlags.withSwiftPackageFlags(toolchain.buildFlags.withSwiftSDKFlags(args));
args = toolchain.buildFlags.withAdditionalFlags(args);

// Add relative path current working directory
const cwd = config.cwd.fsPath;
Expand Down Expand Up @@ -422,7 +422,8 @@ export class SwiftTaskProvider implements vscode.TaskProvider {
resolveTask(task: vscode.Task, token: vscode.CancellationToken): vscode.Task {
// We need to create a new Task object here.
// Reusing the task parameter doesn't seem to work.
const swift = this.workspaceContext.toolchain.getToolchainExecutable("swift");
const toolchain = this.workspaceContext.toolchain;
const swift = toolchain.getToolchainExecutable("swift");
// platform specific
let platform: TaskPlatformSpecificConfig | undefined;
if (process.platform === "win32") {
Expand Down
40 changes: 39 additions & 1 deletion src/toolchain/BuildFlags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class BuildFlags {
*
* @param args original commandline arguments
*/
withSwiftSDKFlags(args: string[]): string[] {
private withSwiftSDKFlags(args: string[]): string[] {
switch (args[0]) {
case "package": {
const subcommand = args.splice(0, 2).concat(this.buildPathFlags());
Expand Down Expand Up @@ -192,6 +192,44 @@ export class BuildFlags {
return indirect ? args.flatMap(arg => ["-Xswiftc", arg]) : args;
}

/**
* Get modified swift arguments with new arguments for disabling
* sandboxing if the `swift.disableSandbox` setting is enabled.
*
* @param args original commandline arguments
*/
private withDisableSandboxFlags(args: string[]): string[] {
if (!configuration.disableSandbox) {
return args;
}
switch (args[0]) {
case "package": {
return [args[0], ...BuildFlags.disableSandboxFlags(), ...args.slice(1)];
}
case "build":
case "run":
case "test": {
return [...args, ...BuildFlags.disableSandboxFlags()];
}
default:
// Do nothing for other commands
return args;
}
}

withAdditionalFlags(args: string[]): string[] {
return this.withSwiftPackageFlags(
this.withDisableSandboxFlags(this.withSwiftSDKFlags(args))
);
}

/**
* Get flags for disabling sandboxing when running SwiftPM
*/
static disableSandboxFlags(): string[] {
return ["--disable-sandbox", "-Xswiftc", "-disable-sandbox"];
}

/**
* Filter argument list
* @param args argument list
Expand Down
8 changes: 4 additions & 4 deletions src/utilities/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,14 @@ export async function execFile(
options.env = { ...(options.env ?? process.env), ...runtimeEnv };
}
}
return new Promise<{ stdout: string; stderr: string }>((resolve, reject) =>
return new Promise<{ stdout: string; stderr: string }>((resolve, reject) => {
cp.execFile(executable, args, options, (error, stdout, stderr) => {
if (error) {
reject(new ExecFileError(error, stdout, stderr));
}
resolve({ stdout, stderr });
})
);
});
});
}

export async function execFileStreamOutput(
Expand Down Expand Up @@ -187,7 +187,7 @@ export async function execSwift(
swift = toolchain.getToolchainExecutable("swift");
}
if (toolchain !== "default") {
args = toolchain.buildFlags.withSwiftSDKFlags(args);
args = toolchain.buildFlags.withAdditionalFlags(args);
}
if (Object.keys(configuration.swiftEnvironmentVariables).length > 0) {
// when adding environment vars we either combine with vars passed
Expand Down
2 changes: 1 addition & 1 deletion test/integration-tests/BackgroundCompilation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,5 @@ suite("BackgroundCompilation Test Suite", () => {
await vscode.workspace.save(uri);

await taskPromise;
}).timeout(120000);
}).timeout(180000);
});
6 changes: 3 additions & 3 deletions test/integration-tests/DiagnosticsManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ suite("DiagnosticsManager Test Suite", async function () {
// after first build and can cause intermittent
// failure if `swiftc` diagnostic is fixed
suiteSetup(async function () {
this.timeout(2 * 60 * 1000); // Allow 2 minutes to build
this.timeout(3 * 60 * 1000); // Allow 3 minutes to build
const task = createBuildAllTask(folderContext);
// This return exit code and output for the task but we will omit it here
// because the failures are expected and we just want the task to build
Expand Down Expand Up @@ -1062,7 +1062,7 @@ suite("DiagnosticsManager Test Suite", async function () {

assertHasDiagnostic(mainUri, expectedDiagnostic1);
assertHasDiagnostic(mainUri, expectedDiagnostic2);
}).timeout(2 * 60 * 1000); // Allow 2 minutes to build
}).timeout(3 * 60 * 1000); // Allow 3 minutes to build

test("Provides clang diagnostics", async () => {
// Build for indexing
Expand Down Expand Up @@ -1099,6 +1099,6 @@ suite("DiagnosticsManager Test Suite", async function () {

assertHasDiagnostic(cUri, expectedDiagnostic1);
assertHasDiagnostic(cUri, expectedDiagnostic2);
}).timeout(2 * 60 * 1000); // Allow 2 minutes to build
}).timeout(3 * 60 * 1000); // Allow 3 minutes to build
});
});
3 changes: 2 additions & 1 deletion test/integration-tests/SwiftSnippet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function normalizePath(...segments: string[]): string {
}

suite("SwiftSnippet Test Suite @slow", function () {
this.timeout(120000);
this.timeout(180000);

const uri = testAssetUri("defaultPackage/Snippets/hello.swift");
const breakpoints = [
Expand All @@ -62,6 +62,7 @@ suite("SwiftSnippet Test Suite @slow", function () {
// Set a breakpoint
vscode.debug.addBreakpoints(breakpoints);
},
requiresDebugger: true,
});

suiteTeardown(async () => {
Expand Down
3 changes: 2 additions & 1 deletion test/integration-tests/commands/build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { Version } from "../../../src/utilities/version";

suite("Build Commands @slow", function () {
// Default timeout is a bit too short, give it a little bit more time
this.timeout(2 * 60 * 1000);
this.timeout(3 * 60 * 1000);

let folderContext: FolderContext;
let workspaceContext: WorkspaceContext;
Expand Down Expand Up @@ -56,6 +56,7 @@ suite("Build Commands @slow", function () {
async teardown() {
await vscode.commands.executeCommand(Workbench.ACTION_CLOSEALLEDITORS);
},
requiresDebugger: true,
});

test("Swift: Run Build", async () => {
Expand Down
1 change: 1 addition & 0 deletions test/integration-tests/debugger/lldb.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ suite("lldb contract test suite", () => {
}
workspaceContext = ctx;
},
requiresDebugger: true,
});

test("getLldbProcess Contract Test, make sure the command returns", async () => {
Expand Down
Loading

0 comments on commit ff19a00

Please sign in to comment.