memfs 0.0.2 → 0.1.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.
@@ -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