@@ -59,6 +59,12 @@ interface IOLog {
59
59
path : string ;
60
60
result ?: string ;
61
61
} [ ] ;
62
+ directoriesRead : {
63
+ path : string ,
64
+ extension : string ,
65
+ exclude : string [ ] ,
66
+ result : string [ ]
67
+ } [ ] ;
62
68
}
63
69
64
70
interface PlaybackControl {
@@ -95,12 +101,15 @@ module Playback {
95
101
96
102
export interface PlaybackIO extends Harness . IO , PlaybackControl { }
97
103
104
+ export interface PlaybackSystem extends ts . System , PlaybackControl { }
105
+
98
106
function createEmptyLog ( ) : IOLog {
99
107
return {
100
108
timestamp : ( new Date ( ) ) . toString ( ) ,
101
109
arguments : [ ] ,
102
110
currentDirectory : "" ,
103
111
filesRead : [ ] ,
112
+ directoriesRead : [ ] ,
104
113
filesWritten : [ ] ,
105
114
filesDeleted : [ ] ,
106
115
filesAppended : [ ] ,
@@ -114,8 +123,10 @@ module Playback {
114
123
} ;
115
124
}
116
125
117
- function initWrapper < T > ( wrapper : PlaybackControl , underlying : T ) {
118
- Object . keys ( underlying ) . forEach ( prop => {
126
+ function initWrapper ( wrapper : PlaybackSystem , underlying : ts . System ) : void ;
127
+ function initWrapper ( wrapper : PlaybackIO , underlying : Harness . IO ) : void ;
128
+ function initWrapper ( wrapper : PlaybackSystem | PlaybackIO , underlying : ts . System | Harness . IO ) : void {
129
+ ts . forEach ( Object . keys ( underlying ) , prop => {
119
130
( < any > wrapper ) [ prop ] = ( < any > underlying ) [ prop ] ;
120
131
} ) ;
121
132
@@ -135,6 +146,93 @@ module Playback {
135
146
wrapper . startRecord = ( fileNameBase ) => {
136
147
recordLogFileNameBase = fileNameBase ;
137
148
recordLog = createEmptyLog ( ) ;
149
+
150
+ if ( typeof underlying . args !== "function" ) {
151
+ recordLog . arguments = < string [ ] > underlying . args ;
152
+ }
153
+ } ;
154
+
155
+ wrapper . startReplayFromFile = logFn => {
156
+ wrapper . startReplayFromString ( underlying . readFile ( logFn ) ) ;
157
+ } ;
158
+ wrapper . endRecord = ( ) => {
159
+ if ( recordLog !== undefined ) {
160
+ let i = 0 ;
161
+ let fn = ( ) => recordLogFileNameBase + i + ".json" ;
162
+ while ( underlying . fileExists ( fn ( ) ) ) i ++ ;
163
+ underlying . writeFile ( fn ( ) , JSON . stringify ( recordLog ) ) ;
164
+ recordLog = undefined ;
165
+ }
166
+ } ;
167
+
168
+ wrapper . fileExists = recordReplay ( wrapper . fileExists , underlying ) (
169
+ path => callAndRecord ( underlying . fileExists ( path ) , recordLog . fileExists , { path } ) ,
170
+ memoize ( path => {
171
+ // If we read from the file, it must exist
172
+ if ( findResultByPath ( wrapper , replayLog . filesRead , path , null ) !== null ) {
173
+ return true ;
174
+ }
175
+ else {
176
+ return findResultByFields ( replayLog . fileExists , { path } , false ) ;
177
+ }
178
+ } )
179
+ ) ;
180
+
181
+ wrapper . getExecutingFilePath = ( ) => {
182
+ if ( replayLog !== undefined ) {
183
+ return replayLog . executingPath ;
184
+ }
185
+ else if ( recordLog !== undefined ) {
186
+ return recordLog . executingPath = underlying . getExecutingFilePath ( ) ;
187
+ }
188
+ else {
189
+ return underlying . getExecutingFilePath ( ) ;
190
+ }
191
+ } ;
192
+
193
+ wrapper . getCurrentDirectory = ( ) => {
194
+ if ( replayLog !== undefined ) {
195
+ return replayLog . currentDirectory || "" ;
196
+ }
197
+ else if ( recordLog !== undefined ) {
198
+ return recordLog . currentDirectory = underlying . getCurrentDirectory ( ) ;
199
+ }
200
+ else {
201
+ return underlying . getCurrentDirectory ( ) ;
202
+ }
203
+ } ;
204
+
205
+ wrapper . resolvePath = recordReplay ( wrapper . resolvePath , underlying ) (
206
+ path => callAndRecord ( underlying . resolvePath ( path ) , recordLog . pathsResolved , { path } ) ,
207
+ memoize ( path => findResultByFields ( replayLog . pathsResolved , { path } , ! ts . isRootedDiskPath ( ts . normalizeSlashes ( path ) ) && replayLog . currentDirectory ? replayLog . currentDirectory + "/" + path : ts . normalizeSlashes ( path ) ) ) ) ;
208
+
209
+ wrapper . readFile = recordReplay ( wrapper . readFile , underlying ) (
210
+ path => {
211
+ let result = underlying . readFile ( path ) ;
212
+ let logEntry = { path, codepage : 0 , result : { contents : result , codepage : 0 } } ;
213
+ recordLog . filesRead . push ( logEntry ) ;
214
+ return result ;
215
+ } ,
216
+ memoize ( path => findResultByPath ( wrapper , replayLog . filesRead , path ) . contents ) ) ;
217
+
218
+ wrapper . readDirectory = recordReplay ( wrapper . readDirectory , underlying ) (
219
+ ( path , extension , exclude ) => {
220
+ let result = ( < ts . System > underlying ) . readDirectory ( path , extension , exclude ) ;
221
+ let logEntry = { path, extension, exclude, result } ;
222
+ recordLog . directoriesRead . push ( logEntry ) ;
223
+ return result ;
224
+ } ,
225
+ ( path , extension , exclude ) => findResultByPath ( wrapper , replayLog . directoriesRead . filter ( d => d . extension === extension && ts . arrayIsEqualTo ( d . exclude , exclude ) ) , path ) ) ;
226
+
227
+ wrapper . writeFile = recordReplay ( wrapper . writeFile , underlying ) (
228
+ ( path , contents ) => callAndRecord ( underlying . writeFile ( path , contents ) , recordLog . filesWritten , { path, contents, bom : false } ) ,
229
+ ( path , contents ) => noOpReplay ( "writeFile" ) ) ;
230
+
231
+ wrapper . exit = ( exitCode ) => {
232
+ if ( recordLog !== undefined ) {
233
+ wrapper . endRecord ( ) ;
234
+ }
235
+ underlying . exit ( exitCode ) ;
138
236
} ;
139
237
}
140
238
@@ -143,9 +241,11 @@ module Playback {
143
241
return < any > ( function ( ) {
144
242
if ( replayLog !== undefined ) {
145
243
return replay . apply ( undefined , arguments ) ;
146
- } else if ( recordLog !== undefined ) {
244
+ }
245
+ else if ( recordLog !== undefined ) {
147
246
return record . apply ( undefined , arguments ) ;
148
- } else {
247
+ }
248
+ else {
149
249
return original . apply ( underlying , arguments ) ;
150
250
}
151
251
} ) ;
@@ -169,15 +269,16 @@ module Playback {
169
269
if ( results . length === 0 ) {
170
270
if ( defaultValue !== undefined ) {
171
271
return defaultValue ;
172
- } else {
272
+ }
273
+ else {
173
274
throw new Error ( "No matching result in log array for: " + JSON . stringify ( expectedFields ) ) ;
174
275
}
175
276
}
176
277
return results [ 0 ] . result ;
177
278
}
178
279
179
280
function findResultByPath < T > ( wrapper : { resolvePath ( s : string ) : string } , logArray : { path : string ; result ?: T } [ ] , expectedPath : string , defaultValue ?: T ) : T {
180
- let normalizedName = ts . normalizeSlashes ( expectedPath ) . toLowerCase ( ) ;
281
+ let normalizedName = ts . normalizePath ( expectedPath ) . toLowerCase ( ) ;
181
282
// Try to find the result through normal fileName
182
283
for ( let i = 0 ; i < logArray . length ; i ++ ) {
183
284
if ( ts . normalizeSlashes ( logArray [ i ] . path ) . toLowerCase ( ) === normalizedName ) {
@@ -193,10 +294,12 @@ module Playback {
193
294
}
194
295
}
195
296
}
297
+
196
298
// If we got here, we didn't find a match
197
299
if ( defaultValue === undefined ) {
198
300
throw new Error ( "No matching result in log array for path: " + expectedPath ) ;
199
- } else {
301
+ }
302
+ else {
200
303
return defaultValue ;
201
304
}
202
305
}
@@ -214,7 +317,8 @@ module Playback {
214
317
}
215
318
if ( pathEquivCache . hasOwnProperty ( key ) ) {
216
319
return pathEquivCache [ key ] ;
217
- } else {
320
+ }
321
+ else {
218
322
return pathEquivCache [ key ] = check ( ) ;
219
323
}
220
324
}
@@ -227,93 +331,18 @@ module Playback {
227
331
let wrapper : PlaybackIO = < any > { } ;
228
332
initWrapper ( wrapper , underlying ) ;
229
333
230
- wrapper . startReplayFromFile = logFn => {
231
- wrapper . startReplayFromString ( underlying . readFile ( logFn ) ) ;
232
- } ;
233
- wrapper . endRecord = ( ) => {
234
- if ( recordLog !== undefined ) {
235
- let i = 0 ;
236
- let fn = ( ) => recordLogFileNameBase + i + ".json" ;
237
- while ( underlying . fileExists ( fn ( ) ) ) i ++ ;
238
- underlying . writeFile ( fn ( ) , JSON . stringify ( recordLog ) ) ;
239
- recordLog = undefined ;
240
- }
241
- } ;
242
-
243
- wrapper . args = ( ) => {
244
- if ( replayLog !== undefined ) {
245
- return replayLog . arguments ;
246
- } else if ( recordLog !== undefined ) {
247
- recordLog . arguments = underlying . args ( ) ;
248
- }
249
- return underlying . args ( ) ;
250
- }
251
-
252
- wrapper . newLine = ( ) => underlying . newLine ( ) ;
253
- wrapper . useCaseSensitiveFileNames = ( ) => underlying . useCaseSensitiveFileNames ( ) ;
254
334
wrapper . directoryName = ( path ) : string => { throw new Error ( "NotSupported" ) ; } ;
255
- wrapper . createDirectory = path => { throw new Error ( "NotSupported" ) ; } ;
335
+ wrapper . createDirectory = ( path ) : void => { throw new Error ( "NotSupported" ) ; } ;
256
336
wrapper . directoryExists = ( path ) : boolean => { throw new Error ( "NotSupported" ) ; } ;
257
- wrapper . deleteFile = path => { throw new Error ( "NotSupported" ) ; } ;
337
+ wrapper . deleteFile = ( path ) : void => { throw new Error ( "NotSupported" ) ; } ;
258
338
wrapper . listFiles = ( path , filter , options ) : string [ ] => { throw new Error ( "NotSupported" ) ; } ;
259
- wrapper . log = text => underlying . log ( text ) ;
260
-
261
- wrapper . fileExists = recordReplay ( wrapper . fileExists , underlying ) (
262
- ( path ) => callAndRecord ( underlying . fileExists ( path ) , recordLog . fileExists , { path : path } ) ,
263
- memoize ( ( path ) => {
264
- // If we read from the file, it must exist
265
- if ( findResultByPath ( wrapper , replayLog . filesRead , path , null ) !== null ) {
266
- return true ;
267
- } else {
268
- return findResultByFields ( replayLog . fileExists , { path : path } , false ) ;
269
- }
270
- } )
271
- ) ;
272
-
273
- wrapper . getExecutingFilePath = ( ) => {
274
- if ( replayLog !== undefined ) {
275
- return replayLog . executingPath ;
276
- } else if ( recordLog !== undefined ) {
277
- return recordLog . executingPath = underlying . getExecutingFilePath ( ) ;
278
- } else {
279
- return underlying . getExecutingFilePath ( ) ;
280
- }
281
- } ;
282
339
283
- wrapper . getCurrentDirectory = ( ) => {
284
- if ( replayLog !== undefined ) {
285
- return replayLog . currentDirectory || "" ;
286
- } else if ( recordLog !== undefined ) {
287
- return recordLog . currentDirectory = underlying . getCurrentDirectory ( ) ;
288
- } else {
289
- return underlying . getCurrentDirectory ( ) ;
290
- }
291
- } ;
292
-
293
- wrapper . resolvePath = recordReplay ( wrapper . resolvePath , underlying ) (
294
- ( path ) => callAndRecord ( underlying . resolvePath ( path ) , recordLog . pathsResolved , { path : path } ) ,
295
- memoize ( ( path ) => findResultByFields ( replayLog . pathsResolved , { path : path } , ! ts . isRootedDiskPath ( ts . normalizeSlashes ( path ) ) && replayLog . currentDirectory ? replayLog . currentDirectory + "/" + path : ts . normalizeSlashes ( path ) ) ) ) ;
296
-
297
- wrapper . readFile = recordReplay ( wrapper . readFile , underlying ) (
298
- ( path ) => {
299
- let result = underlying . readFile ( path ) ;
300
- let logEntry = { path : path , codepage : 0 , result : { contents : result , codepage : 0 } } ;
301
- recordLog . filesRead . push ( logEntry ) ;
302
- return result ;
303
- } ,
304
- memoize ( ( path ) => findResultByPath ( wrapper , replayLog . filesRead , path ) . contents ) ) ;
305
-
306
- wrapper . writeFile = recordReplay ( wrapper . writeFile , underlying ) (
307
- ( path , contents ) => callAndRecord ( underlying . writeFile ( path , contents ) , recordLog . filesWritten , { path : path , contents : contents , bom : false } ) ,
308
- ( path , contents ) => noOpReplay ( "writeFile" ) ) ;
309
-
310
- wrapper . exit = ( exitCode ) => {
311
- if ( recordLog !== undefined ) {
312
- wrapper . endRecord ( ) ;
313
- }
314
- underlying . exit ( exitCode ) ;
315
- } ;
340
+ return wrapper ;
341
+ }
316
342
343
+ export function wrapSystem ( underlying : ts . System ) : PlaybackSystem {
344
+ let wrapper : PlaybackSystem = < any > { } ;
345
+ initWrapper ( wrapper , underlying ) ;
317
346
return wrapper ;
318
347
}
319
348
}
0 commit comments