diff --git a/src/test/common.ts b/src/test/common.ts index 886323e815a5..8335e5c8ae41 100644 --- a/src/test/common.ts +++ b/src/test/common.ts @@ -459,20 +459,39 @@ export async function waitForCondition( errorMessage: string, ): Promise { return new Promise(async (resolve, reject) => { + const startTime = Date.now(); + let checkCount = 0; const timeout = setTimeout(() => { clearTimeout(timeout); // eslint-disable-next-line @typescript-eslint/no-use-before-define - clearTimeout(timer); - reject(new Error(errorMessage)); + clearInterval(timer); + const elapsed = Date.now() - startTime; + const detailedError = `${errorMessage} (waited ${elapsed}ms, checked ${checkCount} times)`; + console.error(`[waitForCondition] Timeout: ${detailedError}`); + reject(new Error(detailedError)); }, timeoutMs); const timer = setInterval(async () => { - if (!(await condition().catch(() => false))) { - return; + checkCount++; + try { + const result = await condition(); + if (!result) { + return; + } + clearTimeout(timeout); + clearInterval(timer); + const elapsed = Date.now() - startTime; + if (IS_SMOKE_TEST) { + console.log(`[waitForCondition] Condition met after ${elapsed}ms (${checkCount} checks)`); + } + resolve(); + } catch (error) { + // Condition check threw an error, log it but continue checking + if (checkCount % 100 === 0) { + // Log every 100 checks + console.error(`[waitForCondition] Error checking condition (check #${checkCount}): ${error}`); + } } - clearTimeout(timeout); - clearTimeout(timer); - resolve(); }, 10); }); } diff --git a/src/test/smoke/runInTerminal.smoke.test.ts b/src/test/smoke/runInTerminal.smoke.test.ts index d5ce409f3ab1..2129ad3380ed 100644 --- a/src/test/smoke/runInTerminal.smoke.test.ts +++ b/src/test/smoke/runInTerminal.smoke.test.ts @@ -43,15 +43,100 @@ suite('Smoke Test: Run Python File In Terminal', () => { 'smokeTests', 'testExecInTerminal.log', ); + + console.log(`[runInTerminal.smoke] Test starting`); + console.log(`[runInTerminal.smoke] Python file: ${file}`); + console.log(`[runInTerminal.smoke] Output file: ${outputFile}`); + console.log(`[runInTerminal.smoke] Python file exists: ${await fs.pathExists(file)}`); + if (await fs.pathExists(outputFile)) { + console.log(`[runInTerminal.smoke] Output file already exists, deleting...`); await fs.unlink(outputFile); + console.log(`[runInTerminal.smoke] Output file deleted`); + } else { + console.log(`[runInTerminal.smoke] Output file does not exist (clean state)`); } + const textDocument = await openFile(file); + console.log(`[runInTerminal.smoke] File opened in editor`); + + // Check active terminals before execution + const terminalsBefore = vscode.window.terminals.length; + console.log(`[runInTerminal.smoke] Number of terminals before execution: ${terminalsBefore}`); + + // On Windows, if terminals exist from previous tests, they may not be ready for new commands + // Give them time to fully initialize before sending commands + if (terminalsBefore > 0 && process.platform === 'win32') { + console.log( + `[runInTerminal.smoke] Windows detected with ${terminalsBefore} existing terminals, waiting 3s for terminal readiness...`, + ); + await new Promise((resolve) => setTimeout(resolve, 3000)); + } + + const startTime = Date.now(); + console.log(`[runInTerminal.smoke] Executing 'python.execInTerminal' command at ${new Date().toISOString()}`); await vscode.commands.executeCommand('python.execInTerminal', textDocument.uri).then(undefined, (err) => { + console.error(`[runInTerminal.smoke] Command failed with error: ${err}`); assert.fail(`Something went wrong running the Python file in the terminal: ${err}`); }); - const checkIfFileHasBeenCreated = () => fs.pathExists(outputFile); - await waitForCondition(checkIfFileHasBeenCreated, 30_000, `"${outputFile}" file not created`); + const commandCompleteTime = Date.now(); + console.log(`[runInTerminal.smoke] Command completed in ${commandCompleteTime - startTime}ms`); + + // Check active terminals after execution + const terminalsAfter = vscode.window.terminals.length; + console.log(`[runInTerminal.smoke] Number of terminals after execution: ${terminalsAfter}`); + if (vscode.window.activeTerminal) { + console.log(`[runInTerminal.smoke] Active terminal name: ${vscode.window.activeTerminal.name}`); + } + + // Add additional wait to allow terminal to start processing + // Windows may need more time for terminal to initialize and start executing + const isWindows = process.platform === 'win32'; + const initialWaitTime = isWindows ? 2000 : 1000; + console.log( + `[runInTerminal.smoke] Waiting ${initialWaitTime}ms for terminal to start processing (isWindows: ${isWindows})...`, + ); + await new Promise((resolve) => setTimeout(resolve, initialWaitTime)); + + // Verify the working directory matches expected + const expectedDir = path.dirname(outputFile); + console.log(`[runInTerminal.smoke] Expected output directory: ${expectedDir}`); + console.log(`[runInTerminal.smoke] Directory exists: ${await fs.pathExists(expectedDir)}`); + + let checkCount = 0; + const checkIfFileHasBeenCreated = async () => { + checkCount++; + const exists = await fs.pathExists(outputFile); + if (checkCount % 100 === 0) { + // Log every 100 checks (~1 second) + const elapsed = Date.now() - startTime; + console.log(`[runInTerminal.smoke] File check #${checkCount} at ${elapsed}ms: ${exists}`); + } + return exists; + }; + + try { + await waitForCondition(checkIfFileHasBeenCreated, 30_000, `"${outputFile}" file not created`); + const totalTime = Date.now() - startTime; + console.log(`[runInTerminal.smoke] SUCCESS: File created after ${totalTime}ms (${checkCount} checks)`); + } catch (error) { + const totalTime = Date.now() - startTime; + console.error(`[runInTerminal.smoke] FAILURE after ${totalTime}ms (${checkCount} checks)`); + console.error(`[runInTerminal.smoke] Output file exists: ${await fs.pathExists(outputFile)}`); + console.error(`[runInTerminal.smoke] Number of terminals: ${vscode.window.terminals.length}`); + + // List directory contents to see if file is there + const dir = path.dirname(outputFile); + try { + const fsModule = await import('fs'); + const files = fsModule.readdirSync(dir); + console.error(`[runInTerminal.smoke] Directory contents (${dir}):`, files); + } catch (e) { + console.error(`[runInTerminal.smoke] Failed to list directory: ${e}`); + } + + throw error; + } }); }); diff --git a/src/test/smoke/smartSend.smoke.test.ts b/src/test/smoke/smartSend.smoke.test.ts index dc1f07f047e7..9d2ee83bec46 100644 --- a/src/test/smoke/smartSend.smoke.test.ts +++ b/src/test/smoke/smartSend.smoke.test.ts @@ -12,6 +12,12 @@ suite('Smoke Test: Run Smart Selection and Advance Cursor', async () => { return this.skip(); } await initialize(); + // Ensure the environments extension is not used for this test + // execSelectionInTerminal was not updated to use the envs extension API + // when execInTerminal was updated in commit e78934859 + await vscode.workspace + .getConfiguration('python') + .update('useEnvironmentsExtension', false, vscode.ConfigurationTarget.Global); return undefined; }); @@ -35,33 +41,190 @@ suite('Smoke Test: Run Smart Selection and Advance Cursor', async () => { 'smart_send_smoke.txt', ); + console.log(`[smartSend.smoke] Test starting`); + console.log(`[smartSend.smoke] Python file: ${file}`); + console.log(`[smartSend.smoke] Output file: ${outputFile}`); + console.log(`[smartSend.smoke] Python file exists: ${await fs.pathExists(file)}`); + + const outputFileExistsBefore = await fs.pathExists(outputFile); + console.log(`[smartSend.smoke] Output file exists before cleanup: ${outputFileExistsBefore}`); await fs.remove(outputFile); + console.log(`[smartSend.smoke] Output file removed`); const textDocument = await openFile(file); + console.log(`[smartSend.smoke] File opened in editor`); + console.log(`[smartSend.smoke] Document has ${textDocument.lineCount} lines`); + console.log(`[smartSend.smoke] First 5 lines of file:`); + for (let i = 0; i < Math.min(5, textDocument.lineCount); i++) { + console.log(`[smartSend.smoke] Line ${i}: ${textDocument.lineAt(i).text}`); + } if (vscode.window.activeTextEditor) { - const myPos = new vscode.Position(0, 0); - vscode.window.activeTextEditor!.selections = [new vscode.Selection(myPos, myPos)]; + // Select the entire file content to execute + // The implementation of execSelectionInTerminal with empty selection only runs the current line, + // not smart selection. So we need to select the actual code we want to execute. + const document = vscode.window.activeTextEditor.document; + const fullRange = new vscode.Range( + document.lineAt(0).range.start, + document.lineAt(document.lineCount - 1).range.end, + ); + vscode.window.activeTextEditor.selection = new vscode.Selection(fullRange.start, fullRange.end); + + const selectedText = vscode.window.activeTextEditor.document.getText( + vscode.window.activeTextEditor.selection, + ); + console.log( + `[smartSend.smoke] Selected entire file (${selectedText.split('\n').length} lines, ${ + selectedText.length + } chars)`, + ); + + // Wait a bit for the editor state to settle + console.log(`[smartSend.smoke] Waiting 500ms for editor state to settle...`); + await new Promise((resolve) => setTimeout(resolve, 500)); } + + const terminalsBefore = vscode.window.terminals.length; + console.log(`[smartSend.smoke] Number of terminals before execution: ${terminalsBefore}`); + + // On Windows, if terminals exist from previous tests, they may not be ready for new commands + // Give them time to fully initialize before sending commands + if (terminalsBefore > 0 && process.platform === 'win32') { + console.log( + `[smartSend.smoke] Windows detected with ${terminalsBefore} existing terminals, waiting 3s for terminal readiness...`, + ); + await new Promise((resolve) => setTimeout(resolve, 3000)); + } + + // Verify the active editor is correct before executing command + if (vscode.window.activeTextEditor) { + console.log( + `[smartSend.smoke] Active editor before command: ${vscode.window.activeTextEditor.document.uri.fsPath}`, + ); + console.log( + `[smartSend.smoke] Active editor language: ${vscode.window.activeTextEditor.document.languageId}`, + ); + } else { + console.error(`[smartSend.smoke] ERROR: No active text editor before command!`); + } + + const startTime = Date.now(); + console.log( + `[smartSend.smoke] Executing first 'python.execSelectionInTerminal' command at ${new Date().toISOString()}`, + ); + console.log(`[smartSend.smoke] Passing document URI to execSelectionInTerminal: ${textDocument.uri.fsPath}`); + await vscode.commands .executeCommand('python.execSelectionInTerminal', textDocument.uri) .then(undefined, (err) => { + console.error(`[smartSend.smoke] First command failed: ${err}`); assert.fail(`Something went wrong running the Python file in the terminal: ${err}`); }); + const firstCmdTime = Date.now(); + console.log(`[smartSend.smoke] First command completed in ${firstCmdTime - startTime}ms`); - const checkIfFileHasBeenCreated = () => fs.pathExists(outputFile); - await waitForCondition(checkIfFileHasBeenCreated, 20_000, `"${outputFile}" file not created`); + // Check if smart selection changed the selection + if (vscode.window.activeTextEditor) { + const selectionAfterCmd = vscode.window.activeTextEditor.selection; + const selectedText = vscode.window.activeTextEditor.document.getText(selectionAfterCmd); + console.log( + `[smartSend.smoke] Selection after command - start: (${selectionAfterCmd.start.line}, ${selectionAfterCmd.start.character}), end: (${selectionAfterCmd.end.line}, ${selectionAfterCmd.end.character})`, + ); + console.log( + `[smartSend.smoke] Selected text after command (first 100 chars): "${selectedText + .substring(0, 100) + .replace(/\n/g, '\\n')}"`, + ); + console.log( + `[smartSend.smoke] Active editor document URI: ${vscode.window.activeTextEditor.document.uri.fsPath}`, + ); + } else { + console.error(`[smartSend.smoke] WARNING: No active text editor after command execution!`); + } + + const terminalsAfter = vscode.window.terminals.length; + console.log(`[smartSend.smoke] Number of terminals after first execution: ${terminalsAfter}`); + if (vscode.window.activeTerminal) { + console.log(`[smartSend.smoke] Active terminal name: ${vscode.window.activeTerminal.name}`); + } + + // Add additional wait to allow terminal to start processing + // Windows may need more time for terminal to initialize and start executing + const isWindows = process.platform === 'win32'; + const initialWaitTime = isWindows ? 2000 : 1000; + console.log( + `[smartSend.smoke] Waiting ${initialWaitTime}ms for terminal to start processing (isWindows: ${isWindows})...`, + ); + await new Promise((resolve) => setTimeout(resolve, initialWaitTime)); + + // Verify the working directory matches expected + const expectedDir = path.dirname(outputFile); + console.log(`[smartSend.smoke] Expected output directory: ${expectedDir}`); + console.log(`[smartSend.smoke] Directory exists: ${await fs.pathExists(expectedDir)}`); + let checkCount = 0; + const checkIfFileHasBeenCreated = async () => { + checkCount++; + const exists = await fs.pathExists(outputFile); + if (checkCount % 100 === 0) { + // Log every 100 checks (~1 second) + const elapsed = Date.now() - startTime; + console.log(`[smartSend.smoke] File creation check #${checkCount} at ${elapsed}ms: ${exists}`); + } + return exists; + }; + + try { + await waitForCondition(checkIfFileHasBeenCreated, 20_000, `"${outputFile}" file not created`); + const createTime = Date.now() - startTime; + console.log(`[smartSend.smoke] SUCCESS: File created after ${createTime}ms (${checkCount} checks)`); + } catch (error) { + const totalTime = Date.now() - startTime; + console.error(`[smartSend.smoke] FAILURE: File not created after ${totalTime}ms (${checkCount} checks)`); + console.error(`[smartSend.smoke] Output file exists: ${await fs.pathExists(outputFile)}`); + console.error(`[smartSend.smoke] Number of terminals: ${vscode.window.terminals.length}`); + + // Check final editor state + if (vscode.window.activeTextEditor) { + console.error( + `[smartSend.smoke] Final active editor: ${vscode.window.activeTextEditor.document.uri.fsPath}`, + ); + const finalSelection = vscode.window.activeTextEditor.selection; + console.error( + `[smartSend.smoke] Final selection - start: (${finalSelection.start.line}, ${finalSelection.start.character}), end: (${finalSelection.end.line}, ${finalSelection.end.character})`, + ); + } + + // List directory contents + const dir = path.dirname(outputFile); + try { + const fsModule = await import('fs'); + const files = fsModule.readdirSync(dir); + console.error(`[smartSend.smoke] Directory contents (${dir}):`, files); + } catch (e) { + console.error(`[smartSend.smoke] Failed to list directory: ${e}`); + } + + throw error; + } + + console.log(`[smartSend.smoke] Executing second 'python.execSelectionInTerminal' command`); await vscode.commands .executeCommand('python.execSelectionInTerminal', textDocument.uri) .then(undefined, (err) => { + console.error(`[smartSend.smoke] Second command failed: ${err}`); assert.fail(`Something went wrong running the Python file in the terminal: ${err}`); }); + console.log(`[smartSend.smoke] Second command completed`); + + console.log(`[smartSend.smoke] Executing third 'python.execSelectionInTerminal' command`); await vscode.commands .executeCommand('python.execSelectionInTerminal', textDocument.uri) .then(undefined, (err) => { + console.error(`[smartSend.smoke] Third command failed: ${err}`); assert.fail(`Something went wrong running the Python file in the terminal: ${err}`); }); + console.log(`[smartSend.smoke] Third command completed`); async function wait() { return new Promise((resolve) => { @@ -71,12 +234,16 @@ suite('Smoke Test: Run Smart Selection and Advance Cursor', async () => { }); } + console.log(`[smartSend.smoke] Waiting 10s for file deletion to complete...`); await wait(); const deletedFile = !(await fs.pathExists(outputFile)); + console.log(`[smartSend.smoke] File exists after deletion commands: ${!deletedFile}`); if (deletedFile) { + console.log(`[smartSend.smoke] SUCCESS: File has been deleted as expected`); assert.ok(true, `"${outputFile}" file has been deleted`); } else { + console.error(`[smartSend.smoke] FAILURE: File still exists`); assert.fail(`"${outputFile}" file still exists`); } }); diff --git a/src/testMultiRootWkspc/smokeTests/create_delete_file.py b/src/testMultiRootWkspc/smokeTests/create_delete_file.py index 399bc4863c15..8902efcc5243 100644 --- a/src/testMultiRootWkspc/smokeTests/create_delete_file.py +++ b/src/testMultiRootWkspc/smokeTests/create_delete_file.py @@ -1,5 +1,20 @@ -with open('smart_send_smoke.txt', 'w') as f: - f.write('This is for smart send smoke test') import os -os.remove('smart_send_smoke.txt') +# Use absolute path to avoid working directory issues +script_dir = os.path.dirname(os.path.abspath(__file__)) +file_path = os.path.join(script_dir, 'smart_send_smoke.txt') + +# For debugging: print working directory and file path +print(f"Working directory: {os.getcwd()}", flush=True) +print(f"File path: {file_path}", flush=True) +print(f"Script location: {os.path.abspath(__file__)}", flush=True) + +with open(file_path, 'w') as f: + f.write('This is for smart send smoke test') + f.flush() # Explicitly flush to ensure write completes + +print(f"Successfully created {file_path}", flush=True) + +print(f"About to delete {file_path}", flush=True) +os.remove(file_path) +print(f"Successfully deleted {file_path}", flush=True) diff --git a/src/testMultiRootWkspc/smokeTests/testExecInTerminal.py b/src/testMultiRootWkspc/smokeTests/testExecInTerminal.py index d83d46a740d9..de0e51a35ede 100644 --- a/src/testMultiRootWkspc/smokeTests/testExecInTerminal.py +++ b/src/testMultiRootWkspc/smokeTests/testExecInTerminal.py @@ -12,5 +12,22 @@ if len(args) == 2: log_file = args[1] +# Ensure we use absolute path to avoid working directory issues +if not os.path.isabs(log_file): + # Get the directory where this script is located + script_dir = os.path.dirname(os.path.abspath(__file__)) + log_file = os.path.join(script_dir, log_file) + +# For debugging: print working directory and file path +print(f"Working directory: {os.getcwd()}", flush=True) +print(f"Log file path: {log_file}", flush=True) +print(f"Script location: {os.path.abspath(__file__)}", flush=True) + +# Ensure parent directory exists +os.makedirs(os.path.dirname(log_file), exist_ok=True) + with open(log_file, "a") as f: f.write(sys.executable) + f.flush() # Explicitly flush to ensure write completes + +print(f"Successfully wrote to {log_file}", flush=True)