@@ -14,20 +14,28 @@ import { PythonEnvUpdatedEvent } from '../../../client/pythonEnvironments/base/l
14
14
import { PythonEnvsChangedEvent } from '../../../client/pythonEnvironments/base/watcher' ;
15
15
import { PythonEnvsResolver } from '../../../client/pythonEnvironments/collection/environmentsResolver' ;
16
16
import * as ExternalDep from '../../../client/pythonEnvironments/common/externalDependencies' ;
17
- import {
18
- EnvironmentInfoService ,
19
- IEnvironmentInfoService ,
20
- } from '../../../client/pythonEnvironments/info/environmentInfoService' ;
17
+ import { EnvironmentInfoService } from '../../../client/pythonEnvironments/info/environmentInfoService' ;
21
18
import { sleep } from '../../core' ;
22
19
import { createEnv , getEnvs , SimpleLocator } from '../base/common' ;
23
20
24
21
suite ( 'Environments Resolver' , ( ) => {
22
+ /**
23
+ * Returns the expected environment to be returned by Environment info service
24
+ */
25
+ function createExpectedEnvInfo ( env : PythonEnvInfo ) : PythonEnvInfo {
26
+ const updatedEnv = cloneDeep ( env ) ;
27
+ updatedEnv . version = {
28
+ ...parseVersion ( '3.8.3-final' ) ,
29
+ sysVersion : '3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:37:02) [MSC v.1924 64 bit (AMD64)]' ,
30
+ } ;
31
+ updatedEnv . executable . filename = env . executable . filename ;
32
+ updatedEnv . executable . sysPrefix = 'path' ;
33
+ updatedEnv . arch = Architecture . x64 ;
34
+ return updatedEnv ;
35
+ }
25
36
suite ( 'iterEnvs()' , ( ) => {
26
37
let stubShellExec : sinon . SinonStub ;
27
- let envService : IEnvironmentInfoService ;
28
-
29
38
setup ( ( ) => {
30
- envService = new EnvironmentInfoService ( ) ;
31
39
stubShellExec = ImportMock . mockFunction (
32
40
ExternalDep ,
33
41
'shellExecute' ,
@@ -44,23 +52,14 @@ suite('Environments Resolver', () => {
44
52
stubShellExec . restore ( ) ;
45
53
} ) ;
46
54
47
- function createExpectedEnvInfo ( env : PythonEnvInfo ) : PythonEnvInfo {
48
- const updatedEnv = cloneDeep ( env ) ;
49
- updatedEnv . version = { ...parseVersion ( '3.8.3-final' ) , sysVersion : '3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:37:02) [MSC v.1924 64 bit (AMD64)]' } ;
50
- updatedEnv . executable . filename = env . executable . filename ;
51
- updatedEnv . executable . sysPrefix = 'path' ;
52
- updatedEnv . arch = Architecture . x64 ;
53
- return updatedEnv ;
54
- }
55
-
56
55
test ( 'Iterator only yields as-is' , async ( ) => {
57
56
const env1 = createEnv ( 'env1' , '3.5.12b1' , PythonEnvKind . Venv , path . join ( 'path' , 'to' , 'exec1' ) ) ;
58
57
const env2 = createEnv ( 'env2' , '3.8.1' , PythonEnvKind . Conda , path . join ( 'path' , 'to' , 'exec2' ) ) ;
59
58
const env3 = createEnv ( 'env3' , '2.7' , PythonEnvKind . System , path . join ( 'path' , 'to' , 'exec3' ) ) ;
60
59
const env4 = createEnv ( 'env4' , '3.9.0rc2' , PythonEnvKind . Unknown , path . join ( 'path' , 'to' , 'exec2' ) ) ;
61
60
const environmentsToBeIterated = [ env1 , env2 , env3 , env4 ] ;
62
- const pythonEnvManager = new SimpleLocator ( environmentsToBeIterated ) ;
63
- const reducer = new PythonEnvsResolver ( pythonEnvManager , envService ) ;
61
+ const pythonEnvReducer = new SimpleLocator ( environmentsToBeIterated ) ;
62
+ const reducer = new PythonEnvsResolver ( pythonEnvReducer , new EnvironmentInfoService ( ) ) ;
64
63
65
64
const iterator = reducer . iterEnvs ( ) ;
66
65
const envs = await getEnvs ( iterator ) ;
@@ -73,9 +72,9 @@ suite('Environments Resolver', () => {
73
72
const env1 = createEnv ( 'env1' , '3.5.12b1' , PythonEnvKind . Unknown , path . join ( 'path' , 'to' , 'exec1' ) ) ;
74
73
const env2 = createEnv ( 'env2' , '3.8.1' , PythonEnvKind . Unknown , path . join ( 'path' , 'to' , 'exec2' ) ) ;
75
74
const environmentsToBeIterated = [ env1 , env2 ] ;
76
- const pythonEnvManager = new SimpleLocator ( environmentsToBeIterated ) ;
75
+ const pythonEnvReducer = new SimpleLocator ( environmentsToBeIterated ) ;
77
76
const onUpdatedEvents : ( PythonEnvUpdatedEvent | null ) [ ] = [ ] ;
78
- const reducer = new PythonEnvsResolver ( pythonEnvManager , envService ) ;
77
+ const reducer = new PythonEnvsResolver ( pythonEnvReducer , new EnvironmentInfoService ( ) ) ;
79
78
80
79
const iterator = reducer . iterEnvs ( ) ; // Act
81
80
@@ -108,9 +107,9 @@ suite('Environments Resolver', () => {
108
107
const updatedEnv = createEnv ( 'env1' , '3.8.1' , PythonEnvKind . System , path . join ( 'path' , 'to' , 'exec' ) ) ;
109
108
const environmentsToBeIterated = [ env ] ;
110
109
const didUpdate = new EventEmitter < PythonEnvUpdatedEvent | null > ( ) ;
111
- const pythonEnvManager = new SimpleLocator ( environmentsToBeIterated , { onUpdated : didUpdate . event } ) ;
110
+ const pythonEnvReducer = new SimpleLocator ( environmentsToBeIterated , { onUpdated : didUpdate . event } ) ;
112
111
const onUpdatedEvents : ( PythonEnvUpdatedEvent | null ) [ ] = [ ] ;
113
- const reducer = new PythonEnvsResolver ( pythonEnvManager , envService ) ;
112
+ const reducer = new PythonEnvsResolver ( pythonEnvReducer , new EnvironmentInfoService ( ) ) ;
114
113
115
114
const iterator = reducer . iterEnvs ( ) ; // Act
116
115
@@ -134,43 +133,112 @@ suite('Environments Resolver', () => {
134
133
// Assert
135
134
// The updates can be anything, even the number of updates, but they should lead to the same final state
136
135
const { length } = onUpdatedEvents ;
137
- assert . deepEqual ( onUpdatedEvents [ length - 2 ] ?. new , createExpectedEnvInfo ( updatedEnv ) , 'The final update to environment is incorrect' ) ;
136
+ assert . deepEqual (
137
+ onUpdatedEvents [ length - 2 ] ?. new ,
138
+ createExpectedEnvInfo ( updatedEnv ) ,
139
+ 'The final update to environment is incorrect' ,
140
+ ) ;
138
141
assert . equal ( onUpdatedEvents [ length - 1 ] , null , 'Last update should be null' ) ;
139
142
didUpdate . dispose ( ) ;
140
143
} ) ;
141
144
} ) ;
142
145
143
146
test ( 'onChanged fires iff onChanged from reducer fires' , ( ) => {
144
- const pythonEnvManager = new SimpleLocator ( [ ] ) ;
147
+ const pythonEnvReducer = new SimpleLocator ( [ ] ) ;
145
148
const event1 : PythonEnvsChangedEvent = { } ;
146
149
const event2 : PythonEnvsChangedEvent = { kind : PythonEnvKind . Unknown } ;
147
150
const expected = [ event1 , event2 ] ;
148
- const reducer = new PythonEnvsResolver ( pythonEnvManager , new EnvironmentInfoService ( ) ) ;
151
+ const reducer = new PythonEnvsResolver ( pythonEnvReducer , new EnvironmentInfoService ( ) ) ;
149
152
150
153
const events : PythonEnvsChangedEvent [ ] = [ ] ;
151
154
reducer . onChanged ( ( e ) => events . push ( e ) ) ;
152
155
153
- pythonEnvManager . fire ( event1 ) ;
154
- pythonEnvManager . fire ( event2 ) ;
156
+ pythonEnvReducer . fire ( event1 ) ;
157
+ pythonEnvReducer . fire ( event2 ) ;
155
158
156
159
assert . deepEqual ( events , expected ) ;
157
160
} ) ;
158
161
159
- test ( 'Calls reducer to resolves environments' , async ( ) => {
160
- const env = createEnv ( 'env1' , '3.8' , PythonEnvKind . Unknown , path . join ( 'path' , 'to' , 'exec' ) ) ;
161
- const resolvedEnv = createEnv ( 'env1' , '3.8.1' , PythonEnvKind . Conda , 'resolved/path/to/exec' ) ;
162
- const pythonEnvManager = new SimpleLocator ( [ ] , {
163
- resolve : async ( e : PythonEnvInfo ) => {
164
- if ( e === env ) {
165
- return resolvedEnv ;
166
- }
167
- return undefined ;
168
- } ,
162
+ suite ( 'resolveEnv()' , ( ) => {
163
+ let stubShellExec : sinon . SinonStub ;
164
+ setup ( ( ) => {
165
+ stubShellExec = ImportMock . mockFunction (
166
+ ExternalDep ,
167
+ 'shellExecute' ,
168
+ new Promise < ExecutionResult < string > > ( ( resolve ) => {
169
+ resolve ( {
170
+ stdout :
171
+ '{"versionInfo": [3, 8, 3, "final", 0], "sysPrefix": "path", "sysVersion": "3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:37:02) [MSC v.1924 64 bit (AMD64)]", "is64Bit": true}' ,
172
+ } ) ;
173
+ } ) ,
174
+ ) ;
175
+ } ) ;
176
+
177
+ teardown ( ( ) => {
178
+ stubShellExec . restore ( ) ;
179
+ } ) ;
180
+
181
+ test ( 'Calls into reducer to get resolved environment, then calls environnment service to resolve environment further and return it' , async ( ) => {
182
+ const env = createEnv ( 'env1' , '3.8' , PythonEnvKind . Unknown , path . join ( 'path' , 'to' , 'exec' ) ) ;
183
+ const resolvedEnvReturnedByReducer = createEnv (
184
+ 'env1' ,
185
+ '3.8.1' ,
186
+ PythonEnvKind . Conda ,
187
+ 'resolved/path/to/exec' ,
188
+ ) ;
189
+ const pythonEnvReducer = new SimpleLocator ( [ ] , {
190
+ resolve : async ( e : PythonEnvInfo ) => {
191
+ if ( e === env ) {
192
+ return resolvedEnvReturnedByReducer ;
193
+ }
194
+ throw new Error ( 'Incorrect environment sent to the reducer' ) ;
195
+ } ,
196
+ } ) ;
197
+ const reducer = new PythonEnvsResolver ( pythonEnvReducer , new EnvironmentInfoService ( ) ) ;
198
+
199
+ const expected = await reducer . resolveEnv ( env ) ;
200
+
201
+ assert . deepEqual ( expected , createExpectedEnvInfo ( resolvedEnvReturnedByReducer ) ) ;
169
202
} ) ;
170
- const reducer = new PythonEnvsResolver ( pythonEnvManager , new EnvironmentInfoService ( ) ) ;
171
203
172
- const expected = await reducer . resolveEnv ( env ) ;
204
+ test ( 'If the reducer resolves environment, but fetching interpreter info returns undefined, return undefined' , async ( ) => {
205
+ stubShellExec . returns (
206
+ new Promise < ExecutionResult < string > > ( ( _resolve , reject ) => {
207
+ reject ( ) ;
208
+ } ) ,
209
+ ) ;
210
+ const env = createEnv ( 'env1' , '3.8' , PythonEnvKind . Unknown , path . join ( 'path' , 'to' , 'exec' ) ) ;
211
+ const resolvedEnvReturnedByReducer = createEnv (
212
+ 'env1' ,
213
+ '3.8.1' ,
214
+ PythonEnvKind . Conda ,
215
+ 'resolved/path/to/exec' ,
216
+ ) ;
217
+ const pythonEnvReducer = new SimpleLocator ( [ ] , {
218
+ resolve : async ( e : PythonEnvInfo ) => {
219
+ if ( e === env ) {
220
+ return resolvedEnvReturnedByReducer ;
221
+ }
222
+ throw new Error ( 'Incorrect environment sent to the reducer' ) ;
223
+ } ,
224
+ } ) ;
225
+ const reducer = new PythonEnvsResolver ( pythonEnvReducer , new EnvironmentInfoService ( ) ) ;
226
+
227
+ const expected = await reducer . resolveEnv ( env ) ;
228
+
229
+ assert . deepEqual ( expected , undefined ) ;
230
+ } ) ;
173
231
174
- assert . deepEqual ( expected , resolvedEnv ) ;
232
+ test ( "If the reducer isn't able to resolve environment, return undefined" , async ( ) => {
233
+ const env = createEnv ( 'env' , '3.8' , PythonEnvKind . Unknown , path . join ( 'path' , 'to' , 'exec' ) ) ;
234
+ const pythonEnvReducer = new SimpleLocator ( [ ] , {
235
+ resolve : async ( ) => undefined ,
236
+ } ) ;
237
+ const reducer = new PythonEnvsResolver ( pythonEnvReducer , new EnvironmentInfoService ( ) ) ;
238
+
239
+ const expected = await reducer . resolveEnv ( env ) ;
240
+
241
+ assert . deepEqual ( expected , undefined ) ;
242
+ } ) ;
175
243
} ) ;
176
244
} ) ;
0 commit comments