2
2
// Licensed under the MIT License.
3
3
4
4
import { assert , expect } from 'chai' ;
5
+ import { cloneDeep } from 'lodash' ;
5
6
import * as path from 'path' ;
6
7
import { ImportMock } from 'ts-mock-imports' ;
7
8
import { EventEmitter } from 'vscode' ;
8
9
import { ExecutionResult } from '../../../client/common/process/types' ;
10
+ import { Architecture } from '../../../client/common/utils/platform' ;
9
11
import { PythonEnvInfo , PythonEnvKind } from '../../../client/pythonEnvironments/base/info' ;
12
+ import { parseVersion } from '../../../client/pythonEnvironments/base/info/pythonVersion' ;
10
13
import { PythonEnvUpdatedEvent } from '../../../client/pythonEnvironments/base/locator' ;
11
14
import { PythonEnvsChangedEvent } from '../../../client/pythonEnvironments/base/watcher' ;
12
15
import { PythonEnvsResolver } from '../../../client/pythonEnvironments/collection/environmentsResolver' ;
13
16
import * as ExternalDep from '../../../client/pythonEnvironments/common/externalDependencies' ;
14
- import { EnvironmentInfoService , IEnvironmentInfoService } from '../../../client/pythonEnvironments/info/environmentInfoService' ;
17
+ import {
18
+ EnvironmentInfoService ,
19
+ IEnvironmentInfoService ,
20
+ } from '../../../client/pythonEnvironments/info/environmentInfoService' ;
15
21
import { sleep } from '../../core' ;
16
22
import { createEnv , getEnvs , SimpleLocator } from '../base/common' ;
17
23
18
- suite ( 'Environments Reducer ' , ( ) => {
24
+ suite ( 'Environments Resolver ' , ( ) => {
19
25
suite ( 'iterEnvs()' , ( ) => {
20
26
let stubShellExec : sinon . SinonStub ;
21
27
let envService : IEnvironmentInfoService ;
@@ -28,40 +34,45 @@ suite('Environments Reducer', () => {
28
34
new Promise < ExecutionResult < string > > ( ( resolve ) => {
29
35
resolve ( {
30
36
stdout :
31
- '{"versionInfo": [3, 8, 3, "final", 0], "sysPrefix": "path", "version ": "3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:37:02) [MSC v.1924 64 bit (AMD64)]", "is64Bit": true}' ,
37
+ '{"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}' ,
32
38
} ) ;
33
39
} ) ,
34
40
) ;
35
41
} ) ;
42
+
36
43
teardown ( ( ) => {
37
44
stubShellExec . restore ( ) ;
38
45
} ) ;
39
46
40
- test ( 'Iterator only yields unique environments' , async ( ) => {
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
+ test ( 'Iterator only yields as-is' , async ( ) => {
41
57
const env1 = createEnv ( 'env1' , '3.5.12b1' , PythonEnvKind . Venv , path . join ( 'path' , 'to' , 'exec1' ) ) ;
42
58
const env2 = createEnv ( 'env2' , '3.8.1' , PythonEnvKind . Conda , path . join ( 'path' , 'to' , 'exec2' ) ) ;
43
59
const env3 = createEnv ( 'env3' , '2.7' , PythonEnvKind . System , path . join ( 'path' , 'to' , 'exec3' ) ) ;
44
- const env4 = createEnv ( 'env4' , '3.9.0rc2' , PythonEnvKind . Unknown , path . join ( 'path' , 'to' , 'exec2' ) ) ; // Same as env2
45
- const env5 = createEnv ( 'env5' , '3.8' , PythonEnvKind . Venv , path . join ( 'path' , 'to' , 'exec1' ) ) ; // Same as env1
46
- const environmentsToBeIterated = [ env1 , env2 , env3 , env4 , env5 ] ; // Contains 3 unique environments
60
+ const env4 = createEnv ( 'env4' , '3.9.0rc2' , PythonEnvKind . Unknown , path . join ( 'path' , 'to' , 'exec2' ) ) ;
61
+ const environmentsToBeIterated = [ env1 , env2 , env3 , env4 ] ;
47
62
const pythonEnvManager = new SimpleLocator ( environmentsToBeIterated ) ;
48
63
const reducer = new PythonEnvsResolver ( pythonEnvManager , envService ) ;
49
64
50
65
const iterator = reducer . iterEnvs ( ) ;
51
66
const envs = await getEnvs ( iterator ) ;
52
67
53
- const expected = [ env1 , env2 , env3 ] ;
54
- assert . deepEqual ( envs , expected ) ;
68
+ assert . deepEqual ( envs , environmentsToBeIterated ) ;
55
69
} ) ;
56
70
57
- test ( 'Single updates for multiple environments are sent correctly followed by the null event' , async ( ) => {
71
+ test ( 'Updates for environments are sent correctly followed by the null event' , async ( ) => {
58
72
// Arrange
59
73
const env1 = createEnv ( 'env1' , '3.5.12b1' , PythonEnvKind . Unknown , path . join ( 'path' , 'to' , 'exec1' ) ) ;
60
74
const env2 = createEnv ( 'env2' , '3.8.1' , PythonEnvKind . Unknown , path . join ( 'path' , 'to' , 'exec2' ) ) ;
61
- const env3 = createEnv ( 'env3' , '2.7' , PythonEnvKind . System , path . join ( 'path' , 'to' , 'exec3' ) ) ;
62
- const env4 = createEnv ( 'env4' , '3.9.0rc2' , PythonEnvKind . Conda , path . join ( 'path' , 'to' , 'exec2' ) ) ; // Same as env2;
63
- const env5 = createEnv ( 'env5' , '3.8' , PythonEnvKind . Venv , path . join ( 'path' , 'to' , 'exec1' ) ) ; // Same as env1;
64
- const environmentsToBeIterated = [ env1 , env2 , env3 , env4 , env5 ] ; // Contains 3 unique environments
75
+ const environmentsToBeIterated = [ env1 , env2 ] ;
65
76
const pythonEnvManager = new SimpleLocator ( environmentsToBeIterated ) ;
66
77
const onUpdatedEvents : ( PythonEnvUpdatedEvent | null ) [ ] = [ ] ;
67
78
const reducer = new PythonEnvsResolver ( pythonEnvManager , envService ) ;
@@ -84,54 +95,18 @@ suite('Environments Reducer', () => {
84
95
85
96
// Assert
86
97
const expectedUpdates = [
87
- { old : env2 , new : mergeEnvironments ( env2 , env4 ) } ,
88
- { old : env1 , new : mergeEnvironments ( env1 , env5 ) } ,
98
+ { old : env1 , new : createExpectedEnvInfo ( env1 ) } ,
99
+ { old : env2 , new : createExpectedEnvInfo ( env2 ) } ,
89
100
null ,
90
101
] ;
91
102
assert . deepEqual ( expectedUpdates , onUpdatedEvents ) ;
92
103
} ) ;
93
104
94
- test ( 'Multiple updates for the same environment are sent correctly followed by the null event' , async ( ) => {
105
+ test ( 'Updates to environments from the incoming iterator are sent correctly followed by the null event' , async ( ) => {
95
106
// Arrange
96
- const env1 = createEnv ( 'env1' , '3.8' , PythonEnvKind . Unknown , path . join ( 'path' , 'to' , 'exec' ) ) ;
97
- const env2 = createEnv ( 'env2' , '3.8.1' , PythonEnvKind . System , path . join ( 'path' , 'to' , 'exec' ) ) ;
98
- const env3 = createEnv ( 'env3' , '3.8.1' , PythonEnvKind . Conda , path . join ( 'path' , 'to' , 'exec' ) ) ;
99
- const environmentsToBeIterated = [ env1 , env2 , env3 ] ; // All refer to the same environment
100
- const pythonEnvManager = new SimpleLocator ( environmentsToBeIterated ) ;
101
- const onUpdatedEvents : ( PythonEnvUpdatedEvent | null ) [ ] = [ ] ;
102
- const reducer = new PythonEnvsResolver ( pythonEnvManager , envService ) ;
103
-
104
- const iterator = reducer . iterEnvs ( ) ; // Act
105
-
106
- // Assert
107
- let { onUpdated } = iterator ;
108
- expect ( onUpdated ) . to . not . equal ( undefined , '' ) ;
109
-
110
- // Arrange
111
- onUpdated = onUpdated ! ;
112
- onUpdated ( ( e ) => {
113
- onUpdatedEvents . push ( e ) ;
114
- } ) ;
115
-
116
- // Act
117
- await getEnvs ( iterator ) ;
118
- await sleep ( 1 ) ; // Resolve pending calls in the background
119
-
120
- // Assert
121
- const env12 = mergeEnvironments ( env1 , env2 ) ;
122
- const expectedUpdates = [
123
- { old : env1 , new : env12 } ,
124
- { old : env12 , new : mergeEnvironments ( env12 , env3 ) } ,
125
- null ,
126
- ] ;
127
- assert . deepEqual ( expectedUpdates , onUpdatedEvents ) ;
128
- } ) ;
129
-
130
- test ( 'Updates to environments from the incoming iterator are passed on correctly followed by the null event' , async ( ) => {
131
- // Arrange
132
- const env1 = createEnv ( 'env1' , '3.8' , PythonEnvKind . Unknown , path . join ( 'path' , 'to' , 'exec' ) ) ;
133
- const env2 = createEnv ( 'env2' , '3.8.1' , PythonEnvKind . System , path . join ( 'path' , 'to' , 'exec' ) ) ;
134
- const environmentsToBeIterated = [ env1 ] ;
107
+ const env = createEnv ( 'env1' , '3.8' , PythonEnvKind . Unknown , path . join ( 'path' , 'to' , 'exec' ) ) ;
108
+ const updatedEnv = createEnv ( 'env1' , '3.8.1' , PythonEnvKind . System , path . join ( 'path' , 'to' , 'exec' ) ) ;
109
+ const environmentsToBeIterated = [ env ] ;
135
110
const didUpdate = new EventEmitter < PythonEnvUpdatedEvent | null > ( ) ;
136
111
const pythonEnvManager = new SimpleLocator ( environmentsToBeIterated , { onUpdated : didUpdate . event } ) ;
137
112
const onUpdatedEvents : ( PythonEnvUpdatedEvent | null ) [ ] = [ ] ;
@@ -151,13 +126,16 @@ suite('Environments Reducer', () => {
151
126
152
127
// Act
153
128
await getEnvs ( iterator ) ;
154
- didUpdate . fire ( { old : env1 , new : env2 } ) ;
129
+ await sleep ( 1 ) ;
130
+ didUpdate . fire ( { old : env , new : updatedEnv } ) ;
155
131
didUpdate . fire ( null ) ; // It is essential for the incoming iterator to fire "null" event signifying it's done
156
132
await sleep ( 1 ) ;
157
133
158
134
// Assert
159
- const expectedUpdates = [ { old : env1 , new : mergeEnvironments ( env1 , env2 ) } , null ] ;
160
- assert . deepEqual ( expectedUpdates , onUpdatedEvents ) ;
135
+ // The updates can be anything, even the number of updates, but they should lead to the same final state
136
+ const { length } = onUpdatedEvents ;
137
+ assert . deepEqual ( onUpdatedEvents [ length - 2 ] ?. new , createExpectedEnvInfo ( updatedEnv ) , 'The final update to environment is incorrect' ) ;
138
+ assert . equal ( onUpdatedEvents [ length - 1 ] , null , 'Last update should be null' ) ;
161
139
didUpdate . dispose ( ) ;
162
140
} ) ;
163
141
} ) ;
0 commit comments