6
6
import * as ts from "../../_namespaces/ts" ;
7
7
import {
8
8
defer ,
9
+ Deferred ,
9
10
} from "../../_namespaces/Utils" ;
10
11
import {
11
12
createWatchedSystem ,
@@ -31,38 +32,39 @@ describe("unittests:: sys:: symlinkWatching::", () => {
31
32
it ( scenario , async ( ) => {
32
33
const fileResult = watchFile ( file ) ;
33
34
const linkResult = watchFile ( link ) ;
34
- delayedOp ( ( ) => sys . writeFile ( getFileName ?.( file ) ?? file , "export const x = 100;" ) ) ;
35
35
36
- // Should invoke on file as well as link
37
- await fileResult . deferred [ 0 ] . promise ;
38
- await linkResult . deferred [ 0 ] . promise ;
39
-
40
- delayedOp ( ( ) => sys . writeFile ( getFileName ?.( link ) ?? link , "export const x = 100;" ) ) ;
41
- // Should invoke on file as well as link
42
- await fileResult . deferred [ 1 ] . promise ;
43
- await linkResult . deferred [ 1 ] . promise ;
36
+ await writeFile ( file ) ;
37
+ await writeFile ( link ) ;
44
38
45
39
fileResult . watcher . close ( ) ;
46
40
linkResult . watcher . close ( ) ;
47
41
48
42
function watchFile ( toWatch : string ) {
49
- const deferred = [ defer ( ) , defer ( ) ] ;
50
- let indexForDefer = 0 ;
51
- return {
43
+ const result = {
52
44
watcher : sys . watchFile ! (
53
45
toWatch ,
54
46
( fileName , eventKind , modifiedTime ) => {
55
47
assert . equal ( fileName , toWatch ) ;
56
48
assert . equal ( eventKind , ts . FileWatcherEventKind . Changed ) ;
57
49
const actual = modifiedTimeToString ( modifiedTime ) ;
58
50
assert ( actual === undefined || actual === modifiedTimeToString ( sys . getModifiedTime ! ( file ) ) ) ;
59
- deferred [ indexForDefer ++ ] . resolve ( ) ;
51
+ result . deferred . resolve ( ) ;
60
52
} ,
61
53
10 ,
62
54
watchOptions ,
63
55
) ,
64
- deferred,
56
+ deferred : undefined ! as Deferred < void > ,
65
57
} ;
58
+ return result ;
59
+ }
60
+
61
+ async function writeFile ( onFile : string ) {
62
+ fileResult . deferred = defer ( ) ;
63
+ linkResult . deferred = defer ( ) ;
64
+ delayedOp ( ( ) => sys . writeFile ( getFileName ?.( onFile ) ?? onFile , "export const x = 100;" ) ) ;
65
+ // Should invoke on file as well as link
66
+ await fileResult . deferred . promise ;
67
+ await linkResult . deferred . promise ;
66
68
}
67
69
} ) ;
68
70
}
@@ -73,52 +75,140 @@ describe("unittests:: sys:: symlinkWatching::", () => {
73
75
link : string ,
74
76
fsWatch : ( dir : string , cb : ts . FsWatchCallback , sys : System ) => ts . FileWatcher ,
75
77
isMacOs : boolean ,
78
+ isWindows : boolean ,
76
79
) {
77
80
it ( `watchDirectory using fsEvents` , async ( ) => {
78
- const expectedEvent = [ "rename" , "change" , "rename" , "change" ] ;
79
- const expectedFileName = [ "file1.ts" , "file1.ts" , "file2.ts" , "file2.ts" ] ;
80
- const fileResult = watchDirectory ( dir ) ;
81
- const linkResult = watchDirectory ( link ) ;
82
- delayedOp ( ( ) => sys . writeFile ( `${ dir } /file1.ts` , "export const x = 100;" ) ) ;
83
-
84
- // Should invoke on file as well as link, rename and change
85
- await fileResult . deferred [ 0 ] . promise ;
86
- await linkResult . deferred [ 0 ] . promise ;
87
- if ( ! isMacOs ) {
88
- // MacOs does not get change events when new file is created
89
- await fileResult . deferred [ 1 ] . promise ;
90
- await linkResult . deferred [ 1 ] . promise ;
81
+ interface Expected {
82
+ indexForDefer : number ;
83
+ deferred : readonly Deferred < void > [ ] ;
84
+ expectedFileName : string ;
85
+ expectedEvent : string [ ] ;
91
86
}
92
-
93
- delayedOp ( ( ) => sys . writeFile ( `${ link } /file2.ts` , "export const x = 100;" ) ) ;
94
- // // Should invoke on file as well as link, rename and change
95
- await fileResult . deferred [ 2 ] . promise ;
96
- await linkResult . deferred [ 2 ] . promise ;
97
- if ( ! isMacOs ) {
98
- // MacOs does not get change events when new file is created
99
- await fileResult . deferred [ 3 ] . promise ;
100
- await linkResult . deferred [ 3 ] . promise ;
87
+ type ExpectedForOperation = Pick < Expected , "expectedEvent" | "expectedFileName" > ;
88
+ interface TableOfEvents {
89
+ fileCreate : ExpectedForOperation ;
90
+ linkFileCreate : ExpectedForOperation ;
91
+ fileChange : ExpectedForOperation ;
92
+ fileModifiedTimeChange : ExpectedForOperation ;
93
+ linkModifiedTimeChange : ExpectedForOperation ;
94
+ linkFileChange : ExpectedForOperation ;
95
+ fileDelete : ExpectedForOperation ;
96
+ linkFileDelete : ExpectedForOperation ;
101
97
}
102
- fileResult . watcher . close ( ) ;
98
+ const tableOfEvents : TableOfEvents = isMacOs ?
99
+ {
100
+ fileCreate : { expectedEvent : [ "rename" ] , expectedFileName : "file1.ts" } ,
101
+ linkFileCreate : { expectedEvent : [ "rename" ] , expectedFileName : "file2.ts" } ,
102
+ fileChange : { expectedEvent : [ "rename" ] , expectedFileName : "file1.ts" } ,
103
+ linkFileChange : { expectedEvent : [ "rename" ] , expectedFileName : "file2.ts" } ,
104
+ fileModifiedTimeChange : { expectedEvent : [ "rename" ] , expectedFileName : "file1.ts" } ,
105
+ linkModifiedTimeChange : { expectedEvent : [ "rename" ] , expectedFileName : "file2.ts" } ,
106
+ fileDelete : { expectedEvent : [ "rename" ] , expectedFileName : "file1.ts" } ,
107
+ linkFileDelete : { expectedEvent : [ "rename" ] , expectedFileName : "file2.ts" } ,
108
+ } :
109
+ isWindows ?
110
+ {
111
+ fileCreate : { expectedEvent : [ "rename" , "change" ] , expectedFileName : "file1.ts" } ,
112
+ linkFileCreate : { expectedEvent : [ "rename" , "change" ] , expectedFileName : "file2.ts" } ,
113
+ fileChange : { expectedEvent : [ "change" , "change" ] , expectedFileName : "file1.ts" } ,
114
+ linkFileChange : { expectedEvent : [ "change" , "change" ] , expectedFileName : "file2.ts" } ,
115
+ fileModifiedTimeChange : { expectedEvent : [ "change" ] , expectedFileName : "file1.ts" } ,
116
+ linkModifiedTimeChange : { expectedEvent : [ "change" ] , expectedFileName : "file2.ts" } ,
117
+ fileDelete : { expectedEvent : [ "rename" ] , expectedFileName : "file1.ts" } ,
118
+ linkFileDelete : { expectedEvent : [ "rename" ] , expectedFileName : "file2.ts" } ,
119
+ } :
120
+ {
121
+ fileCreate : { expectedEvent : [ "rename" , "change" ] , expectedFileName : "file1.ts" } ,
122
+ linkFileCreate : { expectedEvent : [ "rename" , "change" ] , expectedFileName : "file2.ts" } ,
123
+ fileChange : { expectedEvent : [ "change" ] , expectedFileName : "file1.ts" } ,
124
+ linkFileChange : { expectedEvent : [ "change" ] , expectedFileName : "file2.ts" } ,
125
+ fileModifiedTimeChange : { expectedEvent : [ "change" ] , expectedFileName : "file1.ts" } ,
126
+ linkModifiedTimeChange : { expectedEvent : [ "change" ] , expectedFileName : "file2.ts" } ,
127
+ fileDelete : { expectedEvent : [ "rename" ] , expectedFileName : "file1.ts" } ,
128
+ linkFileDelete : { expectedEvent : [ "rename" ] , expectedFileName : "file2.ts" } ,
129
+ } ;
130
+ const dirResult = watchDirectory ( dir ) ;
131
+ const linkResult = watchDirectory ( link ) ;
132
+
133
+ await operation ( "fileCreate" ) ;
134
+ await operation ( "linkFileCreate" ) ;
135
+
136
+ await operation ( "fileChange" ) ;
137
+ await operation ( "linkFileChange" ) ;
138
+
139
+ await operation ( "fileModifiedTimeChange" ) ;
140
+ await operation ( "linkModifiedTimeChange" ) ;
141
+
142
+ await operation ( "fileDelete" ) ;
143
+ await operation ( "linkFileDelete" ) ;
144
+
145
+ dirResult . watcher . close ( ) ;
103
146
linkResult . watcher . close ( ) ;
104
147
105
148
function watchDirectory ( dir : string ) {
106
- const deferred = [ defer ( ) , defer ( ) , defer ( ) , defer ( ) ] ;
107
- let indexForDefer = 0 ;
108
- return {
149
+ const result = {
109
150
dir,
110
151
watcher : fsWatch (
111
152
dir ,
112
153
( event , fileName ) => {
113
- assert . equal ( event , expectedEvent [ indexForDefer ] ) ;
114
- assert ( ! fileName || fileName === expectedFileName [ indexForDefer ] ) ;
115
- deferred [ indexForDefer ++ ] . resolve ( ) ;
116
- if ( isMacOs ) indexForDefer ++ ; // MacOs does not get change events when new file is created so skip that one
154
+ console . log ( dir , result . expected . indexForDefer , event , fileName ) ; // To ensure we can get the data on all OS
155
+ assert . equal ( event , result . expected . expectedEvent [ result . expected . indexForDefer ] ) ;
156
+ assert . equal ( fileName , result . expected . expectedFileName ) ;
157
+ result . expected . deferred [ result . expected . indexForDefer ++ ] . resolve ( ) ;
117
158
} ,
118
159
sys ,
119
160
) ,
120
- deferred ,
161
+ expected : undefined ! as Expected ,
121
162
} ;
163
+ return result ;
164
+ }
165
+
166
+ async function operation ( opType : keyof TableOfEvents ) {
167
+ const expected = tableOfEvents [ opType ] ;
168
+ console . log ( "" ) ;
169
+ console . log ( opType ) ;
170
+ dirResult . expected = {
171
+ indexForDefer : 0 ,
172
+ deferred : ts . arrayOf ( expected . expectedEvent . length , defer ) ,
173
+ ...expected ,
174
+ } ;
175
+ linkResult . expected = {
176
+ indexForDefer : 0 ,
177
+ deferred : ts . arrayOf ( expected . expectedEvent . length , defer ) ,
178
+ ...expected ,
179
+ } ;
180
+ let op ;
181
+ switch ( opType ) {
182
+ case "fileCreate" :
183
+ op = ( ) => sys . writeFile ( `${ dir } /file1.ts` , "export const x = 100;" ) ;
184
+ break ;
185
+ case "linkFileCreate" :
186
+ op = ( ) => sys . writeFile ( `${ link } /file2.ts` , "export const x = 100;" ) ;
187
+ break ;
188
+ case "fileChange" :
189
+ op = ( ) => sys . writeFile ( `${ dir } /file1.ts` , "export const x2 = 100;" ) ;
190
+ break ;
191
+ case "linkFileChange" :
192
+ op = ( ) => sys . writeFile ( `${ link } /file2.ts` , "export const x2 = 100;" ) ;
193
+ break ;
194
+ case "fileModifiedTimeChange" :
195
+ op = ( ) => sys . setModifiedTime ! ( `${ dir } /file1.ts` , new Date ( ) ) ;
196
+ break ;
197
+ case "linkModifiedTimeChange" :
198
+ op = ( ) => sys . setModifiedTime ! ( `${ link } /file2.ts` , new Date ( ) ) ;
199
+ break ;
200
+ case "fileDelete" :
201
+ op = ( ) => sys . deleteFile ! ( `${ dir } /file1.ts` ) ;
202
+ break ;
203
+ case "linkFileDelete" :
204
+ op = ( ) => sys . deleteFile ! ( `${ link } /file2.ts` ) ;
205
+ break ;
206
+ default :
207
+ ts . Debug . assertNever ( opType ) ;
208
+ }
209
+ delayedOp ( op ) ;
210
+ await Promise . all ( dirResult . expected . deferred . map ( d => d . promise ) ) ;
211
+ await Promise . all ( linkResult . expected . deferred . map ( d => d . promise ) ) ;
122
212
}
123
213
} ) ;
124
214
}
@@ -129,6 +219,8 @@ describe("unittests:: sys:: symlinkWatching::", () => {
129
219
130
220
describe ( "with ts.sys::" , ( ) => {
131
221
const root = ts . normalizePath ( IO . joinPath ( IO . getWorkspaceRoot ( ) , "tests/baselines/symlinks" ) ) ;
222
+ const isMacOs = process . platform === "darwin" ;
223
+ const isWindows = process . platform === "win32" ;
132
224
before ( ( ) => {
133
225
cleanup ( ) ;
134
226
ts . sys . writeFile ( `${ root } /polling/file.ts` , "export const x = 10;" ) ;
@@ -184,7 +276,8 @@ describe("unittests:: sys:: symlinkWatching::", () => {
184
276
`${ root } /dirfsevents` ,
185
277
`${ root } /linkeddirfsevents` ,
186
278
( dir , cb ) => fs . watch ( dir , { persistent : true } , cb ) ,
187
- process . platform === "darwin" ,
279
+ isMacOs ,
280
+ isWindows ,
188
281
) ;
189
282
} ) ;
190
283
@@ -220,21 +313,32 @@ describe("unittests:: sys:: symlinkWatching::", () => {
220
313
getFileName ( ) ,
221
314
) ;
222
315
223
- verifyWatchDirectoryUsingFsEvents (
224
- getSys ( ) ,
225
- `${ root } /folder` ,
226
- `${ root } /linked` ,
227
- ( dir , cb , sys ) => sys . fsWatchWorker ( dir , /*recursive*/ false , cb ) ,
228
- /*isMacOs*/ false ,
229
- ) ;
316
+ // TODO (sheetal) add test for each os behaviour
317
+ // verifyWatchDirectoryUsingFsEvents(
318
+ // getSys(),
319
+ // `${root}/folder`,
320
+ // `${root}/linked`,
321
+ // (dir, cb, sys) => sys.fsWatchWorker(dir, /*recursive*/ false, cb),
322
+ // /*isMacOs*/ false,
323
+ // /*isWindows*/ true,
324
+ // );
325
+
326
+ // verifyWatchDirectoryUsingFsEvents(
327
+ // getSys(),
328
+ // `${root}/folder`,
329
+ // `${root}/linked`,
330
+ // (dir, cb, sys) => sys.fsWatchWorker(dir, /*recursive*/ false, cb),
331
+ // /*isMacOs*/ true,
332
+ // /*isWindows*/ false,
333
+ // );
230
334
231
- // TODO (sheetal) add test for mac os behaviour so we have it on host to verify
232
335
// verifyWatchDirectoryUsingFsEvents(
233
336
// getSys(),
234
337
// `${root}/folder`,
235
338
// `${root}/linked`,
236
339
// (dir, cb, sys) => sys.fsWatchWorker(dir, /*recursive*/ false, cb),
237
- // /*isMacOs*/ true
340
+ // /*isMacOs*/ false,
341
+ // /*isWindows*/ false,
238
342
// );
239
343
} ) ;
240
344
} ) ;
0 commit comments