rfuse 1.1.2 → 1.2.3
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.
- checksums.yaml +5 -13
- data/CHANGES.md +6 -0
- data/README.md +3 -2
- data/ext/rfuse/rfuse.c +2 -2
- data/lib/rfuse/version.rb +1 -1
- metadata +25 -42
- data/.gitignore +0 -5
- data/.travis.yml +0 -20
- data/Gemfile +0 -4
- data/Rakefile +0 -17
- data/ext/.gitignore +0 -2
- data/rfuse.gemspec +0 -31
- data/sample/test-ruby.rb +0 -310
- data/spec/basic_spec.rb +0 -243
- data/spec/fuse_file_info_spec.rb +0 -119
- data/spec/main_spec.rb +0 -161
- data/spec/options_spec.rb +0 -143
- data/spec/ruby_loop_spec.rb +0 -63
- data/spec/run_spec.rb +0 -60
- data/spec/signals_spec.rb +0 -108
- data/spec/spec_helper.rb +0 -109
- data/spec/xattr_spec.rb +0 -49
data/spec/basic_spec.rb
DELETED
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require 'pathname'
|
|
3
|
-
require 'tempfile'
|
|
4
|
-
require 'sys/filesystem'
|
|
5
|
-
|
|
6
|
-
describe RFuse::Fuse do
|
|
7
|
-
|
|
8
|
-
let(:dir_stat) { RFuse::Stat.directory(0444) }
|
|
9
|
-
let(:file_stat) { RFuse::Stat.file(0444) }
|
|
10
|
-
let!(:mockfs) { m = mock("fuse"); m.stub(:getattr).and_return(nil); m }
|
|
11
|
-
let(:mountpoint) { tempmount() }
|
|
12
|
-
|
|
13
|
-
context "links" do
|
|
14
|
-
it "should create and resolve symbolic links"
|
|
15
|
-
it "should create and resolve hard links"
|
|
16
|
-
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
context "directories" do
|
|
20
|
-
it "should make directories" do
|
|
21
|
-
|
|
22
|
-
mockfs.stub(:getattr).and_return(nil)
|
|
23
|
-
mockfs.stub(:getattr).with(anything(),"/aDirectory").and_return(nil,dir_stat)
|
|
24
|
-
mockfs.should_receive(:mkdir).with(anything(),"/aDirectory",anything())
|
|
25
|
-
|
|
26
|
-
with_fuse(mountpoint,mockfs) do
|
|
27
|
-
Dir.mkdir("#{mountpoint}/aDirectory")
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
it "should list directories" do
|
|
32
|
-
|
|
33
|
-
mockfs.should_receive(:readdir) do | ctx, path, filler,offset,ffi |
|
|
34
|
-
filler.push("hello",nil,0)
|
|
35
|
-
filler.push("world",nil,0)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
with_fuse(mountpoint,mockfs) do
|
|
39
|
-
entries = Dir.entries(mountpoint)
|
|
40
|
-
entries.size.should == 2
|
|
41
|
-
entries.should include("hello")
|
|
42
|
-
entries.should include("world")
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
context "permissions" do
|
|
48
|
-
it "should process chmod" do
|
|
49
|
-
mockfs.stub(:getattr).with(anything(),"/myPerms").and_return(file_stat)
|
|
50
|
-
|
|
51
|
-
mockfs.should_receive(:chmod).with(anything(),"/myPerms",file_mode(0644))
|
|
52
|
-
|
|
53
|
-
with_fuse(mountpoint,mockfs) do
|
|
54
|
-
File.chmod(0644,"#{mountpoint}/myPerms").should == 1
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
context "timestamps" do
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
it "should support stat with subsecond resolution" do
|
|
63
|
-
testns = Tempfile.new("testns")
|
|
64
|
-
stat = File.stat(testns.path)
|
|
65
|
-
|
|
66
|
-
# so if this Ruby has usec resolution for File.stat
|
|
67
|
-
# we'd expect to skip this test 1 in 100,000 times...
|
|
68
|
-
no_usecs = (stat.mtime.usec == 0)
|
|
69
|
-
|
|
70
|
-
if no_usecs
|
|
71
|
-
puts "Skipping due to no usec resolution for File.stat"
|
|
72
|
-
else
|
|
73
|
-
atime,mtime,ctime = usec_times(60,600,3600)
|
|
74
|
-
|
|
75
|
-
file_stat.atime = atime
|
|
76
|
-
file_stat.mtime = mtime
|
|
77
|
-
file_stat.ctime = ctime
|
|
78
|
-
|
|
79
|
-
# ruby can't set file times with ns res, o we are limited to usecs
|
|
80
|
-
mockfs.stub(:getattr).with(anything(),"/nanos").and_return(file_stat)
|
|
81
|
-
|
|
82
|
-
with_fuse(mountpoint,mockfs) do
|
|
83
|
-
stat = File.stat("#{mountpoint}/nanos")
|
|
84
|
-
stat.atime.usec.should == atime.usec
|
|
85
|
-
stat.atime.should == atime
|
|
86
|
-
stat.ctime.should == ctime
|
|
87
|
-
stat.mtime.should == mtime
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
it "should set file access and modification times subsecond resolution" do
|
|
93
|
-
atime,mtime = usec_times(60,600)
|
|
94
|
-
|
|
95
|
-
atime_ns = (atime.to_i * (10**9)) + (atime.nsec)
|
|
96
|
-
mtime_ns = (mtime.to_i * (10**9)) + (mtime.nsec)
|
|
97
|
-
|
|
98
|
-
mockfs.stub(:getattr).with(anything(),"/usec").and_return(file_stat)
|
|
99
|
-
mockfs.should_receive(:utimens).with(anything,"/usec",atime_ns,mtime_ns)
|
|
100
|
-
|
|
101
|
-
with_fuse(mountpoint,mockfs) do
|
|
102
|
-
File.utime(atime,mtime,"#{mountpoint}/usec").should == 1
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
it "should set file access and modification times" do
|
|
106
|
-
|
|
107
|
-
atime = Time.now()
|
|
108
|
-
mtime = atime + 1
|
|
109
|
-
|
|
110
|
-
mockfs.stub(:getattr).with(anything(),"/times").and_return(file_stat)
|
|
111
|
-
mockfs.should_receive(:utime).with(anything(),"/times",atime.to_i,mtime.to_i)
|
|
112
|
-
|
|
113
|
-
with_fuse(mountpoint,mockfs) do
|
|
114
|
-
File.utime(atime,mtime,"#{mountpoint}/times").should == 1
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
context "file io" do
|
|
121
|
-
|
|
122
|
-
it "should create files" do
|
|
123
|
-
|
|
124
|
-
mockfs.stub(:getattr).with(anything(),"/newfile").and_return(nil,file_stat)
|
|
125
|
-
mockfs.should_receive(:mknod).with(anything(),"/newfile",file_mode(0644),0,0)
|
|
126
|
-
|
|
127
|
-
with_fuse(mountpoint,mockfs) do
|
|
128
|
-
File.open("#{mountpoint}/newfile","w",0644) { |f| }
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
# ruby doesn't seem to have a native method to create these
|
|
133
|
-
# maybe try ruby-mkfifo
|
|
134
|
-
it "should create special device files"
|
|
135
|
-
|
|
136
|
-
it "should read files" do
|
|
137
|
-
|
|
138
|
-
file_stat.size = 12
|
|
139
|
-
mockfs.stub(:getattr).with(anything(),"/test").and_return(file_stat)
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
reads = 0
|
|
143
|
-
mockfs.stub(:read) { |ctx,path,size,offset,ffi|
|
|
144
|
-
reads += 2
|
|
145
|
-
"hello\000world\000"[offset,reads]
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
with_fuse(mountpoint,mockfs) do
|
|
149
|
-
File.open("#{mountpoint}/test") do |f|
|
|
150
|
-
val = f.gets
|
|
151
|
-
val.should == "hello\000world\000"
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
it "should read over null characters in a real file" do
|
|
157
|
-
file_stat.size = 2
|
|
158
|
-
File.open("/tmp/nulltest","w") { |f| f.print "\000\000" }
|
|
159
|
-
|
|
160
|
-
mockfs.stub(:getattr).with(anything(),"/testnull").and_return(file_stat)
|
|
161
|
-
|
|
162
|
-
mockfs.stub(:read) { |ctx,path,size,offset,ffi|
|
|
163
|
-
IO.read("/tmp/nulltest",size,offset)
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
with_fuse(mountpoint,mockfs) do
|
|
167
|
-
File.open("#{mountpoint}/testnull") do |f|
|
|
168
|
-
val = f.gets
|
|
169
|
-
val.should == "\000\000"
|
|
170
|
-
val.size.should == 2
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
context "filesystem statistics" do
|
|
178
|
-
|
|
179
|
-
let (:statvfs) {
|
|
180
|
-
RFuse::StatVfs.new(
|
|
181
|
-
:bsize => 2048,
|
|
182
|
-
"frsize" => 1024,
|
|
183
|
-
"blocks" => 9999,
|
|
184
|
-
"bfree" => 8888,
|
|
185
|
-
"bavail" => 7777,
|
|
186
|
-
"files" => 6000,
|
|
187
|
-
"ffree" => 5555)
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
it "should report filesystem statistics" do
|
|
191
|
-
mockfs.stub(:getattr).with(anything(),"/test").and_return(dir_stat)
|
|
192
|
-
mockfs.stub(:getattr).with(anything(),"/test/statfs").and_return(file_stat)
|
|
193
|
-
|
|
194
|
-
mockfs.should_receive(:statfs).with(anything(),"/test/statfs").and_return(statvfs)
|
|
195
|
-
|
|
196
|
-
#also exercise StatVfs
|
|
197
|
-
statvfs.f_files=6666
|
|
198
|
-
|
|
199
|
-
with_fuse(mountpoint,mockfs) do
|
|
200
|
-
|
|
201
|
-
results = Sys::Filesystem.stat("#{mountpoint}/test/statfs")
|
|
202
|
-
results.block_size.should == 2048
|
|
203
|
-
results.fragment_size.should == 1024
|
|
204
|
-
results.blocks.should == 9999
|
|
205
|
-
results.blocks_available.should == 7777
|
|
206
|
-
results.blocks_free.should == 8888
|
|
207
|
-
results.files.should == 6666
|
|
208
|
-
results.files_available == 5555
|
|
209
|
-
end
|
|
210
|
-
end
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
context "exceptions" do
|
|
214
|
-
|
|
215
|
-
it "should capture exceptions appropriately" do
|
|
216
|
-
|
|
217
|
-
mockfs.should_receive(:getattr).with(anything(),"/exceptions").and_raise(RuntimeError)
|
|
218
|
-
|
|
219
|
-
with_fuse(mountpoint,mockfs) do
|
|
220
|
-
begin
|
|
221
|
-
File.stat("#{mountpoint}/exceptions")
|
|
222
|
-
raise "should not get here"
|
|
223
|
-
rescue Errno::ENOENT
|
|
224
|
-
#all good
|
|
225
|
-
end
|
|
226
|
-
end
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
it "should pass Errno exceptions through" do
|
|
230
|
-
mockfs.should_receive(:getattr).with(anything(),"/exceptions").and_raise(Errno::EPERM)
|
|
231
|
-
|
|
232
|
-
with_fuse(mountpoint,mockfs) do
|
|
233
|
-
begin
|
|
234
|
-
File.stat("#{mountpoint}/exceptions")
|
|
235
|
-
raise "should not get here"
|
|
236
|
-
rescue Errno::EPERM
|
|
237
|
-
#all good
|
|
238
|
-
end
|
|
239
|
-
end
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
end
|
|
243
|
-
end
|
data/spec/fuse_file_info_spec.rb
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe RFuse::Fuse do
|
|
4
|
-
|
|
5
|
-
let(:dir_stat) { RFuse::Stat.directory(0444) }
|
|
6
|
-
let(:file_stat) { RFuse::Stat.file(0444) }
|
|
7
|
-
let!(:mockfs) { m = mock("fuse"); m.stub(:getattr).and_return(nil); m }
|
|
8
|
-
let(:mountpoint) { tempmount() }
|
|
9
|
-
let(:open_files) { Hash.new() }
|
|
10
|
-
|
|
11
|
-
it "should pass fileinfo to #release" do
|
|
12
|
-
|
|
13
|
-
file_handle = Object.new()
|
|
14
|
-
stored_ffi = nil
|
|
15
|
-
captured_ex = nil
|
|
16
|
-
|
|
17
|
-
mockfs.stub(:getattr).with(anything(),"/ffirelease").and_return(file_stat)
|
|
18
|
-
|
|
19
|
-
mockfs.should_receive(:open).with(anything(),"/ffirelease",anything()) { |ctx,path,ffi|
|
|
20
|
-
stored_ffi = ffi
|
|
21
|
-
ffi.fh = file_handle
|
|
22
|
-
ctx.uid.should > 0
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
mockfs.should_receive(:release).with(anything(),"/ffirelease",anything()) { |ctx,path,ffi|
|
|
26
|
-
# the return value of release is ignored, so exceptions here are lost
|
|
27
|
-
begin
|
|
28
|
-
ffi.fh.should == file_handle
|
|
29
|
-
ffi.should == stored_ffi
|
|
30
|
-
# Not sure why ctx.uid is not still set during release
|
|
31
|
-
ctx.uid.should == 0
|
|
32
|
-
rescue Exception => ex
|
|
33
|
-
captured_ex = ex
|
|
34
|
-
end
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
with_fuse(mountpoint,mockfs) do
|
|
38
|
-
f1 = File.new("#{mountpoint}/ffirelease")
|
|
39
|
-
f1.close()
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
raise captured_ex if captured_ex
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
it "should pass fileinfo to #releasedir" do
|
|
46
|
-
|
|
47
|
-
file_handle = Object.new()
|
|
48
|
-
stored_ffi = nil
|
|
49
|
-
captured_ex = nil
|
|
50
|
-
|
|
51
|
-
mockfs.stub(:getattr).with(anything(),"/ffirelease").and_return(dir_stat)
|
|
52
|
-
|
|
53
|
-
mockfs.should_receive(:opendir).with(anything(),"/ffirelease",anything()) { |ctx,path,ffi|
|
|
54
|
-
stored_ffi = ffi
|
|
55
|
-
ffi.fh = file_handle
|
|
56
|
-
ctx.uid.should > 0
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
mockfs.should_receive(:readdir) do | ctx, path, filler,offset,ffi |
|
|
60
|
-
filler.push("hello",nil,0)
|
|
61
|
-
filler.push("world",nil,0)
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
mockfs.should_receive(:releasedir).with(anything(),"/ffirelease",anything()) { |ctx,path,ffi|
|
|
65
|
-
# the return value of release is ignored, so exceptions here are lost
|
|
66
|
-
begin
|
|
67
|
-
ffi.fh.should == file_handle
|
|
68
|
-
ffi.should == stored_ffi
|
|
69
|
-
# Not entirely sure why ctx.uid is not set here
|
|
70
|
-
ctx.uid.should == 0
|
|
71
|
-
rescue Exception => ex
|
|
72
|
-
captured_ex = ex
|
|
73
|
-
end
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
with_fuse(mountpoint,mockfs) do
|
|
77
|
-
entries = Dir.entries("#{mountpoint}/ffirelease")
|
|
78
|
-
entries.size.should == 2
|
|
79
|
-
entries.should include("hello")
|
|
80
|
-
entries.should include("world")
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
raise captured_ex if captured_ex
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
context "file handles" do
|
|
87
|
-
it "should retain file handles over GC" do
|
|
88
|
-
|
|
89
|
-
file_stat.size = 11
|
|
90
|
-
|
|
91
|
-
mockfs.stub(:getattr).with(anything(),"/one").and_return(file_stat)
|
|
92
|
-
mockfs.stub(:getattr).with(anything(),"/two").and_return(file_stat)
|
|
93
|
-
|
|
94
|
-
open_files = {}
|
|
95
|
-
mockfs.stub(:open) { |ctx,path,ffi|
|
|
96
|
-
ffi.fh = Object.new()
|
|
97
|
-
open_files[path] = ffi.fh.object_id
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
mockfs.stub(:read) { |ctx,path,size,offset,ffi|
|
|
101
|
-
GC.start()
|
|
102
|
-
open_files[path].should == ffi.fh.object_id
|
|
103
|
-
"hello world"
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
with_fuse(mountpoint,mockfs) do
|
|
107
|
-
f1 = File.new("#{mountpoint}/one")
|
|
108
|
-
f2 = File.new("#{mountpoint}/two")
|
|
109
|
-
|
|
110
|
-
val = f1.gets
|
|
111
|
-
val.should == "hello world"
|
|
112
|
-
f2.gets.should == "hello world"
|
|
113
|
-
|
|
114
|
-
f1.close()
|
|
115
|
-
f2.close()
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
end
|
data/spec/main_spec.rb
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
class MockFuse < RFuse::Fuse; end
|
|
4
|
-
class DuckFuse
|
|
5
|
-
def initialize(val); end;
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
describe RFuse do
|
|
9
|
-
|
|
10
|
-
# required to capture stderr output of help text from C: library functions
|
|
11
|
-
matcher :print_to_stderr do |expected|
|
|
12
|
-
supports_block_expectations
|
|
13
|
-
|
|
14
|
-
match do |actual|
|
|
15
|
-
#$stdout.puts "STDERR=#{$stderr} #{$stderr.fileno}"
|
|
16
|
-
@captured = File.open(Dir.tmpdir + "/rfuse.stderr","w+") do |f|
|
|
17
|
-
f.sync
|
|
18
|
-
old_stderr = STDERR.dup
|
|
19
|
-
old_f = f.dup
|
|
20
|
-
begin
|
|
21
|
-
STDERR.reopen(f)
|
|
22
|
-
actual.call
|
|
23
|
-
ensure
|
|
24
|
-
STDERR.reopen(old_stderr)
|
|
25
|
-
end
|
|
26
|
-
old_f.rewind
|
|
27
|
-
old_f.read
|
|
28
|
-
end
|
|
29
|
-
expected.match(@captured)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
match_when_negated do |actual|
|
|
33
|
-
!matches?(actual)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
failure_message do
|
|
37
|
-
"Expected stderr output...\n#{@captured}\nto match RE - #{expected}"
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
failure_message_when_negated do
|
|
41
|
-
"Expected stderr output...\n#{@captured}\nto not match RE - #{expected}"
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
let(:mockfs) { m = double("fuse"); m.stub(:getattr).and_return(nil); m }
|
|
46
|
-
let(:mountpoint) { tempmount() }
|
|
47
|
-
|
|
48
|
-
describe ".main" do
|
|
49
|
-
|
|
50
|
-
let(:re_usage) { Regexp.new("^Usage:\n.*-h.*-d.*\n",Regexp::MULTILINE) }
|
|
51
|
-
let(:re_help) { Regexp.new("^Fuse options: \\(\\d.\\d\\)\n.*help.*\n.*debug.*\n\n",Regexp::MULTILINE) }
|
|
52
|
-
let(:re_fuse) { Regexp.new(".*(^\\s+-o.*$)+.*",Regexp::MULTILINE) }
|
|
53
|
-
let(:re_extra_header) { Regexp.new("Filesystem options:\n",Regexp::MULTILINE) }
|
|
54
|
-
|
|
55
|
-
# self.main(argv=ARGV,extra_options=[],extra_option_usage="",device=nil,exec=File.basename($0))
|
|
56
|
-
context "with no mountpoint" do
|
|
57
|
-
it "prints usage information to stdout" do
|
|
58
|
-
expect { RFuse.main([]) { } }.to output(re_usage).to_stdout
|
|
59
|
-
end
|
|
60
|
-
it "prints mountpoint failure on stderr" do
|
|
61
|
-
expect { RFuse.main([]) { } }.to output("rfuse: failed, no mountpoint provided\n").to_stderr
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
context "with help option" do
|
|
66
|
-
it "does not start filesystem" do
|
|
67
|
-
expect(mockfs).to receive(:init).exactly(0).times
|
|
68
|
-
RFuse.main([mountpoint,"-h"]) { mockfs }
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
it "prints usage and kernel options" do
|
|
72
|
-
# TODO: In Fuse 3.0, this will get complicated because help output moves to stdout
|
|
73
|
-
re = Regexp.new(re_help.to_s + re_fuse.to_s)
|
|
74
|
-
expect { RFuse.main([mountpoint,"-h"]) { mockfs } }.to print_to_stderr(re)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
it "does not print filesystem options header if no extra options" do
|
|
78
|
-
re = Regexp.new(re_help.to_s + re_fuse.to_s + re_extra_header.to_s)
|
|
79
|
-
expect { RFuse.main([mountpoint,"-h"]) { mockfs } }.not_to print_to_stderr(re)
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
it "prints local option header if there are local options" do
|
|
83
|
-
re = Regexp.new(re_help.to_s + re_fuse.to_s + re_extra_header.to_s + "TestOptionUsage")
|
|
84
|
-
expect { RFuse.main([mountpoint,"-h"],[:myoption],"TestOptionUsage") { mockfs } }.to print_to_stderr(re)
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
it "yields parsed options and cleaned argv" do
|
|
90
|
-
# We know that main uses parse_options which is tested elsewhere
|
|
91
|
-
expect { |b| RFuse.main([mountpoint,"-o","myoption"],[:myoption],&b) }.to \
|
|
92
|
-
yield_with_args(a_hash_including(:mountpoint,:myoption),[mountpoint])
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
context "yield raises exception" do
|
|
96
|
-
it "prints usage output" do
|
|
97
|
-
expect { RFuse.main([mountpoint]) { raise RFuse::Error, "MyError"}}.to output(re_usage).to_stdout
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
it "prints the error message" do
|
|
101
|
-
expect { RFuse.main([mountpoint]) { raise RFuse::Error, "MyError"}}.to output("rfuse failed: MyError\n").to_stderr
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
it "creates and runs the yielded Fuse filesystem" do
|
|
106
|
-
# We test create and run separately
|
|
107
|
-
# expect RFuse.create then mounted? and run
|
|
108
|
-
fuse = double(fuse)
|
|
109
|
-
fuse.stub(:mounted?).and_return(true,false)
|
|
110
|
-
expect(fuse).to receive(:run)
|
|
111
|
-
expect(RFuse).to receive(:create).with(fuse,[mountpoint],{:mountpoint => mountpoint},[]) { fuse }
|
|
112
|
-
RFuse.main([mountpoint]) { fuse }
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
describe ".create" do
|
|
117
|
-
let(:argv) { [mountpoint] }
|
|
118
|
-
context "with a Fuse object" do
|
|
119
|
-
let(:fs) { MockFuse.new(mountpoint) }
|
|
120
|
-
it "returns the object" do
|
|
121
|
-
fuse = RFuse.create(fs)
|
|
122
|
-
expect(fuse).to be(fs)
|
|
123
|
-
expect(fuse).to be_mounted
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
context "with a subclass of Fuse" do
|
|
128
|
-
let(:fs) { MockFuse }
|
|
129
|
-
|
|
130
|
-
it "creates a new Fuse object from subclass of Fuse" do
|
|
131
|
-
fuse = RFuse.create(fs,[mountpoint])
|
|
132
|
-
expect(fuse).to be_kind_of(MockFuse)
|
|
133
|
-
expect(fuse.mountpoint).to eq(mountpoint)
|
|
134
|
-
expect(fuse).to be_mounted
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
context "with a Class" do
|
|
139
|
-
let(:fs) { DuckFuse }
|
|
140
|
-
it "creates a FuseDelegator around a new instance" do
|
|
141
|
-
expect(fs).to receive(:new).with("OptionValue").and_call_original()
|
|
142
|
-
expect(RFuse::FuseDelegator).to receive(:new).with(an_instance_of(DuckFuse),mountpoint).and_call_original()
|
|
143
|
-
fuse = RFuse.create(fs,[mountpoint],{:myopt => "OptionValue"},[:myopt])
|
|
144
|
-
expect(fuse).to be_kind_of(RFuse::FuseDelegator)
|
|
145
|
-
expect(fuse.mountpoint).to eq(mountpoint)
|
|
146
|
-
expect(fuse).to be_mounted
|
|
147
|
-
end
|
|
148
|
-
end
|
|
149
|
-
context "with a non-Fuse Object" do
|
|
150
|
-
let(:fs) { mockfs }
|
|
151
|
-
it "starts FuseDelegator with non Fuse object returned from yield" do
|
|
152
|
-
expect(RFuse::FuseDelegator).to receive(:new).with(mockfs,mountpoint).and_call_original()
|
|
153
|
-
fuse = RFuse.create(fs,[mountpoint])
|
|
154
|
-
expect(fuse).to be_kind_of(RFuse::FuseDelegator)
|
|
155
|
-
expect(fuse.mountpoint).to eq(mountpoint)
|
|
156
|
-
expect(fuse).to be_mounted
|
|
157
|
-
end
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
end
|
|
161
|
-
end
|
data/spec/options_spec.rb
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require 'pathname'
|
|
3
|
-
require 'tempfile'
|
|
4
|
-
|
|
5
|
-
describe RFuse do
|
|
6
|
-
|
|
7
|
-
let(:dir_stat) { RFuse::Stat.directory(0444) }
|
|
8
|
-
let(:file_stat) { RFuse::Stat.file(0444) }
|
|
9
|
-
let!(:mockfs) { m = mock("fuse"); m.stub(:getattr).and_return(nil); m }
|
|
10
|
-
let(:mountpoint) { tempmount() }
|
|
11
|
-
|
|
12
|
-
context "mount options" do
|
|
13
|
-
it "should handle -h" do
|
|
14
|
-
fuse = RFuse::FuseDelegator.new(mockfs,mountpoint,"-h")
|
|
15
|
-
fuse.mounted?.should be_falsey
|
|
16
|
-
lambda { fuse.loop }.should raise_error(RFuse::Error)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
it "should behave sensibly for bad mountpoint" do
|
|
20
|
-
fuse = RFuse::FuseDelegator.new(mockfs,"bad/mount/point")
|
|
21
|
-
fuse.mounted?.should be_falsey
|
|
22
|
-
lambda { fuse.loop }.should raise_error(RFuse::Error)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
it "should behave sensibly for bad options" do
|
|
26
|
-
fuse = RFuse::FuseDelegator.new(mockfs,mountpoint,"-eviloption")
|
|
27
|
-
fuse.mounted?.should be_falsey
|
|
28
|
-
lambda { fuse.loop }.should raise_error(RFuse::Error)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
it "should handle a Pathname as a mountpoint" do
|
|
32
|
-
fuse = RFuse::FuseDelegator.new(mockfs,Pathname.new(mountpoint))
|
|
33
|
-
fuse.mounted?.should be(true)
|
|
34
|
-
fuse.unmount()
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
context "#parse_options" do
|
|
39
|
-
|
|
40
|
-
it "should detect -h" do
|
|
41
|
-
argv = [ "/mountpoint","-h" ]
|
|
42
|
-
result = RFuse.parse_options(argv)
|
|
43
|
-
|
|
44
|
-
result[:help].should be(true)
|
|
45
|
-
result[:mountpoint].should == "/mountpoint"
|
|
46
|
-
result[:debug].should be_falsey
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
it "should detect -h mixed with -o" do
|
|
50
|
-
argv = [ "/mountpoint","-h", "-o", "debug" ]
|
|
51
|
-
result = RFuse.parse_options(argv)
|
|
52
|
-
|
|
53
|
-
result[:help].should be(true)
|
|
54
|
-
result[:mountpoint].should == "/mountpoint"
|
|
55
|
-
result[:debug].should be(true)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
it "should detect debug" do
|
|
59
|
-
argv = [ "/mountpoint","-o","debug" ]
|
|
60
|
-
result = RFuse.parse_options(argv)
|
|
61
|
-
|
|
62
|
-
result[:debug].should be(true)
|
|
63
|
-
result[:help].should be_falsey
|
|
64
|
-
|
|
65
|
-
argv = [ "/mountpoint","-o","default_permissions,debug" ]
|
|
66
|
-
result = RFuse.parse_options(argv)
|
|
67
|
-
result[:debug].should be(true)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
it "detects debug as -d" do
|
|
71
|
-
argv = [ "/mountpoint","-o","someopt","-d" ]
|
|
72
|
-
result = RFuse.parse_options(argv)
|
|
73
|
-
result[:debug].should be(true)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
it "should remove local options" do
|
|
77
|
-
argv = [ "/mountpoint","-o","debug,myoption" ]
|
|
78
|
-
|
|
79
|
-
result = RFuse.parse_options(argv,:myoption)
|
|
80
|
-
|
|
81
|
-
result[:debug].should be(true)
|
|
82
|
-
result[:myoption].should be(true)
|
|
83
|
-
|
|
84
|
-
argv.should == [ "/mountpoint", "-o", "debug" ]
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
it "should remove the only local option" do
|
|
88
|
-
argv = ["/mountpoint","-o","myoption" ]
|
|
89
|
-
|
|
90
|
-
result = RFuse.parse_options(argv,:myoption)
|
|
91
|
-
|
|
92
|
-
result[:myoption].should be(true)
|
|
93
|
-
argv.should == [ "/mountpoint" ]
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
it "parses the value from the only local option" do
|
|
98
|
-
argv = [ "adevice", "/mountpoint", "-o","someopt=somevalue"]
|
|
99
|
-
result = RFuse.parse_options(argv,:someopt)
|
|
100
|
-
|
|
101
|
-
result[:someopt].should == "somevalue"
|
|
102
|
-
argv.should == [ "/mountpoint" ]
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
it "should parse values from options" do
|
|
106
|
-
argv = [ "/mountpoint", "-o", "debug,someopt=somevalue" ]
|
|
107
|
-
result = RFuse.parse_options(argv)
|
|
108
|
-
|
|
109
|
-
result[:someopt].should == "somevalue"
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
it "should parse values and remove local options" do
|
|
113
|
-
argv = [ "/mountpoint", "-o", "debug,someopt=somevalue" ]
|
|
114
|
-
result = RFuse.parse_options(argv,:someopt)
|
|
115
|
-
|
|
116
|
-
result[:someopt].should == "somevalue"
|
|
117
|
-
argv[2].should == "debug"
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
it "should parse and remove optional device" do
|
|
121
|
-
|
|
122
|
-
argv = [ "a device", "/mountpoint" , "-o", "rw,debug,default_permissions" ]
|
|
123
|
-
result = RFuse.parse_options(argv)
|
|
124
|
-
|
|
125
|
-
result[:device].should == "a device"
|
|
126
|
-
result[:mountpoint].should == "/mountpoint"
|
|
127
|
-
result[:rw].should be(true)
|
|
128
|
-
result[:debug].should be(true)
|
|
129
|
-
result[:default_permissions].should be(true)
|
|
130
|
-
|
|
131
|
-
argv.should == [ "/mountpoint" , "-o", "rw,debug,default_permissions" ]
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
context "with '-' in device" do
|
|
135
|
-
it "should parse the device correctly" do
|
|
136
|
-
argv = [ "a-device", "/mountpoint" , "-o", "rw,debug,default_permissions" ]
|
|
137
|
-
result = RFuse.parse_options(argv)
|
|
138
|
-
|
|
139
|
-
result[:device].should == "a-device"
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
end
|