@@ -9,19 +9,22 @@ import { exec } from 'child_process';
99import * as path from 'path' ;
1010import { Uri } from 'vscode' ;
1111import '../../../client/common/extensions' ;
12+ import { createDeferredFromPromise , Deferred } from '../../../client/common/utils/async' ;
13+ import { StopWatch } from '../../../client/common/utils/stopWatch' ;
1214import {
13- IInterpreterLocatorService , WORKSPACE_VIRTUAL_ENV_SERVICE
15+ IInterpreterLocatorService ,
16+ IInterpreterWatcherBuilder ,
17+ WORKSPACE_VIRTUAL_ENV_SERVICE
1418} from '../../../client/interpreter/contracts' ;
19+ import { WorkspaceVirtualEnvWatcherService } from '../../../client/interpreter/locators/services/workspaceVirtualEnvWatcherService' ;
1520import { IServiceContainer } from '../../../client/ioc/types' ;
16- import {
17- deleteFiles , isOs , isPythonVersionInProcess , OSType ,
18- PYTHON_PATH , rootWorkspaceUri , waitForCondition
19- } from '../../common' ;
21+ import { deleteFiles , isPythonVersionInProcess , PYTHON_PATH , rootWorkspaceUri , waitForCondition } from '../../common' ;
2022import { IS_MULTI_ROOT_TEST } from '../../constants' ;
21- import { initialize , IS_VSTS , multirootPath } from '../../initialize' ;
23+ import { sleep } from '../../core' ;
24+ import { initialize , multirootPath } from '../../initialize' ;
2225
2326const timeoutMs = 60_000 ;
24- suite ( 'Interpreters - Workspace VirtualEnv Service' , function ( ) {
27+ suite ( 'Interpreters - Workspace VirtualEnv Service' , function ( ) {
2528 this . timeout ( timeoutMs ) ;
2629 this . retries ( 0 ) ;
2730
@@ -31,43 +34,65 @@ suite('Interpreters - Workspace VirtualEnv Service', function () {
3134 const venvPrefix = '.venv' ;
3235 let serviceContainer : IServiceContainer ;
3336
37+ async function manuallyTriggerFSWatcher ( deferred : Deferred < void > ) {
38+ // Monitoring files on virtualized environments can be finicky...
39+ // Lets trigger the fs watcher manually for the tests.
40+ const stopWatch = new StopWatch ( ) ;
41+ const builder = serviceContainer . get < IInterpreterWatcherBuilder > ( IInterpreterWatcherBuilder ) ;
42+ const watcher = ( await builder . getWorkspaceVirtualEnvInterpreterWatcher (
43+ workspaceUri
44+ ) ) as WorkspaceVirtualEnvWatcherService ;
45+ while ( ! deferred . completed && stopWatch . elapsedTime < timeoutMs - 10_000 ) {
46+ watcher . createHandler ( workspaceUri ) . ignoreErrors ( ) ;
47+ await sleep ( 1000 ) ;
48+ }
49+ }
3450 async function waitForInterpreterToBeDetected ( envNameToLookFor : string ) {
3551 const predicate = async ( ) => {
3652 const items = await locator . getInterpreters ( workspaceUri ) ;
3753 return items . some ( item => item . envName === envNameToLookFor ) ;
3854 } ;
39- await waitForCondition ( predicate , timeoutMs , `${ envNameToLookFor } , Environment not detected in the workspace ${ workspaceUri . fsPath } ` ) ;
55+ const promise = waitForCondition (
56+ predicate ,
57+ timeoutMs ,
58+ `${ envNameToLookFor } , Environment not detected in the workspace ${ workspaceUri . fsPath } `
59+ ) ;
60+ const deferred = createDeferredFromPromise ( promise ) ;
61+ manuallyTriggerFSWatcher ( deferred ) . ignoreErrors ( ) ;
62+ await deferred . promise ;
4063 }
4164 async function createVirtualEnvironment ( envSuffix : string ) {
4265 // Ensure env is random to avoid conflicts in tests (currupting test data).
4366 const envName = `${ venvPrefix } ${ envSuffix } ${ new Date ( ) . getTime ( ) . toString ( ) } ` ;
4467 return new Promise < string > ( ( resolve , reject ) => {
45- exec ( `${ PYTHON_PATH . fileToCommandArgument ( ) } -m venv ${ envName } ` , { cwd : workspaceUri . fsPath } , ( ex , _ , stderr ) => {
46- if ( ex ) {
47- return reject ( ex ) ;
48- }
49- if ( stderr && stderr . length > 0 ) {
50- reject ( new Error ( `Failed to create Env ${ envName } , ${ PYTHON_PATH } , Error: ${ stderr } ` ) ) ;
51- } else {
52- resolve ( envName ) ;
68+ exec (
69+ `${ PYTHON_PATH . fileToCommandArgument ( ) } -m venv ${ envName } ` ,
70+ { cwd : workspaceUri . fsPath } ,
71+ ( ex , _ , stderr ) => {
72+ if ( ex ) {
73+ return reject ( ex ) ;
74+ }
75+ if ( stderr && stderr . length > 0 ) {
76+ reject ( new Error ( `Failed to create Env ${ envName } , ${ PYTHON_PATH } , Error: ${ stderr } ` ) ) ;
77+ } else {
78+ resolve ( envName ) ;
79+ }
5380 }
54- } ) ;
81+ ) ;
5582 } ) ;
5683 }
5784
58- suiteSetup ( async function ( ) {
59- // skip for Linux CI, see #3848
60- if ( isOs ( OSType . Linux ) && IS_VSTS ) {
61- return this . skip ( ) ;
62- }
63-
85+ suiteSetup ( async function ( ) {
6486 // skip for Python < 3, no venv support
6587 if ( await isPythonVersionInProcess ( undefined , '2' ) ) {
6688 return this . skip ( ) ;
6789 }
6890
6991 serviceContainer = ( await initialize ( ) ) . serviceContainer ;
70- locator = serviceContainer . get < IInterpreterLocatorService > ( IInterpreterLocatorService , WORKSPACE_VIRTUAL_ENV_SERVICE ) ;
92+ locator = serviceContainer . get < IInterpreterLocatorService > (
93+ IInterpreterLocatorService ,
94+ WORKSPACE_VIRTUAL_ENV_SERVICE
95+ ) ;
7196 // This test is required, we need to wait for interpreter listing completes,
7297 // before proceeding with other tests.
7398 await deleteFiles ( path . join ( workspaceUri . fsPath , `${ venvPrefix } *` ) ) ;
@@ -91,15 +116,18 @@ suite('Interpreters - Workspace VirtualEnv Service', function () {
91116 await waitForInterpreterToBeDetected ( env2 ) ;
92117 } ) ;
93118
94- test ( 'Detect a new Virtual Environment, and other workspace folder must not be affected (multiroot)' , async function ( ) {
119+ test ( 'Detect a new Virtual Environment, and other workspace folder must not be affected (multiroot)' , async function ( ) {
95120 if ( ! IS_MULTI_ROOT_TEST ) {
96121 return this . skip ( ) ;
97122 }
98123 // There should be nothing in workspacec4.
99124 let items4 = await locator . getInterpreters ( workspace4 ) ;
100125 expect ( items4 ) . to . be . lengthOf ( 0 ) ;
101126
102- const [ env1 , env2 ] = await Promise . all ( [ createVirtualEnvironment ( 'first3' ) , createVirtualEnvironment ( 'second3' ) ] ) ;
127+ const [ env1 , env2 ] = await Promise . all ( [
128+ createVirtualEnvironment ( 'first3' ) ,
129+ createVirtualEnvironment ( 'second3' )
130+ ] ) ;
103131 await Promise . all ( [ waitForInterpreterToBeDetected ( env1 ) , waitForInterpreterToBeDetected ( env2 ) ] ) ;
104132
105133 // Workspace4 should still not have any interpreters.
0 commit comments