rfusefs 1.0.0 → 1.0.1.RC0
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.
- data/.gitignore +1 -1
- data/.travis.yml +8 -0
- data/README.rdoc +13 -21
- data/Rakefile +1 -0
- data/lib/fuse/fusedir.rb +15 -0
- data/lib/fuse/rfusefs-fuse.rb +26 -8
- data/lib/fusefs/metadir.rb +2 -1
- data/lib/fusefs/pathmapper.rb +185 -56
- data/lib/fusefs/sqlitemapper.rb +125 -0
- data/lib/rfusefs/version.rb +1 -1
- data/lib/rfusefs.rb +55 -1
- data/rfusefs.gemspec +30 -0
- data/spec/metadir_spec.rb +24 -24
- data/spec/mount_unmount_spec.rb +21 -0
- data/spec/pathmapper_spec.rb +143 -53
- data/spec/rfusefs_spec.rb +23 -1
- data/spec/sample_spec.rb +9 -9
- data/spec/spec_helper.rb +0 -5
- data/spec/sqlitemapper_spec.rb +135 -0
- metadata +49 -9
data/lib/rfusefs.rb
CHANGED
@@ -8,6 +8,59 @@ require 'rfusefs/version'
|
|
8
8
|
module FuseFS
|
9
9
|
@mounts = { }
|
10
10
|
|
11
|
+
# Convenience method to launch a FuseFS filesystem with nice error messages
|
12
|
+
#
|
13
|
+
# @param [Array<String>] argv command line arguments
|
14
|
+
# @param [Array<Symbol>] options list of additional options
|
15
|
+
# @param [String] option_usage describing additional option usage
|
16
|
+
# @param [String] device a description of the device field
|
17
|
+
# @param [String] exec the executable file
|
18
|
+
#
|
19
|
+
# @yieldparam [Hash<Symbol,String>] options
|
20
|
+
# options parsed from ARGV including...
|
21
|
+
# * :device - the optional mount device
|
22
|
+
# * :mountpoint - required mountpoint
|
23
|
+
# * :help - true if -h was supplied
|
24
|
+
#
|
25
|
+
# @yieldreturn [FuseDir] an RFuseFS filesystem
|
26
|
+
#
|
27
|
+
# @example
|
28
|
+
# MY_OPTIONS = [ :myfs ]
|
29
|
+
# OPTION_USAGE = " -o myfs=VAL how to use the myfs option"
|
30
|
+
#
|
31
|
+
# # Normally from the command line...
|
32
|
+
# ARGV = [ "some/device", "/mnt/point", "-h", "-o", "debug,myfs=aValue" ]
|
33
|
+
#
|
34
|
+
# FuseFS.main(ARGV, MY_OPTIONS, OPTION_USAGE, "/path/to/somedevice", $0) do |options|
|
35
|
+
#
|
36
|
+
# # options ==
|
37
|
+
# { :device => "some/device",
|
38
|
+
# :mountpoint => "/mnt/point",
|
39
|
+
# :help => true,
|
40
|
+
# :debug => true,
|
41
|
+
# :myfs => "aValue"
|
42
|
+
# }
|
43
|
+
#
|
44
|
+
# fs = MyFS.new(options)
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
def FuseFS.main(argv=ARGV,options=[],option_usage="",device=nil,exec=File.basename($0))
|
48
|
+
options = RFuse.parse_options(argv,*options)
|
49
|
+
|
50
|
+
if options[:mountpoint]
|
51
|
+
fs = yield options
|
52
|
+
|
53
|
+
puts RFuse.usage(device,exec) if options[:help] || !fs
|
54
|
+
puts "Options:\n" if options[:help]
|
55
|
+
|
56
|
+
FuseFS.start(fs,*argv) if fs || options[:help]
|
57
|
+
|
58
|
+
puts option_usage if options[:help]
|
59
|
+
else
|
60
|
+
puts "rfusefs: failed, no mountpoint provided",RFuse.usage(device,exec)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
11
64
|
# Start the FuseFS root at mountpoint with opts.
|
12
65
|
# @param [Object] root see {set_root}
|
13
66
|
# @param mountpoint [String] {mount_under}
|
@@ -15,7 +68,6 @@ module FuseFS
|
|
15
68
|
# @note RFuseFS extension
|
16
69
|
# @return [void]
|
17
70
|
def FuseFS.start(root,mountpoint,*opts)
|
18
|
-
print "Starting FuseFS #{root} at #{mountpoint} with #{opts}\n"
|
19
71
|
Signal.trap("TERM") { FuseFS.exit() }
|
20
72
|
Signal.trap("INT") { FuseFS.exit() }
|
21
73
|
FuseFS.set_root(root)
|
@@ -89,7 +141,9 @@ module FuseFS
|
|
89
141
|
# you cannot access your filesystem using ruby File operations.
|
90
142
|
# @note RFuseFS extension
|
91
143
|
def FuseFS.run
|
144
|
+
@fs.mounted()
|
92
145
|
@fuse.loop if @fuse.mounted?
|
146
|
+
@fs.unmounted()
|
93
147
|
end
|
94
148
|
|
95
149
|
# Exit the run loop and teardown FUSE
|
data/rfusefs.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "rfusefs/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "rfusefs"
|
7
|
+
s.version = RFuseFS::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Grant Gardner"]
|
10
|
+
s.email = ["grant@lastweekend.com.au"]
|
11
|
+
s.homepage = "http://rubygems.org/gems/rfusefs"
|
12
|
+
s.summary = %q{Filesystem in Ruby Userspace}
|
13
|
+
s.description = %q{A more Ruby like way to write FUSE filesystems - inspired by (compatible with) FuseFS, implemented over RFuse}
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,spec-fusefs}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.has_rdoc = 'yard'
|
21
|
+
s_extra_rdoc_files = 'History.rdoc'
|
22
|
+
|
23
|
+
s.add_dependency("rfuse", ">= 1.0.4RC0")
|
24
|
+
s.add_development_dependency("rake")
|
25
|
+
s.add_development_dependency("rspec")
|
26
|
+
s.add_development_dependency("yard")
|
27
|
+
s.add_development_dependency("redcarpet")
|
28
|
+
s.add_development_dependency("sqlite3")
|
29
|
+
s.add_development_dependency("rb-inotify")
|
30
|
+
end
|
data/spec/metadir_spec.rb
CHANGED
@@ -220,44 +220,44 @@ describe FuseFS::MetaDir do
|
|
220
220
|
|
221
221
|
end
|
222
222
|
context "in a mounted FUSE filesystem" do
|
223
|
+
|
224
|
+
let(:mountpoint) { Pathname.new(Dir.mktmpdir(["rfusefs","metadir"])) }
|
225
|
+
let(:metadir) { FuseFS::MetaDir.new() }
|
226
|
+
let(:testdir) { mountpoint + "test" }
|
227
|
+
let(:testfile) { testdir + "hello.txt" }
|
228
|
+
|
223
229
|
before(:all) do
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
puts "#{@mountpoint}"
|
228
|
-
@mountpoint.mkdir unless @mountpoint.directory?
|
229
|
-
@metadir = FuseFS::MetaDir.new()
|
230
|
-
@metadir.mkdir("/test")
|
231
|
-
@metadir.write_to("/test/hello.txt","Hello World!\n")
|
232
|
-
FuseFS.mount(@metadir,@mountpoint)
|
233
|
-
@testdir = (@mountpoint + "test")
|
234
|
-
@testfile = (@testdir + "hello.txt")
|
230
|
+
metadir.mkdir("/test")
|
231
|
+
metadir.write_to("/test/hello.txt","Hello World!\n")
|
232
|
+
FuseFS.mount(metadir,mountpoint)
|
235
233
|
#Give FUSE some time to get started
|
236
|
-
sleep(
|
234
|
+
sleep(0.5)
|
237
235
|
end
|
238
236
|
|
239
237
|
after(:all) do
|
240
|
-
FuseFS.unmount(
|
238
|
+
FuseFS.unmount(mountpoint)
|
239
|
+
sleep(0.5)
|
240
|
+
FileUtils.rm_r(mountpoint)
|
241
241
|
end
|
242
242
|
|
243
243
|
it "should list directory contents" do
|
244
|
-
|
244
|
+
testdir.entries().should =~ pathnames(".","..","hello.txt")
|
245
245
|
end
|
246
246
|
|
247
247
|
it "should read files" do
|
248
|
-
|
249
|
-
|
248
|
+
testfile.file?.should be_true
|
249
|
+
testfile.read().should == "Hello World!\n"
|
250
250
|
end
|
251
251
|
|
252
252
|
it "should create directories" do
|
253
|
-
newdir =
|
253
|
+
newdir = testdir + "newdir"
|
254
254
|
newdir.mkdir()
|
255
255
|
newdir.directory?.should be_true
|
256
|
-
|
256
|
+
testdir.entries().should =~ pathnames(".","..","hello.txt","newdir")
|
257
257
|
end
|
258
258
|
|
259
259
|
it "should create files" do
|
260
|
-
newfile =
|
260
|
+
newfile = testdir + "newfile"
|
261
261
|
newfile.open("w") do |file|
|
262
262
|
file << "A new file\n"
|
263
263
|
end
|
@@ -265,14 +265,14 @@ describe FuseFS::MetaDir do
|
|
265
265
|
end
|
266
266
|
|
267
267
|
it "should move directories" do
|
268
|
-
fromdir =
|
268
|
+
fromdir = testdir + "fromdir"
|
269
269
|
fromdir.mkdir()
|
270
270
|
subfile = fromdir + "afile"
|
271
271
|
subfile.open("w") do |file|
|
272
272
|
file << "testfile\n"
|
273
273
|
end
|
274
274
|
|
275
|
-
movedir = (
|
275
|
+
movedir = (mountpoint + "movedir")
|
276
276
|
movedir.directory?.should be_false
|
277
277
|
fromdir.rename(movedir)
|
278
278
|
movedir.directory?.should be_true
|
@@ -283,10 +283,10 @@ describe FuseFS::MetaDir do
|
|
283
283
|
end
|
284
284
|
|
285
285
|
it "should move files" do
|
286
|
-
movefile = (
|
286
|
+
movefile = (mountpoint + "moved.txt")
|
287
287
|
movefile.file?.should be_false
|
288
|
-
|
289
|
-
|
288
|
+
testfile.should be_true
|
289
|
+
testfile.rename(movefile)
|
290
290
|
movefile.read.should == "Hello World!\n"
|
291
291
|
end
|
292
292
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rfusefs'
|
3
|
+
require 'tmpdir'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
describe "a mounted FuseFS" do
|
7
|
+
let(:mountpoint) { Pathname.new(Dir.mktmpdir("rfusefs_mount_unmount")) }
|
8
|
+
|
9
|
+
after(:each) { FileUtils.rmdir mountpoint }
|
10
|
+
|
11
|
+
it "should get mounted and unmounted callbacks" do
|
12
|
+
mock_fs = FuseFS::FuseDir.new()
|
13
|
+
mock_fs.should_receive(:mounted)
|
14
|
+
mock_fs.should_receive(:unmounted)
|
15
|
+
|
16
|
+
t = Thread.new { sleep 0.5 ; puts "exiting" ; FuseFS.exit }
|
17
|
+
FuseFS.start(mock_fs,mountpoint)
|
18
|
+
t.join
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
data/spec/pathmapper_spec.rb
CHANGED
@@ -1,112 +1,202 @@
|
|
1
1
|
#Pathmapper is hard to test because it is difficult to mock Dir/Pathname/File etc...
|
2
2
|
require "spec_helper"
|
3
3
|
require "fusefs/pathmapper"
|
4
|
+
require 'tmpdir'
|
5
|
+
require 'pathname'
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
class PMFixture
|
8
|
+
attr_reader :tmpdir
|
9
|
+
|
10
|
+
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")
|
15
|
+
end
|
16
|
+
|
17
|
+
def pathmap(real_file,mapped_path)
|
18
|
+
File.open(real_file.to_s,"w") do |f|
|
19
|
+
f << mapped_path
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def fs
|
24
|
+
@fs ||= FuseFS::PathMapperFS.create(@tmpdir) do |file|
|
13
25
|
File.file?(file) ? IO.read(file.to_s) : nil
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def mount()
|
30
|
+
return @mountpoint if @mountpoint
|
31
|
+
@mountpoint = Pathname.new(Dir.mktmpdir("rfusefs_pathmapper_mnt"))
|
32
|
+
FuseFS.mount(fs,@mountpoint)
|
33
|
+
sleep(0.5)
|
34
|
+
@mountpoint
|
35
|
+
end
|
36
|
+
|
37
|
+
def cleanup
|
38
|
+
if @mountpoint
|
39
|
+
FuseFS.unmount(@mountpoint)
|
40
|
+
sleep(0.5)
|
41
|
+
FileUtils.rmdir(@mountpoint)
|
42
|
+
end
|
43
|
+
FileUtils.rm_r(@tmpdir)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
describe FuseFS::PathMapperFS do
|
49
|
+
before(:each) do
|
50
|
+
@fixture = PMFixture.new
|
51
|
+
@tmpdir = @fixture.tmpdir
|
52
|
+
@pathmapFS = @fixture.fs
|
53
|
+
end
|
54
|
+
|
55
|
+
after(:each) do
|
56
|
+
@fixture.cleanup
|
57
|
+
end
|
58
|
+
|
59
|
+
context "fusefs api" do
|
60
|
+
|
61
|
+
it "maps files and directories" do
|
22
62
|
@pathmapFS.directory?("/").should be_true
|
23
63
|
@pathmapFS.directory?("/textfiles").should be_true
|
24
64
|
@pathmapFS.directory?("/pictures/201103").should be_true
|
25
65
|
@pathmapFS.file?("/textfiles/hello").should be_true
|
66
|
+
@pathmapFS.directory?("/textfiles/hello").should be_false
|
26
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
|
27
71
|
end
|
28
|
-
|
29
|
-
it "
|
72
|
+
|
73
|
+
it "lists the mapped contents of directories" do
|
30
74
|
@pathmapFS.contents("/").should =~ [ "textfiles","artist","pictures" ]
|
31
75
|
@pathmapFS.contents("/artist").should =~ [ "album" ]
|
32
76
|
@pathmapFS.contents("/textfiles").should =~ [ "hello" ]
|
33
77
|
end
|
34
78
|
|
35
|
-
it "
|
79
|
+
it "reports the size of a file" do
|
36
80
|
@pathmapFS.size("/textfiles/hello").should == 16
|
37
81
|
end
|
38
82
|
|
39
|
-
it "
|
83
|
+
it "reads the contents of a file" do
|
84
|
+
@pathmapFS.read_file("/textfiles/hello").should == "/textfiles/hello"
|
85
|
+
end
|
86
|
+
|
87
|
+
it "does not allow writes" do
|
88
|
+
@pathmapFS.can_write?("/textfiles/hello").should be_false
|
89
|
+
end
|
90
|
+
|
91
|
+
it "reports the atime,mtime and ctime of the mapped file" do
|
40
92
|
atime,mtime,ctime = @pathmapFS.times("/pictures/201103/apicture.jpg")
|
41
93
|
picture = @tmpdir + "apicture.jpeg"
|
42
94
|
atime.should == picture.atime()
|
43
95
|
mtime.should == picture.mtime()
|
44
96
|
ctime.should == picture.ctime()
|
45
97
|
end
|
46
|
-
end
|
47
98
|
|
48
|
-
|
49
|
-
|
99
|
+
it "reports filesystem statistics"
|
100
|
+
|
101
|
+
context "writing to a pathmapped FS" do
|
102
|
+
before(:each) do
|
103
|
+
@pathmapFS.allow_write=true
|
104
|
+
@pathmapFS.write_to("textfiles/hello","updated content")
|
105
|
+
end
|
106
|
+
|
107
|
+
it "updates the contents of the real file" do
|
108
|
+
hello_path = @tmpdir + "hello.txt"
|
109
|
+
hello_path.read.should == "updated content"
|
110
|
+
end
|
111
|
+
|
112
|
+
it "updates the contents of the mapped file" do
|
113
|
+
@pathmapFS.read_file("textfiles/hello").should == "updated content"
|
114
|
+
end
|
115
|
+
|
116
|
+
it "changes the reported file size" do
|
117
|
+
@pathmapFS.size("textfiles/hello").should == 15
|
118
|
+
end
|
119
|
+
|
120
|
+
it "changes the filesystem statistics"
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
50
124
|
|
51
125
|
context "a real Fuse mounted filesystem" do
|
52
|
-
before(:
|
53
|
-
|
54
|
-
|
55
|
-
@pathmapFS.use_raw_file_access = true
|
56
|
-
FuseFS.mount(@pathmapFS,@mountpoint)
|
57
|
-
sleep(1)
|
126
|
+
before(:each) do
|
127
|
+
@pathmapFS.allow_write=true
|
128
|
+
@mountpoint = @fixture.mount
|
58
129
|
end
|
59
130
|
|
60
|
-
it "
|
131
|
+
it "maps files and directories" do
|
61
132
|
(@mountpoint + "textfiles").directory?.should be_true
|
62
|
-
(@mountpoint + "pictures/201103").directory?.should be_true
|
63
133
|
(@mountpoint + "textfiles/hello").file?.should be_true
|
64
|
-
(@mountpoint + "artist/album/mysong.mp3").file?.should be_true
|
65
134
|
end
|
66
135
|
|
67
|
-
it "
|
68
|
-
|
136
|
+
it "lists the mapped contents of directories" do
|
137
|
+
(@mountpoint + "textfiles").entries.should =~ pathnames(".","..","hello")
|
69
138
|
end
|
70
139
|
|
71
|
-
it "
|
140
|
+
it "represents the stat information of the underlying files" do
|
72
141
|
hellopath=(@mountpoint + "textfiles/hello")
|
73
142
|
realpath=(@tmpdir + "hello.txt")
|
74
143
|
mappedstat = hellopath.stat
|
75
144
|
realstat = realpath.stat
|
76
145
|
mappedstat.size.should == realstat.size
|
77
|
-
puts "#{realstat.atime.to_f},#{mappedstat.atime.to_f}"
|
78
146
|
mappedstat.atime.should == realstat.atime
|
79
147
|
mappedstat.mtime.should == realstat.mtime
|
80
148
|
mappedstat.ctime.should == realstat.ctime
|
81
149
|
end
|
82
150
|
|
83
|
-
it "
|
84
|
-
hellopath
|
151
|
+
it "reads the files" do
|
152
|
+
hellopath= @mountpoint + "textfiles/hello"
|
85
153
|
hellopath.read.should == "/textfiles/hello"
|
86
|
-
|
154
|
+
end
|
155
|
+
|
156
|
+
it "writes the files" do
|
157
|
+
hellopath= @mountpoint + "textfiles/hello"
|
158
|
+
real_path = @tmpdir + "hello.txt"
|
159
|
+
hellopath.open("w") do |f|
|
160
|
+
f.print "updated content"
|
161
|
+
end
|
162
|
+
hellopath.read.should == "updated content"
|
163
|
+
real_path.read.should == "updated content"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context "a real Fuse mount with raw file access" do
|
168
|
+
|
169
|
+
before(:each) do
|
170
|
+
@pathmapFS.use_raw_file_access = true
|
171
|
+
@pathmapFS.allow_write = true
|
172
|
+
@mountpoint = @fixture.mount
|
173
|
+
end
|
174
|
+
|
175
|
+
it "reads files" do
|
176
|
+
hello_path = (@mountpoint + "textfiles/hello")
|
177
|
+
hello_path.open do |f|
|
87
178
|
f.seek(2)
|
88
179
|
f.read(3).should == "ext"
|
89
180
|
end
|
90
|
-
|
181
|
+
|
182
|
+
hello_path.sysopen do |f|
|
91
183
|
f.sysseek(1)
|
92
184
|
f.sysread(3).should == "tex"
|
93
185
|
end
|
94
186
|
end
|
95
187
|
|
96
|
-
|
97
|
-
|
98
|
-
|
188
|
+
it "writes files" do
|
189
|
+
hello_path = (@mountpoint + "textfiles/hello")
|
190
|
+
real_path = @tmpdir + "hello.txt"
|
191
|
+
hello_path.open("r+") do |f|
|
192
|
+
f.sysseek(2)
|
193
|
+
f.syswrite("zzz")
|
194
|
+
f.sysseek(0)
|
195
|
+
f.sysread(6).should == "/tzzzf"
|
196
|
+
end
|
197
|
+
|
198
|
+
real_path.read.should == "/tzzzfiles/hello"
|
99
199
|
end
|
100
200
|
|
101
201
|
end
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
end
|
106
|
-
|
107
|
-
after(:all) do
|
108
|
-
FileUtils.rm_rf(@tmpdir.to_s)
|
109
|
-
end
|
110
|
-
|
111
|
-
|
112
202
|
end
|
data/spec/rfusefs_spec.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe FuseFS do
|
4
|
+
|
4
5
|
TEST_FILE = "/aPath/aFile"
|
5
6
|
TEST_DIR = "/aPath"
|
6
7
|
ROOT_PATH = "/"
|
@@ -41,7 +42,7 @@ describe FuseFS do
|
|
41
42
|
@mock_fuse = FuseFS::FuseDir.new()
|
42
43
|
@fuse = FuseFS::RFuseFS.new(@mock_fuse)
|
43
44
|
end
|
44
|
-
|
45
|
+
|
45
46
|
describe :readdir do
|
46
47
|
before(:each) do
|
47
48
|
@mock_fuse.should_receive(:contents).with("/apath").and_return(["afile"])
|
@@ -390,7 +391,28 @@ describe FuseFS do
|
|
390
391
|
end
|
391
392
|
|
392
393
|
end
|
394
|
+
context "extended attributes" do
|
395
|
+
|
396
|
+
let(:xattr) { {} }
|
397
|
+
before(:each) { @mock_fuse.stub!(:xattr).with(TEST_FILE).and_return(xattr) }
|
398
|
+
|
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" ]
|
408
|
+
end
|
409
|
+
|
410
|
+
it "should raise ENODATA is no attribute is available" do
|
411
|
+
lambda{@fuse.getxattr(nil,TEST_FILE,"user.xxxx") }.should raise_error(Errno::ENODATA)
|
412
|
+
end
|
393
413
|
|
414
|
+
|
415
|
+
end
|
394
416
|
end
|
395
417
|
|
396
418
|
describe "a FuseFS filesystem with gid/uid specific behaviour" do
|
data/spec/sample_spec.rb
CHANGED
@@ -5,26 +5,26 @@ require 'pathname'
|
|
5
5
|
require 'hello'
|
6
6
|
|
7
7
|
describe "Access Hello World sample from Ruby file operations" do
|
8
|
+
let(:mountpoint) { Pathname.new(Dir.mktmpdir("rfusefs_sample")) }
|
9
|
+
|
8
10
|
before(:all) do
|
9
|
-
tmpdir = Pathname.new(Dir.tmpdir) + "rfusefs"
|
10
|
-
tmpdir.mkdir unless tmpdir.directory?
|
11
|
-
@mountpoint = tmpdir + "sample_spec"
|
12
|
-
@mountpoint.mkdir unless @mountpoint.directory?
|
13
11
|
hello = HelloDir.new()
|
14
|
-
FuseFS.mount(hello
|
12
|
+
FuseFS.mount(hello,mountpoint)
|
15
13
|
#Give FUSE some time to get started
|
16
|
-
sleep(
|
14
|
+
sleep(0.5)
|
17
15
|
end
|
18
16
|
|
19
17
|
after(:all) do
|
20
|
-
FuseFS.unmount(
|
18
|
+
FuseFS.unmount(mountpoint)
|
19
|
+
sleep(0.5)
|
20
|
+
FileUtils.rmdir(mountpoint)
|
21
21
|
end
|
22
22
|
|
23
23
|
it "should list expected root directory contents" do
|
24
|
-
Dir.entries(
|
24
|
+
Dir.entries(mountpoint.to_s).should =~ [".","..","hello.txt"]
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should output the expected sample contents" do
|
28
|
-
(
|
28
|
+
(mountpoint + "hello.txt").read().should == "Hello, World!\n"
|
29
29
|
end
|
30
30
|
end
|
data/spec/spec_helper.rb
CHANGED