From 38398b9a303b492ef9762f4e3be3b6c7d8f4091b Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 10 Jan 2024 13:55:06 -0800 Subject: [PATCH 01/23] Smoke tests for formatting --- .vscode/launch.json | 45 +++++----- package.json | 1 + src/test/ts_tests/index.ts | 8 +- src/test/ts_tests/runSmokeTest.ts | 34 +++++++ .../test_data/project/.vscode/settings.json | 6 ++ .../test_data/project/myscript.formatted | 3 + .../ts_tests/test_data/project/myscript.py | 2 + .../test_data/project/myscript.unformatted | 2 + .../tests/common/minimal.smoke.test.ts | 89 +++++++++++++++++++ 9 files changed, 166 insertions(+), 24 deletions(-) create mode 100644 src/test/ts_tests/runSmokeTest.ts create mode 100644 src/test/ts_tests/test_data/project/.vscode/settings.json create mode 100644 src/test/ts_tests/test_data/project/myscript.formatted create mode 100644 src/test/ts_tests/test_data/project/myscript.py create mode 100644 src/test/ts_tests/test_data/project/myscript.unformatted create mode 100644 src/test/ts_tests/tests/common/minimal.smoke.test.ts diff --git a/.vscode/launch.json b/.vscode/launch.json index 6e1f4f9..628ab3c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,12 +9,8 @@ "name": "Debug Extension Only", "type": "extensionHost", "request": "launch", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "outFiles": [ - "${workspaceFolder}/dist/**/*.js" - ], + "args": ["--extensionDevelopmentPath=${workspaceFolder}"], + "outFiles": ["${workspaceFolder}/dist/**/*.js"], "preLaunchTask": "npm: watch", "presentation": { "hidden": false, @@ -42,10 +38,22 @@ "--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/out/test/ts_tests/index" ], - "outFiles": [ - "${workspaceFolder}/out/**/*.js", - "${workspaceFolder}/dist/**/*.js" + "outFiles": ["${workspaceFolder}/out/**/*.js", "${workspaceFolder}/dist/**/*.js"], + "preLaunchTask": "tasks: watch-tests" + }, + { + "name": "TS Smoke Tests", + "type": "extensionHost", + "request": "launch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}", + "--extensionTestsPath=${workspaceFolder}/out/test/ts_tests/index", + "--timeout=600000" ], + "outFiles": ["${workspaceFolder}/out/**/*.js", "${workspaceFolder}/dist/**/*.js"], + "env": { + "SMOKE_TESTS": "true" + }, "preLaunchTask": "tasks: watch-tests" }, { @@ -53,9 +61,7 @@ "type": "python", "request": "launch", "console": "integratedTerminal", - "purpose": [ - "debug-test" - ], + "purpose": ["debug-test"], "justMyCode": true, "presentation": { "hidden": true, @@ -67,12 +73,8 @@ "name": "Debug Extension (hidden)", "type": "extensionHost", "request": "launch", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "outFiles": [ - "${workspaceFolder}/dist/**/*.js" - ], + "args": ["--extensionDevelopmentPath=${workspaceFolder}"], + "outFiles": ["${workspaceFolder}/dist/**/*.js"], "env": { "USE_DEBUGPY": "True" }, @@ -101,10 +103,7 @@ "compounds": [ { "name": "Debug Extension and Python", - "configurations": [ - "Python debug server (hidden)", - "Debug Extension (hidden)" - ], + "configurations": ["Python debug server (hidden)", "Debug Extension (hidden)"], "stopAll": true, "preLaunchTask": "npm: watch", "presentation": { @@ -114,4 +113,4 @@ } } ] -} \ No newline at end of file +} diff --git a/package.json b/package.json index e0a423a..ecac6c1 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "package": "webpack --mode production --devtool hidden-source-map", "pretest": "npm run compile-tests && npm run compile && npm run lint", "tests": "node ./out/test/ts_tests/runTest.js", + "smoke-tests": "node ./out/test/ts_tests/runSmokeTest.js", "vsce-package": "vsce package -o black-formatter.vsix", "vscode:prepublish": "npm run package", "watch": "webpack --watch", diff --git a/src/test/ts_tests/index.ts b/src/test/ts_tests/index.ts index 6a96237..af5f602 100644 --- a/src/test/ts_tests/index.ts +++ b/src/test/ts_tests/index.ts @@ -1,6 +1,7 @@ import * as glob from 'glob'; import Mocha from 'mocha'; import * as path from 'path'; +import { env } from 'process'; export function run(): Promise { // Create the mocha test @@ -12,7 +13,12 @@ export function run(): Promise { const testsRoot = path.resolve(__dirname, './tests'); return new Promise((c, e) => { - const files = glob.globSync('**/**.test.js', { cwd: testsRoot }); + let files = []; + if (env.SMOKE_TESTS) { + files = glob.globSync('**/**.smoke.test.js', { cwd: testsRoot }); + } else { + files = glob.globSync('**/**.unit.test.js', { cwd: testsRoot }); + } // Add files to the test suite files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f))); diff --git a/src/test/ts_tests/runSmokeTest.ts b/src/test/ts_tests/runSmokeTest.ts new file mode 100644 index 0000000..0f0633f --- /dev/null +++ b/src/test/ts_tests/runSmokeTest.ts @@ -0,0 +1,34 @@ +import * as path from 'path'; + +import { runTests } from '@vscode/test-electron'; +import { EXTENSION_ROOT_DIR } from '../../common/constants'; + +const TEST_PROJECT_DIR = path.join(EXTENSION_ROOT_DIR, 'src', 'test', 'ts_tests', 'test_data', 'project'); + +async function main() { + try { + // The folder containing the Extension Manifest package.json + // Passed to `--extensionDevelopmentPath` + const extensionDevelopmentPath = EXTENSION_ROOT_DIR; + + // The path to test runner + // Passed to --extensionTestsPath + const extensionTestsPath = path.resolve(__dirname, './index'); + + // Download VS Code, unzip it and run the integration test + // eslint-disable-next-line @typescript-eslint/naming-convention + await runTests({ + extensionDevelopmentPath, + extensionTestsPath, + extensionTestsEnv: { SMOKE_TESTS: 'true' }, + timeout: 60000, + launchArgs: [TEST_PROJECT_DIR], + }); + } catch (err) { + console.error('Failed to run tests'); + console.error(err); + process.exit(1); + } +} + +main(); diff --git a/src/test/ts_tests/test_data/project/.vscode/settings.json b/src/test/ts_tests/test_data/project/.vscode/settings.json new file mode 100644 index 0000000..2d70953 --- /dev/null +++ b/src/test/ts_tests/test_data/project/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter", + "editor.formatOnSave": true + } +} diff --git a/src/test/ts_tests/test_data/project/myscript.formatted b/src/test/ts_tests/test_data/project/myscript.formatted new file mode 100644 index 0000000..57c7405 --- /dev/null +++ b/src/test/ts_tests/test_data/project/myscript.formatted @@ -0,0 +1,3 @@ +import sys + +print(sys.executable) diff --git a/src/test/ts_tests/test_data/project/myscript.py b/src/test/ts_tests/test_data/project/myscript.py new file mode 100644 index 0000000..14566f5 --- /dev/null +++ b/src/test/ts_tests/test_data/project/myscript.py @@ -0,0 +1,2 @@ +import sys +print(sys.executable) \ No newline at end of file diff --git a/src/test/ts_tests/test_data/project/myscript.unformatted b/src/test/ts_tests/test_data/project/myscript.unformatted new file mode 100644 index 0000000..14566f5 --- /dev/null +++ b/src/test/ts_tests/test_data/project/myscript.unformatted @@ -0,0 +1,2 @@ +import sys +print(sys.executable) \ No newline at end of file diff --git a/src/test/ts_tests/tests/common/minimal.smoke.test.ts b/src/test/ts_tests/tests/common/minimal.smoke.test.ts new file mode 100644 index 0000000..2c5fa40 --- /dev/null +++ b/src/test/ts_tests/tests/common/minimal.smoke.test.ts @@ -0,0 +1,89 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import * as path from 'path'; +import * as vscode from 'vscode'; +import * as fsapi from 'fs-extra'; +import { EXTENSION_ROOT_DIR } from '../../../../common/constants'; +import { assert } from 'chai'; + +const TEST_PROJECT_DIR = path.join(EXTENSION_ROOT_DIR, 'src', 'test', 'ts_tests', 'test_data', 'project'); +const TIMEOUT = 100000; + +suite('Smoke Tests', () => { + let disposables: vscode.Disposable[] = []; + suiteSetup(async () => { + const pythonExt = vscode.extensions.getExtension('ms-python.python'); + if (!pythonExt) { + await vscode.commands.executeCommand('workbench.extensions.installExtension', 'ms-python.python'); + } + }); + + setup(async () => { + disposables = []; + await vscode.commands.executeCommand('workbench.action.closeAllEditors'); + }); + teardown(async () => { + await vscode.commands.executeCommand('workbench.action.closeAllEditors'); + + disposables.forEach((d) => d.dispose()); + disposables = []; + }); + + async function ensurePythonExt() { + const pythonExt = vscode.extensions.getExtension('ms-python.python'); + assert.ok(pythonExt, 'Python Extension not found'); + await pythonExt?.activate(); + } + + async function ensureBlackExt() { + const extension = vscode.extensions.getExtension('ms-python.black-formatter'); + assert.ok(extension, 'Extension not found'); + await extension?.activate(); + } + + test('Extension loads', async function () { + this.timeout(TIMEOUT); + + await vscode.workspace.openTextDocument(path.join(TEST_PROJECT_DIR, 'myscript.py')); + + await ensurePythonExt(); + + const extension = vscode.extensions.getExtension('ms-python.black-formatter'); + assert.ok(extension, 'Extension not found'); + + if (extension) { + let timeout = TIMEOUT; + while (!extension.isActive && timeout > 0) { + await new Promise((resolve) => setTimeout(resolve, 100)); + timeout -= 100; + } + assert.ok(extension.isActive, `Extension not activated in ${TIMEOUT / 1000} seconds`); + } + }); + + test('Black formats a file', async function () { + this.timeout(TIMEOUT); + + await ensurePythonExt(); + + const unformatted = await fsapi.readFile(path.join(TEST_PROJECT_DIR, 'myscript.unformatted'), { + encoding: 'utf8', + }); + const formatted = await fsapi.readFile(path.join(TEST_PROJECT_DIR, 'myscript.formatted'), { encoding: 'utf8' }); + await fsapi.writeFile(path.join(TEST_PROJECT_DIR, 'myscript.py'), unformatted, { encoding: 'utf8' }); + + const doc = await vscode.workspace.openTextDocument(path.join(TEST_PROJECT_DIR, 'myscript.py')); + await vscode.window.showTextDocument(doc); + + await ensureBlackExt(); + + const editor = vscode.window.activeTextEditor; + assert.ok(editor, 'No active editor'); + + assert.ok(editor?.document.uri.fsPath.endsWith('myscript.py'), 'Active editor is not myscript.py'); + await vscode.workspace.saveAll(); + const actualText = editor?.document.getText(); + assert.equal(actualText, formatted); + }); +}); From b7a3ee75eb76894948cac18a84fd7204322d0790 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Tue, 16 Jan 2024 19:56:39 -0800 Subject: [PATCH 02/23] Somewhat working --- .vscode/launch.json | 3 +- src/test/ts_tests/runSmokeTest.ts | 7 ++- .../tests/common/minimal.smoke.test.ts | 47 ++++++++++++++----- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 628ab3c..db1a279 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -48,7 +48,8 @@ "args": [ "--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/out/test/ts_tests/index", - "--timeout=600000" + "--timeout=600000", + "${workspaceFolder}/src/test/ts_tests/test_data/project" ], "outFiles": ["${workspaceFolder}/out/**/*.js", "${workspaceFolder}/dist/**/*.js"], "env": { diff --git a/src/test/ts_tests/runSmokeTest.ts b/src/test/ts_tests/runSmokeTest.ts index 0f0633f..9a826a1 100644 --- a/src/test/ts_tests/runSmokeTest.ts +++ b/src/test/ts_tests/runSmokeTest.ts @@ -1,3 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +/* eslint-disable @typescript-eslint/naming-convention */ + import * as path from 'path'; import { runTests } from '@vscode/test-electron'; @@ -16,12 +20,11 @@ async function main() { const extensionTestsPath = path.resolve(__dirname, './index'); // Download VS Code, unzip it and run the integration test - // eslint-disable-next-line @typescript-eslint/naming-convention await runTests({ extensionDevelopmentPath, extensionTestsPath, extensionTestsEnv: { SMOKE_TESTS: 'true' }, - timeout: 60000, + timeout: 360000, launchArgs: [TEST_PROJECT_DIR], }); } catch (err) { diff --git a/src/test/ts_tests/tests/common/minimal.smoke.test.ts b/src/test/ts_tests/tests/common/minimal.smoke.test.ts index 2c5fa40..c3e1868 100644 --- a/src/test/ts_tests/tests/common/minimal.smoke.test.ts +++ b/src/test/ts_tests/tests/common/minimal.smoke.test.ts @@ -8,11 +8,14 @@ import { EXTENSION_ROOT_DIR } from '../../../../common/constants'; import { assert } from 'chai'; const TEST_PROJECT_DIR = path.join(EXTENSION_ROOT_DIR, 'src', 'test', 'ts_tests', 'test_data', 'project'); -const TIMEOUT = 100000; +const TIMEOUT = 360000; + +suite('Smoke Tests', function () { + this.timeout(TIMEOUT); -suite('Smoke Tests', () => { let disposables: vscode.Disposable[] = []; - suiteSetup(async () => { + suiteSetup(async function () { + this.timeout(TIMEOUT); const pythonExt = vscode.extensions.getExtension('ms-python.python'); if (!pythonExt) { await vscode.commands.executeCommand('workbench.extensions.installExtension', 'ms-python.python'); @@ -36,15 +39,13 @@ suite('Smoke Tests', () => { await pythonExt?.activate(); } - async function ensureBlackExt() { + async function ensureBlackExt(): Promise { const extension = vscode.extensions.getExtension('ms-python.black-formatter'); assert.ok(extension, 'Extension not found'); await extension?.activate(); } - test('Extension loads', async function () { - this.timeout(TIMEOUT); - + test('Extension loads', async () => { await vscode.workspace.openTextDocument(path.join(TEST_PROJECT_DIR, 'myscript.py')); await ensurePythonExt(); @@ -62,9 +63,7 @@ suite('Smoke Tests', () => { } }); - test('Black formats a file', async function () { - this.timeout(TIMEOUT); - + test('Black formats a file', async () => { await ensurePythonExt(); const unformatted = await fsapi.readFile(path.join(TEST_PROJECT_DIR, 'myscript.unformatted'), { @@ -80,9 +79,33 @@ suite('Smoke Tests', () => { const editor = vscode.window.activeTextEditor; assert.ok(editor, 'No active editor'); - assert.ok(editor?.document.uri.fsPath.endsWith('myscript.py'), 'Active editor is not myscript.py'); - await vscode.workspace.saveAll(); + + const formatReady = new Promise((resolve) => { + const disposable = vscode.workspace.onDidChangeTextDocument((e) => { + if (e.document.uri.fsPath.includes('Black')) { + const text = e.document.getText(); + if (text.includes('textDocument/didOpen')) { + disposable.dispose(); + resolve(); + } + } + }); + }); + await formatReady; + + const formatDone = new Promise((resolve) => { + const disposable = vscode.workspace.onDidSaveTextDocument((e) => { + if (e.uri.fsPath.endsWith('myscript.py')) { + disposable.dispose(); + resolve(); + } + }); + }); + + await vscode.commands.executeCommand('workbench.action.files.save'); + await formatDone; + const actualText = editor?.document.getText(); assert.equal(actualText, formatted); }); From b7191682c9818ae43768a9a501408b7b94a17f96 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Tue, 30 Jan 2024 18:05:27 -0800 Subject: [PATCH 03/23] Some tests working --- .vscode/launch.json | 1 - bundled/tool/lsp_server.py | 4 +-- src/test/ts_tests/runSmokeTest.ts | 12 +++++-- .../ts_tests/test_data/project/myscript.py | 3 +- .../tests/common/minimal.smoke.test.ts | 34 +++++++++---------- 5 files changed, 30 insertions(+), 24 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index db1a279..9c874cb 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -48,7 +48,6 @@ "args": [ "--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/out/test/ts_tests/index", - "--timeout=600000", "${workspaceFolder}/src/test/ts_tests/test_data/project" ], "outFiles": ["${workspaceFolder}/out/**/*.js", "${workspaceFolder}/dist/**/*.js"], diff --git a/bundled/tool/lsp_server.py b/bundled/tool/lsp_server.py index 9b2ad57..f47fb6b 100644 --- a/bundled/tool/lsp_server.py +++ b/bundled/tool/lsp_server.py @@ -277,6 +277,8 @@ def initialize(params: lsp.InitializeParams) -> None: paths = "\r\n ".join(sys.path) log_to_output(f"sys.path used to run Server:\r\n {paths}") + _update_workspace_settings_with_version_info(WORKSPACE_SETTINGS) + @LSP_SERVER.feature(lsp.EXIT) def on_exit(_params: Optional[Any] = None) -> None: @@ -374,8 +376,6 @@ def _update_workspace_settings(settings): "workspaceFS": key, } - _update_workspace_settings_with_version_info(WORKSPACE_SETTINGS) - def _get_settings_by_path(file_path: pathlib.Path): workspaces = {s["workspaceFS"] for s in WORKSPACE_SETTINGS.values()} diff --git a/src/test/ts_tests/runSmokeTest.ts b/src/test/ts_tests/runSmokeTest.ts index 9a826a1..192a023 100644 --- a/src/test/ts_tests/runSmokeTest.ts +++ b/src/test/ts_tests/runSmokeTest.ts @@ -2,15 +2,24 @@ // Licensed under the MIT License. /* eslint-disable @typescript-eslint/naming-convention */ +import * as cp from 'child_process'; import * as path from 'path'; -import { runTests } from '@vscode/test-electron'; +import { runTests, downloadAndUnzipVSCode, resolveCliArgsFromVSCodeExecutablePath } from '@vscode/test-electron'; import { EXTENSION_ROOT_DIR } from '../../common/constants'; const TEST_PROJECT_DIR = path.join(EXTENSION_ROOT_DIR, 'src', 'test', 'ts_tests', 'test_data', 'project'); async function main() { try { + const vscodeExecutablePath = await downloadAndUnzipVSCode('stable'); + + const [cli, ...args] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath); + cp.spawnSync(cli, [...args, '--install-extension', 'ms-python.python'], { + encoding: 'utf-8', + stdio: 'inherit', + }); + // The folder containing the Extension Manifest package.json // Passed to `--extensionDevelopmentPath` const extensionDevelopmentPath = EXTENSION_ROOT_DIR; @@ -24,7 +33,6 @@ async function main() { extensionDevelopmentPath, extensionTestsPath, extensionTestsEnv: { SMOKE_TESTS: 'true' }, - timeout: 360000, launchArgs: [TEST_PROJECT_DIR], }); } catch (err) { diff --git a/src/test/ts_tests/test_data/project/myscript.py b/src/test/ts_tests/test_data/project/myscript.py index 14566f5..57c7405 100644 --- a/src/test/ts_tests/test_data/project/myscript.py +++ b/src/test/ts_tests/test_data/project/myscript.py @@ -1,2 +1,3 @@ import sys -print(sys.executable) \ No newline at end of file + +print(sys.executable) diff --git a/src/test/ts_tests/tests/common/minimal.smoke.test.ts b/src/test/ts_tests/tests/common/minimal.smoke.test.ts index c3e1868..5412c42 100644 --- a/src/test/ts_tests/tests/common/minimal.smoke.test.ts +++ b/src/test/ts_tests/tests/common/minimal.smoke.test.ts @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +import * as cp from 'child_process'; import * as path from 'path'; import * as vscode from 'vscode'; import * as fsapi from 'fs-extra'; @@ -8,24 +9,18 @@ import { EXTENSION_ROOT_DIR } from '../../../../common/constants'; import { assert } from 'chai'; const TEST_PROJECT_DIR = path.join(EXTENSION_ROOT_DIR, 'src', 'test', 'ts_tests', 'test_data', 'project'); -const TIMEOUT = 360000; +const TIMEOUT = 30000; // 30 seconds suite('Smoke Tests', function () { this.timeout(TIMEOUT); let disposables: vscode.Disposable[] = []; - suiteSetup(async function () { - this.timeout(TIMEOUT); - const pythonExt = vscode.extensions.getExtension('ms-python.python'); - if (!pythonExt) { - await vscode.commands.executeCommand('workbench.extensions.installExtension', 'ms-python.python'); - } - }); setup(async () => { disposables = []; await vscode.commands.executeCommand('workbench.action.closeAllEditors'); }); + teardown(async () => { await vscode.commands.executeCommand('workbench.action.closeAllEditors'); @@ -33,26 +28,29 @@ suite('Smoke Tests', function () { disposables = []; }); - async function ensurePythonExt() { + async function ensurePythonExt(activate?: boolean): Promise { const pythonExt = vscode.extensions.getExtension('ms-python.python'); assert.ok(pythonExt, 'Python Extension not found'); - await pythonExt?.activate(); + if (activate) { + await pythonExt?.activate(); + } } - async function ensureBlackExt(): Promise { + async function ensureBlackExt(activate?: boolean): Promise { const extension = vscode.extensions.getExtension('ms-python.black-formatter'); - assert.ok(extension, 'Extension not found'); - await extension?.activate(); + assert.ok(extension, 'Black Formatter Extension not found'); + if (activate) { + await extension?.activate(); + } } test('Extension loads', async () => { await vscode.workspace.openTextDocument(path.join(TEST_PROJECT_DIR, 'myscript.py')); - await ensurePythonExt(); + await ensurePythonExt(true); + await ensureBlackExt(false); const extension = vscode.extensions.getExtension('ms-python.black-formatter'); - assert.ok(extension, 'Extension not found'); - if (extension) { let timeout = TIMEOUT; while (!extension.isActive && timeout > 0) { @@ -64,7 +62,7 @@ suite('Smoke Tests', function () { }); test('Black formats a file', async () => { - await ensurePythonExt(); + await ensurePythonExt(true); const unformatted = await fsapi.readFile(path.join(TEST_PROJECT_DIR, 'myscript.unformatted'), { encoding: 'utf8', @@ -85,7 +83,7 @@ suite('Smoke Tests', function () { const disposable = vscode.workspace.onDidChangeTextDocument((e) => { if (e.document.uri.fsPath.includes('Black')) { const text = e.document.getText(); - if (text.includes('textDocument/didOpen')) { + if (text.includes('FOUND black==')) { disposable.dispose(); resolve(); } From 1f2c1200f3487ce8f72043f235684ce14f568dbe Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Tue, 30 Jan 2024 18:06:12 -0800 Subject: [PATCH 04/23] Tweaks --- src/test/ts_tests/tests/common/minimal.smoke.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ts_tests/tests/common/minimal.smoke.test.ts b/src/test/ts_tests/tests/common/minimal.smoke.test.ts index 5412c42..27cae41 100644 --- a/src/test/ts_tests/tests/common/minimal.smoke.test.ts +++ b/src/test/ts_tests/tests/common/minimal.smoke.test.ts @@ -44,7 +44,7 @@ suite('Smoke Tests', function () { } } - test('Extension loads', async () => { + test('Ensure Black Formatter Extension loads', async () => { await vscode.workspace.openTextDocument(path.join(TEST_PROJECT_DIR, 'myscript.py')); await ensurePythonExt(true); @@ -61,7 +61,7 @@ suite('Smoke Tests', function () { } }); - test('Black formats a file', async () => { + test('Ensure Black Formatter formats a file on save', async () => { await ensurePythonExt(true); const unformatted = await fsapi.readFile(path.join(TEST_PROJECT_DIR, 'myscript.unformatted'), { From 5d4adb83ea292d7614c0ace04fe043057d454755 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Tue, 30 Jan 2024 18:42:16 -0800 Subject: [PATCH 05/23] Fail test if no python is found by python extension --- src/test/ts_tests/tests/common/minimal.smoke.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/ts_tests/tests/common/minimal.smoke.test.ts b/src/test/ts_tests/tests/common/minimal.smoke.test.ts index 27cae41..2d3d84c 100644 --- a/src/test/ts_tests/tests/common/minimal.smoke.test.ts +++ b/src/test/ts_tests/tests/common/minimal.smoke.test.ts @@ -79,7 +79,7 @@ suite('Smoke Tests', function () { assert.ok(editor, 'No active editor'); assert.ok(editor?.document.uri.fsPath.endsWith('myscript.py'), 'Active editor is not myscript.py'); - const formatReady = new Promise((resolve) => { + const formatReady = new Promise((resolve, reject) => { const disposable = vscode.workspace.onDidChangeTextDocument((e) => { if (e.document.uri.fsPath.includes('Black')) { const text = e.document.getText(); @@ -87,6 +87,10 @@ suite('Smoke Tests', function () { disposable.dispose(); resolve(); } + if (text.includes('Python interpreter missing')) { + disposable.dispose(); + reject(); + } } }); }); From c5e0d9bffd4de05c6688124a1463db03fe07d51c Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Tue, 30 Jan 2024 18:49:43 -0800 Subject: [PATCH 06/23] Add smoke test to CI --- .github/workflows/pr-check.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 76debe6..782bdc3 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -120,8 +120,14 @@ jobs: run: npm run pretest shell: bash - - name: Run TS tests + - name: Run TS Unit tests uses: GabrielBB/xvfb-action@v1.6 with: run: npm run tests working-directory: ${{ env.special-working-directory }} + + - name: Run TS Smoke tests + uses: GabrielBB/xvfb-action@v1.6 + with: + run: npm run smoke-tests + working-directory: ${{ env.special-working-directory }} From 1469d6a324ba9d034c89537ee75eeb8c665a2347 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Tue, 30 Jan 2024 19:07:13 -0800 Subject: [PATCH 07/23] Add logging --- src/test/ts_tests/runSmokeTest.ts | 11 +++++------ src/test/ts_tests/tests/common/minimal.smoke.test.ts | 6 ++++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/test/ts_tests/runSmokeTest.ts b/src/test/ts_tests/runSmokeTest.ts index 192a023..fbafddb 100644 --- a/src/test/ts_tests/runSmokeTest.ts +++ b/src/test/ts_tests/runSmokeTest.ts @@ -12,23 +12,22 @@ const TEST_PROJECT_DIR = path.join(EXTENSION_ROOT_DIR, 'src', 'test', 'ts_tests' async function main() { try { + console.log('Downloading VS Code...'); const vscodeExecutablePath = await downloadAndUnzipVSCode('stable'); + console.log('Finished downloading VS Code.'); const [cli, ...args] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath); + console.log('Installing Python extension...', [cli, ...args, '--install-extension', 'ms-python.python']); cp.spawnSync(cli, [...args, '--install-extension', 'ms-python.python'], { encoding: 'utf-8', stdio: 'inherit', }); + console.log('Finished installing Python extension.'); - // The folder containing the Extension Manifest package.json - // Passed to `--extensionDevelopmentPath` const extensionDevelopmentPath = EXTENSION_ROOT_DIR; - - // The path to test runner - // Passed to --extensionTestsPath const extensionTestsPath = path.resolve(__dirname, './index'); - // Download VS Code, unzip it and run the integration test + console.log('Running tests...'); await runTests({ extensionDevelopmentPath, extensionTestsPath, diff --git a/src/test/ts_tests/tests/common/minimal.smoke.test.ts b/src/test/ts_tests/tests/common/minimal.smoke.test.ts index 2d3d84c..23991a0 100644 --- a/src/test/ts_tests/tests/common/minimal.smoke.test.ts +++ b/src/test/ts_tests/tests/common/minimal.smoke.test.ts @@ -79,15 +79,18 @@ suite('Smoke Tests', function () { assert.ok(editor, 'No active editor'); assert.ok(editor?.document.uri.fsPath.endsWith('myscript.py'), 'Active editor is not myscript.py'); + console.log('Waiting for Black formatter to load...'); const formatReady = new Promise((resolve, reject) => { const disposable = vscode.workspace.onDidChangeTextDocument((e) => { if (e.document.uri.fsPath.includes('Black')) { const text = e.document.getText(); if (text.includes('FOUND black==')) { + console.log('Waiting for Black formatter to finished loading'); disposable.dispose(); resolve(); } if (text.includes('Python interpreter missing')) { + console.log('Waiting for Black formatter failed to load'); disposable.dispose(); reject(); } @@ -96,6 +99,7 @@ suite('Smoke Tests', function () { }); await formatReady; + console.log('Waiting for Black formatter to format...'); const formatDone = new Promise((resolve) => { const disposable = vscode.workspace.onDidSaveTextDocument((e) => { if (e.uri.fsPath.endsWith('myscript.py')) { @@ -105,8 +109,10 @@ suite('Smoke Tests', function () { }); }); + console.log('Triggering save to start format-on-save...'); await vscode.commands.executeCommand('workbench.action.files.save'); await formatDone; + console.log('Formatting done'); const actualText = editor?.document.getText(); assert.equal(actualText, formatted); From dbd94cc0f070fae83a746087b8651aa973058319 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Tue, 30 Jan 2024 19:15:20 -0800 Subject: [PATCH 08/23] Tweak more things --- src/test/ts_tests/runSmokeTest.ts | 2 +- src/test/ts_tests/tests/common/minimal.smoke.test.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/ts_tests/runSmokeTest.ts b/src/test/ts_tests/runSmokeTest.ts index fbafddb..b725854 100644 --- a/src/test/ts_tests/runSmokeTest.ts +++ b/src/test/ts_tests/runSmokeTest.ts @@ -18,7 +18,7 @@ async function main() { const [cli, ...args] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath); console.log('Installing Python extension...', [cli, ...args, '--install-extension', 'ms-python.python']); - cp.spawnSync(cli, [...args, '--install-extension', 'ms-python.python'], { + cp.spawnSync(`"${cli}"`, [...args, '--install-extension', 'ms-python.python'], { encoding: 'utf-8', stdio: 'inherit', }); diff --git a/src/test/ts_tests/tests/common/minimal.smoke.test.ts b/src/test/ts_tests/tests/common/minimal.smoke.test.ts index 23991a0..30dce7d 100644 --- a/src/test/ts_tests/tests/common/minimal.smoke.test.ts +++ b/src/test/ts_tests/tests/common/minimal.smoke.test.ts @@ -84,6 +84,7 @@ suite('Smoke Tests', function () { const disposable = vscode.workspace.onDidChangeTextDocument((e) => { if (e.document.uri.fsPath.includes('Black')) { const text = e.document.getText(); + console.log(text); if (text.includes('FOUND black==')) { console.log('Waiting for Black formatter to finished loading'); disposable.dispose(); From 3845c652444275452d719dd0d83d65e6dd71cd81 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Tue, 30 Jan 2024 19:18:45 -0800 Subject: [PATCH 09/23] Try relative path --- src/test/ts_tests/runSmokeTest.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/ts_tests/runSmokeTest.ts b/src/test/ts_tests/runSmokeTest.ts index b725854..4f48e90 100644 --- a/src/test/ts_tests/runSmokeTest.ts +++ b/src/test/ts_tests/runSmokeTest.ts @@ -17,8 +17,9 @@ async function main() { console.log('Finished downloading VS Code.'); const [cli, ...args] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath); - console.log('Installing Python extension...', [cli, ...args, '--install-extension', 'ms-python.python']); - cp.spawnSync(`"${cli}"`, [...args, '--install-extension', 'ms-python.python'], { + const command = path.relative(EXTENSION_ROOT_DIR, cli); + console.log('Installing Python extension...', [command, ...args, '--install-extension', 'ms-python.python']); + cp.spawnSync(command, [...args, '--install-extension', 'ms-python.python'], { encoding: 'utf-8', stdio: 'inherit', }); From b82a9b13a8ecd2639a2ada41e4aa5ebb33ec5333 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Tue, 30 Jan 2024 19:22:05 -0800 Subject: [PATCH 10/23] Force black extension load --- src/test/ts_tests/tests/common/minimal.smoke.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ts_tests/tests/common/minimal.smoke.test.ts b/src/test/ts_tests/tests/common/minimal.smoke.test.ts index 30dce7d..9d400d3 100644 --- a/src/test/ts_tests/tests/common/minimal.smoke.test.ts +++ b/src/test/ts_tests/tests/common/minimal.smoke.test.ts @@ -73,7 +73,7 @@ suite('Smoke Tests', function () { const doc = await vscode.workspace.openTextDocument(path.join(TEST_PROJECT_DIR, 'myscript.py')); await vscode.window.showTextDocument(doc); - await ensureBlackExt(); + await ensureBlackExt(true); const editor = vscode.window.activeTextEditor; assert.ok(editor, 'No active editor'); From 4b8f46baeb218d704000e2cf07e4508e9a8a422c Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Tue, 30 Jan 2024 19:31:39 -0800 Subject: [PATCH 11/23] More test tweaks --- .github/workflows/pr-check.yml | 5 +++ .../tests/common/minimal.smoke.test.ts | 31 ++++++++++--------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 782bdc3..97f1dfe 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -112,6 +112,11 @@ jobs: cache: 'npm' cache-dependency-path: ${{ env.special-working-directory-relative }}/package-lock.json + - name: Use Python 3.x + uses: actions/setup-python@v5 + with: + python-version: '3.x' + - name: Install Node dependencies run: npm ci shell: bash diff --git a/src/test/ts_tests/tests/common/minimal.smoke.test.ts b/src/test/ts_tests/tests/common/minimal.smoke.test.ts index 9d400d3..403b404 100644 --- a/src/test/ts_tests/tests/common/minimal.smoke.test.ts +++ b/src/test/ts_tests/tests/common/minimal.smoke.test.ts @@ -79,24 +79,25 @@ suite('Smoke Tests', function () { assert.ok(editor, 'No active editor'); assert.ok(editor?.document.uri.fsPath.endsWith('myscript.py'), 'Active editor is not myscript.py'); + vscode.workspace.workspaceFolders?.forEach((f) => console.log(`Loaded workspace: ${f.uri.fsPath}`)); + console.log('Waiting for Black formatter to load...'); const formatReady = new Promise((resolve, reject) => { - const disposable = vscode.workspace.onDidChangeTextDocument((e) => { - if (e.document.uri.fsPath.includes('Black')) { - const text = e.document.getText(); - console.log(text); - if (text.includes('FOUND black==')) { - console.log('Waiting for Black formatter to finished loading'); - disposable.dispose(); - resolve(); - } - if (text.includes('Python interpreter missing')) { - console.log('Waiting for Black formatter failed to load'); - disposable.dispose(); - reject(); + disposables.push( + vscode.workspace.onDidChangeTextDocument((e) => { + if (e.document.uri.fsPath.includes('Black')) { + const text = e.document.getText(); + console.log(text); + if (text.includes('FOUND black==') || text.includes('initialized')) { + console.log('Waiting for Black formatter to finished loading'); + resolve(); + } else if (text.includes('Python interpreter missing')) { + console.log('Waiting for Black formatter failed to load'); + reject(); + } } - } - }); + }), + ); }); await formatReady; From 11f09641b2bf0e907abab0d50ba7e841571543f3 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Tue, 30 Jan 2024 19:50:14 -0800 Subject: [PATCH 12/23] Try more logs --- src/common/python.ts | 6 +++++- src/extension.ts | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/common/python.ts b/src/common/python.ts index ccd8a05..0e9a9a8 100644 --- a/src/common/python.ts +++ b/src/common/python.ts @@ -25,17 +25,21 @@ async function getPythonExtensionAPI(): Promise { export async function initializePython(disposables: Disposable[]): Promise { try { + console.log('Initializing python extension.'); const api = await getPythonExtensionAPI(); - + console.log('Python extension initialized.'); if (api) { disposables.push( api.environments.onDidChangeActiveEnvironmentPath((e) => { + console.log('Python interpreter changed.'); onDidChangePythonInterpreterEvent.fire({ path: [e.path], resource: e.resource?.uri }); }), ); traceLog('Waiting for interpreter from python extension.'); + console.log('Waiting for interpreter from python extension.'); onDidChangePythonInterpreterEvent.fire(await getInterpreterDetails()); + console.log('Python interpreter resolved.'); } } catch (error) { traceError('Error initializing python: ', error); diff --git a/src/extension.ts b/src/extension.ts index 19d4e53..8188554 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -40,6 +40,7 @@ export async function activate(context: vscode.ExtensionContext): Promise traceVerbose(`Configuration: ${JSON.stringify(serverInfo)}`); const runServer = async () => { + console.log('Preparing to start server'); const projectRoot = await getProjectRoot(); const workspaceSetting = await getWorkspaceSettings(serverId, projectRoot, true); if (workspaceSetting.interpreter.length === 0) { @@ -51,6 +52,7 @@ export async function activate(context: vscode.ExtensionContext): Promise 'Please use Python 3.8 or greater.', ); } else { + console.log('Starting server'); lsClient = await restartServer(workspaceSetting, serverId, serverName, outputChannel, lsClient); } }; From f3fb5821f08702ad797d12eddf31412625c47a2e Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Tue, 30 Jan 2024 19:54:52 -0800 Subject: [PATCH 13/23] Even more logs --- src/common/python.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/common/python.ts b/src/common/python.ts index 0e9a9a8..cb92d83 100644 --- a/src/common/python.ts +++ b/src/common/python.ts @@ -52,13 +52,16 @@ export async function resolveInterpreter(interpreter: string[]): Promise { + console.log('Resolving python interpreter.'); const api = await getPythonExtensionAPI(); const environment = await api?.environments.resolveEnvironment( api?.environments.getActiveEnvironmentPath(resource), ); if (environment?.executable.uri && checkVersion(environment)) { + console.log(`Python interpreter: ${environment?.executable.uri.fsPath}`); return { path: [environment?.executable.uri.fsPath], resource }; } + console.log('Python interpreter not found.'); return { path: undefined, resource }; } From 52c3e5df78b25af37f52196fca474fd4c007f4fd Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Tue, 30 Jan 2024 19:57:57 -0800 Subject: [PATCH 14/23] Add python deps --- .github/workflows/pr-check.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 97f1dfe..eced055 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -112,10 +112,19 @@ jobs: cache: 'npm' cache-dependency-path: ${{ env.special-working-directory-relative }}/package-lock.json - - name: Use Python 3.x + - name: Use Python 3.8 uses: actions/setup-python@v5 with: - python-version: '3.x' + python-version: '3.8' + + - name: Update pip, install wheel and nox + run: python -m pip install -U pip wheel nox + shell: bash + + # This will install libraries to a target directory. + - name: Install bundled python libraries + run: python -m nox --session install_bundled_libs + shell: bash - name: Install Node dependencies run: npm ci From ae24f3f43bf5f4a4569e99be6a231df653135d04 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 31 Jan 2024 10:45:09 -0800 Subject: [PATCH 15/23] add server command log --- src/common/server.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/common/server.ts b/src/common/server.ts index 6405fdd..a3b3b42 100644 --- a/src/common/server.ts +++ b/src/common/server.ts @@ -47,11 +47,18 @@ async function createServer( // Set notification type newEnv.LS_SHOW_NOTIFICATION = settings.showNotifications; + if (await fsapi.pathExists(SERVER_SCRIPT_PATH)) { + console.log('Server script exists'); + } else { + console.log('Server script does not exists'); + } + const args = newEnv.USE_DEBUGPY === 'False' || !isDebugScript ? settings.interpreter.slice(1).concat([SERVER_SCRIPT_PATH]) : settings.interpreter.slice(1).concat([DEBUG_SERVER_SCRIPT_PATH]); traceInfo(`Server run command: ${[command, ...args].join(' ')}`); + console.log(`Server run command: ${[command, ...args].join(' ')}`); const serverOptions: ServerOptions = { command, From 422542846e7f5bc6f5827d2df70bc3f5bf2f5551 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 31 Jan 2024 11:23:58 -0800 Subject: [PATCH 16/23] Add client error logs --- src/common/server.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/common/server.ts b/src/common/server.ts index a3b3b42..7231fd2 100644 --- a/src/common/server.ts +++ b/src/common/server.ts @@ -124,10 +124,13 @@ export async function restartServer( }), ); try { + console.log('Server: Start requested.'); await newLSClient.start(); } catch (ex) { updateStatus(l10n.t('Server failed to start.'), LanguageStatusSeverity.Error); traceError(`Server: Start failed: ${ex}`); + console.log('Server: Start Failed'); + console.log(ex); } await newLSClient.setTrace(getLSClientTraceLevel(outputChannel.logLevel, env.logLevel)); return newLSClient; From be78ec9d0ecb6148f66a136688ddfa0d6a5613ea Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 31 Jan 2024 11:33:26 -0800 Subject: [PATCH 17/23] more client logs --- src/common/server.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/common/server.ts b/src/common/server.ts index 7231fd2..96892a6 100644 --- a/src/common/server.ts +++ b/src/common/server.ts @@ -111,13 +111,16 @@ export async function restartServer( switch (e.newState) { case State.Stopped: traceVerbose(`Server State: Stopped`); + console.log('Server stopped'); break; case State.Starting: traceVerbose(`Server State: Starting`); + console.log('Server state starting'); unregisterEmptyFormatter(); break; case State.Running: traceVerbose(`Server State: Running`); + console.log('Server state running'); updateStatus(undefined, LanguageStatusSeverity.Information, false); break; } From 5970769dbff25089693e0cfbd3ab2068541f7547 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 31 Jan 2024 15:08:52 -0800 Subject: [PATCH 18/23] Fix test --- src/common/python.ts | 8 ----- src/common/server.ts | 13 -------- src/extension.ts | 2 -- src/test/ts_tests/runSmokeTest.ts | 5 --- .../tests/common/minimal.smoke.test.ts | 31 ++----------------- 5 files changed, 3 insertions(+), 56 deletions(-) diff --git a/src/common/python.ts b/src/common/python.ts index cb92d83..b29dff1 100644 --- a/src/common/python.ts +++ b/src/common/python.ts @@ -25,21 +25,16 @@ async function getPythonExtensionAPI(): Promise { export async function initializePython(disposables: Disposable[]): Promise { try { - console.log('Initializing python extension.'); const api = await getPythonExtensionAPI(); - console.log('Python extension initialized.'); if (api) { disposables.push( api.environments.onDidChangeActiveEnvironmentPath((e) => { - console.log('Python interpreter changed.'); onDidChangePythonInterpreterEvent.fire({ path: [e.path], resource: e.resource?.uri }); }), ); traceLog('Waiting for interpreter from python extension.'); - console.log('Waiting for interpreter from python extension.'); onDidChangePythonInterpreterEvent.fire(await getInterpreterDetails()); - console.log('Python interpreter resolved.'); } } catch (error) { traceError('Error initializing python: ', error); @@ -52,16 +47,13 @@ export async function resolveInterpreter(interpreter: string[]): Promise { - console.log('Resolving python interpreter.'); const api = await getPythonExtensionAPI(); const environment = await api?.environments.resolveEnvironment( api?.environments.getActiveEnvironmentPath(resource), ); if (environment?.executable.uri && checkVersion(environment)) { - console.log(`Python interpreter: ${environment?.executable.uri.fsPath}`); return { path: [environment?.executable.uri.fsPath], resource }; } - console.log('Python interpreter not found.'); return { path: undefined, resource }; } diff --git a/src/common/server.ts b/src/common/server.ts index 96892a6..6405fdd 100644 --- a/src/common/server.ts +++ b/src/common/server.ts @@ -47,18 +47,11 @@ async function createServer( // Set notification type newEnv.LS_SHOW_NOTIFICATION = settings.showNotifications; - if (await fsapi.pathExists(SERVER_SCRIPT_PATH)) { - console.log('Server script exists'); - } else { - console.log('Server script does not exists'); - } - const args = newEnv.USE_DEBUGPY === 'False' || !isDebugScript ? settings.interpreter.slice(1).concat([SERVER_SCRIPT_PATH]) : settings.interpreter.slice(1).concat([DEBUG_SERVER_SCRIPT_PATH]); traceInfo(`Server run command: ${[command, ...args].join(' ')}`); - console.log(`Server run command: ${[command, ...args].join(' ')}`); const serverOptions: ServerOptions = { command, @@ -111,29 +104,23 @@ export async function restartServer( switch (e.newState) { case State.Stopped: traceVerbose(`Server State: Stopped`); - console.log('Server stopped'); break; case State.Starting: traceVerbose(`Server State: Starting`); - console.log('Server state starting'); unregisterEmptyFormatter(); break; case State.Running: traceVerbose(`Server State: Running`); - console.log('Server state running'); updateStatus(undefined, LanguageStatusSeverity.Information, false); break; } }), ); try { - console.log('Server: Start requested.'); await newLSClient.start(); } catch (ex) { updateStatus(l10n.t('Server failed to start.'), LanguageStatusSeverity.Error); traceError(`Server: Start failed: ${ex}`); - console.log('Server: Start Failed'); - console.log(ex); } await newLSClient.setTrace(getLSClientTraceLevel(outputChannel.logLevel, env.logLevel)); return newLSClient; diff --git a/src/extension.ts b/src/extension.ts index 8188554..19d4e53 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -40,7 +40,6 @@ export async function activate(context: vscode.ExtensionContext): Promise traceVerbose(`Configuration: ${JSON.stringify(serverInfo)}`); const runServer = async () => { - console.log('Preparing to start server'); const projectRoot = await getProjectRoot(); const workspaceSetting = await getWorkspaceSettings(serverId, projectRoot, true); if (workspaceSetting.interpreter.length === 0) { @@ -52,7 +51,6 @@ export async function activate(context: vscode.ExtensionContext): Promise 'Please use Python 3.8 or greater.', ); } else { - console.log('Starting server'); lsClient = await restartServer(workspaceSetting, serverId, serverName, outputChannel, lsClient); } }; diff --git a/src/test/ts_tests/runSmokeTest.ts b/src/test/ts_tests/runSmokeTest.ts index 4f48e90..287ef2b 100644 --- a/src/test/ts_tests/runSmokeTest.ts +++ b/src/test/ts_tests/runSmokeTest.ts @@ -12,23 +12,18 @@ const TEST_PROJECT_DIR = path.join(EXTENSION_ROOT_DIR, 'src', 'test', 'ts_tests' async function main() { try { - console.log('Downloading VS Code...'); const vscodeExecutablePath = await downloadAndUnzipVSCode('stable'); - console.log('Finished downloading VS Code.'); const [cli, ...args] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath); const command = path.relative(EXTENSION_ROOT_DIR, cli); - console.log('Installing Python extension...', [command, ...args, '--install-extension', 'ms-python.python']); cp.spawnSync(command, [...args, '--install-extension', 'ms-python.python'], { encoding: 'utf-8', stdio: 'inherit', }); - console.log('Finished installing Python extension.'); const extensionDevelopmentPath = EXTENSION_ROOT_DIR; const extensionTestsPath = path.resolve(__dirname, './index'); - console.log('Running tests...'); await runTests({ extensionDevelopmentPath, extensionTestsPath, diff --git a/src/test/ts_tests/tests/common/minimal.smoke.test.ts b/src/test/ts_tests/tests/common/minimal.smoke.test.ts index 403b404..e099dbd 100644 --- a/src/test/ts_tests/tests/common/minimal.smoke.test.ts +++ b/src/test/ts_tests/tests/common/minimal.smoke.test.ts @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import * as cp from 'child_process'; import * as path from 'path'; import * as vscode from 'vscode'; import * as fsapi from 'fs-extra'; @@ -62,6 +61,7 @@ suite('Smoke Tests', function () { }); test('Ensure Black Formatter formats a file on save', async () => { + await vscode.commands.executeCommand('workbench.action.closeAllEditors'); await ensurePythonExt(true); const unformatted = await fsapi.readFile(path.join(TEST_PROJECT_DIR, 'myscript.unformatted'), { @@ -70,38 +70,15 @@ suite('Smoke Tests', function () { const formatted = await fsapi.readFile(path.join(TEST_PROJECT_DIR, 'myscript.formatted'), { encoding: 'utf8' }); await fsapi.writeFile(path.join(TEST_PROJECT_DIR, 'myscript.py'), unformatted, { encoding: 'utf8' }); + await ensureBlackExt(true); + const doc = await vscode.workspace.openTextDocument(path.join(TEST_PROJECT_DIR, 'myscript.py')); await vscode.window.showTextDocument(doc); - await ensureBlackExt(true); - const editor = vscode.window.activeTextEditor; assert.ok(editor, 'No active editor'); assert.ok(editor?.document.uri.fsPath.endsWith('myscript.py'), 'Active editor is not myscript.py'); - vscode.workspace.workspaceFolders?.forEach((f) => console.log(`Loaded workspace: ${f.uri.fsPath}`)); - - console.log('Waiting for Black formatter to load...'); - const formatReady = new Promise((resolve, reject) => { - disposables.push( - vscode.workspace.onDidChangeTextDocument((e) => { - if (e.document.uri.fsPath.includes('Black')) { - const text = e.document.getText(); - console.log(text); - if (text.includes('FOUND black==') || text.includes('initialized')) { - console.log('Waiting for Black formatter to finished loading'); - resolve(); - } else if (text.includes('Python interpreter missing')) { - console.log('Waiting for Black formatter failed to load'); - reject(); - } - } - }), - ); - }); - await formatReady; - - console.log('Waiting for Black formatter to format...'); const formatDone = new Promise((resolve) => { const disposable = vscode.workspace.onDidSaveTextDocument((e) => { if (e.uri.fsPath.endsWith('myscript.py')) { @@ -111,10 +88,8 @@ suite('Smoke Tests', function () { }); }); - console.log('Triggering save to start format-on-save...'); await vscode.commands.executeCommand('workbench.action.files.save'); await formatDone; - console.log('Formatting done'); const actualText = editor?.document.getText(); assert.equal(actualText, formatted); From 5fd4def4cebf933896a254974f532913bb4d146a Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 31 Jan 2024 15:40:14 -0800 Subject: [PATCH 19/23] Use FS events --- .../ts_tests/test_data/project/myscript.py | 3 +-- .../tests/common/minimal.smoke.test.ts | 22 +++++++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/test/ts_tests/test_data/project/myscript.py b/src/test/ts_tests/test_data/project/myscript.py index 57c7405..14566f5 100644 --- a/src/test/ts_tests/test_data/project/myscript.py +++ b/src/test/ts_tests/test_data/project/myscript.py @@ -1,3 +1,2 @@ import sys - -print(sys.executable) +print(sys.executable) \ No newline at end of file diff --git a/src/test/ts_tests/tests/common/minimal.smoke.test.ts b/src/test/ts_tests/tests/common/minimal.smoke.test.ts index e099dbd..508511a 100644 --- a/src/test/ts_tests/tests/common/minimal.smoke.test.ts +++ b/src/test/ts_tests/tests/common/minimal.smoke.test.ts @@ -80,18 +80,26 @@ suite('Smoke Tests', function () { assert.ok(editor?.document.uri.fsPath.endsWith('myscript.py'), 'Active editor is not myscript.py'); const formatDone = new Promise((resolve) => { - const disposable = vscode.workspace.onDidSaveTextDocument((e) => { - if (e.uri.fsPath.endsWith('myscript.py')) { - disposable.dispose(); - resolve(); - } - }); + const watcher = vscode.workspace.createFileSystemWatcher( + new vscode.RelativePattern(TEST_PROJECT_DIR, 'myscript.py'), + true, // We don't need create events + false, // We need change events + true, // We don't need delete events + ); + disposables.push( + watcher, + watcher.onDidChange((e) => { + if (e.fsPath.endsWith('myscript.py')) { + resolve(); + } + }), + ); }); await vscode.commands.executeCommand('workbench.action.files.save'); await formatDone; - const actualText = editor?.document.getText(); + const actualText = await fsapi.readFile(path.join(TEST_PROJECT_DIR, 'myscript.py'), { encoding: 'utf8' }); assert.equal(actualText, formatted); }); }); From c10b730cc13dc5964fb8e915c45bba261851a927 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 31 Jan 2024 16:42:17 -0800 Subject: [PATCH 20/23] Fix test reliability --- .../ts_tests/test_data/project/myscript.formatted | 3 ++- .../test_data/project/myscript.unformatted | 4 ++-- .../ts_tests/tests/common/minimal.smoke.test.ts | 15 +++++++++++---- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/test/ts_tests/test_data/project/myscript.formatted b/src/test/ts_tests/test_data/project/myscript.formatted index 57c7405..39d270e 100644 --- a/src/test/ts_tests/test_data/project/myscript.formatted +++ b/src/test/ts_tests/test_data/project/myscript.formatted @@ -1,3 +1,4 @@ +import os import sys -print(sys.executable) +print(os.fspath(sys.executable)) diff --git a/src/test/ts_tests/test_data/project/myscript.unformatted b/src/test/ts_tests/test_data/project/myscript.unformatted index 14566f5..56997f8 100644 --- a/src/test/ts_tests/test_data/project/myscript.unformatted +++ b/src/test/ts_tests/test_data/project/myscript.unformatted @@ -1,2 +1,2 @@ -import sys -print(sys.executable) \ No newline at end of file +import os;import sys +print(os.fspath(sys.executable)) \ No newline at end of file diff --git a/src/test/ts_tests/tests/common/minimal.smoke.test.ts b/src/test/ts_tests/tests/common/minimal.smoke.test.ts index 508511a..8e3d262 100644 --- a/src/test/ts_tests/tests/common/minimal.smoke.test.ts +++ b/src/test/ts_tests/tests/common/minimal.smoke.test.ts @@ -63,16 +63,17 @@ suite('Smoke Tests', function () { test('Ensure Black Formatter formats a file on save', async () => { await vscode.commands.executeCommand('workbench.action.closeAllEditors'); await ensurePythonExt(true); + const scriptPath = path.join(TEST_PROJECT_DIR, 'myscript.py'); const unformatted = await fsapi.readFile(path.join(TEST_PROJECT_DIR, 'myscript.unformatted'), { encoding: 'utf8', }); const formatted = await fsapi.readFile(path.join(TEST_PROJECT_DIR, 'myscript.formatted'), { encoding: 'utf8' }); - await fsapi.writeFile(path.join(TEST_PROJECT_DIR, 'myscript.py'), unformatted, { encoding: 'utf8' }); + await fsapi.writeFile(scriptPath, unformatted, { encoding: 'utf8' }); await ensureBlackExt(true); - const doc = await vscode.workspace.openTextDocument(path.join(TEST_PROJECT_DIR, 'myscript.py')); + const doc = await vscode.workspace.openTextDocument(scriptPath); await vscode.window.showTextDocument(doc); const editor = vscode.window.activeTextEditor; @@ -89,8 +90,11 @@ suite('Smoke Tests', function () { disposables.push( watcher, watcher.onDidChange((e) => { - if (e.fsPath.endsWith('myscript.py')) { + const text = fsapi.readFileSync(e.fsPath, { encoding: 'utf8' }); + if (!text.includes(';')) { resolve(); + } else { + vscode.commands.executeCommand('workbench.action.files.save'); } }), ); @@ -99,7 +103,10 @@ suite('Smoke Tests', function () { await vscode.commands.executeCommand('workbench.action.files.save'); await formatDone; - const actualText = await fsapi.readFile(path.join(TEST_PROJECT_DIR, 'myscript.py'), { encoding: 'utf8' }); + const actualText = await fsapi.readFile(scriptPath, { encoding: 'utf8' }); assert.equal(actualText, formatted); + + //cleanup + await fsapi.writeFile(scriptPath, '', { encoding: 'utf8' }); }); }); From a4f60f25d42a8d00b722258406fccbe39af25680 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 31 Jan 2024 16:48:57 -0800 Subject: [PATCH 21/23] Try with timer --- src/test/ts_tests/tests/common/minimal.smoke.test.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/ts_tests/tests/common/minimal.smoke.test.ts b/src/test/ts_tests/tests/common/minimal.smoke.test.ts index 8e3d262..99e11b8 100644 --- a/src/test/ts_tests/tests/common/minimal.smoke.test.ts +++ b/src/test/ts_tests/tests/common/minimal.smoke.test.ts @@ -93,16 +93,18 @@ suite('Smoke Tests', function () { const text = fsapi.readFileSync(e.fsPath, { encoding: 'utf8' }); if (!text.includes(';')) { resolve(); - } else { - vscode.commands.executeCommand('workbench.action.files.save'); } }), ); }); + const timer = setInterval(() => { + vscode.commands.executeCommand('workbench.action.files.save'); + }, 1000); + disposables.push({ dispose: () => clearInterval(timer) }); + await vscode.commands.executeCommand('workbench.action.files.save'); await formatDone; - const actualText = await fsapi.readFile(scriptPath, { encoding: 'utf8' }); assert.equal(actualText, formatted); From 1a7e9a7737b6a6e6a88955ea699463c9fe3018a7 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 31 Jan 2024 16:54:10 -0800 Subject: [PATCH 22/23] Add logging --- .github/workflows/pr-check.yml | 152 +++++++++--------- .../tests/common/minimal.smoke.test.ts | 6 +- 2 files changed, 81 insertions(+), 77 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index eced055..7651d77 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -11,82 +11,82 @@ env: special-working-directory-relative: '🐍 🐛' jobs: - build-vsix: - name: Create VSIX - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Build VSIX - uses: ./.github/actions/build-vsix - with: - node_version: ${{ env.NODE_VERSION}} - - lint: - name: Lint - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Lint - uses: ./.github/actions/lint - with: - node_version: ${{ env.NODE_VERSION }} - - tests: - name: Tests - runs-on: ${{ matrix.os }} - defaults: - run: - working-directory: ${{ env.special-working-directory }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest] - python: ['3.8', '3.9', '3.10', '3.11', '3.12'] - - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - path: ${{ env.special-working-directory-relative }} - - # Install bundled libs using 3.8 even though you test it on other versions. - - name: Use Python 3.8 - uses: actions/setup-python@v5 - with: - python-version: '3.8' - - - name: Update pip, install wheel and nox - run: python -m pip install -U pip wheel nox - shell: bash - - # This will install libraries to a target directory. - - name: Install bundled python libraries - run: python -m nox --session install_bundled_libs - shell: bash - - # Now that the bundle is installed to target using python 3.8 - # switch back the python we want to test with - - name: Use Python ${{ matrix.python }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python }} - - # The new python may not have nox so install it again - - name: Update pip, install wheel and nox (again) - run: python -m pip install -U pip wheel nox - shell: bash - - - name: Run tests - run: python -m nox --session tests - shell: bash - - - name: Validate README.md - run: python -m nox --session validate_readme - shell: bash + # build-vsix: + # name: Create VSIX + # runs-on: ubuntu-latest + # steps: + # - name: Checkout + # uses: actions/checkout@v3 + + # - name: Build VSIX + # uses: ./.github/actions/build-vsix + # with: + # node_version: ${{ env.NODE_VERSION}} + + # lint: + # name: Lint + # runs-on: ubuntu-latest + # steps: + # - name: Checkout + # uses: actions/checkout@v3 + + # - name: Lint + # uses: ./.github/actions/lint + # with: + # node_version: ${{ env.NODE_VERSION }} + + # tests: + # name: Tests + # runs-on: ${{ matrix.os }} + # defaults: + # run: + # working-directory: ${{ env.special-working-directory }} + # strategy: + # fail-fast: false + # matrix: + # os: [ubuntu-latest, windows-latest] + # python: ['3.8', '3.9', '3.10', '3.11', '3.12'] + + # steps: + # - name: Checkout + # uses: actions/checkout@v3 + # with: + # path: ${{ env.special-working-directory-relative }} + + # # Install bundled libs using 3.8 even though you test it on other versions. + # - name: Use Python 3.8 + # uses: actions/setup-python@v5 + # with: + # python-version: '3.8' + + # - name: Update pip, install wheel and nox + # run: python -m pip install -U pip wheel nox + # shell: bash + + # # This will install libraries to a target directory. + # - name: Install bundled python libraries + # run: python -m nox --session install_bundled_libs + # shell: bash + + # # Now that the bundle is installed to target using python 3.8 + # # switch back the python we want to test with + # - name: Use Python ${{ matrix.python }} + # uses: actions/setup-python@v5 + # with: + # python-version: ${{ matrix.python }} + + # # The new python may not have nox so install it again + # - name: Update pip, install wheel and nox (again) + # run: python -m pip install -U pip wheel nox + # shell: bash + + # - name: Run tests + # run: python -m nox --session tests + # shell: bash + + # - name: Validate README.md + # run: python -m nox --session validate_readme + # shell: bash ts-tests: name: TypeScript Tests diff --git a/src/test/ts_tests/tests/common/minimal.smoke.test.ts b/src/test/ts_tests/tests/common/minimal.smoke.test.ts index 99e11b8..c265f10 100644 --- a/src/test/ts_tests/tests/common/minimal.smoke.test.ts +++ b/src/test/ts_tests/tests/common/minimal.smoke.test.ts @@ -8,7 +8,7 @@ import { EXTENSION_ROOT_DIR } from '../../../../common/constants'; import { assert } from 'chai'; const TEST_PROJECT_DIR = path.join(EXTENSION_ROOT_DIR, 'src', 'test', 'ts_tests', 'test_data', 'project'); -const TIMEOUT = 30000; // 30 seconds +const TIMEOUT = 60000; // 60 seconds suite('Smoke Tests', function () { this.timeout(TIMEOUT); @@ -92,13 +92,17 @@ suite('Smoke Tests', function () { watcher.onDidChange((e) => { const text = fsapi.readFileSync(e.fsPath, { encoding: 'utf8' }); if (!text.includes(';')) { + console.log('Saved with format changes'); resolve(); + } else { + console.log('Saved without format changes'); } }), ); }); const timer = setInterval(() => { + console.log('Saving file'); vscode.commands.executeCommand('workbench.action.files.save'); }, 1000); disposables.push({ dispose: () => clearInterval(timer) }); From b3a58fbaa550ba44693d59e8523068bf27b41b82 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 31 Jan 2024 16:58:30 -0800 Subject: [PATCH 23/23] Increase timeout --- .github/workflows/pr-check.yml | 152 +++++++++--------- .../tests/common/minimal.smoke.test.ts | 2 +- 2 files changed, 77 insertions(+), 77 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 7651d77..eced055 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -11,82 +11,82 @@ env: special-working-directory-relative: '🐍 🐛' jobs: - # build-vsix: - # name: Create VSIX - # runs-on: ubuntu-latest - # steps: - # - name: Checkout - # uses: actions/checkout@v3 - - # - name: Build VSIX - # uses: ./.github/actions/build-vsix - # with: - # node_version: ${{ env.NODE_VERSION}} - - # lint: - # name: Lint - # runs-on: ubuntu-latest - # steps: - # - name: Checkout - # uses: actions/checkout@v3 - - # - name: Lint - # uses: ./.github/actions/lint - # with: - # node_version: ${{ env.NODE_VERSION }} - - # tests: - # name: Tests - # runs-on: ${{ matrix.os }} - # defaults: - # run: - # working-directory: ${{ env.special-working-directory }} - # strategy: - # fail-fast: false - # matrix: - # os: [ubuntu-latest, windows-latest] - # python: ['3.8', '3.9', '3.10', '3.11', '3.12'] - - # steps: - # - name: Checkout - # uses: actions/checkout@v3 - # with: - # path: ${{ env.special-working-directory-relative }} - - # # Install bundled libs using 3.8 even though you test it on other versions. - # - name: Use Python 3.8 - # uses: actions/setup-python@v5 - # with: - # python-version: '3.8' - - # - name: Update pip, install wheel and nox - # run: python -m pip install -U pip wheel nox - # shell: bash - - # # This will install libraries to a target directory. - # - name: Install bundled python libraries - # run: python -m nox --session install_bundled_libs - # shell: bash - - # # Now that the bundle is installed to target using python 3.8 - # # switch back the python we want to test with - # - name: Use Python ${{ matrix.python }} - # uses: actions/setup-python@v5 - # with: - # python-version: ${{ matrix.python }} - - # # The new python may not have nox so install it again - # - name: Update pip, install wheel and nox (again) - # run: python -m pip install -U pip wheel nox - # shell: bash - - # - name: Run tests - # run: python -m nox --session tests - # shell: bash - - # - name: Validate README.md - # run: python -m nox --session validate_readme - # shell: bash + build-vsix: + name: Create VSIX + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Build VSIX + uses: ./.github/actions/build-vsix + with: + node_version: ${{ env.NODE_VERSION}} + + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Lint + uses: ./.github/actions/lint + with: + node_version: ${{ env.NODE_VERSION }} + + tests: + name: Tests + runs-on: ${{ matrix.os }} + defaults: + run: + working-directory: ${{ env.special-working-directory }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] + python: ['3.8', '3.9', '3.10', '3.11', '3.12'] + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + path: ${{ env.special-working-directory-relative }} + + # Install bundled libs using 3.8 even though you test it on other versions. + - name: Use Python 3.8 + uses: actions/setup-python@v5 + with: + python-version: '3.8' + + - name: Update pip, install wheel and nox + run: python -m pip install -U pip wheel nox + shell: bash + + # This will install libraries to a target directory. + - name: Install bundled python libraries + run: python -m nox --session install_bundled_libs + shell: bash + + # Now that the bundle is installed to target using python 3.8 + # switch back the python we want to test with + - name: Use Python ${{ matrix.python }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + + # The new python may not have nox so install it again + - name: Update pip, install wheel and nox (again) + run: python -m pip install -U pip wheel nox + shell: bash + + - name: Run tests + run: python -m nox --session tests + shell: bash + + - name: Validate README.md + run: python -m nox --session validate_readme + shell: bash ts-tests: name: TypeScript Tests diff --git a/src/test/ts_tests/tests/common/minimal.smoke.test.ts b/src/test/ts_tests/tests/common/minimal.smoke.test.ts index c265f10..156a8bb 100644 --- a/src/test/ts_tests/tests/common/minimal.smoke.test.ts +++ b/src/test/ts_tests/tests/common/minimal.smoke.test.ts @@ -8,7 +8,7 @@ import { EXTENSION_ROOT_DIR } from '../../../../common/constants'; import { assert } from 'chai'; const TEST_PROJECT_DIR = path.join(EXTENSION_ROOT_DIR, 'src', 'test', 'ts_tests', 'test_data', 'project'); -const TIMEOUT = 60000; // 60 seconds +const TIMEOUT = 120000; // 120 seconds suite('Smoke Tests', function () { this.timeout(TIMEOUT);