rfusefs 1.0.2.RC0 → 1.0.2.RC1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: