memfs 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -43,10 +43,6 @@ module MemFs
43
43
  entry.gid = gid if gid && gid != -1
44
44
  end
45
45
 
46
- def directory?(path)
47
- find(path).is_a?(Fake::Directory)
48
- end
49
-
50
46
  def dirname(path)
51
47
  File.dirname(path)
52
48
  end
@@ -128,10 +124,6 @@ module MemFs
128
124
  find_parent!(new_name).add_entry Fake::Symlink.new(new_name, old_name)
129
125
  end
130
126
 
131
- def symlink?(path)
132
- find(path).is_a?(Fake::Symlink)
133
- end
134
-
135
127
  def touch(*paths)
136
128
  paths.each do |path|
137
129
  entry = find(path)
data/lib/memfs/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module MemFs
2
- VERSION = '0.0.2'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -110,6 +110,12 @@ module MemFs
110
110
  expect(directory.entries).not_to have_value(file)
111
111
  end
112
112
  end
113
+
114
+ describe "#type" do
115
+ it "returns 'directory'" do
116
+ expect(directory.type).to eq('directory')
117
+ end
118
+ end
113
119
  end
114
120
  end
115
121
  end
@@ -29,6 +29,18 @@ module MemFs
29
29
  let(:value) { time }
30
30
  end
31
31
 
32
+ it_behaves_like 'it has accessors for', :block_device do
33
+ let(:value) { true }
34
+ end
35
+
36
+ it_behaves_like 'it has accessors for', :character_device do
37
+ let(:value) { true }
38
+ end
39
+
40
+ it_behaves_like 'it has accessors for', :ctime do
41
+ let(:value) { time }
42
+ end
43
+
32
44
  it_behaves_like 'it has accessors for', :mtime do
33
45
  let(:value) { time }
34
46
  end
@@ -50,32 +62,13 @@ module MemFs
50
62
  let(:value) { parent }
51
63
  end
52
64
 
53
- describe ".delete" do
54
- it "removes the entry from its parent" do
55
- entry.delete
56
- expect(parent.entries).not_to have_value(entry)
57
- end
58
- end
59
-
60
- describe '.dereferenced' do
61
- it "returns the entry itself" do
62
- expect(entry.dereferenced).to be(entry)
63
- end
64
- end
65
-
66
- describe '.find' do
67
- it "raises an error" do
68
- expect { entry.find('test') }.to raise_error(Errno::ENOTDIR)
69
- end
70
- end
71
-
72
65
  describe ".new" do
73
66
  it "sets its default uid to the current user's uid" do
74
- expect(entry.uid).to eq(Etc.getpwuid.uid)
67
+ expect(entry.uid).to eq(Process.euid)
75
68
  end
76
69
 
77
70
  it "sets its default gid to the current user's gid" do
78
- expect(entry.gid).to eq(Etc.getpwuid.gid)
71
+ expect(entry.gid).to eq(Process.egid)
79
72
  end
80
73
 
81
74
  it "extract its name from the path passed as argument" do
@@ -99,9 +92,34 @@ module MemFs
99
92
  end
100
93
  end
101
94
 
102
- describe ".path" do
103
- it "returns the complete path of the entry" do
104
- expect(entry.path).to eq('/parent/test')
95
+ describe "#delete" do
96
+ it "removes the entry from its parent" do
97
+ entry.delete
98
+ expect(parent.entries).not_to have_value(entry)
99
+ end
100
+ end
101
+
102
+ describe '#dereferenced' do
103
+ it "returns the entry itself" do
104
+ expect(entry.dereferenced).to be(entry)
105
+ end
106
+ end
107
+
108
+ describe "#dereferenced_name" do
109
+ it "returns the entry name" do
110
+ expect(entry.dereferenced_name).to eq('test')
111
+ end
112
+ end
113
+
114
+ describe "#dereferenced_path" do
115
+ it "returns the entry path" do
116
+ expect(entry.dereferenced_path).to eq('/parent/test')
117
+ end
118
+ end
119
+
120
+ describe '#find' do
121
+ it "raises an error" do
122
+ expect { entry.find('test') }.to raise_error(Errno::ENOTDIR)
105
123
  end
106
124
  end
107
125
 
@@ -117,6 +135,12 @@ module MemFs
117
135
  end
118
136
  end
119
137
 
138
+ describe "#path" do
139
+ it "returns the complete path of the entry" do
140
+ expect(entry.path).to eq('/parent/test')
141
+ end
142
+ end
143
+
120
144
  describe "#touch" do
121
145
  let(:time) { Time.now - 5000 }
122
146
 
@@ -135,6 +159,12 @@ module MemFs
135
159
  expect(entry.mtime).not_to eq(time)
136
160
  end
137
161
  end
162
+
163
+ describe "#type" do
164
+ it "returns 'unknown" do
165
+ expect(entry.type).to eq('unknown')
166
+ end
167
+ end
138
168
  end
139
169
  end
140
170
  end
@@ -79,6 +79,15 @@ module MemFs
79
79
  end
80
80
  end
81
81
 
82
+ describe "#truncate" do
83
+ subject { File::Content.new('x'*50) }
84
+
85
+ it "truncates the content to length characters" do
86
+ subject.truncate(5)
87
+ expect(subject.length).to eq(5)
88
+ end
89
+ end
90
+
82
91
  describe "#write" do
83
92
  it "writes the given string in content" do
84
93
  subject.write 'test'
@@ -32,6 +32,28 @@ module MemFs
32
32
  end
33
33
  end
34
34
  end
35
+
36
+ describe "#type" do
37
+ context "when the file is a regular file" do
38
+ it "returns 'file'" do
39
+ expect(file.type).to eq('file')
40
+ end
41
+ end
42
+
43
+ context "when the file is a block device" do
44
+ it "returns 'blockSpecial'" do
45
+ file.block_device = true
46
+ expect(file.type).to eq('blockSpecial')
47
+ end
48
+ end
49
+
50
+ context "when the file is a character device" do
51
+ it "returns 'characterSpecial'" do
52
+ file.character_device = true
53
+ expect(file.type).to eq('characterSpecial')
54
+ end
55
+ end
56
+ end
35
57
  end
36
58
  end
37
59
  end
@@ -32,12 +32,82 @@ module MemFs
32
32
  end
33
33
  end
34
34
 
35
+ describe "#dereferenced_name" do
36
+ context "when the symlink's target exists" do
37
+ it "returns its target name" do
38
+ fs.touch('/test-file')
39
+ symlink = Symlink.new('/test-link', '/test-file')
40
+ expect(symlink.dereferenced_name).to eq('test-file')
41
+ end
42
+ end
43
+
44
+ context "when the symlink's target does not exist" do
45
+ it "returns its target name" do
46
+ symlink = Symlink.new('/test-link', '/no-file')
47
+ expect(symlink.dereferenced_name).to eq('no-file')
48
+ end
49
+ end
50
+ end
51
+
52
+ describe "#dereferenced_path" do
53
+ context "when the symlink's target exists" do
54
+ it "returns its target path" do
55
+ fs.touch('/test-file')
56
+ symlink = Symlink.new('/test-link', '/test-file')
57
+ expect(symlink.dereferenced_path).to eq('/test-file')
58
+ end
59
+ end
60
+
61
+ context "when the symlink's target does not exist" do
62
+ it "raises an exception" do
63
+ symlink = Symlink.new('/test-link', '/no-file')
64
+ expect {
65
+ symlink.dereferenced_path
66
+ }.to raise_exception
67
+ end
68
+ end
69
+ end
70
+
71
+ describe '#find' do
72
+ let(:file) { fs.find!('/test-dir/test-file') }
73
+
74
+ before :each do
75
+ fs.mkdir '/test-dir'
76
+ fs.touch '/test-dir/test-file'
77
+ end
78
+
79
+ context "when the symlink's target exists" do
80
+ subject { Symlink.new('/test-dir-link', '/test-dir') }
81
+
82
+ it "forwards the search to it" do
83
+ entry = subject.find('test-file')
84
+ expect(entry).to eq(file)
85
+ end
86
+ end
87
+
88
+ context "when the symlink's target does not exist" do
89
+ subject { Symlink.new('/test-no-link', '/no-dir') }
90
+
91
+ it "returns nil" do
92
+ entry = subject.find('test-file')
93
+ expect(entry).to be_nil
94
+ end
95
+ end
96
+ end
97
+
35
98
  describe '#target' do
36
99
  it "returns the target of the symlink" do
37
100
  s = Symlink.new('/test-link', '/test-file')
38
101
  expect(s.target).to eq('/test-file')
39
102
  end
40
103
  end
104
+
105
+ describe "#type" do
106
+ it "returns 'link'" do
107
+ s = Symlink.new('/test-link', '/test-file')
108
+ expect(s.type).to eq('link')
109
+ end
110
+ end
41
111
  end
42
112
  end
43
113
  end
@@ -2,11 +2,36 @@ require 'spec_helper'
2
2
 
3
3
  module MemFs
4
4
  describe File::Stat do
5
+ let(:file_stat) { File::Stat.new('/test-file') }
6
+ let(:dereferenced_file_stat) { File::Stat.new('/test-file', true) }
7
+
8
+ let(:dir_link_stat) { File::Stat.new('/test-dir-link') }
9
+ let(:dereferenced_dir_link_stat) { File::Stat.new('/test-dir-link', true) }
10
+
11
+ let(:link_stat) { File::Stat.new('/test-link') }
12
+ let(:dereferenced_link_stat) { File::Stat.new('/test-link', true) }
13
+
14
+ let(:dir_stat) { File::Stat.new('/test-dir') }
15
+ let(:dereferenced_dir_stat) { File::Stat.new('/test-dir', true) }
16
+
17
+ let(:entry) { fs.find!('/test-file') }
18
+
19
+ before :each do
20
+ fs.mkdir('/test-dir')
21
+ fs.touch('/test-file')
22
+ fs.symlink('/test-file', '/test-link')
23
+ fs.symlink('/test-dir', '/test-dir-link')
24
+ fs.symlink('/no-file', '/test-no-file-link')
25
+ end
26
+
5
27
  describe '.new' do
6
- context "when optional follow_symlink argument is set to true" do
7
- it "raises an error if the end-of-links-chain target doesn't exist" do
8
- fs.symlink('/test-file', '/test-link')
9
- expect { File::Stat.new('/test-link', true) }.to raise_error(Errno::ENOENT)
28
+ context "when optional dereference argument is set to true" do
29
+ context "when the last target of the link chain does not exist" do
30
+ it "raises an exception" do
31
+ expect {
32
+ File::Stat.new('/test-no-file-link', true)
33
+ }.to raise_error(Errno::ENOENT)
34
+ end
10
35
  end
11
36
  end
12
37
  end
@@ -15,30 +40,23 @@ module MemFs
15
40
  let(:time) { Time.now - 500000 }
16
41
 
17
42
  it "returns the access time of the entry" do
18
- fs.touch('/test-file')
19
43
  entry = fs.find!('/test-file')
20
44
  entry.atime = time
21
- expect(File::Stat.new('/test-file').atime).to eq(time)
45
+ expect(file_stat.atime).to eq(time)
22
46
  end
23
47
 
24
48
  context "when the entry is a symlink" do
25
- context "and the optional follow_symlink argument is true" do
49
+ context "and the optional dereference argument is true" do
26
50
  it "returns the access time of the last target of the link chain" do
27
- fs.touch('/test-file')
28
- entry = fs.find!('/test-file')
29
51
  entry.atime = time
30
- fs.symlink('/test-file', '/test-link')
31
- expect(File::Stat.new('/test-link', true).atime).to eq(time)
52
+ expect(dereferenced_link_stat.atime).to eq(time)
32
53
  end
33
54
  end
34
55
 
35
- context "and the optional follow_symlink argument is false" do
56
+ context "and the optional dereference argument is false" do
36
57
  it "returns the access time of the symlink itself" do
37
- fs.touch('/test-file')
38
- entry = fs.find!('/test-file')
39
58
  entry.atime = time
40
- fs.symlink('/test-file', '/test-link')
41
- expect(File::Stat.new('/test-link').atime).not_to eq(time)
59
+ expect(link_stat.atime).not_to eq(time)
42
60
  end
43
61
  end
44
62
  end
@@ -46,52 +64,130 @@ module MemFs
46
64
 
47
65
  describe "#blksize" do
48
66
  it "returns the block size of the file" do
49
- fs.touch('/test-file')
50
- expect(File::Stat.new('/test-file').blksize).to be(4096)
67
+ expect(file_stat.blksize).to be(4096)
51
68
  end
52
69
  end
53
70
 
54
- describe "#dev" do
55
- it "returns an integer representing the device on which stat resides" do
56
- fs.touch('/test-file')
57
- expect(File::Stat.new('/test-file').dev).to be_a(Fixnum)
71
+ describe "#blockdev?" do
72
+ context "when the file is a block device" do
73
+ it "returns true" do
74
+ fs.touch('/block-file')
75
+ file = fs.find('/block-file')
76
+ file.block_device = true
77
+ block_stat = File::Stat.new('/block-file')
78
+ expect(block_stat.blockdev?).to be_true
79
+ end
80
+ end
81
+
82
+ context "when the file is not a block device" do
83
+ it "returns false" do
84
+ expect(file_stat.blockdev?).to be_false
85
+ end
58
86
  end
59
87
  end
60
88
 
61
- describe '#directory?' do
62
- before :each do
63
- fs.mkdir('/test')
64
- fs.touch('/test-file')
65
- fs.symlink('/test', '/link-to-dir')
66
- fs.symlink('/test-file', '/link-to-file')
89
+ describe "#chardev?" do
90
+ context "when the file is a character device" do
91
+ it "returns true" do
92
+ fs.touch('/character-file')
93
+ file = fs.find('/character-file')
94
+ file.character_device = true
95
+ character_stat = File::Stat.new('/character-file')
96
+ expect(character_stat.chardev?).to be_true
97
+ end
67
98
  end
68
99
 
69
- it "returns true if the entry is a directory" do
70
- expect(File::Stat.new('/test')).to be_directory
100
+ context "when the file is not a character device" do
101
+ it "returns false" do
102
+ expect(file_stat.chardev?).to be_false
103
+ end
71
104
  end
105
+ end
106
+
107
+ describe '#ctime' do
108
+ let(:time) { Time.now - 500000 }
72
109
 
73
- it "returns false if the entry is not a directory" do
74
- expect(File::Stat.new('/test-file')).not_to be_directory
110
+ it "returns the access time of the entry" do
111
+ entry.ctime = time
112
+ expect(file_stat.ctime).to eq(time)
75
113
  end
76
114
 
77
115
  context "when the entry is a symlink" do
78
- context "and the optional follow_symlink argument is true" do
79
- it "returns true if the last target of the link chain is a directory" do
80
- expect(File::Stat.new('/link-to-dir', true)).to be_directory
116
+ context "and the optional dereference argument is true" do
117
+ it "returns the access time of the last target of the link chain" do
118
+ entry.ctime = time
119
+ expect(dereferenced_link_stat.ctime).to eq(time)
120
+ end
121
+ end
122
+
123
+ context "and the optional dereference argument is false" do
124
+ it "returns the access time of the symlink itself" do
125
+ entry.ctime = time
126
+ expect(link_stat.ctime).not_to eq(time)
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ describe "#dev" do
133
+ it "returns an integer representing the device on which stat resides" do
134
+ expect(file_stat.dev).to be_a(Fixnum)
135
+ end
136
+ end
137
+
138
+ describe '#directory?' do
139
+ context 'when dereference is true' do
140
+ context "when the entry is a directory" do
141
+ it "returns true" do
142
+ expect(dereferenced_dir_stat.directory?).to be_true
143
+ end
144
+ end
145
+
146
+ context "when the entry is not a directory" do
147
+ it "returns false" do
148
+ expect(dereferenced_file_stat.directory?).to be_false
149
+ end
150
+ end
151
+
152
+ context "when the entry is a symlink" do
153
+ context "and the last target of the link chain is a directory" do
154
+ it "returns true" do
155
+ expect(dereferenced_dir_link_stat.directory?).to be_true
156
+ end
157
+ end
158
+
159
+ context "and the last target of the link chain is not a directory" do
160
+ it "returns false" do
161
+ expect(dereferenced_link_stat.directory?).to be_false
162
+ end
163
+ end
164
+ end
165
+ end
166
+
167
+ context 'when dereference is false' do
168
+ context "when the entry is a directory" do
169
+ it "returns true" do
170
+ expect(dir_stat.directory?).to be_true
81
171
  end
172
+ end
82
173
 
83
- it "returns false if the last target of the link chain is not a directory" do
84
- expect(File::Stat.new('/link-to-file', true)).not_to be_directory
174
+ context "when the entry is not a directory" do
175
+ it "returns false" do
176
+ expect(file_stat.directory?).to be_false
85
177
  end
86
178
  end
87
179
 
88
- context "and the optional follow_symlink argument is false" do
89
- it "returns false if the last target of the link chain is a directory" do
90
- expect(File::Stat.new('/link-to-dir', false)).not_to be_directory
180
+ context "when the entry is a symlink" do
181
+ context "and the last target of the link chain is a directory" do
182
+ it "returns false" do
183
+ expect(dir_link_stat.directory?).to be_false
184
+ end
91
185
  end
92
186
 
93
- it "returns false if the last target of the link chain is not a directory" do
94
- expect(File::Stat.new('/link-to-file', false)).not_to be_directory
187
+ context "and the last target of the link chain is not a directory" do
188
+ it "returns false" do
189
+ expect(link_stat.directory?).to be_false
190
+ end
95
191
  end
96
192
  end
97
193
  end
@@ -99,109 +195,657 @@ module MemFs
99
195
 
100
196
  describe '#entry' do
101
197
  it "returns the comcerned entry" do
102
- entry = fs.touch('/test-file')
103
- stat = File::Stat.new('/test-file')
104
- expect(stat.entry).to be_a(Fake::File)
198
+ expect(file_stat.entry).to be_a(Fake::File)
199
+ end
200
+ end
201
+
202
+ describe "#executable?" do
203
+ let(:access) { 0 }
204
+ let(:gid) { 0 }
205
+ let(:uid) { 0 }
206
+
207
+ before :each do
208
+ entry.mode = access
209
+ entry.uid = uid
210
+ entry.gid = gid
211
+ end
212
+
213
+ context "when the file is not executable by anyone" do
214
+ it "return false" do
215
+ expect(file_stat.executable?).to be_false
216
+ end
217
+ end
218
+
219
+ context "when the file is user executable" do
220
+ let(:access) { MemFs::Fake::Entry::UEXEC }
221
+
222
+ context "and the current user owns the file" do
223
+ let(:uid) { Process.euid }
224
+
225
+ it "returns true" do
226
+ expect(file_stat.executable?).to be_true
227
+ end
228
+ end
229
+ end
230
+
231
+ context "when the file is group executable" do
232
+ let(:access) { MemFs::Fake::Entry::GEXEC }
233
+
234
+ context "and the current user is part of the owner group" do
235
+ let(:gid) { Process.egid }
236
+
237
+ it "returns true" do
238
+ expect(file_stat.executable?).to be_true
239
+ end
240
+ end
241
+ end
242
+
243
+ context "when the file is executable by anyone" do
244
+ let(:access) { MemFs::Fake::Entry::OEXEC }
245
+
246
+ context "and the user has no specific right on it" do
247
+ it "returns true" do
248
+ expect(file_stat.executable?).to be_true
249
+ end
250
+ end
251
+ end
252
+
253
+ context "when the file does not exist" do
254
+ it "returns false" do
255
+ expect(file_stat.executable?).to be_false
256
+ end
257
+ end
258
+ end
259
+
260
+ describe "#executable_real?" do
261
+ let(:access) { 0 }
262
+ let(:gid) { 0 }
263
+ let(:uid) { 0 }
264
+
265
+ before :each do
266
+ entry.mode = access
267
+ entry.uid = uid
268
+ entry.gid = gid
269
+ end
270
+
271
+ context "when the file is not executable by anyone" do
272
+ it "return false" do
273
+ expect(file_stat.executable_real?).to be_false
274
+ end
275
+ end
276
+
277
+ context "when the file is user executable" do
278
+ let(:access) { MemFs::Fake::Entry::UEXEC }
279
+
280
+ context "and the current user owns the file" do
281
+ let(:uid) { Process.uid }
282
+
283
+ it "returns true" do
284
+ expect(file_stat.executable_real?).to be_true
285
+ end
286
+ end
287
+ end
288
+
289
+ context "when the file is group executable" do
290
+ let(:access) { MemFs::Fake::Entry::GEXEC }
291
+
292
+ context "and the current user is part of the owner group" do
293
+ let(:gid) { Process.gid }
294
+
295
+ it "returns true" do
296
+ expect(file_stat.executable_real?).to be_true
297
+ end
298
+ end
299
+ end
300
+
301
+ context "when the file is executable by anyone" do
302
+ let(:access) { MemFs::Fake::Entry::OEXEC }
303
+
304
+ context "and the user has no specific right on it" do
305
+ it "returns true" do
306
+ expect(file_stat.executable_real?).to be_true
307
+ end
308
+ end
309
+ end
310
+
311
+ context "when the file does not exist" do
312
+ it "returns false" do
313
+ expect(file_stat.executable_real?).to be_false
314
+ end
105
315
  end
106
316
  end
107
317
 
108
318
  describe "#file?" do
109
- it "returns true if the entry is a regular file" do
110
- fs.touch('/test-file')
111
- expect(File.stat('/test-file')).to be_file
319
+ context 'when dereference is true' do
320
+ context "when the entry is a regular file" do
321
+ it "returns true" do
322
+ expect(dereferenced_file_stat.file?).to be_true
323
+ end
324
+ end
325
+
326
+ context "when the entry is not a regular file" do
327
+ it "returns false" do
328
+ expect(dereferenced_dir_stat.file?).to be_false
329
+ end
330
+ end
331
+
332
+ context "when the entry is a symlink" do
333
+ context "and the last target of the link chain is a regular file" do
334
+ it "returns true" do
335
+ expect(dereferenced_link_stat.file?).to be_true
336
+ end
337
+ end
338
+
339
+ context "and the last target of the link chain is not a regular file" do
340
+ it "returns false" do
341
+ expect(dereferenced_dir_link_stat.file?).to be_false
342
+ end
343
+ end
344
+ end
112
345
  end
113
346
 
114
- it "returns false if the entry is not a regular file" do
115
- fs.mkdir('/test-dir')
116
- expect(File.stat('/test-dir')).not_to be_file
347
+ context 'when dereference is false' do
348
+ context "when the entry is a regular file" do
349
+ it "returns true" do
350
+ expect(file_stat.file?).to be_true
351
+ end
352
+ end
353
+
354
+ context "when the entry is not a regular file" do
355
+ it "returns false" do
356
+ expect(dir_stat.file?).to be_false
357
+ end
358
+ end
359
+
360
+ context "when the entry is a symlink" do
361
+ context "and the last target of the link chain is a regular file" do
362
+ it "returns false" do
363
+ expect(link_stat.file?).to be_false
364
+ end
365
+ end
366
+
367
+ context "and the last target of the link chain is not a regular file" do
368
+ it "returns false" do
369
+ expect(dir_link_stat.file?).to be_false
370
+ end
371
+ end
372
+ end
373
+ end
374
+ end
375
+
376
+ describe "#ftype" do
377
+ context "when the entry is a regular file" do
378
+ it "returns 'file'" do
379
+ expect(file_stat.ftype).to eq('file')
380
+ end
381
+ end
382
+
383
+ context "when the entry is a directory" do
384
+ it "returns 'directory'" do
385
+ expect(dir_stat.ftype).to eq('directory')
386
+ end
387
+ end
388
+
389
+ context "when the entry is a block device" do
390
+ it "returns 'blockSpecial'" do
391
+ fs.touch('/block-file')
392
+ file = fs.find('/block-file')
393
+ file.block_device = true
394
+ block_stat = File::Stat.new('/block-file')
395
+ expect(block_stat.ftype).to eq('blockSpecial')
396
+ end
397
+ end
398
+
399
+ context "when the entry is a character device" do
400
+ it "returns 'characterSpecial'" do
401
+ fs.touch('/character-file')
402
+ file = fs.find('/character-file')
403
+ file.character_device = true
404
+ character_stat = File::Stat.new('/character-file')
405
+ expect(character_stat.ftype).to eq('characterSpecial')
406
+ end
117
407
  end
118
408
 
119
409
  context "when the entry is a symlink" do
120
- it "returns true if its target is a regular file" do
121
- fs.touch('/test-file')
122
- fs.symlink('/test-file', '/test-link')
123
- expect(File.stat('/test-link')).to be_file
410
+ it "returns 'link'" do
411
+ expect(link_stat.ftype).to eq('link')
124
412
  end
413
+ end
414
+
415
+ # fifo and socket not handled for now
125
416
 
126
- it "returns false if its target is not a regular file" do
127
- fs.mkdir('/test-dir')
128
- fs.symlink('/test-dir', '/test-link')
129
- expect(File.stat('/test-link')).not_to be_file
417
+ context "when the entry has no specific type" do
418
+ it "returns 'unknown'" do
419
+ root = fs.find('/')
420
+ root.add_entry Fake::Entry.new('test-entry')
421
+ entry_stat = File::Stat.new('/test-entry')
422
+ expect(entry_stat.ftype).to eq('unknown')
130
423
  end
131
424
  end
132
425
  end
133
426
 
134
427
  describe "#gid" do
135
428
  it "returns the group id of the named entry" do
136
- fs.touch('/test-file')
137
429
  fs.chown(nil, 42, '/test-file')
138
- expect(File::Stat.new('/test-file').gid).to be(42)
430
+ expect(file_stat.gid).to be(42)
431
+ end
432
+ end
433
+
434
+ describe "#grpowned?" do
435
+ context "when the effective user group owns of the file" do
436
+ it "returns true" do
437
+ fs.chown(0, Process.egid, '/test-file')
438
+ expect(file_stat.grpowned?).to be_true
439
+ end
440
+ end
441
+
442
+ context "when the effective user group does not own of the file" do
443
+ it "returns false" do
444
+ fs.chown(0, 0, '/test-file')
445
+ expect(file_stat.grpowned?).to be_false
446
+ end
139
447
  end
140
448
  end
141
449
 
142
450
  describe "#ino" do
143
451
  it "returns the inode number for stat." do
144
- fs.touch('/test-file')
145
- expect(File::Stat.new('/test-file').ino).to be_a(Fixnum)
452
+ expect(file_stat.ino).to be_a(Fixnum)
146
453
  end
147
454
  end
148
455
 
149
456
  describe '#mode' do
150
457
  it "returns an integer representing the permission bits of stat" do
151
- fs.touch('/test-file')
152
458
  fs.chmod(0777, '/test-file')
153
- expect(File::Stat.new('/test-file').mode).to be(0100777)
459
+ expect(file_stat.mode).to be(0100777)
460
+ end
461
+ end
462
+
463
+ describe "#owned?" do
464
+ context "when the effective user owns of the file" do
465
+ it "returns true" do
466
+ fs.chown(Process.euid, 0, '/test-file')
467
+ expect(file_stat.owned?).to be_true
468
+ end
469
+ end
470
+
471
+ context "when the effective user does not own of the file" do
472
+ it "returns false" do
473
+ fs.chown(0, 0, '/test-file')
474
+ expect(file_stat.owned?).to be_false
475
+ end
476
+ end
477
+ end
478
+
479
+ describe "#pipe?" do
480
+ # Pipes are not handled for now
481
+
482
+ context "when the file is not a pipe" do
483
+ it "returns false" do
484
+ expect(file_stat.pipe?).to be_false
485
+ end
486
+ end
487
+ end
488
+
489
+ describe "#readable?" do
490
+ let(:access) { 0 }
491
+ let(:gid) { 0 }
492
+ let(:uid) { 0 }
493
+
494
+ before :each do
495
+ entry.mode = access
496
+ entry.uid = uid
497
+ entry.gid = gid
498
+ end
499
+
500
+ context "when the file is not readable by anyone" do
501
+ it "return false" do
502
+ expect(file_stat.readable?).to be_false
503
+ end
504
+ end
505
+
506
+ context "when the file is user readable" do
507
+ let(:access) { MemFs::Fake::Entry::UREAD }
508
+
509
+ context "and the current user owns the file" do
510
+ let(:uid) { Process.euid }
511
+
512
+ it "returns true" do
513
+ expect(file_stat.readable?).to be_true
514
+ end
515
+ end
516
+ end
517
+
518
+ context "when the file is group readable" do
519
+ let(:access) { MemFs::Fake::Entry::GREAD }
520
+
521
+ context "and the current user is part of the owner group" do
522
+ let(:gid) { Process.egid }
523
+
524
+ it "returns true" do
525
+ expect(file_stat.readable?).to be_true
526
+ end
527
+ end
528
+ end
529
+
530
+ context "when the file is readable by anyone" do
531
+ let(:access) { MemFs::Fake::Entry::OREAD }
532
+
533
+ context "and the user has no specific right on it" do
534
+ it "returns true" do
535
+ expect(file_stat.readable?).to be_true
536
+ end
537
+ end
538
+ end
539
+ end
540
+
541
+ describe "#readable_real?" do
542
+ let(:access) { 0 }
543
+ let(:gid) { 0 }
544
+ let(:uid) { 0 }
545
+
546
+ before :each do
547
+ entry.mode = access
548
+ entry.uid = uid
549
+ entry.gid = gid
550
+ end
551
+
552
+ context "when the file is not readable by anyone" do
553
+ it "return false" do
554
+ expect(file_stat.readable_real?).to be_false
555
+ end
556
+ end
557
+
558
+ context "when the file is user readable" do
559
+ let(:access) { MemFs::Fake::Entry::UREAD }
560
+
561
+ context "and the current user owns the file" do
562
+ let(:uid) { Process.euid }
563
+
564
+ it "returns true" do
565
+ expect(file_stat.readable_real?).to be_true
566
+ end
567
+ end
568
+ end
569
+
570
+ context "when the file is group readable" do
571
+ let(:access) { MemFs::Fake::Entry::GREAD }
572
+
573
+ context "and the current user is part of the owner group" do
574
+ let(:gid) { Process.egid }
575
+
576
+ it "returns true" do
577
+ expect(file_stat.readable_real?).to be_true
578
+ end
579
+ end
580
+ end
581
+
582
+ context "when the file is readable by anyone" do
583
+ let(:access) { MemFs::Fake::Entry::OREAD }
584
+
585
+ context "and the user has no specific right on it" do
586
+ it "returns true" do
587
+ expect(file_stat.readable_real?).to be_true
588
+ end
589
+ end
590
+ end
591
+
592
+ context "when the file does not exist" do
593
+ it "returns false" do
594
+ expect(file_stat.readable_real?).to be_false
595
+ end
596
+ end
597
+ end
598
+
599
+ describe "#setgid?" do
600
+ context "when the file has the setgid bit set" do
601
+ it "returns true" do
602
+ fs.chmod(02000, '/test-file')
603
+ expect(file_stat.setgid?).to be_true
604
+ end
605
+ end
606
+
607
+ context "when the file does not have the setgid bit set" do
608
+ it "returns false" do
609
+ expect(file_stat.setgid?).to be_false
610
+ end
611
+ end
612
+ end
613
+
614
+ describe "#setuid?" do
615
+ context "when the file has the setuid bit set" do
616
+ it "returns true" do
617
+ fs.chmod(04000, '/test-file')
618
+ expect(file_stat.setuid?).to be_true
619
+ end
620
+ end
621
+
622
+ context "when the file does not have the setuid bit set" do
623
+ it "returns false" do
624
+ expect(file_stat.setuid?).to be_false
625
+ end
626
+ end
627
+ end
628
+
629
+ describe "#socket?" do
630
+ # Sockets are not handled for now
631
+
632
+ context "when the file is not a socket" do
633
+ it "returns false" do
634
+ expect(file_stat.socket?).to be_false
635
+ end
154
636
  end
155
637
  end
156
638
 
157
639
  describe "#sticky?" do
158
640
  it "returns true if the named file has the sticky bit set" do
159
- fs.touch('/test-file')
160
641
  fs.chmod(01777, '/test-file')
161
- expect(File::Stat.new('/test-file')).to be_sticky
642
+ expect(file_stat.sticky?).to be_true
162
643
  end
163
644
 
164
645
  it "returns false if the named file hasn't' the sticky bit set" do
165
- fs.touch('/test-file')
166
- expect(File::Stat.new('/test-file')).not_to be_sticky
646
+ expect(file_stat.sticky?).to be_false
167
647
  end
168
648
  end
169
649
 
170
650
  describe '#symlink?' do
171
- it "returns true if the entry is a symlink" do
172
- fs.touch('/test-file')
173
- fs.symlink('/test-file', '/test-link')
174
- expect(File::Stat.new('/test-link').symlink?).to be_true
651
+ context 'when dereference is true' do
652
+ context "when the entry is a symlink" do
653
+ it "returns false" do
654
+ expect(dereferenced_link_stat.symlink?).to be_false
655
+ end
656
+ end
657
+
658
+ context "when the entry is not a symlink" do
659
+ it "returns false" do
660
+ expect(dereferenced_file_stat.symlink?).to be_false
661
+ end
662
+ end
175
663
  end
176
664
 
177
- it "returns false if the entry is not a symlink" do
178
- fs.touch('/test-file')
179
- expect(File::Stat.new('/test-file').symlink?).to be_false
665
+ context 'when dereference is false' do
666
+ context "when the entry is a symlink" do
667
+ it "returns true" do
668
+ expect(link_stat.symlink?).to be_true
669
+ end
670
+ end
671
+
672
+ context "when the entry is not a symlink" do
673
+ it "returns false" do
674
+ expect(file_stat.symlink?).to be_false
675
+ end
676
+ end
180
677
  end
181
678
  end
182
679
 
183
680
  describe "#uid" do
184
681
  it "returns the user id of the named entry" do
185
- fs.touch('/test-file')
186
682
  fs.chown(42, nil, '/test-file')
187
- expect(File::Stat.new('/test-file').uid).to be(42)
683
+ expect(file_stat.uid).to be(42)
684
+ end
685
+ end
686
+
687
+ describe "#world_reable?" do
688
+ context "when +file_name+ is readable by others" do
689
+ it "returns an integer representing the file permission bits of +file_name+" do
690
+ fs.chmod(MemFs::Fake::Entry::OREAD, '/test-file')
691
+ expect(file_stat.world_readable?).to eq(MemFs::Fake::Entry::OREAD)
692
+ end
693
+ end
694
+
695
+ context "when +file_name+ is not readable by others" do
696
+ it "returns nil" do
697
+ fs.chmod(MemFs::Fake::Entry::UREAD, '/test-file')
698
+ expect(file_stat.world_readable?).to be_nil
699
+ end
188
700
  end
189
701
  end
190
702
 
191
703
  describe "#world_writable?" do
192
704
  context "when +file_name+ is writable by others" do
193
705
  it "returns an integer representing the file permission bits of +file_name+" do
194
- fs.touch('/test-file')
195
- fs.chmod(0777, '/test-file')
196
- expect(File::Stat.new('/test-file')).to be_world_writable
706
+ fs.chmod(MemFs::Fake::Entry::OWRITE, '/test-file')
707
+ expect(file_stat.world_writable?).to eq(MemFs::Fake::Entry::OWRITE)
197
708
  end
198
709
  end
199
710
 
200
711
  context "when +file_name+ is not writable by others" do
201
712
  it "returns nil" do
202
- fs.touch('/test-file')
203
- fs.chmod(0644, '/test-file')
204
- expect(File::Stat.new('/test-file')).not_to be_world_writable
713
+ fs.chmod(MemFs::Fake::Entry::UWRITE, '/test-file')
714
+ expect(file_stat.world_writable?).to be_nil
715
+ end
716
+ end
717
+ end
718
+
719
+ describe "#writable?" do
720
+ let(:access) { 0 }
721
+ let(:gid) { 0 }
722
+ let(:uid) { 0 }
723
+
724
+ before :each do
725
+ entry.mode = access
726
+ entry.uid = uid
727
+ entry.gid = gid
728
+ end
729
+
730
+ context "when the file is not executable by anyone" do
731
+ it "return false" do
732
+ expect(file_stat.writable?).to be_false
733
+ end
734
+ end
735
+
736
+ context "when the file is user executable" do
737
+ let(:access) { MemFs::Fake::Entry::UWRITE }
738
+
739
+ context "and the current user owns the file" do
740
+ let(:uid) { Process.euid }
741
+
742
+ it "returns true" do
743
+ expect(file_stat.writable?).to be_true
744
+ end
745
+ end
746
+ end
747
+
748
+ context "when the file is group executable" do
749
+ let(:access) { MemFs::Fake::Entry::GWRITE }
750
+
751
+ context "and the current user is part of the owner group" do
752
+ let(:gid) { Process.egid }
753
+
754
+ it "returns true" do
755
+ expect(file_stat.writable?).to be_true
756
+ end
757
+ end
758
+ end
759
+
760
+ context "when the file is executable by anyone" do
761
+ let(:access) { MemFs::Fake::Entry::OWRITE }
762
+
763
+ context "and the user has no specific right on it" do
764
+ it "returns true" do
765
+ expect(file_stat.writable?).to be_true
766
+ end
767
+ end
768
+ end
769
+
770
+ context "when the file does not exist" do
771
+ it "returns false" do
772
+ expect(file_stat.writable?).to be_false
773
+ end
774
+ end
775
+ end
776
+
777
+ describe "#writable_real?" do
778
+ let(:access) { 0 }
779
+ let(:gid) { 0 }
780
+ let(:uid) { 0 }
781
+
782
+ before :each do
783
+ entry.mode = access
784
+ entry.uid = uid
785
+ entry.gid = gid
786
+ end
787
+
788
+ context "when the file is not executable by anyone" do
789
+ it "return false" do
790
+ expect(file_stat.writable_real?).to be_false
791
+ end
792
+ end
793
+
794
+ context "when the file is user executable" do
795
+ let(:access) { MemFs::Fake::Entry::UWRITE }
796
+
797
+ context "and the current user owns the file" do
798
+ let(:uid) { Process.euid }
799
+
800
+ it "returns true" do
801
+ expect(file_stat.writable_real?).to be_true
802
+ end
803
+ end
804
+ end
805
+
806
+ context "when the file is group executable" do
807
+ let(:access) { MemFs::Fake::Entry::GWRITE }
808
+
809
+ context "and the current user is part of the owner group" do
810
+ let(:gid) { Process.egid }
811
+
812
+ it "returns true" do
813
+ expect(file_stat.writable_real?).to be_true
814
+ end
815
+ end
816
+ end
817
+
818
+ context "when the file is executable by anyone" do
819
+ let(:access) { MemFs::Fake::Entry::OWRITE }
820
+
821
+ context "and the user has no specific right on it" do
822
+ it "returns true" do
823
+ expect(file_stat.writable_real?).to be_true
824
+ end
825
+ end
826
+ end
827
+
828
+ context "when the file does not exist" do
829
+ it "returns false" do
830
+ expect(file_stat.writable_real?).to be_false
831
+ end
832
+ end
833
+ end
834
+
835
+ describe "#zero?" do
836
+ context "when the file has a zero size" do
837
+ it "returns true" do
838
+ expect(file_stat.zero?).to be_true
839
+ end
840
+ end
841
+
842
+ context "when the file does not have a zero size" do
843
+ before :each do
844
+ fs.find!('/test-file').content << 'test'
845
+ end
846
+
847
+ it "returns false" do
848
+ expect(file_stat.zero?).to be_false
205
849
  end
206
850
  end
207
851
  end