memfs 0.4.3 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +5 -0
- data/README.md +3 -2
- data/lib/memfs/dir.rb +2 -2
- data/lib/memfs/file_system.rb +4 -2
- data/lib/memfs/version.rb +1 -1
- data/spec/fileutils_spec.rb +229 -191
- data/spec/memfs/dir_spec.rb +109 -95
- data/spec/memfs/fake/directory_spec.rb +8 -8
- data/spec/memfs/fake/entry_spec.rb +3 -3
- data/spec/memfs/fake/file/content_spec.rb +3 -5
- data/spec/memfs/fake/symlink_spec.rb +11 -11
- data/spec/memfs/file/stat_spec.rb +14 -14
- data/spec/memfs/file_spec.rb +269 -269
- data/spec/memfs/file_system_spec.rb +12 -0
- data/spec/memfs_spec.rb +18 -20
- metadata +3 -3
data/spec/memfs/dir_spec.rb
CHANGED
@@ -2,56 +2,54 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module MemFs
|
4
4
|
describe Dir do
|
5
|
-
subject {
|
5
|
+
subject { described_class.new('/test') }
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
before { subject.mkdir '/test' }
|
7
|
+
before { described_class.mkdir '/test' }
|
10
8
|
|
11
9
|
it 'is Enumerable' do
|
12
|
-
expect(
|
10
|
+
expect(subject).to be_an(Enumerable)
|
13
11
|
end
|
14
12
|
|
15
13
|
describe '[]' do
|
16
14
|
context 'when a string is given' do
|
17
15
|
it 'acts like calling glob' do
|
18
|
-
expect(
|
16
|
+
expect(described_class['/*']).to eq %w[/tmp /test]
|
19
17
|
end
|
20
18
|
end
|
21
19
|
|
22
20
|
context 'when a list of strings is given' do
|
23
21
|
it 'acts like calling glob' do
|
24
|
-
expect(
|
22
|
+
expect(described_class['/tm*', '/te*']).to eq %w[/tmp /test]
|
25
23
|
end
|
26
24
|
end
|
27
25
|
end
|
28
26
|
|
29
27
|
describe '.chdir' do
|
30
28
|
it 'changes the current working directory' do
|
31
|
-
|
32
|
-
expect(
|
29
|
+
described_class.chdir '/test'
|
30
|
+
expect(described_class.getwd).to eq('/test')
|
33
31
|
end
|
34
32
|
|
35
33
|
it 'returns zero' do
|
36
|
-
expect(
|
34
|
+
expect(described_class.chdir('/test')).to be_zero
|
37
35
|
end
|
38
36
|
|
39
37
|
it 'raises an error when the folder does not exist' do
|
40
|
-
expect {
|
38
|
+
expect { described_class.chdir('/nowhere') }.to raise_error(Errno::ENOENT)
|
41
39
|
end
|
42
40
|
|
43
41
|
context 'when a block is given' do
|
44
42
|
it 'changes current working directory for the block' do
|
45
|
-
|
46
|
-
expect(
|
43
|
+
described_class.chdir '/test' do
|
44
|
+
expect(described_class.pwd).to eq('/test')
|
47
45
|
end
|
48
46
|
end
|
49
47
|
|
50
48
|
it 'gets back to previous directory once the block is finished' do
|
51
|
-
|
49
|
+
described_class.chdir '/'
|
52
50
|
expect {
|
53
|
-
|
54
|
-
}.to_not change {
|
51
|
+
described_class.chdir('/test') {}
|
52
|
+
}.to_not change { described_class.pwd }
|
55
53
|
end
|
56
54
|
end
|
57
55
|
end
|
@@ -61,27 +59,27 @@ module MemFs
|
|
61
59
|
|
62
60
|
it "changes the process's idea of the file system root" do
|
63
61
|
|
64
|
-
|
65
|
-
|
62
|
+
described_class.mkdir('/test/subdir')
|
63
|
+
described_class.chroot('/test')
|
66
64
|
|
67
65
|
expect(File.exist?('/subdir')).to be true
|
68
66
|
end
|
69
67
|
|
70
68
|
it 'returns zero' do
|
71
|
-
expect(
|
69
|
+
expect(described_class.chroot('/test')).to eq 0
|
72
70
|
end
|
73
71
|
|
74
72
|
context 'when the given path is a file' do
|
75
73
|
before { _fs.touch('/test/test-file') }
|
76
74
|
|
77
75
|
it 'raises an exception' do
|
78
|
-
expect {
|
76
|
+
expect { described_class.chroot('/test/test-file') }.to raise_error(Errno::ENOTDIR)
|
79
77
|
end
|
80
78
|
end
|
81
79
|
|
82
80
|
context "when the given path doesn't exist" do
|
83
81
|
it 'raises an exception' do
|
84
|
-
expect {
|
82
|
+
expect { described_class.chroot('/no-dir') }.to raise_error(Errno::ENOENT)
|
85
83
|
end
|
86
84
|
end
|
87
85
|
|
@@ -89,40 +87,42 @@ module MemFs
|
|
89
87
|
before { allow(Process).to receive_messages(uid: 42) }
|
90
88
|
|
91
89
|
it 'raises an exception' do
|
92
|
-
expect {
|
90
|
+
expect { described_class.chroot('/no-dir') }.to raise_error(Errno::EPERM)
|
93
91
|
end
|
94
92
|
end
|
95
93
|
end
|
96
94
|
|
97
95
|
describe '.delete' do
|
96
|
+
subject { described_class }
|
98
97
|
it_behaves_like 'aliased method', :delete, :rmdir
|
99
98
|
end
|
100
99
|
|
101
100
|
describe '.entries' do
|
102
101
|
it 'returns an array containing all of the filenames in the given directory' do
|
103
|
-
%w[/test/dir1 /test/dir2].each { |dir|
|
102
|
+
%w[/test/dir1 /test/dir2].each { |dir| described_class.mkdir dir }
|
104
103
|
_fs.touch '/test/file1', '/test/file2'
|
105
|
-
expect(
|
104
|
+
expect(described_class.entries('/test')).to eq(%w[. .. dir1 dir2 file1 file2])
|
106
105
|
end
|
107
106
|
end
|
108
107
|
|
109
108
|
describe '.exist?' do
|
109
|
+
subject { described_class }
|
110
110
|
it_behaves_like 'aliased method', :exist?, :exists?
|
111
111
|
end
|
112
112
|
|
113
113
|
describe '.exists?' do
|
114
114
|
it 'returns true if the given +path+ exists and is a directory' do
|
115
|
-
|
116
|
-
expect(
|
115
|
+
described_class.mkdir('/test-dir')
|
116
|
+
expect(described_class.exists?('/test-dir')).to be true
|
117
117
|
end
|
118
118
|
|
119
119
|
it 'returns false if the given +path+ does not exist' do
|
120
|
-
expect(
|
120
|
+
expect(described_class.exists?('/test-dir')).to be false
|
121
121
|
end
|
122
122
|
|
123
123
|
it 'returns false if the given +path+ is not a directory' do
|
124
124
|
_fs.touch('/test-file')
|
125
|
-
expect(
|
125
|
+
expect(described_class.exists?('/test-file')).to be false
|
126
126
|
end
|
127
127
|
end
|
128
128
|
|
@@ -134,26 +134,26 @@ module MemFs
|
|
134
134
|
context 'when a block is given' do
|
135
135
|
it 'calls the block once for each entry in the named directory' do
|
136
136
|
expect { |blk|
|
137
|
-
|
137
|
+
described_class.foreach('/test', &blk)
|
138
138
|
}.to yield_control.exactly(4).times
|
139
139
|
end
|
140
140
|
|
141
141
|
it 'passes each entry as a parameter to the block' do
|
142
142
|
expect { |blk|
|
143
|
-
|
143
|
+
described_class.foreach('/test', &blk)
|
144
144
|
}.to yield_successive_args('.', '..', 'test-file', 'test-file2')
|
145
145
|
end
|
146
146
|
|
147
147
|
context "and the directory doesn't exist" do
|
148
148
|
it 'raises an exception' do
|
149
|
-
expect {
|
149
|
+
expect { described_class.foreach('/no-dir') {} }.to raise_error
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
153
153
|
context 'and the given path is not a directory' do
|
154
154
|
it 'raises an exception' do
|
155
155
|
expect {
|
156
|
-
|
156
|
+
described_class.foreach('/test/test-file') {}
|
157
157
|
}.to raise_error
|
158
158
|
end
|
159
159
|
end
|
@@ -161,20 +161,20 @@ module MemFs
|
|
161
161
|
|
162
162
|
context 'when no block is given' do
|
163
163
|
it 'returns an enumerator' do
|
164
|
-
list =
|
164
|
+
list = described_class.foreach('/test-dir')
|
165
165
|
expect(list).to be_an(Enumerator)
|
166
166
|
end
|
167
167
|
|
168
168
|
context "and the directory doesn't exist" do
|
169
169
|
it 'returns an enumerator' do
|
170
|
-
list =
|
170
|
+
list = described_class.foreach('/no-dir')
|
171
171
|
expect(list).to be_an(Enumerator)
|
172
172
|
end
|
173
173
|
end
|
174
174
|
|
175
175
|
context 'and the given path is not a directory' do
|
176
176
|
it 'returns an enumerator' do
|
177
|
-
list =
|
177
|
+
list = described_class.foreach('/test-dir/test-file')
|
178
178
|
expect(list).to be_an(Enumerator)
|
179
179
|
end
|
180
180
|
end
|
@@ -183,7 +183,7 @@ module MemFs
|
|
183
183
|
|
184
184
|
describe '.getwd' do
|
185
185
|
it 'returns the path to the current working directory' do
|
186
|
-
expect(
|
186
|
+
expect(described_class.getwd).to eq(FileSystem.instance.getwd)
|
187
187
|
end
|
188
188
|
end
|
189
189
|
|
@@ -201,7 +201,7 @@ module MemFs
|
|
201
201
|
|
202
202
|
shared_examples 'returning matching filenames' do |pattern, filenames|
|
203
203
|
it "with #{pattern}" do
|
204
|
-
expect(
|
204
|
+
expect(described_class.glob(pattern)).to eq filenames
|
205
205
|
end
|
206
206
|
end
|
207
207
|
|
@@ -222,37 +222,37 @@ module MemFs
|
|
222
222
|
|
223
223
|
context 'when a flag is given' do
|
224
224
|
it 'uses it to compare filenames' do
|
225
|
-
expect(
|
225
|
+
expect(described_class.glob('/TEST*', File::FNM_CASEFOLD)).to eq \
|
226
226
|
%w[/test0 /test1 /test2]
|
227
227
|
end
|
228
228
|
end
|
229
229
|
|
230
230
|
context 'when a block is given' do
|
231
231
|
it 'calls the block with every matching filenames' do
|
232
|
-
expect { |blk|
|
232
|
+
expect { |blk| described_class.glob('/test*', &blk) }.to \
|
233
233
|
yield_successive_args('/test0', '/test1', '/test2')
|
234
234
|
end
|
235
235
|
|
236
236
|
it 'returns nil' do
|
237
|
-
expect(
|
237
|
+
expect(described_class.glob('/*') {}).to be nil
|
238
238
|
end
|
239
239
|
end
|
240
240
|
|
241
241
|
context 'when pattern is an array of patterns' do
|
242
242
|
it 'returns the list of files matching any pattern' do
|
243
|
-
expect(
|
243
|
+
expect(described_class.glob(['/*0', '/*1'])).to eq %w[/test0 /test1]
|
244
244
|
end
|
245
245
|
end
|
246
246
|
end
|
247
247
|
|
248
248
|
describe '.home' do
|
249
249
|
it 'returns the home directory of the current user' do
|
250
|
-
expect(
|
250
|
+
expect(described_class.home).to eq ENV['HOME']
|
251
251
|
end
|
252
252
|
|
253
253
|
context 'when a username is given' do
|
254
254
|
it 'returns the home directory of the given user' do
|
255
|
-
home_dir =
|
255
|
+
home_dir = described_class.home(ENV['USER'])
|
256
256
|
expect(home_dir).to eq ENV['HOME']
|
257
257
|
end
|
258
258
|
end
|
@@ -260,13 +260,25 @@ module MemFs
|
|
260
260
|
|
261
261
|
describe '.mkdir' do
|
262
262
|
it 'creates a directory' do
|
263
|
-
|
263
|
+
described_class.mkdir '/new-folder'
|
264
264
|
expect(File.directory?('/new-folder')).to be true
|
265
265
|
end
|
266
266
|
|
267
|
+
it 'sets directory permissions to default 0777' do
|
268
|
+
described_class.mkdir '/new-folder'
|
269
|
+
expect(File.stat('/new-folder').mode).to eq(0100777)
|
270
|
+
end
|
271
|
+
|
272
|
+
context 'when permissions are specified' do
|
273
|
+
it 'sets directory permissions to specified value' do
|
274
|
+
described_class.mkdir '/new-folder', 0644
|
275
|
+
expect(File.stat('/new-folder').mode).to eq(0100644)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
267
279
|
context 'when the directory already exist' do
|
268
280
|
it 'raises an exception' do
|
269
|
-
expect {
|
281
|
+
expect { described_class.mkdir('/') }.to raise_error(Errno::EEXIST)
|
270
282
|
end
|
271
283
|
end
|
272
284
|
end
|
@@ -274,29 +286,29 @@ module MemFs
|
|
274
286
|
describe '.open' do
|
275
287
|
context 'when no block is given' do
|
276
288
|
it 'returns the opened directory' do
|
277
|
-
expect(
|
289
|
+
expect(described_class.open('/test')).to be_a(Dir)
|
278
290
|
end
|
279
291
|
end
|
280
292
|
|
281
293
|
context 'when a block is given' do
|
282
294
|
it 'calls the block with the opened directory as argument' do
|
283
|
-
expect { |blk|
|
295
|
+
expect { |blk| described_class.open('/test', &blk) }.to yield_with_args(Dir)
|
284
296
|
end
|
285
297
|
|
286
298
|
it 'returns nil' do
|
287
|
-
expect(
|
299
|
+
expect(described_class.open('/test') {}).to be_nil
|
288
300
|
end
|
289
301
|
|
290
302
|
it 'ensures the directory is closed' do
|
291
303
|
dir = nil
|
292
|
-
|
304
|
+
described_class.open('/test') { |d| dir = d }
|
293
305
|
expect { dir.close }.to raise_error(IOError)
|
294
306
|
end
|
295
307
|
end
|
296
308
|
|
297
309
|
context "when the given directory doesn't exist" do
|
298
310
|
it 'raises an exception' do
|
299
|
-
expect {
|
311
|
+
expect { described_class.open('/no-dir') }.to raise_error
|
300
312
|
end
|
301
313
|
end
|
302
314
|
|
@@ -304,7 +316,7 @@ module MemFs
|
|
304
316
|
before { _fs.touch('/test/test-file') }
|
305
317
|
|
306
318
|
it 'raises an exception' do
|
307
|
-
expect {
|
319
|
+
expect { described_class.open('/test/test-file') }.to raise_error
|
308
320
|
end
|
309
321
|
end
|
310
322
|
end
|
@@ -312,7 +324,7 @@ module MemFs
|
|
312
324
|
describe '.new' do
|
313
325
|
context "when the given directory doesn't exist" do
|
314
326
|
it 'raises an exception' do
|
315
|
-
expect {
|
327
|
+
expect { described_class.new('/no-dir') }.to raise_error
|
316
328
|
end
|
317
329
|
end
|
318
330
|
|
@@ -320,44 +332,46 @@ module MemFs
|
|
320
332
|
before { _fs.touch('/test/test-file') }
|
321
333
|
|
322
334
|
it 'raises an exception' do
|
323
|
-
expect {
|
335
|
+
expect { described_class.new('/test/test-file') }.to raise_error
|
324
336
|
end
|
325
337
|
end
|
326
338
|
end
|
327
339
|
|
328
340
|
describe '.pwd' do
|
341
|
+
subject { described_class }
|
329
342
|
it_behaves_like 'aliased method', :pwd, :getwd
|
330
343
|
end
|
331
344
|
|
332
345
|
describe '.rmdir' do
|
333
346
|
it 'deletes the named directory' do
|
334
|
-
|
335
|
-
|
336
|
-
expect(
|
347
|
+
described_class.mkdir('/test-dir')
|
348
|
+
described_class.rmdir('/test-dir')
|
349
|
+
expect(described_class.exists?('/test-dir')).to be false
|
337
350
|
end
|
338
351
|
|
339
352
|
context 'when the directory is not empty' do
|
340
353
|
it 'raises an exception' do
|
341
|
-
|
342
|
-
|
343
|
-
expect {
|
354
|
+
described_class.mkdir('/test-dir')
|
355
|
+
described_class.mkdir('/test-dir/test-sub-dir')
|
356
|
+
expect { described_class.rmdir('/test-dir') }.to raise_error(Errno::ENOTEMPTY)
|
344
357
|
end
|
345
358
|
end
|
346
359
|
end
|
347
360
|
|
348
361
|
describe '.tmpdir' do
|
349
362
|
it 'returns /tmp' do
|
350
|
-
expect(
|
363
|
+
expect(described_class.tmpdir).to eq '/tmp'
|
351
364
|
end
|
352
365
|
end
|
353
366
|
|
354
367
|
describe '.unlink' do
|
368
|
+
subject { described_class }
|
355
369
|
it_behaves_like 'aliased method', :unlink, :rmdir
|
356
370
|
end
|
357
371
|
|
358
372
|
describe '#close' do
|
359
373
|
it 'closes the directory' do
|
360
|
-
dir =
|
374
|
+
dir = described_class.open('/test')
|
361
375
|
dir.close
|
362
376
|
expect { dir.close }.to raise_error(IOError)
|
363
377
|
end
|
@@ -367,58 +381,58 @@ module MemFs
|
|
367
381
|
before { _fs.touch('/test/test-file', '/test/test-file2') }
|
368
382
|
|
369
383
|
it 'calls the block once for each entry in this directory' do
|
370
|
-
expect { |blk|
|
384
|
+
expect { |blk| subject.each(&blk) }.to yield_control.exactly(4).times
|
371
385
|
end
|
372
386
|
|
373
387
|
it 'passes the filename of each entry as a parameter to the block' do
|
374
388
|
expect { |blk|
|
375
|
-
|
389
|
+
subject.each(&blk)
|
376
390
|
}.to yield_successive_args('.', '..', 'test-file', 'test-file2')
|
377
391
|
end
|
378
392
|
|
379
393
|
context 'when no block is given' do
|
380
394
|
it 'returns an enumerator' do
|
381
|
-
expect(
|
395
|
+
expect(subject.each).to be_an(Enumerator)
|
382
396
|
end
|
383
397
|
end
|
384
398
|
end
|
385
399
|
|
386
400
|
describe '#path' do
|
387
401
|
it "returns the path parameter passed to dir's constructor" do
|
388
|
-
expect(
|
402
|
+
expect(subject.path).to eq '/test'
|
389
403
|
end
|
390
404
|
end
|
391
405
|
|
392
406
|
describe '#pos' do
|
393
407
|
it 'returns the current position in dir' do
|
394
|
-
3.times {
|
395
|
-
expect(
|
408
|
+
3.times { subject.read }
|
409
|
+
expect(subject.pos).to eq 3
|
396
410
|
end
|
397
411
|
end
|
398
412
|
|
399
413
|
describe '#pos=' do
|
400
|
-
before { 3.times {
|
414
|
+
before { 3.times { subject.read } }
|
401
415
|
|
402
416
|
it 'seeks to a particular location in dir' do
|
403
|
-
|
404
|
-
expect(
|
417
|
+
subject.pos = 1
|
418
|
+
expect(subject.pos).to eq 1
|
405
419
|
end
|
406
420
|
|
407
421
|
it 'returns the given position' do
|
408
|
-
expect(
|
422
|
+
expect(subject.pos = 2).to eq 2
|
409
423
|
end
|
410
424
|
|
411
425
|
context 'when the location has not been seeked yet' do
|
412
426
|
it "doesn't change the location" do
|
413
|
-
|
414
|
-
expect(
|
427
|
+
subject.pos = 42
|
428
|
+
expect(subject.pos).to eq 3
|
415
429
|
end
|
416
430
|
end
|
417
431
|
|
418
432
|
context 'when the location is negative' do
|
419
433
|
it "doesn't change the location" do
|
420
|
-
|
421
|
-
expect(
|
434
|
+
subject.pos = -1
|
435
|
+
expect(subject.pos).to eq 3
|
422
436
|
end
|
423
437
|
end
|
424
438
|
end
|
@@ -430,73 +444,73 @@ module MemFs
|
|
430
444
|
end
|
431
445
|
|
432
446
|
it 'reads the next entry from dir and returns it' do
|
433
|
-
expect(
|
447
|
+
expect(subject.read).to eq '.'
|
434
448
|
end
|
435
449
|
|
436
450
|
context 'when calling several times' do
|
437
451
|
it 'returns the next entry each time' do
|
438
|
-
2.times {
|
439
|
-
expect(
|
452
|
+
2.times { subject.read }
|
453
|
+
expect(subject.read).to eq 'a'
|
440
454
|
end
|
441
455
|
end
|
442
456
|
|
443
457
|
context 'when there are no entries left' do
|
444
458
|
it 'returns nil' do
|
445
|
-
4.times {
|
446
|
-
expect(
|
459
|
+
4.times { subject.read }
|
460
|
+
expect(subject.read).to be_nil
|
447
461
|
end
|
448
462
|
end
|
449
463
|
end
|
450
464
|
|
451
465
|
describe '#rewind' do
|
452
466
|
it 'repositions dir to the first entry' do
|
453
|
-
3.times {
|
454
|
-
|
455
|
-
expect(
|
467
|
+
3.times { subject.read }
|
468
|
+
subject.rewind
|
469
|
+
expect(subject.read).to eq '.'
|
456
470
|
end
|
457
471
|
|
458
472
|
it 'returns the dir itself' do
|
459
|
-
expect(
|
473
|
+
expect(subject.rewind).to be subject
|
460
474
|
end
|
461
475
|
end
|
462
476
|
|
463
477
|
describe '#seek' do
|
464
|
-
before { 3.times {
|
478
|
+
before { 3.times { subject.read } }
|
465
479
|
|
466
480
|
it 'seeks to a particular location in dir' do
|
467
|
-
|
468
|
-
expect(
|
481
|
+
subject.seek(1)
|
482
|
+
expect(subject.pos).to eq 1
|
469
483
|
end
|
470
484
|
|
471
485
|
it 'returns the dir itself' do
|
472
|
-
expect(
|
486
|
+
expect(subject.seek(2)).to be subject
|
473
487
|
end
|
474
488
|
|
475
489
|
context 'when the location has not been seeked yet' do
|
476
490
|
it "doesn't change the location" do
|
477
|
-
|
478
|
-
expect(
|
491
|
+
subject.seek(42)
|
492
|
+
expect(subject.pos).to eq 3
|
479
493
|
end
|
480
494
|
end
|
481
495
|
|
482
496
|
context 'when the location is negative' do
|
483
497
|
it "doesn't change the location" do
|
484
|
-
|
485
|
-
expect(
|
498
|
+
subject.seek(-1)
|
499
|
+
expect(subject.pos).to eq 3
|
486
500
|
end
|
487
501
|
end
|
488
502
|
end
|
489
503
|
|
490
504
|
describe '#tell' do
|
491
505
|
it 'returns the current position in dir' do
|
492
|
-
3.times {
|
493
|
-
expect(
|
506
|
+
3.times { subject.read }
|
507
|
+
expect(subject.tell).to eq 3
|
494
508
|
end
|
495
509
|
end
|
496
510
|
|
497
511
|
describe '#to_path' do
|
498
512
|
it "returns the path parameter passed to dir's constructor" do
|
499
|
-
expect(
|
513
|
+
expect(subject.to_path).to eq '/test'
|
500
514
|
end
|
501
515
|
end
|
502
516
|
end
|