memfs 0.5.0 → 2.0.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 +5 -5
- data/.github/dependabot.yml +19 -0
- data/.github/workflows/ci.yml +64 -0
- data/.gitignore +1 -0
- data/.rspec +2 -2
- data/.rubocop.yml +81 -12
- data/CHANGELOG.md +41 -10
- data/Gemfile +19 -0
- data/Guardfile +5 -3
- data/README.md +7 -6
- data/Rakefile +4 -2
- data/bin/_guard-core +16 -0
- data/bin/coverage_summary +51 -0
- data/bin/guard +16 -0
- data/bin/rake +16 -0
- data/bin/rspec +16 -0
- data/bin/rubocop +16 -0
- data/lib/memfs/dir.rb +86 -21
- data/lib/memfs/fake/directory.rb +31 -3
- data/lib/memfs/fake/entry.rb +41 -25
- data/lib/memfs/fake/file/content.rb +6 -5
- data/lib/memfs/fake/file.rb +6 -5
- data/lib/memfs/fake/symlink.rb +2 -0
- data/lib/memfs/file/stat.rb +21 -14
- data/lib/memfs/file.rb +92 -77
- data/lib/memfs/file_system.rb +17 -12
- data/lib/memfs/filesystem_access.rb +2 -0
- data/lib/memfs/io.rb +183 -153
- data/lib/memfs/version.rb +3 -1
- data/lib/memfs.rb +112 -5
- data/memfs.gemspec +0 -14
- data/spec/fileutils_spec.rb +86 -58
- data/spec/memfs/dir_spec.rb +175 -27
- data/spec/memfs/fake/directory_spec.rb +8 -4
- data/spec/memfs/fake/entry_spec.rb +16 -10
- data/spec/memfs/fake/file/content_spec.rb +1 -1
- data/spec/memfs/fake/file_spec.rb +1 -1
- data/spec/memfs/fake/symlink_spec.rb +3 -3
- data/spec/memfs/file/stat_spec.rb +30 -15
- data/spec/memfs/file_spec.rb +271 -104
- data/spec/memfs/file_system_spec.rb +20 -19
- data/spec/memfs_spec.rb +67 -2
- data/spec/spec_helper.rb +40 -23
- metadata +17 -135
- data/.travis.yml +0 -6
data/spec/memfs/dir_spec.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'pathname'
|
|
2
2
|
|
|
3
3
|
module MemFs
|
|
4
|
-
describe Dir do
|
|
4
|
+
::RSpec.describe Dir do
|
|
5
5
|
subject { described_class.new('/test') }
|
|
6
6
|
|
|
7
7
|
before { described_class.mkdir '/test' }
|
|
@@ -13,13 +13,13 @@ module MemFs
|
|
|
13
13
|
describe '[]' do
|
|
14
14
|
context 'when a string is given' do
|
|
15
15
|
it 'acts like calling glob' do
|
|
16
|
-
expect(described_class['/*']).to eq
|
|
16
|
+
expect(described_class['/*']).to eq [expected_path('/tmp'), expected_path('/test')]
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
context 'when a list of strings is given' do
|
|
21
21
|
it 'acts like calling glob' do
|
|
22
|
-
expect(described_class['/tm*', '/te*']).to eq
|
|
22
|
+
expect(described_class['/tm*', '/te*']).to eq [expected_path('/tmp'), expected_path('/test')]
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
end
|
|
@@ -27,7 +27,7 @@ module MemFs
|
|
|
27
27
|
describe '.chdir' do
|
|
28
28
|
it 'changes the current working directory' do
|
|
29
29
|
described_class.chdir '/test'
|
|
30
|
-
expect(described_class.getwd).to eq('/test')
|
|
30
|
+
expect(described_class.getwd).to eq(expected_path('/test'))
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
it 'returns zero' do
|
|
@@ -41,7 +41,7 @@ module MemFs
|
|
|
41
41
|
context 'when a block is given' do
|
|
42
42
|
it 'changes current working directory for the block' do
|
|
43
43
|
described_class.chdir '/test' do
|
|
44
|
-
expect(described_class.pwd).to eq('/test')
|
|
44
|
+
expect(described_class.pwd).to eq(expected_path('/test'))
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -54,11 +54,26 @@ module MemFs
|
|
|
54
54
|
end
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
+
if MemFs.ruby_version_gte?('2.6')
|
|
58
|
+
describe '.children' do
|
|
59
|
+
it 'returns an array containing all of the filenames except for "." and ".." in this directory.' do
|
|
60
|
+
%w[/test/dir1 /test/dir2].each { |dir| described_class.mkdir dir }
|
|
61
|
+
_fs.touch '/test/file1', '/test/file2'
|
|
62
|
+
expect(described_class.children('/test')).to eq(%w[dir1 dir2 file1 file2])
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
else
|
|
66
|
+
describe '.children' do
|
|
67
|
+
it 'raises an error' do
|
|
68
|
+
expect { described_class.children('/test') }.to raise_error(NoMethodError)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
57
73
|
describe '.chroot' do
|
|
58
74
|
before { allow(Process).to receive_messages(uid: 0) }
|
|
59
75
|
|
|
60
76
|
it "changes the process's idea of the file system root" do
|
|
61
|
-
|
|
62
77
|
described_class.mkdir('/test/subdir')
|
|
63
78
|
described_class.chroot('/test')
|
|
64
79
|
|
|
@@ -97,6 +112,38 @@ module MemFs
|
|
|
97
112
|
it_behaves_like 'aliased method', :delete, :rmdir
|
|
98
113
|
end
|
|
99
114
|
|
|
115
|
+
describe '.empty?' do
|
|
116
|
+
context 'when the given directory is empty' do
|
|
117
|
+
it 'returns true' do
|
|
118
|
+
expect(described_class.empty?('/test')).to be true
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
context 'when the given directory is non-empty' do
|
|
123
|
+
before { Dir.mkdir('/test/sub-dir') }
|
|
124
|
+
|
|
125
|
+
it 'returns false' do
|
|
126
|
+
expect(described_class.empty?('/test')).to be false
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
context 'when the given directory does not exist' do
|
|
131
|
+
it 'raises an exception' do
|
|
132
|
+
expect {
|
|
133
|
+
described_class.empty?('/nothing')
|
|
134
|
+
}.to raise_exception(Errno::ENOENT)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
context 'when the given entry is not a directory' do
|
|
139
|
+
before { _fs.touch '/test/file1' }
|
|
140
|
+
|
|
141
|
+
it 'returns false' do
|
|
142
|
+
expect(described_class.empty?('/test/file1')).to be false
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
100
147
|
describe '.entries' do
|
|
101
148
|
it 'returns an array containing all of the filenames in the given directory' do
|
|
102
149
|
%w[/test/dir1 /test/dir2].each { |dir| described_class.mkdir dir }
|
|
@@ -146,7 +193,9 @@ module MemFs
|
|
|
146
193
|
|
|
147
194
|
context "and the directory doesn't exist" do
|
|
148
195
|
it 'raises an exception' do
|
|
149
|
-
expect {
|
|
196
|
+
expect {
|
|
197
|
+
described_class.foreach('/no-dir') {}
|
|
198
|
+
}.to raise_error Errno::ENOENT
|
|
150
199
|
end
|
|
151
200
|
end
|
|
152
201
|
|
|
@@ -154,7 +203,7 @@ module MemFs
|
|
|
154
203
|
it 'raises an exception' do
|
|
155
204
|
expect {
|
|
156
205
|
described_class.foreach('/test/test-file') {}
|
|
157
|
-
}.to raise_error
|
|
206
|
+
}.to raise_error Errno::ENOTDIR
|
|
158
207
|
end
|
|
159
208
|
end
|
|
160
209
|
end
|
|
@@ -201,7 +250,8 @@ module MemFs
|
|
|
201
250
|
|
|
202
251
|
shared_examples 'returning matching filenames' do |pattern, filenames|
|
|
203
252
|
it "with #{pattern}" do
|
|
204
|
-
|
|
253
|
+
expected = filenames.map { |f| expected_path(f) }
|
|
254
|
+
expect(described_class.glob(pattern)).to eq expected
|
|
205
255
|
end
|
|
206
256
|
end
|
|
207
257
|
|
|
@@ -215,6 +265,8 @@ module MemFs
|
|
|
215
265
|
it_behaves_like 'returning matching filenames', '/test?', %w[/test0 /test1 /test2]
|
|
216
266
|
it_behaves_like 'returning matching filenames', '/test[01]', %w[/test0 /test1]
|
|
217
267
|
it_behaves_like 'returning matching filenames', '/test[^2]', %w[/test0 /test1]
|
|
268
|
+
it_behaves_like 'returning matching filenames', Pathname.new('/'), %w[/]
|
|
269
|
+
it_behaves_like 'returning matching filenames', Pathname.new('/*'), %w[/tmp /test0 /test1 /test2]
|
|
218
270
|
|
|
219
271
|
if defined?(File::FNM_EXTGLOB)
|
|
220
272
|
it_behaves_like 'returning matching filenames', '/test{1,2}', %w[/test1 /test2]
|
|
@@ -223,14 +275,14 @@ module MemFs
|
|
|
223
275
|
context 'when a flag is given' do
|
|
224
276
|
it 'uses it to compare filenames' do
|
|
225
277
|
expect(described_class.glob('/TEST*', File::FNM_CASEFOLD)).to eq \
|
|
226
|
-
|
|
278
|
+
[expected_path('/test0'), expected_path('/test1'), expected_path('/test2')]
|
|
227
279
|
end
|
|
228
280
|
end
|
|
229
281
|
|
|
230
282
|
context 'when a block is given' do
|
|
231
283
|
it 'calls the block with every matching filenames' do
|
|
232
284
|
expect { |blk| described_class.glob('/test*', &blk) }.to \
|
|
233
|
-
yield_successive_args('/test0', '/test1', '/test2')
|
|
285
|
+
yield_successive_args(expected_path('/test0'), expected_path('/test1'), expected_path('/test2'))
|
|
234
286
|
end
|
|
235
287
|
|
|
236
288
|
it 'returns nil' do
|
|
@@ -240,20 +292,22 @@ module MemFs
|
|
|
240
292
|
|
|
241
293
|
context 'when pattern is an array of patterns' do
|
|
242
294
|
it 'returns the list of files matching any pattern' do
|
|
243
|
-
expect(described_class.glob(['/*0', '/*1'])).to eq
|
|
295
|
+
expect(described_class.glob(['/*0', '/*1'])).to eq [expected_path('/test0'), expected_path('/test1')]
|
|
244
296
|
end
|
|
245
297
|
end
|
|
246
298
|
end
|
|
247
299
|
|
|
248
300
|
describe '.home' do
|
|
249
301
|
it 'returns the home directory of the current user' do
|
|
250
|
-
|
|
302
|
+
# Dir.home uses forward slashes; ENV['HOME'] may have backslashes on Windows
|
|
303
|
+
expect(described_class.home).to eq ENV['HOME'].tr('\\', '/')
|
|
251
304
|
end
|
|
252
305
|
|
|
253
306
|
context 'when a username is given' do
|
|
254
307
|
it 'returns the home directory of the given user' do
|
|
255
|
-
|
|
256
|
-
|
|
308
|
+
username = ENV['USER'] || ENV['USERNAME']
|
|
309
|
+
home_dir = described_class.home(username)
|
|
310
|
+
expect(home_dir).to eq ENV['HOME'].tr('\\', '/')
|
|
257
311
|
end
|
|
258
312
|
end
|
|
259
313
|
end
|
|
@@ -264,15 +318,15 @@ module MemFs
|
|
|
264
318
|
expect(File.directory?('/new-folder')).to be true
|
|
265
319
|
end
|
|
266
320
|
|
|
267
|
-
it 'sets directory permissions to default
|
|
321
|
+
it 'sets directory permissions to default 0o777' do
|
|
268
322
|
described_class.mkdir '/new-folder'
|
|
269
|
-
expect(File.stat('/new-folder').mode).to eq(
|
|
323
|
+
expect(File.stat('/new-folder').mode).to eq(0o100777)
|
|
270
324
|
end
|
|
271
325
|
|
|
272
326
|
context 'when permissions are specified' do
|
|
273
327
|
it 'sets directory permissions to specified value' do
|
|
274
|
-
described_class.mkdir '/new-folder',
|
|
275
|
-
expect(File.stat('/new-folder').mode).to eq(
|
|
328
|
+
described_class.mkdir '/new-folder', 0o644
|
|
329
|
+
expect(File.stat('/new-folder').mode).to eq(0o100644)
|
|
276
330
|
end
|
|
277
331
|
end
|
|
278
332
|
|
|
@@ -308,7 +362,9 @@ module MemFs
|
|
|
308
362
|
|
|
309
363
|
context "when the given directory doesn't exist" do
|
|
310
364
|
it 'raises an exception' do
|
|
311
|
-
expect {
|
|
365
|
+
expect {
|
|
366
|
+
described_class.open('/no-dir')
|
|
367
|
+
}.to raise_error Errno::ENOENT
|
|
312
368
|
end
|
|
313
369
|
end
|
|
314
370
|
|
|
@@ -316,7 +372,9 @@ module MemFs
|
|
|
316
372
|
before { _fs.touch('/test/test-file') }
|
|
317
373
|
|
|
318
374
|
it 'raises an exception' do
|
|
319
|
-
expect {
|
|
375
|
+
expect {
|
|
376
|
+
described_class.open('/test/test-file')
|
|
377
|
+
}.to raise_error Errno::ENOTDIR
|
|
320
378
|
end
|
|
321
379
|
end
|
|
322
380
|
end
|
|
@@ -324,7 +382,9 @@ module MemFs
|
|
|
324
382
|
describe '.new' do
|
|
325
383
|
context "when the given directory doesn't exist" do
|
|
326
384
|
it 'raises an exception' do
|
|
327
|
-
expect {
|
|
385
|
+
expect {
|
|
386
|
+
described_class.new('/no-dir')
|
|
387
|
+
}.to raise_error Errno::ENOENT
|
|
328
388
|
end
|
|
329
389
|
end
|
|
330
390
|
|
|
@@ -332,7 +392,9 @@ module MemFs
|
|
|
332
392
|
before { _fs.touch('/test/test-file') }
|
|
333
393
|
|
|
334
394
|
it 'raises an exception' do
|
|
335
|
-
expect {
|
|
395
|
+
expect {
|
|
396
|
+
described_class.new('/test/test-file')
|
|
397
|
+
}.to raise_error Errno::ENOTDIR
|
|
336
398
|
end
|
|
337
399
|
end
|
|
338
400
|
end
|
|
@@ -360,7 +422,87 @@ module MemFs
|
|
|
360
422
|
|
|
361
423
|
describe '.tmpdir' do
|
|
362
424
|
it 'returns /tmp' do
|
|
363
|
-
expect(described_class.tmpdir).to eq '/tmp'
|
|
425
|
+
expect(described_class.tmpdir).to eq expected_path('/tmp')
|
|
426
|
+
end
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
describe '::Tmpname' do
|
|
430
|
+
it 'is defined' do
|
|
431
|
+
expect(described_class.const_defined?(:Tmpname)).to be true
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
it 'responds to .create' do
|
|
435
|
+
expect(described_class::Tmpname).to respond_to(:create)
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
describe '.mktmpdir' do
|
|
440
|
+
context 'when no block is given' do
|
|
441
|
+
it 'creates a temporary directory and returns its path' do
|
|
442
|
+
path = described_class.mktmpdir
|
|
443
|
+
expect(path).to start_with(expected_path('/tmp/d'))
|
|
444
|
+
expect(described_class.exist?(path)).to be true
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
it 'accepts a prefix' do
|
|
448
|
+
path = described_class.mktmpdir('myprefix')
|
|
449
|
+
expect(path).to start_with(expected_path('/tmp/myprefix'))
|
|
450
|
+
expect(described_class.exist?(path)).to be true
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
it 'accepts a prefix and suffix as an array' do
|
|
454
|
+
path = described_class.mktmpdir(['prefix_', '_suffix'])
|
|
455
|
+
expect(path).to start_with(expected_path('/tmp/prefix_'))
|
|
456
|
+
expect(path).to end_with('_suffix')
|
|
457
|
+
expect(described_class.exist?(path)).to be true
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
it 'accepts a custom tmpdir' do
|
|
461
|
+
described_class.mkdir('/custom_tmp')
|
|
462
|
+
path = described_class.mktmpdir(nil, '/custom_tmp')
|
|
463
|
+
expect(path).to start_with(expected_path('/custom_tmp/d'))
|
|
464
|
+
expect(described_class.exist?(path)).to be true
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
context 'when a block is given' do
|
|
469
|
+
it 'creates a temporary directory, yields it, and removes it' do
|
|
470
|
+
yielded_path = nil
|
|
471
|
+
described_class.mktmpdir do |path|
|
|
472
|
+
yielded_path = path
|
|
473
|
+
expect(path).to start_with(expected_path('/tmp/d'))
|
|
474
|
+
expect(described_class.exist?(path)).to be true
|
|
475
|
+
end
|
|
476
|
+
expect(described_class.exist?(yielded_path)).to be false
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
it 'removes the directory even if an exception occurs' do
|
|
480
|
+
yielded_path = nil
|
|
481
|
+
expect do
|
|
482
|
+
described_class.mktmpdir do |path|
|
|
483
|
+
yielded_path = path
|
|
484
|
+
expect(described_class.exist?(path)).to be true
|
|
485
|
+
raise 'test exception'
|
|
486
|
+
end
|
|
487
|
+
end.to raise_error('test exception')
|
|
488
|
+
expect(described_class.exist?(yielded_path)).to be false
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
it 'works with a prefix and block' do
|
|
492
|
+
yielded_path = nil
|
|
493
|
+
described_class.mktmpdir('test_') do |path|
|
|
494
|
+
yielded_path = path
|
|
495
|
+
expect(path).to start_with(expected_path('/tmp/test_'))
|
|
496
|
+
expect(described_class.exist?(path)).to be true
|
|
497
|
+
end
|
|
498
|
+
expect(described_class.exist?(yielded_path)).to be false
|
|
499
|
+
end
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
it 'creates unique directory names' do
|
|
503
|
+
path1 = described_class.mktmpdir
|
|
504
|
+
path2 = described_class.mktmpdir
|
|
505
|
+
expect(path1).not_to eq(path2)
|
|
364
506
|
end
|
|
365
507
|
end
|
|
366
508
|
|
|
@@ -397,9 +539,15 @@ module MemFs
|
|
|
397
539
|
end
|
|
398
540
|
end
|
|
399
541
|
|
|
542
|
+
describe '#fileno' do
|
|
543
|
+
it 'raises an exception' do
|
|
544
|
+
expect { subject.fileno }.to raise_exception(NotImplementedError)
|
|
545
|
+
end
|
|
546
|
+
end
|
|
547
|
+
|
|
400
548
|
describe '#path' do
|
|
401
549
|
it "returns the path parameter passed to dir's constructor" do
|
|
402
|
-
expect(subject.path).to eq '/test'
|
|
550
|
+
expect(subject.path).to eq expected_path('/test')
|
|
403
551
|
end
|
|
404
552
|
end
|
|
405
553
|
|
|
@@ -510,7 +658,7 @@ module MemFs
|
|
|
510
658
|
|
|
511
659
|
describe '#to_path' do
|
|
512
660
|
it "returns the path parameter passed to dir's constructor" do
|
|
513
|
-
expect(subject.to_path).to eq '/test'
|
|
661
|
+
expect(subject.to_path).to eq expected_path('/test')
|
|
514
662
|
end
|
|
515
663
|
end
|
|
516
664
|
end
|
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
|
2
2
|
|
|
3
3
|
module MemFs
|
|
4
4
|
module Fake
|
|
5
|
-
describe Directory do
|
|
5
|
+
::RSpec.describe Directory do
|
|
6
6
|
subject(:directory) { described_class.new('test') }
|
|
7
7
|
|
|
8
8
|
describe '.new' do
|
|
@@ -70,6 +70,10 @@ module MemFs
|
|
|
70
70
|
it 'should remove any leading / in the path' do
|
|
71
71
|
expect(directory.find('/sub_dir/file')).to be(file)
|
|
72
72
|
end
|
|
73
|
+
|
|
74
|
+
it 'should remove any trailing / in the path' do
|
|
75
|
+
expect(directory.find('sub_dir/file/')).to be(file)
|
|
76
|
+
end
|
|
73
77
|
end
|
|
74
78
|
|
|
75
79
|
describe '#parent=' do
|
|
@@ -87,16 +91,16 @@ module MemFs
|
|
|
87
91
|
end
|
|
88
92
|
|
|
89
93
|
describe '#path' do
|
|
90
|
-
let(:root) { described_class.new(
|
|
94
|
+
let(:root) { described_class.new(root_path) }
|
|
91
95
|
|
|
92
96
|
it 'returns the directory path' do
|
|
93
97
|
directory.parent = root
|
|
94
|
-
expect(directory.path).to eq('/test')
|
|
98
|
+
expect(directory.path).to eq(expected_path('/test'))
|
|
95
99
|
end
|
|
96
100
|
|
|
97
101
|
context 'when the directory is /' do
|
|
98
102
|
it 'returns /' do
|
|
99
|
-
expect(root.path).to eq(
|
|
103
|
+
expect(root.path).to eq(root_path)
|
|
100
104
|
end
|
|
101
105
|
end
|
|
102
106
|
end
|
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
|
2
2
|
|
|
3
3
|
module MemFs
|
|
4
4
|
module Fake
|
|
5
|
-
describe Entry do
|
|
5
|
+
::RSpec.describe Entry do
|
|
6
6
|
let(:entry) { described_class.new('test') }
|
|
7
7
|
let(:parent) { Directory.new('parent') }
|
|
8
8
|
let(:time) { Time.now - 5000 }
|
|
@@ -13,11 +13,11 @@ module MemFs
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
shared_examples 'it has accessors for' do |attribute|
|
|
16
|
-
let(:
|
|
16
|
+
let(:expected_value) { defined?(expected) ? expected : value }
|
|
17
17
|
|
|
18
18
|
it attribute do
|
|
19
19
|
entry.send(:"#{attribute}=", value)
|
|
20
|
-
expect(entry.public_send(attribute)).to eq(
|
|
20
|
+
expect(entry.public_send(attribute)).to eq(expected_value)
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
|
|
@@ -54,8 +54,8 @@ module MemFs
|
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
it_behaves_like 'it has accessors for', :mode do
|
|
57
|
-
let(:value) {
|
|
58
|
-
let(:expected) {
|
|
57
|
+
let(:value) { 0o777 }
|
|
58
|
+
let(:expected) { 0o100777 }
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
it_behaves_like 'it has accessors for', :parent do
|
|
@@ -113,7 +113,13 @@ module MemFs
|
|
|
113
113
|
|
|
114
114
|
describe '#dereferenced_path' do
|
|
115
115
|
it 'returns the entry path' do
|
|
116
|
-
expect(entry.dereferenced_path).to eq('/parent/test')
|
|
116
|
+
expect(entry.dereferenced_path).to eq(expected_path('/parent/test'))
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
describe '#fileno' do
|
|
121
|
+
it 'raises an exception' do
|
|
122
|
+
expect { subject.fileno }.to raise_exception(NotImplementedError)
|
|
117
123
|
end
|
|
118
124
|
end
|
|
119
125
|
|
|
@@ -125,25 +131,25 @@ module MemFs
|
|
|
125
131
|
|
|
126
132
|
describe '#dev' do
|
|
127
133
|
it 'returns an integer representing the device on which the entry resides' do
|
|
128
|
-
expect(entry.dev).to be_a(
|
|
134
|
+
expect(entry.dev).to be_a(Integer)
|
|
129
135
|
end
|
|
130
136
|
end
|
|
131
137
|
|
|
132
138
|
describe '#ino' do
|
|
133
139
|
it 'Returns the inode number for the entry' do
|
|
134
|
-
expect(entry.ino).to be_a(
|
|
140
|
+
expect(entry.ino).to be_a(Integer)
|
|
135
141
|
end
|
|
136
142
|
end
|
|
137
143
|
|
|
138
144
|
describe '#path' do
|
|
139
145
|
it 'returns the complete path of the entry' do
|
|
140
|
-
expect(entry.path).to eq('/parent/test')
|
|
146
|
+
expect(entry.path).to eq(expected_path('/parent/test'))
|
|
141
147
|
end
|
|
142
148
|
end
|
|
143
149
|
|
|
144
150
|
describe 'paths' do
|
|
145
151
|
it 'returns an array containing the entry path' do
|
|
146
|
-
expect(entry.paths).to eq ['/parent/test']
|
|
152
|
+
expect(entry.paths).to eq [expected_path('/parent/test')]
|
|
147
153
|
end
|
|
148
154
|
end
|
|
149
155
|
|
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
|
2
2
|
|
|
3
3
|
module MemFs
|
|
4
4
|
module Fake
|
|
5
|
-
describe Symlink do
|
|
5
|
+
::RSpec.describe Symlink do
|
|
6
6
|
describe '#content' do
|
|
7
7
|
it "returns the target's content" do
|
|
8
8
|
MemFs::File.open('/test-file', 'w') { |f| f.puts 'test' }
|
|
@@ -54,7 +54,7 @@ module MemFs
|
|
|
54
54
|
it 'returns its target path' do
|
|
55
55
|
_fs.touch('/test-file')
|
|
56
56
|
symlink = described_class.new('/test-link', '/test-file')
|
|
57
|
-
expect(symlink.dereferenced_path).to eq('/test-file')
|
|
57
|
+
expect(symlink.dereferenced_path).to eq(expected_path('/test-file'))
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
|
|
@@ -63,7 +63,7 @@ module MemFs
|
|
|
63
63
|
symlink = described_class.new('/test-link', '/no-file')
|
|
64
64
|
expect {
|
|
65
65
|
symlink.dereferenced_path
|
|
66
|
-
}.to
|
|
66
|
+
}.to raise_error Errno::ENOENT
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
end
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
module MemFs
|
|
4
|
-
describe File::Stat do
|
|
4
|
+
::RSpec.describe File::Stat do
|
|
5
5
|
let(:file_stat) { described_class.new('/test-file') }
|
|
6
|
-
let(:dereferenced_file_stat) { described_class.new('/test-file', true) }
|
|
6
|
+
let(:dereferenced_file_stat) { described_class.new('/test-file', dereference: true) }
|
|
7
7
|
|
|
8
8
|
let(:dir_link_stat) { described_class.new('/test-dir-link') }
|
|
9
|
-
let(:dereferenced_dir_link_stat) { described_class.new('/test-dir-link', true) }
|
|
9
|
+
let(:dereferenced_dir_link_stat) { described_class.new('/test-dir-link', dereference: true) }
|
|
10
10
|
|
|
11
11
|
let(:link_stat) { described_class.new('/test-link') }
|
|
12
|
-
let(:dereferenced_link_stat) { described_class.new('/test-link', true) }
|
|
12
|
+
let(:dereferenced_link_stat) { described_class.new('/test-link', dereference: true) }
|
|
13
13
|
|
|
14
14
|
let(:dir_stat) { described_class.new('/test-dir') }
|
|
15
|
-
let(:dereferenced_dir_stat) { described_class.new('/test-dir', true) }
|
|
15
|
+
let(:dereferenced_dir_stat) { described_class.new('/test-dir', dereference: true) }
|
|
16
16
|
|
|
17
17
|
let(:entry) { _fs.find!('/test-file') }
|
|
18
18
|
|
|
@@ -29,7 +29,7 @@ module MemFs
|
|
|
29
29
|
context 'when the last target of the link chain does not exist' do
|
|
30
30
|
it 'raises an exception' do
|
|
31
31
|
expect {
|
|
32
|
-
described_class.new('/test-no-file-link', true)
|
|
32
|
+
described_class.new('/test-no-file-link', dereference: true)
|
|
33
33
|
}.to raise_error(Errno::ENOENT)
|
|
34
34
|
end
|
|
35
35
|
end
|
|
@@ -131,7 +131,7 @@ module MemFs
|
|
|
131
131
|
|
|
132
132
|
describe '#dev' do
|
|
133
133
|
it 'returns an integer representing the device on which stat resides' do
|
|
134
|
-
expect(file_stat.dev).to be_a(
|
|
134
|
+
expect(file_stat.dev).to be_a(Integer)
|
|
135
135
|
end
|
|
136
136
|
end
|
|
137
137
|
|
|
@@ -373,6 +373,18 @@ module MemFs
|
|
|
373
373
|
end
|
|
374
374
|
end
|
|
375
375
|
|
|
376
|
+
describe '#nlink' do
|
|
377
|
+
context 'when the entry is a regular file' do
|
|
378
|
+
it "returns expected nlinks for a file" do
|
|
379
|
+
expect(file_stat.nlink).to eq(1)
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
it "returns expected nlinks for a directory" do
|
|
383
|
+
expect(dir_stat.nlink).to eq(2)
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
|
|
376
388
|
describe '#ftype' do
|
|
377
389
|
context 'when the entry is a regular file' do
|
|
378
390
|
it "returns 'file'" do
|
|
@@ -441,7 +453,7 @@ module MemFs
|
|
|
441
453
|
|
|
442
454
|
context 'when the effective user group does not own of the file' do
|
|
443
455
|
it 'returns false' do
|
|
444
|
-
_fs.chown(
|
|
456
|
+
_fs.chown(9999, 9999, '/test-file')
|
|
445
457
|
expect(file_stat.grpowned?).to be false
|
|
446
458
|
end
|
|
447
459
|
end
|
|
@@ -449,14 +461,14 @@ module MemFs
|
|
|
449
461
|
|
|
450
462
|
describe '#ino' do
|
|
451
463
|
it 'returns the inode number for stat.' do
|
|
452
|
-
expect(file_stat.ino).to be_a(
|
|
464
|
+
expect(file_stat.ino).to be_a(Integer)
|
|
453
465
|
end
|
|
454
466
|
end
|
|
455
467
|
|
|
456
468
|
describe '#mode' do
|
|
457
469
|
it 'returns an integer representing the permission bits of stat' do
|
|
458
|
-
_fs.chmod(
|
|
459
|
-
expect(file_stat.mode).to be(
|
|
470
|
+
_fs.chmod(0o777, '/test-file')
|
|
471
|
+
expect(file_stat.mode).to be(0o100777)
|
|
460
472
|
end
|
|
461
473
|
end
|
|
462
474
|
|
|
@@ -470,7 +482,7 @@ module MemFs
|
|
|
470
482
|
|
|
471
483
|
context 'when the effective user does not own of the file' do
|
|
472
484
|
it 'returns false' do
|
|
473
|
-
_fs.chown(
|
|
485
|
+
_fs.chown(9999, 9999, '/test-file')
|
|
474
486
|
expect(file_stat.owned?).to be false
|
|
475
487
|
end
|
|
476
488
|
end
|
|
@@ -599,13 +611,14 @@ module MemFs
|
|
|
599
611
|
describe '#setgid?' do
|
|
600
612
|
context 'when the file has the setgid bit set' do
|
|
601
613
|
it 'returns true' do
|
|
602
|
-
_fs.chmod(
|
|
614
|
+
_fs.chmod(0o2000, '/test-file')
|
|
603
615
|
expect(file_stat.setgid?).to be true
|
|
604
616
|
end
|
|
605
617
|
end
|
|
606
618
|
|
|
607
619
|
context 'when the file does not have the setgid bit set' do
|
|
608
620
|
it 'returns false' do
|
|
621
|
+
_fs.chmod(0o644, '/test-file')
|
|
609
622
|
expect(file_stat.setgid?).to be false
|
|
610
623
|
end
|
|
611
624
|
end
|
|
@@ -614,13 +627,14 @@ module MemFs
|
|
|
614
627
|
describe '#setuid?' do
|
|
615
628
|
context 'when the file has the setuid bit set' do
|
|
616
629
|
it 'returns true' do
|
|
617
|
-
_fs.chmod(
|
|
630
|
+
_fs.chmod(0o4000, '/test-file')
|
|
618
631
|
expect(file_stat.setuid?).to be true
|
|
619
632
|
end
|
|
620
633
|
end
|
|
621
634
|
|
|
622
635
|
context 'when the file does not have the setuid bit set' do
|
|
623
636
|
it 'returns false' do
|
|
637
|
+
_fs.chmod(0o644, '/test-file')
|
|
624
638
|
expect(file_stat.setuid?).to be false
|
|
625
639
|
end
|
|
626
640
|
end
|
|
@@ -638,11 +652,12 @@ module MemFs
|
|
|
638
652
|
|
|
639
653
|
describe '#sticky?' do
|
|
640
654
|
it 'returns true if the named file has the sticky bit set' do
|
|
641
|
-
_fs.chmod(
|
|
655
|
+
_fs.chmod(0o1777, '/test-file')
|
|
642
656
|
expect(file_stat.sticky?).to be true
|
|
643
657
|
end
|
|
644
658
|
|
|
645
659
|
it "returns false if the named file hasn't' the sticky bit set" do
|
|
660
|
+
_fs.chmod(0o666, '/test-file')
|
|
646
661
|
expect(file_stat.sticky?).to be false
|
|
647
662
|
end
|
|
648
663
|
end
|