@@ -7,8 +7,9 @@ import { EOL } from 'os';
77import  *  as  path  from  'path' ; 
88import  {  SemVer  }  from  'semver' ; 
99import  {  anything ,  capture ,  instance ,  mock ,  verify ,  when  }  from  'ts-mockito' ; 
10- import  *  as  typemoq  from  'typemoq' ; 
11- import  {  EventEmitter ,  Uri ,  workspace  as  workspaceType ,  WorkspaceConfiguration  }  from  'vscode' ; 
10+ import  {  EventEmitter ,  Uri  }  from  'vscode' ; 
11+ import  {  IWorkspaceService  }  from  '../../../client/common/application/types' ; 
12+ import  {  WorkspaceService  }  from  '../../../client/common/application/workspace' ; 
1213import  {  PlatformService  }  from  '../../../client/common/platform/platformService' ; 
1314import  {  IPlatformService  }  from  '../../../client/common/platform/types' ; 
1415import  {  CurrentProcess  }  from  '../../../client/common/process/currentProcess' ; 
@@ -18,15 +19,14 @@ import { IProcessService, IProcessServiceFactory } from '../../../client/common/
1819import  {  TerminalHelper  }  from  '../../../client/common/terminal/helper' ; 
1920import  {  ITerminalHelper  }  from  '../../../client/common/terminal/types' ; 
2021import  {  ICurrentProcess  }  from  '../../../client/common/types' ; 
21- import  {  clearCache  }  from  '../../../client/common/utils/cacheUtils' ; 
2222import  {  getNamesAndValues  }  from  '../../../client/common/utils/enum' ; 
2323import  {  Architecture ,  OSType  }  from  '../../../client/common/utils/platform' ; 
2424import  {  EnvironmentVariablesProvider  }  from  '../../../client/common/variables/environmentVariablesProvider' ; 
2525import  {  IEnvironmentVariablesProvider  }  from  '../../../client/common/variables/types' ; 
2626import  {  EXTENSION_ROOT_DIR  }  from  '../../../client/constants' ; 
2727import  {  EnvironmentActivationService  }  from  '../../../client/interpreter/activation/service' ; 
28- import  {  InterpreterType ,  PythonInterpreter  }  from  '../../../client/interpreter/contracts' ; 
29- import  {  mockedVSCodeNamespaces  }  from  '../../vscode-mock ' ; 
28+ import  {  IInterpreterService ,   InterpreterType ,  PythonInterpreter  }  from  '../../../client/interpreter/contracts' ; 
29+ import  {  InterpreterService  }  from  '../../../client/interpreter/interpreterService ' ; 
3030
3131const  getEnvironmentPrefix  =  'e8b39361-0157-4923-80e1-22d70d46dee6' ; 
3232const  defaultShells  =  { 
@@ -45,8 +45,10 @@ suite('Interpreters Activation - Python Environment Variables', () => {
4545 let  processService : IProcessService ; 
4646 let  currentProcess : ICurrentProcess ; 
4747 let  envVarsService : IEnvironmentVariablesProvider ; 
48-  let  workspace : typemoq . IMock < typeof  workspaceType > ; 
49- 
48+  let  workspace : IWorkspaceService ; 
49+  let  interpreterService : IInterpreterService ; 
50+  let  onDidChangeEnvVariables : EventEmitter < Uri  |  undefined > ; 
51+  let  onDidChangeInterpreter : EventEmitter < void > ; 
5052 const  pythonInterpreter : PythonInterpreter  =  { 
5153 path : '/foo/bar/python.exe' , 
5254 version : new  SemVer ( '3.6.6-final' ) , 
@@ -63,21 +65,22 @@ suite('Interpreters Activation - Python Environment Variables', () => {
6365 processService  =  mock ( ProcessService ) ; 
6466 currentProcess  =  mock ( CurrentProcess ) ; 
6567 envVarsService  =  mock ( EnvironmentVariablesProvider ) ; 
66-  workspace  =  mockedVSCodeNamespaces . workspace ! ; 
67-  when ( envVarsService . onDidEnvironmentVariablesChange ) . thenReturn ( new  EventEmitter < Uri  |  undefined > ( ) . event ) ; 
68-  service  =  new  EnvironmentActivationService ( instance ( helper ) ,  instance ( platform ) ,  instance ( processServiceFactory ) ,  instance ( currentProcess ) ,  instance ( envVarsService ) ) ; 
69- 
70-  const  cfg  =  typemoq . Mock . ofType < WorkspaceConfiguration > ( ) ; 
71-  workspace . setup ( w  =>  w . getConfiguration ( typemoq . It . isValue ( 'python' ) ,  typemoq . It . isAny ( ) ) ) . returns ( ( )  =>  cfg . object ) ; 
72-  workspace . setup ( w  =>  w . workspaceFolders ) . returns ( ( )  =>  [ ] ) ; 
73-  cfg . setup ( c  =>  c . inspect ( typemoq . It . isValue ( 'pythonPath' ) ) ) . returns ( ( )  =>  { 
74-  return  {  globalValue : 'GlobalValuepython'  }  as  any ; 
75-  } ) ; 
76-  clearCache ( ) ; 
68+  interpreterService  =  mock ( InterpreterService ) ; 
69+  workspace  =  mock ( WorkspaceService ) ; 
70+  onDidChangeEnvVariables  =  new  EventEmitter < Uri  |  undefined > ( ) ; 
71+  onDidChangeInterpreter  =  new  EventEmitter < void > ( ) ; 
72+  when ( envVarsService . onDidEnvironmentVariablesChange ) . thenReturn ( onDidChangeEnvVariables . event ) ; 
73+  when ( interpreterService . onDidChangeInterpreter ) . thenReturn ( onDidChangeInterpreter . event ) ; 
74+  service  =  new  EnvironmentActivationService ( 
75+  instance ( helper ) , 
76+  instance ( platform ) , 
77+  instance ( processServiceFactory ) , 
78+  instance ( currentProcess ) , 
79+  instance ( workspace ) , 
80+  instance ( interpreterService ) , 
81+  instance ( envVarsService ) 
82+  ) ; 
7783 } 
78-  teardown ( ( )  =>  { 
79-  mockedVSCodeNamespaces . workspace ! . reset ( ) ; 
80-  } ) ; 
8184
8285 function  title ( resource ?: Uri ,  interpreter ?: PythonInterpreter )  { 
8386 return  `${ resource  ? 'With a resource'  : 'Without a resource' } ${ interpreter  ? ' and an interpreter'  : '' }  ` ; 
@@ -218,6 +221,64 @@ suite('Interpreters Activation - Python Environment Variables', () => {
218221 verify ( envVarsService . getEnvironmentVariables ( resource ) ) . once ( ) ; 
219222 verify ( processService . shellExec ( anything ( ) ,  anything ( ) ) ) . once ( ) ; 
220223 } ) ; 
224+  test ( 'Cache Variables' ,  async  ( )  =>  { 
225+  const  cmd  =  [ '1' ,  '2' ] ; 
226+  const  varsFromEnv  =  {  one : '11' ,  two : '22' ,  HELLO : 'xxx'  } ; 
227+  const  stdout  =  `${ getEnvironmentPrefix } ${ EOL } ${ JSON . stringify ( varsFromEnv ) }  ` ; 
228+  when ( platform . osType ) . thenReturn ( osType . value ) ; 
229+  when ( helper . getEnvironmentActivationShellCommands ( resource ,  anything ( ) ,  interpreter ) ) . thenResolve ( cmd ) ; 
230+  when ( processServiceFactory . create ( resource ) ) . thenResolve ( instance ( processService ) ) ; 
231+  when ( envVarsService . getEnvironmentVariables ( resource ) ) . thenResolve ( { } ) ; 
232+  when ( processService . shellExec ( anything ( ) ,  anything ( ) ) ) . thenResolve ( {  stdout : stdout  } ) ; 
233+ 
234+  const  env  =  await  service . getActivatedEnvironmentVariables ( resource ,  interpreter ) ; 
235+  const  env2  =  await  service . getActivatedEnvironmentVariables ( resource ,  interpreter ) ; 
236+  const  env3  =  await  service . getActivatedEnvironmentVariables ( resource ,  interpreter ) ; 
237+ 
238+  expect ( env ) . to . deep . equal ( varsFromEnv ) ; 
239+  // All same objects. 
240+  expect ( env ) 
241+  . to . equal ( env2 ) 
242+  . to . equal ( env3 ) ; 
243+ 
244+  // All methods invoked only once. 
245+  verify ( helper . getEnvironmentActivationShellCommands ( resource ,  anything ( ) ,  interpreter ) ) . once ( ) ; 
246+  verify ( processServiceFactory . create ( resource ) ) . once ( ) ; 
247+  verify ( envVarsService . getEnvironmentVariables ( resource ) ) . once ( ) ; 
248+  verify ( processService . shellExec ( anything ( ) ,  anything ( ) ) ) . once ( ) ; 
249+  } ) ; 
250+  async  function  testClearingCache ( bustCache : Function )  { 
251+  const  cmd  =  [ '1' ,  '2' ] ; 
252+  const  varsFromEnv  =  {  one : '11' ,  two : '22' ,  HELLO : 'xxx'  } ; 
253+  const  stdout  =  `${ getEnvironmentPrefix } ${ EOL } ${ JSON . stringify ( varsFromEnv ) }  ` ; 
254+  when ( platform . osType ) . thenReturn ( osType . value ) ; 
255+  when ( helper . getEnvironmentActivationShellCommands ( resource ,  anything ( ) ,  interpreter ) ) . thenResolve ( cmd ) ; 
256+  when ( processServiceFactory . create ( resource ) ) . thenResolve ( instance ( processService ) ) ; 
257+  when ( envVarsService . getEnvironmentVariables ( resource ) ) . thenResolve ( { } ) ; 
258+  when ( processService . shellExec ( anything ( ) ,  anything ( ) ) ) . thenResolve ( {  stdout : stdout  } ) ; 
259+ 
260+  const  env  =  await  service . getActivatedEnvironmentVariables ( resource ,  interpreter ) ; 
261+  bustCache ( ) ; 
262+  const  env2  =  await  service . getActivatedEnvironmentVariables ( resource ,  interpreter ) ; 
263+ 
264+  expect ( env ) . to . deep . equal ( varsFromEnv ) ; 
265+  // Objects are different (not same reference). 
266+  expect ( env ) . to . not . equal ( env2 ) ; 
267+  // However variables are the same. 
268+  expect ( env ) . to . deep . equal ( env2 ) ; 
269+ 
270+  // All methods invoked twice as cache was blown. 
271+  verify ( helper . getEnvironmentActivationShellCommands ( resource ,  anything ( ) ,  interpreter ) ) . twice ( ) ; 
272+  verify ( processServiceFactory . create ( resource ) ) . twice ( ) ; 
273+  verify ( envVarsService . getEnvironmentVariables ( resource ) ) . twice ( ) ; 
274+  verify ( processService . shellExec ( anything ( ) ,  anything ( ) ) ) . twice ( ) ; 
275+  } 
276+  test ( 'Cache Variables get cleared when changing interpreter' ,  async  ( )  =>  { 
277+  await  testClearingCache ( onDidChangeInterpreter . fire . bind ( onDidChangeInterpreter ) ) ; 
278+  } ) ; 
279+  test ( 'Cache Variables get cleared when changing env variables file' ,  async  ( )  =>  { 
280+  await  testClearingCache ( onDidChangeEnvVariables . fire . bind ( onDidChangeEnvVariables ) ) ; 
281+  } ) ; 
221282 } ) ; 
222283 } ) ; 
223284 } ) ; 
0 commit comments