rfusefs 1.0.2.RC0 → 1.0.2.RC1

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.
@@ -3,40 +3,47 @@ require "spec_helper"
3
3
  require "fusefs/pathmapper"
4
4
  require 'tmpdir'
5
5
  require 'pathname'
6
+ require 'sys/filesystem'
7
+ require 'ffi-xattr/extensions'
6
8
 
7
9
  class PMFixture
8
10
  attr_reader :tmpdir
9
11
 
10
12
  def initialize()
11
- @tmpdir = Pathname.new(Dir.mktmpdir("rfusefs_pathmapper"))
12
- pathmap(@tmpdir + "hello.txt","/textfiles/hello")
13
- pathmap(@tmpdir + "mysong.mp3","/artist/album/mysong.mp3")
14
- pathmap(@tmpdir + "apicture.jpeg","/pictures/201103/apicture.jpg")
13
+ #Note - these names define the filesystem stats so if you change them those tests will break
15
14
  end
16
15
 
17
- def pathmap(real_file,mapped_path)
18
- File.open(real_file.to_s,"w") do |f|
19
- f << mapped_path
16
+ def tmpdir
17
+ @tmpdir ||= Pathname.new(Dir.mktmpdir("rfusefs_pathmapper"))
18
+ end
19
+
20
+ def real_path(file)
21
+ tmpdir + file
22
+ end
23
+
24
+ def pathmap(file,mapped_path, content = mapped_path, options = {})
25
+ real_file = tmpdir + file
26
+ real_file.open("w") do |f|
27
+ f << content
20
28
  end
29
+ fs.map_file(real_file,mapped_path,options)
21
30
  end
22
31
 
23
32
  def fs
24
- @fs ||= FuseFS::PathMapperFS.create(@tmpdir) do |file|
25
- File.file?(file) ? IO.read(file.to_s) : nil
26
- end
33
+ @fs ||= FuseFS::PathMapperFS.new()
27
34
  end
28
35
 
29
36
  def mount()
30
37
  return @mountpoint if @mountpoint
31
38
  @mountpoint = Pathname.new(Dir.mktmpdir("rfusefs_pathmapper_mnt"))
32
39
  FuseFS.mount(fs,@mountpoint)
33
- sleep(0.5)
40
+ sleep(0.5)
34
41
  @mountpoint
35
42
  end
36
43
 
37
44
  def cleanup
38
45
  if @mountpoint
39
- FuseFS.unmount(@mountpoint)
46
+ FuseFS.unmount(@mountpoint)
40
47
  sleep(0.5)
41
48
  FileUtils.rmdir(@mountpoint)
42
49
  end
@@ -46,134 +53,333 @@ end
46
53
 
47
54
 
48
55
  describe FuseFS::PathMapperFS do
49
- before(:each) do
50
- @fixture = PMFixture.new
51
- @tmpdir = @fixture.tmpdir
52
- @pathmapFS = @fixture.fs
56
+
57
+ let(:fixture) { PMFixture.new() }
58
+ let(:pathmap_fs) { fixture.fs }
59
+ let(:tmpdir) { fixture.tmpdir }
60
+ let(:mountpoint) { fixture.mount }
61
+
62
+ before(:each) do
63
+ fixture.pathmap("hello.txt","/textfiles/hello")
64
+ fixture.pathmap("mysong.mp3","/artist/album/mysong.mp3")
65
+ fixture.pathmap("apicture.jpeg","/pictures/201103/apicture.jpg")
53
66
  end
54
67
 
55
68
  after(:each) do
56
- @fixture.cleanup
69
+ fixture.cleanup
57
70
  end
58
71
 
59
72
  context "fusefs api" do
60
73
 
61
74
  it "maps files and directories" do
62
- @pathmapFS.directory?("/").should be_true
63
- @pathmapFS.directory?("/textfiles").should be_true
64
- @pathmapFS.directory?("/pictures/201103").should be_true
65
- @pathmapFS.file?("/textfiles/hello").should be_true
66
- @pathmapFS.directory?("/textfiles/hello").should be_false
67
- @pathmapFS.file?("/artist/album/mysong.mp3").should be_true
68
- @pathmapFS.directory?("/artist/album/mysong.mp3").should be_false
69
- @pathmapFS.file?("/some/unknown/path").should be_false
70
- @pathmapFS.directory?("/some/unknown/path").should be_false
75
+ pathmap_fs.directory?("/").should be_true
76
+ pathmap_fs.directory?("/textfiles").should be_true
77
+ pathmap_fs.directory?("/pictures/201103").should be_true
78
+ pathmap_fs.file?("/textfiles/hello").should be_true
79
+ pathmap_fs.directory?("/textfiles/hello").should be_false
80
+ pathmap_fs.file?("/artist/album/mysong.mp3").should be_true
81
+ pathmap_fs.directory?("/artist/album/mysong.mp3").should be_false
82
+ pathmap_fs.file?("/some/unknown/path").should be_false
83
+ pathmap_fs.directory?("/some/unknown/path").should be_false
71
84
  end
72
85
 
73
86
  it "lists the mapped contents of directories" do
74
- @pathmapFS.contents("/").should =~ [ "textfiles","artist","pictures" ]
75
- @pathmapFS.contents("/artist").should =~ [ "album" ]
76
- @pathmapFS.contents("/textfiles").should =~ [ "hello" ]
87
+ pathmap_fs.contents("/").should =~ [ "textfiles","artist","pictures" ]
88
+ pathmap_fs.contents("/artist").should =~ [ "album" ]
89
+ pathmap_fs.contents("/textfiles").should =~ [ "hello" ]
77
90
  end
78
91
 
79
92
  it "reports the size of a file" do
80
- @pathmapFS.size("/textfiles/hello").should == 16
93
+ pathmap_fs.size("/textfiles/hello").should == 16
81
94
  end
82
95
 
83
96
  it "reads the contents of a file" do
84
- @pathmapFS.read_file("/textfiles/hello").should == "/textfiles/hello"
97
+ pathmap_fs.read_file("/textfiles/hello").should == "/textfiles/hello"
85
98
  end
86
99
 
87
100
  it "does not allow writes" do
88
- @pathmapFS.can_write?("/textfiles/hello").should be_false
101
+ pathmap_fs.can_write?("/textfiles/hello").should be_false
89
102
  end
90
103
 
91
104
  it "reports the atime,mtime and ctime of the mapped file" do
92
- atime,mtime,ctime = @pathmapFS.times("/pictures/201103/apicture.jpg")
93
- picture = @tmpdir + "apicture.jpeg"
105
+ atime,mtime,ctime = pathmap_fs.times("/pictures/201103/apicture.jpg")
106
+ picture = tmpdir + "apicture.jpeg"
94
107
  atime.should == picture.atime()
95
108
  mtime.should == picture.mtime()
96
109
  ctime.should == picture.ctime()
97
110
  end
98
111
 
99
- it "reports filesystem statistics"
112
+ context "with extended attributes" do
113
+ let (:hello_realpath) {fixture.real_path("hello.txt")}
114
+ let (:hello_xattr) { Xattr.new(hello_realpath) }
115
+ let (:pm_file_xattr) { pathmap_fs.xattr("/textfiles/hello") }
116
+ let (:pm_dir_xattr) { pathmap_fs.xattr("/textfiles") }
117
+
118
+ before(:each) do
119
+ # attribute set on real file
120
+ hello_xattr["user.file_attr"] = "fileValue"
121
+
122
+ # additional attribute on file
123
+ pathmap_fs.node("/textfiles/hello")[:xattr] =
124
+ { "user.add_attr" => "addValue" }
125
+
126
+ # additional attribute on directory
127
+ pathmap_fs.node("/textfiles")[:xattr] =
128
+ { "user.dir_attr" => "dirValue" }
129
+
130
+ end
131
+
132
+ it "should list extended attributes" do
133
+ pm_file_xattr.keys.should include("user.file_attr")
134
+ pm_file_xattr.keys.should include("user.add_attr")
135
+ pm_file_xattr.keys.size.should == 2
136
+ end
137
+
138
+ it "should read extended attributes from underlying file" do
139
+ pm_file_xattr["user.file_attr"].should == "fileValue"
140
+ end
141
+
142
+ it "should read additional attributes" do
143
+ # make sure additional attributes are not on the real file
144
+ hello_xattr.list.should_not include("user.add_attr")
145
+
146
+ pm_file_xattr["user.add_attr"].should == "addValue"
147
+ end
148
+
149
+ it "should write extended attributes to the underlying file" do
150
+ pm_file_xattr["user.file_attr"] = "written"
151
+ hello_xattr["user.file_attr"].should == "written"
152
+ end
153
+
154
+ it "should remove extended attributes from the underlying file" do
155
+ pm_file_xattr.delete("user.file_attr")
156
+ hello_xattr.list.should_not include("user.file_attr")
157
+ end
158
+
159
+ it "raise EACCES when writing to additional attributes" do
160
+ lambda {pm_file_xattr["user.add_attr"] = "newValue"}.should raise_error(Errno::EACCES)
161
+ end
162
+
163
+ it "raise EACCES when removing additional attributes" do
164
+ lambda {pm_file_xattr.delete("user.add_attr")}.should raise_error(Errno::EACCES)
165
+ end
166
+
167
+ it "should list additional attributes from virtual directories" do
168
+ pm_dir_xattr.keys.should include("user.dir_attr")
169
+ pm_dir_xattr.keys.size.should == 1
170
+ end
171
+
172
+ it "should read additional attributes from virtual directories" do
173
+ pm_dir_xattr["user.dir_attr"].should == "dirValue"
174
+
175
+ end
176
+
177
+ it "should raise EACCES when writing additional attributes on virtual directories" do
178
+ lambda {pm_dir_xattr["user.dir_attr"] = "newValue"}.should raise_error(Errno::EACCES)
179
+ end
180
+
181
+ it "should raise EACCES when deleting additional attributes on virtual directories" do
182
+ lambda {pm_dir_xattr.delete("user.dir_attr")}.should raise_error(Errno::EACCES)
183
+ end
184
+
185
+ it "should accept xattr as option to #map_file" do
186
+ fixture.pathmap("mapped_xattr.txt","/textfiles/mapped_xattr","content",
187
+ :xattr => { "user.xattr" => "map_file" })
188
+ pathmap_fs.xattr("/textfiles/mapped_xattr")["user.xattr"].should == "map_file"
189
+ end
190
+ end
191
+
192
+ context "filesystem statistics" do
193
+
194
+ it "reports accumulated stats about mapped files" do
195
+ used_space, used_nodes, max_space, max_nodes = pathmap_fs.statistics("/pictures/201103/apicture.jpg")
196
+ used_space.should == 69
197
+ used_nodes.should == 9
198
+ max_space.should be_nil
199
+ max_nodes.should be_nil
200
+ end
201
+ end
100
202
 
101
203
  context "writing to a pathmapped FS" do
102
204
  before(:each) do
103
- @pathmapFS.allow_write=true
104
- @pathmapFS.write_to("textfiles/hello","updated content")
205
+ pathmap_fs.allow_write=true
206
+ pathmap_fs.write_to("textfiles/hello","updated content")
105
207
  end
106
208
 
107
209
  it "updates the contents of the real file" do
108
- hello_path = @tmpdir + "hello.txt"
210
+ hello_path = tmpdir + "hello.txt"
109
211
  hello_path.read.should == "updated content"
110
212
  end
111
213
 
112
214
  it "updates the contents of the mapped file" do
113
- @pathmapFS.read_file("textfiles/hello").should == "updated content"
215
+ pathmap_fs.read_file("textfiles/hello").should == "updated content"
114
216
  end
115
217
 
116
218
  it "changes the reported file size" do
117
- @pathmapFS.size("textfiles/hello").should == 15
219
+ pathmap_fs.size("textfiles/hello").should == 15
118
220
  end
119
221
 
120
- it "changes the filesystem statistics"
222
+ it "changes the filesystem statistics" do
223
+ used_space, used_nodes, max_space, max_nodes = pathmap_fs.statistics("/pictures/201103/apicture.jpg")
224
+ used_space.should == 68
225
+ end
121
226
  end
122
227
 
123
228
  end
124
229
 
125
230
  context "a real Fuse mounted filesystem" do
126
231
  before(:each) do
127
- @pathmapFS.allow_write=true
128
- @mountpoint = @fixture.mount
232
+ pathmap_fs.allow_write=true
129
233
  end
130
234
 
131
235
  it "maps files and directories" do
132
- (@mountpoint + "textfiles").directory?.should be_true
133
- (@mountpoint + "textfiles/hello").file?.should be_true
236
+ (mountpoint + "textfiles").directory?.should be_true
237
+ (mountpoint + "textfiles/hello").file?.should be_true
134
238
  end
135
239
 
136
240
  it "lists the mapped contents of directories" do
137
- (@mountpoint + "textfiles").entries.should =~ pathnames(".","..","hello")
241
+ (mountpoint + "textfiles").entries.should =~ pathnames(".","..","hello")
138
242
  end
139
243
 
140
244
  it "represents the stat information of the underlying files" do
141
- hellopath=(@mountpoint + "textfiles/hello")
142
- realpath=(@tmpdir + "hello.txt")
245
+ hellopath=(mountpoint + "textfiles/hello")
246
+ realpath=(tmpdir + "hello.txt")
143
247
  mappedstat = hellopath.stat
144
248
  realstat = realpath.stat
145
249
  mappedstat.size.should == realstat.size
146
- mappedstat.atime.should == realstat.atime
250
+ mappedstat.atime.should == realstat.atime
147
251
  mappedstat.mtime.should == realstat.mtime
148
252
  mappedstat.ctime.should == realstat.ctime
149
253
  end
150
254
 
151
255
  it "reads the files" do
152
- hellopath= @mountpoint + "textfiles/hello"
256
+ hellopath= mountpoint + "textfiles/hello"
153
257
  hellopath.read.should == "/textfiles/hello"
154
258
  end
155
259
 
156
260
  it "writes the files" do
157
- hellopath= @mountpoint + "textfiles/hello"
158
- real_path = @tmpdir + "hello.txt"
261
+ hellopath= mountpoint + "textfiles/hello"
262
+ real_path = tmpdir + "hello.txt"
159
263
  hellopath.open("w") do |f|
160
264
  f.print "updated content"
161
- end
265
+ end
162
266
  hellopath.read.should == "updated content"
163
267
  real_path.read.should == "updated content"
164
268
  end
269
+
270
+ context "extended attributes" do
271
+ let (:hello_realpath) {fixture.real_path("hello.txt")}
272
+ let (:hello_xattr) { hello_realpath.xattr }
273
+ let (:file_xattr) { (mountpoint + "textfiles/hello").xattr }
274
+ let (:dir_xattr) { (mountpoint + "textfiles").xattr }
275
+
276
+ before(:each) do
277
+ # attribute set on real file
278
+ hello_xattr["user.file_attr"] = "fileValue"
279
+
280
+ # additional attribute on file
281
+ pathmap_fs.node("/textfiles/hello")[:xattr] =
282
+ { "user.add_attr" => "addValue" }
283
+
284
+ # additional attribute on directory
285
+ pathmap_fs.node("/textfiles")[:xattr] =
286
+ { "user.dir_attr" => "dirValue" }
287
+
288
+ end
289
+
290
+ it "should list extended attributes" do
291
+ file_xattr.list.should include("user.file_attr")
292
+ file_xattr.list.should include("user.add_attr")
293
+ file_xattr.list.size.should == 2
294
+ end
295
+
296
+ it "should read extended attributes from underlying file" do
297
+ file_xattr["user.file_attr"].should == "fileValue"
298
+ end
299
+
300
+ it "should read additional attributes" do
301
+ file_xattr["user.add_attr"].should == "addValue"
302
+ end
303
+
304
+ it "should write extended attributes to the underlying file" do
305
+ file_xattr["user.file_attr"] = "written"
306
+ hello_xattr["user.file_attr"].should == "written"
307
+ end
308
+
309
+ it "should remove extended attributes from the underlying file" do
310
+ file_xattr.remove("user.file_attr")
311
+ hello_xattr.list.should_not include("user.file_attr")
312
+ end
313
+
314
+ it "raise EACCES when writing to additional attributes" do
315
+ lambda {file_xattr["user.add_attr"] = "newValue"}.should raise_error(Errno::EACCES)
316
+ end
317
+
318
+ it "raise EACCES when removing additional attributes" do
319
+ lambda {file_xattr.remove("user.add_attr")}.should raise_error(Errno::EACCES)
320
+ end
321
+
322
+ it "should list additional attributes from virtual directories" do
323
+ dir_xattr.list.should include("user.dir_attr")
324
+ dir_xattr.list.size.should == 1
325
+ end
326
+
327
+ it "should read additional attributes from virtual directories" do
328
+ dir_xattr["user.dir_attr"].should == "dirValue"
329
+ end
330
+
331
+ it "should raise EACCES when writing additional attributes on virtual directories" do
332
+ lambda {dir_xattr["user.dir_attr"] = "newValue"}.should raise_error(Errno::EACCES)
333
+ end
334
+
335
+ it "should raise EACCES when deleting additional attributes on virtual directories" do
336
+ lambda {dir_xattr.remove("user.dir_attr")}.should raise_error(Errno::EACCES)
337
+ end
338
+
339
+ end
340
+
341
+ context "filesystem statistics" do
342
+ before(:each) do
343
+ fixture.pathmap("bigfile.txt","/textfiles/bigfile","x" * 2048)
344
+ end
345
+
346
+ it "reports stats for files" do
347
+ statfs = Sys::Filesystem.stat(mountpoint.to_path)
348
+ # These are fixed
349
+ statfs.block_size.should == 1024
350
+ statfs.fragment_size.should == 1024
351
+
352
+ # These are dependant on the tests above creating files/directories
353
+ statfs.files.should == 10
354
+ statfs.files_available == 10
355
+
356
+ # assume test are less than 1 block, so dependant on bigfile above
357
+ statfs.blocks.should == 2
358
+ statfs.blocks_available.should == 0
359
+ statfs.blocks_free.should == 0
360
+ end
361
+
362
+ it "reports stats for files after writing" do
363
+
364
+ (mountpoint + "textfiles/bigfile").open("w") { |f| f.print("y" * 4096) }
365
+ statfs = Sys::Filesystem.stat(mountpoint.to_path)
366
+ statfs.files.should == 10
367
+ statfs.blocks.should == 4
368
+
369
+ end
370
+
371
+ end
165
372
  end
166
373
 
167
374
  context "a real Fuse mount with raw file access" do
168
375
 
169
376
  before(:each) do
170
- @pathmapFS.use_raw_file_access = true
171
- @pathmapFS.allow_write = true
172
- @mountpoint = @fixture.mount
377
+ pathmap_fs.use_raw_file_access = true
378
+ pathmap_fs.allow_write = true
173
379
  end
174
380
 
175
381
  it "reads files" do
176
- hello_path = (@mountpoint + "textfiles/hello")
382
+ hello_path = (mountpoint + "textfiles/hello")
177
383
  hello_path.open do |f|
178
384
  f.seek(2)
179
385
  f.read(3).should == "ext"
@@ -186,17 +392,26 @@ describe FuseFS::PathMapperFS do
186
392
  end
187
393
 
188
394
  it "writes files" do
189
- hello_path = (@mountpoint + "textfiles/hello")
190
- real_path = @tmpdir + "hello.txt"
395
+ hello_path = (mountpoint + "textfiles/hello")
396
+ real_path = tmpdir + "hello.txt"
191
397
  hello_path.open("r+") do |f|
192
398
  f.sysseek(2)
193
399
  f.syswrite("zzz")
194
400
  f.sysseek(0)
195
401
  f.sysread(6).should == "/tzzzf"
196
- end
402
+ end
197
403
 
198
- real_path.read.should == "/tzzzfiles/hello"
404
+ real_path.read.should == "/tzzzfiles/hello"
199
405
  end
200
406
 
407
+ it "reports filesystem statistics after raw write" do
408
+ hello_path = (mountpoint + "textfiles/hello")
409
+ hello_path.open("w") do |f|
410
+ f.syswrite("z" * 2048)
411
+ end
412
+
413
+ statfs = Sys::Filesystem.stat(mountpoint.to_path)
414
+ statfs.blocks.should == 2
415
+ end
201
416
  end
202
417
  end
data/spec/rfusefs_spec.rb CHANGED
@@ -197,10 +197,23 @@ describe FuseFS do
197
197
  filetype(stat.mode).should == RFuse::Stat::S_IFREG
198
198
  stat.size.should == 0
199
199
  end
200
-
200
+
201
+ it "should create zero length files" do
202
+ ffi = Struct::FuseFileInfo.new()
203
+ ffi.flags = Fcntl::O_WRONLY
204
+ @mock_fuse.stub!(:file?).with(TEST_FILE).and_return(false)
205
+ @mock_fuse.stub!(:directory?).with(TEST_FILE).and_return(false)
206
+ @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
207
+ @mock_fuse.should_receive(:write_to).once.with(TEST_FILE,"")
208
+ @fuse.mknod(nil,TEST_FILE,RFuse::Stat::S_IFREG | 0644,0,0)
209
+ @fuse.open(nil,TEST_FILE,ffi)
210
+ @fuse.flush(nil,TEST_FILE,ffi)
211
+ @fuse.release(nil,TEST_FILE,ffi)
212
+ end
213
+
201
214
  it ":mkdir should not raise error if can_mkdir?" do
202
215
  @mock_fuse.should_receive(:can_mkdir?).with(TEST_FILE).and_return(true)
203
- @fuse.mkdir(nil,TEST_FILE,004555)
216
+ @fuse.mkdir(nil,TEST_FILE,004555)
204
217
  end
205
218
 
206
219
  end
@@ -254,9 +267,11 @@ describe FuseFS do
254
267
  @fuse.release(nil,TEST_FILE,ffi)
255
268
 
256
269
  end
257
-
270
+
258
271
  it "should do sensible things for files opened RDWR"
259
-
272
+
273
+ it "should pass on buffered data when requested (fsync)"
274
+
260
275
  end
261
276
 
262
277
  context "raw reading" do
@@ -278,19 +293,21 @@ describe FuseFS do
278
293
  end
279
294
 
280
295
  context "raw writing" do
281
- it "should call raw_truncate,raw_write,raw_close if raw_open returns true" do
296
+ it "should call other raw_* methods if raw_open returns true" do
282
297
  ffi = Struct::FuseFileInfo.new()
283
- ffi.flags = Fcntl::O_WRONLY
298
+ ffi.flags = Fcntl::O_WRONLY
284
299
  raw = Object.new()
285
300
  @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
286
301
  @mock_fuse.should_receive(:raw_open).with(TEST_FILE,"w",true).and_return(raw)
287
302
  @mock_fuse.should_receive(:raw_truncate).with(TEST_FILE,0,raw)
288
303
  @mock_fuse.should_receive(:raw_write).with(TEST_FILE,0,5,"12345",raw).once().and_return(5)
289
304
  @mock_fuse.should_receive(:raw_write).with(TEST_FILE,5,5,"67890",raw).once().and_return(5)
305
+ @mock_fuse.should_receive(:raw_sync).with(TEST_FILE, false, raw)
290
306
  @mock_fuse.should_receive(:raw_close).with(TEST_FILE,raw)
291
307
  @fuse.open(nil,TEST_FILE,ffi)
292
308
  @fuse.ftruncate(nil,TEST_FILE,0,ffi)
293
309
  @fuse.write(nil,TEST_FILE,"12345",0,ffi).should == 5
310
+ @fuse.fsync(nil,TEST_FILE,0,ffi)
294
311
  @fuse.write(nil,TEST_FILE,"67890",5,ffi).should == 5
295
312
  @fuse.flush(nil,TEST_FILE,ffi)
296
313
  @fuse.release(nil,TEST_FILE,ffi)
@@ -393,24 +410,63 @@ describe FuseFS do
393
410
  end
394
411
  context "extended attributes" do
395
412
 
396
- let(:xattr) { {} }
413
+ let(:xattr) { mock(:xattr) }
397
414
  before(:each) { @mock_fuse.stub!(:xattr).with(TEST_FILE).and_return(xattr) }
398
415
 
399
- it "should get, set and list attributes" do
400
- xattr["user.one"] = "xattr one"
401
-
402
- @fuse.getxattr(nil,TEST_FILE,"user.one").should == "xattr one"
403
- @fuse.setxattr(nil,TEST_FILE,"user.two","xattr two")
404
- xattr["user.two"].should == "xattr two"
405
- @fuse.listxattr(nil,TEST_FILE).should =~ [ "user.one", "user.two" ]
406
- @fuse.removexattr(nil,TEST_FILE,"user.two")
407
- xattr.keys.should =~ [ "user.one" ]
416
+ it "should list attributes via #keys on result of #xattr" do
417
+ xattr.should_receive(:keys).and_return(["one","two"])
418
+ @fuse.listxattr(nil,TEST_FILE).should == [ "one","two" ]
408
419
  end
409
420
 
410
- it "should raise ENODATA is no attribute is available" do
421
+ it "should get attributes via #xattr.[]" do
422
+ xattr.should_receive(:[]).with("user.one").and_return("one")
423
+
424
+ @fuse.getxattr(nil,TEST_FILE,"user.one").should == "one"
425
+ end
426
+
427
+ it "should set attributes via #xattr.[]=" do
428
+ xattr.should_receive(:[]=).with("user.two","two")
429
+
430
+ @fuse.setxattr(nil,TEST_FILE,"user.two","two",0)
431
+ end
432
+
433
+ it "should remove attributes via #xattr.delete" do
434
+ xattr.should_receive(:delete).with("user.three")
435
+
436
+ @fuse.removexattr(nil,TEST_FILE,"user.three")
437
+ end
438
+
439
+ it "should raise ENODATA when #xattr.[] returns nil" do
440
+
441
+ xattr.should_receive(:[]).with("user.xxxx").and_return(nil)
411
442
  lambda{@fuse.getxattr(nil,TEST_FILE,"user.xxxx") }.should raise_error(Errno::ENODATA)
412
443
  end
413
444
  end
445
+
446
+ context "#statfs" do
447
+ # used space, used files, total_space, total_files
448
+ let(:stats) { [ 1000 * 1024, 5, 1200 * 1024, 12 ] }
449
+ it "should convert simple array into StatVfs" do
450
+
451
+ @mock_fuse.should_receive(:statistics).with(TEST_FILE).and_return(stats)
452
+
453
+ result = @fuse.statfs(nil,TEST_FILE)
454
+ result.should be_kind_of(RFuse::StatVfs)
455
+ result.f_bsize.should == 1024
456
+ result.f_blocks.should == 1200
457
+ result.f_bavail.should == 200
458
+ result.f_files.should == 12
459
+ result.f_ffree.should == 7
460
+ end
461
+
462
+ it "passes on raw statistics" do
463
+ statvfs = Object.new()
464
+ @mock_fuse.should_receive(:statistics).with(TEST_FILE).and_return(statvfs)
465
+
466
+ @fuse.statfs(nil,TEST_FILE).should equal(statvfs)
467
+ end
468
+
469
+ end
414
470
  end
415
471
 
416
472
  describe "a FuseFS filesystem with gid/uid specific behaviour" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rfusefs
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2.RC0
4
+ version: 1.0.2.RC1
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-01-02 00:00:00.000000000 Z
12
+ date: 2014-02-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rfuse
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 1.0.4
21
+ version: 1.0.5RC0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
- version: 1.0.4
29
+ version: 1.0.5RC0
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: rake
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -107,6 +107,38 @@ dependencies:
107
107
  - - ! '>='
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: sys-filesystem
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: ffi-xattr
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: 0.1.1
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: 0.1.1
110
142
  description: A more Ruby like way to write FUSE filesystems - inspired by (compatible
111
143
  with) FuseFS, implemented over RFuse
112
144
  email: