From 99ac9caa2b34d550a20ab06fb3f4344d327316cb Mon Sep 17 00:00:00 2001 From: Sean McManus Date: Thu, 8 Oct 2026 16:34:24 -0700 Subject: [PATCH] Make multi-root inactive folding routing test deterministic --- .../tests/inactiveFolding.test.ts | 95 ++++--------------- 1 file changed, 20 insertions(+), 75 deletions(-) diff --git a/Extension/test/scenarios/MultirootDeadlockTest/tests/inactiveFolding.test.ts b/Extension/test/scenarios/MultirootDeadlockTest/tests/inactiveFolding.test.ts index f97597c64..4f544ca10 100644 --- a/Extension/test/scenarios/MultirootDeadlockTest/tests/inactiveFolding.test.ts +++ b/Extension/test/scenarios/MultirootDeadlockTest/tests/inactiveFolding.test.ts @@ -11,75 +11,69 @@ import { suite } from 'mocha'; import * as path from 'path'; import * as sinon from 'sinon'; import * as vscode from 'vscode'; -import * as api from 'vscode-cpptools'; -import * as apit from 'vscode-cpptools/out/testApi'; import * as extension from '../../../../src/LanguageServer/extension'; import * as testHelpers from '../../../common/testHelpers'; suite("Inactive region folding in a multi-root workspace", function (): void { - let testHook: apit.CppToolsTestHook; let firstWorkspaceFolder: vscode.WorkspaceFolder; let workspaceFolder: vscode.WorkspaceFolder; suiteSetup(async function (): Promise { await testHelpers.activateCppExtension(); - const cpptools: apit.CppToolsTestApi = await apit.getCppToolsTestApi(api.Version.latest) - ?? assert.fail("Could not get CppToolsTestApi"); - testHook = cpptools.getTestHook(); firstWorkspaceFolder = vscode.workspace.workspaceFolders?.[0] ?? assert.fail("First workspace folder is unavailable"); workspaceFolder = vscode.workspace.workspaceFolders?.[1] ?? assert.fail("Second workspace folder is unavailable"); }); - suiteTeardown(function (): void { - testHook.dispose(); - }); - test("routes manual folding operations by URI during a workspace client switch", async () => { - const configuration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("C_Cpp", workspaceFolder.uri); - const previousCodeFoldingValue: string | undefined = configuration.inspect("codeFolding")?.globalValue; - await configuration.update("codeFolding", "enabled", vscode.ConfigurationTarget.Global); + const sandbox: sinon.SinonSandbox = sinon.createSandbox(); let releaseEditorChange: (() => void) | undefined; - let editorChangeStub: sinon.SinonStub | undefined; let editorChangePromise: Promise | undefined; let editor: vscode.TextEditor | undefined; let firstEditor: vscode.TextEditor | undefined; try { - editor = await openFileAndWaitForIntelliSense(); - await vscode.commands.executeCommand("editor.unfoldAll"); - const firstDocument: vscode.TextDocument = await vscode.workspace.openTextDocument( path.join(firstWorkspaceFolder.uri.fsPath, "test.cpp")); firstEditor = await vscode.window.showTextDocument(firstDocument); await extension.clients.didChangeActiveEditor(firstEditor); const firstClient = extension.clients.ActiveClient; - const owner = extension.clients.getClientFor(editor.document.uri); + const document: vscode.TextDocument = await vscode.workspace.openTextDocument( + path.join(workspaceFolder.uri.fsPath, "code_folding.cpp")); + const owner = extension.clients.getClientFor(document.uri); assert.notStrictEqual(firstClient, owner); + const ownerFoldStub: sinon.SinonStub = sandbox.stub(owner, "foldAllInactiveRegions").resolves(); + const ownerUnfoldStub: sinon.SinonStub = sandbox.stub(owner, "unfoldAllInactiveRegions").resolves(); + const firstFoldStub: sinon.SinonStub = sandbox.stub(firstClient, "foldAllInactiveRegions").resolves(); + const firstUnfoldStub: sinon.SinonStub = sandbox.stub(firstClient, "unfoldAllInactiveRegions").resolves(); + const pendingEditorChange: Promise = new Promise(resolve => releaseEditorChange = resolve); - editorChangeStub = sinon.stub(owner, "didChangeActiveEditor").returns(pendingEditorChange); - const activeEditor: vscode.TextEditor = await vscode.window.showTextDocument(editor.document, editor.viewColumn, false); - editorChangePromise = extension.clients.didChangeActiveEditor(activeEditor); + // Hold the client switch open; only command dispatch is under test. + sandbox.stub(owner, "didChangeActiveEditor").returns(pendingEditorChange); + editor = await vscode.window.showTextDocument(document); + editorChangePromise = extension.clients.didChangeActiveEditor(editor); assert.strictEqual(extension.clients.ActiveClient, firstClient); await vscode.commands.executeCommand("C_Cpp.FoldAllInactiveRegions"); - await assertInactiveBranchIsFolded(editor); + sinon.assert.calledOnce(ownerFoldStub); + sinon.assert.notCalled(firstFoldStub); + assert.strictEqual(extension.clients.ActiveClient, firstClient); await vscode.commands.executeCommand("C_Cpp.UnfoldAllInactiveRegions"); - await assertInactiveBranchIsUnfolded(editor); + sinon.assert.calledOnce(ownerUnfoldStub); + sinon.assert.notCalled(firstUnfoldStub); + assert.strictEqual(extension.clients.ActiveClient, firstClient); } finally { releaseEditorChange?.(); await editorChangePromise; - editorChangeStub?.restore(); + sandbox.restore(); if (editor) { await closeEditor(editor); } if (firstEditor) { await closeEditor(firstEditor); } - await testHelpers.delay(150); - await configuration.update("codeFolding", previousCodeFoldingValue, vscode.ConfigurationTarget.Global); } }); @@ -87,53 +81,4 @@ suite("Inactive region folding in a multi-root workspace", function (): void { await vscode.window.showTextDocument(editor.document, editor.viewColumn, false); await vscode.commands.executeCommand("workbench.action.closeActiveEditor"); } - - async function assertInactiveBranchIsFolded(editor: vscode.TextEditor): Promise { - let line: number = 24; - for (let i: number = 0; i < 20; ++i) { - const activeEditor: vscode.TextEditor = await vscode.window.showTextDocument(editor.document, editor.viewColumn, false); - activeEditor.selection = new vscode.Selection(24, 0, 24, 0); - await vscode.commands.executeCommand("cursorMove", { to: "down", by: "wrappedLine", value: 1 }); - line = activeEditor.selection.active.line; - if (line === 28) { - return; - } - await testHelpers.delay(50); - } - - assert.strictEqual(line, 28); - } - - async function assertInactiveBranchIsUnfolded(editor: vscode.TextEditor): Promise { - const activeEditor: vscode.TextEditor = await vscode.window.showTextDocument(editor.document, editor.viewColumn, false); - activeEditor.selection = new vscode.Selection(24, 0, 24, 0); - await vscode.commands.executeCommand("cursorMove", { to: "down", by: "wrappedLine", value: 1 }); - assert.strictEqual(activeEditor.selection.active.line, 25); - } - - function waitForIntelliSenseReady(fileName: string): Promise { - return new Promise((resolve, reject) => { - const timeout: NodeJS.Timeout = setTimeout(() => { - listener.dispose(); - reject(new Error(`Timed out waiting for IntelliSense for ${fileName}`)); - }, testHelpers.defaultTimeout); - const listener: vscode.Disposable = testHook.IntelliSenseStatusChanged(result => { - if (result.filename === fileName && result.status === apit.Status.IntelliSenseReady) { - clearTimeout(timeout); - listener.dispose(); - resolve(); - } - }); - }); - } - - async function openFileAndWaitForIntelliSense(): Promise { - const fileName: string = "code_folding.cpp"; - const filePath: string = path.join(workspaceFolder.uri.fsPath, fileName); - const ready: Promise = waitForIntelliSenseReady(fileName); - const document: vscode.TextDocument = await vscode.workspace.openTextDocument(filePath); - const editor: vscode.TextEditor = await vscode.window.showTextDocument(document); - await ready; - return editor; - } });