virtfs 0.0.1
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 +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +154 -0
- data/Rakefile +5 -0
- data/lib/virtfs-nativefs-thick.rb +1 -0
- data/lib/virtfs-nativefs-thin.rb +1 -0
- data/lib/virtfs.rb +38 -0
- data/lib/virtfs/activation.rb +97 -0
- data/lib/virtfs/block_io.rb +140 -0
- data/lib/virtfs/byte_range.rb +71 -0
- data/lib/virtfs/context.rb +300 -0
- data/lib/virtfs/context_manager.rb +175 -0
- data/lib/virtfs/context_switch_class_methods.rb +96 -0
- data/lib/virtfs/delegate_module.rb +40 -0
- data/lib/virtfs/dir_instance_delegate.rb +3 -0
- data/lib/virtfs/exception.rb +13 -0
- data/lib/virtfs/file_instance_delegate.rb +3 -0
- data/lib/virtfs/file_modes_and_options.rb +293 -0
- data/lib/virtfs/find_class_methods.rb +106 -0
- data/lib/virtfs/io_buffer.rb +133 -0
- data/lib/virtfs/io_instance_delegate.rb +3 -0
- data/lib/virtfs/kernel.rb +146 -0
- data/lib/virtfs/nativefs/thick.rb +30 -0
- data/lib/virtfs/nativefs/thick/dir_class_methods.rb +38 -0
- data/lib/virtfs/nativefs/thick/file_class_methods.rb +178 -0
- data/lib/virtfs/nativefs/thin.rb +32 -0
- data/lib/virtfs/nativefs/thin/dir.rb +30 -0
- data/lib/virtfs/nativefs/thin/dir_class_methods.rb +41 -0
- data/lib/virtfs/nativefs/thin/file.rb +112 -0
- data/lib/virtfs/nativefs/thin/file_class_methods.rb +181 -0
- data/lib/virtfs/protofs/protofs.rb +7 -0
- data/lib/virtfs/protofs/protofs_base.rb +12 -0
- data/lib/virtfs/protofs/protofs_dir.rb +13 -0
- data/lib/virtfs/protofs/protofs_dir_class.rb +31 -0
- data/lib/virtfs/protofs/protofs_file.rb +27 -0
- data/lib/virtfs/protofs/protofs_file_class.rb +136 -0
- data/lib/virtfs/stat.rb +100 -0
- data/lib/virtfs/thin_dir_delegator.rb +79 -0
- data/lib/virtfs/thin_file_delegator.rb +77 -0
- data/lib/virtfs/thin_io_delegator_methods.rb +301 -0
- data/lib/virtfs/thin_io_delegator_methods_bufferio.rb +337 -0
- data/lib/virtfs/v_dir.rb +238 -0
- data/lib/virtfs/v_file.rb +480 -0
- data/lib/virtfs/v_io.rb +243 -0
- data/lib/virtfs/v_pathname.rb +128 -0
- data/lib/virtfs/version.rb +3 -0
- data/spec/activate_spec.rb +202 -0
- data/spec/chroot_spec.rb +120 -0
- data/spec/context_manager_class_spec.rb +246 -0
- data/spec/context_manager_instance_spec.rb +255 -0
- data/spec/context_spec.rb +335 -0
- data/spec/data/UTF-16LE-data.txt +0 -0
- data/spec/data/UTF-8-data.txt +212 -0
- data/spec/dir_class_spec.rb +506 -0
- data/spec/dir_instance_spec.rb +208 -0
- data/spec/file_class_spec.rb +2106 -0
- data/spec/file_instance_spec.rb +154 -0
- data/spec/file_modes_and_options_spec.rb +1556 -0
- data/spec/find_spec.rb +142 -0
- data/spec/io_bufferio_size_shared_examples.rb +371 -0
- data/spec/io_bufferio_size_spec.rb +861 -0
- data/spec/io_bufferio_spec.rb +801 -0
- data/spec/io_class_spec.rb +145 -0
- data/spec/io_instance_spec.rb +516 -0
- data/spec/kernel_spec.rb +285 -0
- data/spec/mount_spec.rb +186 -0
- data/spec/nativefs_local_root_spec.rb +132 -0
- data/spec/path_spec.rb +39 -0
- data/spec/spec_helper.rb +126 -0
- data/tasks/rspec.rake +3 -0
- data/tasks/yard.rake +7 -0
- data/test/UTF-8-demo.txt +212 -0
- data/test/bench.rb +18 -0
- data/test/bio_internal_test.rb +45 -0
- data/test/delegate_io.rb +31 -0
- data/test/delegate_module.rb +62 -0
- data/test/encode_test.rb +42 -0
- data/test/enoent_test.rb +30 -0
- data/test/namespace_test.rb +42 -0
- data/test/read_block_valid_encoding.rb +44 -0
- data/test/read_test.rb +78 -0
- data/test/stream_readers.rb +46 -0
- data/test/utf-16-demo.txt +0 -0
- data/test/utf8_to_utf16.rb +77 -0
- data/test/wrapper_test.rb +34 -0
- data/virtfs.gemspec +29 -0
- metadata +230 -0
@@ -0,0 +1,801 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe VirtFS::VIO, "(#{$fs_interface} interface)" do
|
4
|
+
before(:all) do
|
5
|
+
@data_dir = VfsRealFile.join(__dir__, "data")
|
6
|
+
@utf_8_filename = VfsRealFile.join(@data_dir, "UTF-8-data.txt")
|
7
|
+
@utf_16_filename = VfsRealFile.join(@data_dir, "UTF-16LE-data.txt")
|
8
|
+
|
9
|
+
@start_marker = "START OF FILE:\n"
|
10
|
+
@end_marker = ":END OF FILE"
|
11
|
+
@data1 = "0123456789"
|
12
|
+
@data2 = "abcdefghijklmnopqrstuvwzyz\n"
|
13
|
+
|
14
|
+
@default_encoding = Encoding.default_external
|
15
|
+
@binary_encoding = Encoding.find("ASCII-8BIT")
|
16
|
+
end
|
17
|
+
|
18
|
+
before(:each) do
|
19
|
+
reset_context
|
20
|
+
|
21
|
+
@temp_file = Tempfile.new("VirtFS-IO")
|
22
|
+
@temp_file.write(@start_marker)
|
23
|
+
(0..9).each do
|
24
|
+
@temp_file.write(@data1)
|
25
|
+
@temp_file.write(@data2)
|
26
|
+
end
|
27
|
+
@temp_file.write(@end_marker)
|
28
|
+
@temp_file.close
|
29
|
+
|
30
|
+
@full_path = @temp_file.path
|
31
|
+
@file_size = VfsRealFile.size(@full_path)
|
32
|
+
|
33
|
+
@temp_write = Tempfile.new("VirtFS-IO")
|
34
|
+
@temp_write.close
|
35
|
+
@write_file_path = @temp_write.path
|
36
|
+
|
37
|
+
@root = File::SEPARATOR
|
38
|
+
@native_fs = nativefs_class.new
|
39
|
+
VirtFS.mount(@native_fs, @root)
|
40
|
+
|
41
|
+
@vfile_read_obj = VirtFS::VFile.new(@full_path, "r")
|
42
|
+
@vfile_write_obj = VirtFS::VFile.new(@write_file_path, "w")
|
43
|
+
end
|
44
|
+
|
45
|
+
after(:each) do
|
46
|
+
@vfile_read_obj.close unless @vfile_read_obj.closed?
|
47
|
+
@vfile_write_obj.close unless @vfile_write_obj.closed?
|
48
|
+
VirtFS.umount(@root)
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#<<" do
|
52
|
+
it "should return the IO object" do
|
53
|
+
expect(@vfile_write_obj << "hello").to eq(@vfile_write_obj)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should update the current file position" do
|
57
|
+
write_str = "0123456789"
|
58
|
+
last_pos = @vfile_write_obj.pos
|
59
|
+
(0..9).each do
|
60
|
+
@vfile_write_obj << write_str
|
61
|
+
pos = @vfile_write_obj.pos
|
62
|
+
expect(pos).to eq(last_pos + write_str.bytesize)
|
63
|
+
last_pos = pos
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should update the size of the file" do
|
68
|
+
write_str = "0123456789"
|
69
|
+
last_size = @vfile_write_obj.size
|
70
|
+
(0..9).each do
|
71
|
+
@vfile_write_obj << write_str
|
72
|
+
size = @vfile_write_obj.size
|
73
|
+
expect(size).to eq(last_size + write_str.bytesize)
|
74
|
+
last_size = size
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should write data that's readable" do
|
79
|
+
write_str = "0123456789"
|
80
|
+
(0..9).each do
|
81
|
+
@vfile_write_obj << write_str
|
82
|
+
end
|
83
|
+
|
84
|
+
@vfile_write_obj.close
|
85
|
+
@vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
|
86
|
+
|
87
|
+
(0..9).each do
|
88
|
+
expect(@vfile_write_obj.sysread(write_str.bytesize)).to eq(write_str)
|
89
|
+
end
|
90
|
+
|
91
|
+
expect do
|
92
|
+
@vfile_write_obj.sysread(write_str.bytesize)
|
93
|
+
end.to raise_error(
|
94
|
+
EOFError, "end of file reached"
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should accept non-string objects as input" do
|
99
|
+
write_obj = 123456789
|
100
|
+
test_str = write_obj.to_s
|
101
|
+
|
102
|
+
@vfile_write_obj << write_obj
|
103
|
+
|
104
|
+
@vfile_write_obj.close
|
105
|
+
@vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
|
106
|
+
|
107
|
+
expect(@vfile_write_obj.sysread(test_str.bytesize)).to eq(test_str)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should append to an existing file" do
|
111
|
+
write_str = ":NEW END OF FILE"
|
112
|
+
new_end_marker = @end_marker + write_str
|
113
|
+
|
114
|
+
vfile_test_obj = VirtFS::VFile.new(@full_path, "a")
|
115
|
+
vfile_test_obj << write_str
|
116
|
+
vfile_test_obj.close
|
117
|
+
|
118
|
+
fobj = VfsRealFile.new(@full_path, "r")
|
119
|
+
fobj.seek(-new_end_marker.bytesize, IO::SEEK_END)
|
120
|
+
expect(fobj.sysread(new_end_marker.bytesize)).to eq(new_end_marker)
|
121
|
+
fobj.close
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should support read/write" do
|
125
|
+
new_text = "ADDED TEXT\n"
|
126
|
+
|
127
|
+
vfile_test_obj = VirtFS::VFile.new(@full_path, "r+")
|
128
|
+
vfile_test_obj.pos = 0
|
129
|
+
rv = vfile_test_obj.read(@start_marker.bytesize)
|
130
|
+
expect(rv).to eq(@start_marker)
|
131
|
+
|
132
|
+
test_text = rv + new_text
|
133
|
+
|
134
|
+
vfile_test_obj << new_text
|
135
|
+
vfile_test_obj.pos = 0
|
136
|
+
expect(vfile_test_obj.read(test_text.bytesize)).to eq(test_text)
|
137
|
+
vfile_test_obj.close
|
138
|
+
|
139
|
+
fobj = VfsRealFile.new(@full_path, "r")
|
140
|
+
expect(fobj.sysread(test_text.bytesize)).to eq(test_text)
|
141
|
+
fobj.close
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe "#eof, #eof?" do
|
146
|
+
it "should return false when the file is not at EOF" do
|
147
|
+
expect(@vfile_read_obj.eof).to be false
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should return true when the file is at EOF" do
|
151
|
+
@vfile_read_obj.seek(0, IO::SEEK_END)
|
152
|
+
expect(@vfile_read_obj.eof).to be true
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should raise IOError when the file isn't open for reading" do
|
156
|
+
expect do
|
157
|
+
@vfile_write_obj.eof
|
158
|
+
end.to raise_error(
|
159
|
+
IOError, /not opened for reading/
|
160
|
+
)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe "#external_encoding" do
|
165
|
+
it "should return the default external encoding, when not changed" do
|
166
|
+
expect(@vfile_read_obj.external_encoding).to eq(Encoding.default_external)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe "#fdatasync" do
|
171
|
+
it "should return 0" do
|
172
|
+
expect(@vfile_write_obj.fdatasync).to eq(0)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe "#flush" do
|
177
|
+
it "should return the IO object" do
|
178
|
+
expect(@vfile_write_obj.flush).to eq(@vfile_write_obj)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe "#fsync" do
|
183
|
+
it "should return 0" do
|
184
|
+
expect(@vfile_write_obj.fsync).to eq(0)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
describe "#internal_encoding" do
|
189
|
+
it "should return the default internal encoding, when not changed" do
|
190
|
+
expect(@vfile_read_obj.internal_encoding).to eq(Encoding.default_internal)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
describe "#lineno" do
|
195
|
+
it "should return 0 for newly opened file" do
|
196
|
+
expect(@vfile_read_obj.lineno).to eq(0)
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should raise IOError when the file isn't open for reading" do
|
200
|
+
expect do
|
201
|
+
@vfile_write_obj.lineno
|
202
|
+
end.to raise_error(
|
203
|
+
IOError, /not opened for reading/
|
204
|
+
)
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should increment with each line read" do
|
208
|
+
expected_lineno = 1
|
209
|
+
while @vfile_read_obj.gets
|
210
|
+
expect(@vfile_read_obj.lineno).to eq(expected_lineno)
|
211
|
+
expected_lineno += 1
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
describe "#lineno=" do
|
217
|
+
it "should return the new value" do
|
218
|
+
new_val = 128
|
219
|
+
expect(@vfile_read_obj.lineno = new_val).to eq(new_val)
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should raise IOError when the file isn't open for reading" do
|
223
|
+
expect do
|
224
|
+
@vfile_write_obj.lineno = 10
|
225
|
+
end.to raise_error(
|
226
|
+
IOError, /not opened for reading/
|
227
|
+
)
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should set the lineno" do
|
231
|
+
set_lineno = 100
|
232
|
+
@vfile_read_obj.lineno = set_lineno
|
233
|
+
expected_lineno = set_lineno + 1
|
234
|
+
while @vfile_read_obj.gets
|
235
|
+
expect(@vfile_read_obj.lineno).to eq(expected_lineno)
|
236
|
+
expected_lineno += 1
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
describe "#pos" do
|
242
|
+
it "should return 0 for a newly opened file" do
|
243
|
+
expect(@vfile_read_obj.pos).to eq(0)
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should return the new position after a seek" do
|
247
|
+
offset = @file_size / 2
|
248
|
+
@vfile_read_obj.seek(offset)
|
249
|
+
expect(@vfile_read_obj.pos).to eq(offset)
|
250
|
+
end
|
251
|
+
|
252
|
+
it "should return the new position after a read" do
|
253
|
+
rv = @vfile_read_obj.sysread(@data1.bytesize)
|
254
|
+
expect(rv.bytesize).to eq(@data1.bytesize)
|
255
|
+
expect(@vfile_read_obj.pos).to eq(@data1.bytesize)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
describe "#pos=" do
|
260
|
+
it "should return the new position" do
|
261
|
+
expect(@vfile_read_obj.pos = 10).to eq(10)
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should raise Errno::EINVAL when position is negative" do
|
265
|
+
expect do
|
266
|
+
@vfile_read_obj.pos = -10
|
267
|
+
end.to raise_error(
|
268
|
+
Errno::EINVAL, /Invalid argument/
|
269
|
+
)
|
270
|
+
end
|
271
|
+
|
272
|
+
it "should change the read position within the file" do
|
273
|
+
@vfile_read_obj.pos = @start_marker.bytesize
|
274
|
+
rv = @vfile_read_obj.sysread(@data1.bytesize) # change to #read
|
275
|
+
expect(rv).to eq(@data1)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
describe "#print" do
|
280
|
+
it "should return nil" do
|
281
|
+
expect(@vfile_write_obj.print("hello")).to be_nil
|
282
|
+
end
|
283
|
+
|
284
|
+
it "should write data that's readable" do
|
285
|
+
write_str = "0123456789"
|
286
|
+
(0..9).each do
|
287
|
+
@vfile_write_obj.print write_str
|
288
|
+
end
|
289
|
+
|
290
|
+
@vfile_write_obj.close
|
291
|
+
@vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
|
292
|
+
|
293
|
+
(0..9).each do
|
294
|
+
expect(@vfile_write_obj.sysread(write_str.bytesize)).to eq(write_str)
|
295
|
+
end
|
296
|
+
|
297
|
+
expect do
|
298
|
+
@vfile_write_obj.sysread(write_str.bytesize)
|
299
|
+
end.to raise_error(
|
300
|
+
EOFError, "end of file reached"
|
301
|
+
)
|
302
|
+
end
|
303
|
+
|
304
|
+
it "should accept non-string objects as input" do
|
305
|
+
write_obj = 123456789
|
306
|
+
test_str = write_obj.to_s
|
307
|
+
|
308
|
+
@vfile_write_obj.print write_obj
|
309
|
+
|
310
|
+
@vfile_write_obj.close
|
311
|
+
@vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
|
312
|
+
|
313
|
+
expect(@vfile_write_obj.sysread(test_str.bytesize)).to eq(test_str)
|
314
|
+
end
|
315
|
+
|
316
|
+
it "should concatenate string arguments" do
|
317
|
+
print_args = %w( one, two, three, four )
|
318
|
+
test_str = print_args.join
|
319
|
+
|
320
|
+
@vfile_write_obj.print(*print_args)
|
321
|
+
|
322
|
+
@vfile_write_obj.close
|
323
|
+
@vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
|
324
|
+
|
325
|
+
expect(@vfile_write_obj.sysread(test_str.bytesize)).to eq(test_str)
|
326
|
+
end
|
327
|
+
|
328
|
+
it "should concatenate non-string arguments" do
|
329
|
+
print_args = [1, 2, 3, 4]
|
330
|
+
test_str = "1234"
|
331
|
+
|
332
|
+
@vfile_write_obj.print(*print_args)
|
333
|
+
|
334
|
+
@vfile_write_obj.close
|
335
|
+
@vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
|
336
|
+
|
337
|
+
expect(@vfile_write_obj.sysread(test_str.bytesize)).to eq(test_str)
|
338
|
+
end
|
339
|
+
|
340
|
+
# it "should print $_ by default" do
|
341
|
+
# test_str = "default string"
|
342
|
+
#
|
343
|
+
# $_ = test_str
|
344
|
+
# @vfile_write_obj.print
|
345
|
+
#
|
346
|
+
# @vfile_write_obj.close
|
347
|
+
# @vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
|
348
|
+
#
|
349
|
+
# expect(@vfile_write_obj.sysread(test_str.bytesize)).to eq(test_str)
|
350
|
+
# end
|
351
|
+
|
352
|
+
it "should append $\ to the output - if it's set" do
|
353
|
+
write_str = "Hello World"
|
354
|
+
ors = ":END"
|
355
|
+
test_str = write_str + ors
|
356
|
+
|
357
|
+
$\ = ors
|
358
|
+
@vfile_write_obj.print write_str
|
359
|
+
$\ = nil
|
360
|
+
|
361
|
+
@vfile_write_obj.close
|
362
|
+
@vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
|
363
|
+
|
364
|
+
expect(@vfile_write_obj.sysread(test_str.bytesize)).to eq(test_str)
|
365
|
+
end
|
366
|
+
|
367
|
+
it "should insert $, between fields - if it's set" do
|
368
|
+
print_args = [1, 2, 3, 4]
|
369
|
+
ofs = ", "
|
370
|
+
test_str = "1, 2, 3, 4"
|
371
|
+
|
372
|
+
$, = ofs
|
373
|
+
@vfile_write_obj.print(*print_args)
|
374
|
+
$, = nil
|
375
|
+
|
376
|
+
@vfile_write_obj.close
|
377
|
+
@vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
|
378
|
+
|
379
|
+
expect(@vfile_write_obj.sysread(test_str.bytesize)).to eq(test_str)
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
describe "#printf" do
|
384
|
+
it "should return nil" do
|
385
|
+
expect(@vfile_write_obj.printf("hello")).to be_nil
|
386
|
+
end
|
387
|
+
|
388
|
+
it "should output a formatted string" do
|
389
|
+
fmt = "%s %s: %d"
|
390
|
+
args = ["Hello", "World", 123]
|
391
|
+
test_str = format(fmt, *args)
|
392
|
+
|
393
|
+
@vfile_write_obj.printf(fmt, *args)
|
394
|
+
|
395
|
+
@vfile_write_obj.close
|
396
|
+
@vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
|
397
|
+
|
398
|
+
expect(@vfile_write_obj.sysread(test_str.bytesize)).to eq(test_str)
|
399
|
+
end
|
400
|
+
|
401
|
+
it "should output a formatted string - given hash args" do
|
402
|
+
fmt = "%{word1} %{word2}: %{num}"
|
403
|
+
args = {:word1 => "Hello", :num => 123, :word2 => "World"}
|
404
|
+
test_str = format(fmt, args)
|
405
|
+
|
406
|
+
@vfile_write_obj.printf(fmt, args)
|
407
|
+
|
408
|
+
@vfile_write_obj.close
|
409
|
+
@vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
|
410
|
+
|
411
|
+
expect(@vfile_write_obj.sysread(test_str.bytesize)).to eq(test_str)
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
describe "#putc" do
|
416
|
+
it "should return its arg" do
|
417
|
+
arg = "hello"
|
418
|
+
expect(@vfile_write_obj.putc arg).to eq(arg)
|
419
|
+
end
|
420
|
+
|
421
|
+
it "should output the first character of a string" do
|
422
|
+
write_obj = "hello"
|
423
|
+
test_str = write_obj[0]
|
424
|
+
|
425
|
+
@vfile_write_obj.putc write_obj
|
426
|
+
|
427
|
+
@vfile_write_obj.close
|
428
|
+
@vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
|
429
|
+
|
430
|
+
expect(@vfile_write_obj.sysread(test_str.bytesize)).to eq(test_str)
|
431
|
+
end
|
432
|
+
|
433
|
+
it "should output the character representation of an integer" do
|
434
|
+
write_obj = 65
|
435
|
+
test_str = write_obj.chr
|
436
|
+
|
437
|
+
@vfile_write_obj.putc write_obj
|
438
|
+
|
439
|
+
@vfile_write_obj.close
|
440
|
+
@vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
|
441
|
+
|
442
|
+
expect(@vfile_write_obj.sysread(test_str.bytesize)).to eq(test_str)
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
describe "#puts" do
|
447
|
+
it "should return nil" do
|
448
|
+
expect(@vfile_write_obj.puts "hello").to be_nil
|
449
|
+
end
|
450
|
+
|
451
|
+
it "should output a single new line - when called without args" do
|
452
|
+
@vfile_write_obj.puts
|
453
|
+
|
454
|
+
@vfile_write_obj.close
|
455
|
+
@vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
|
456
|
+
|
457
|
+
expect(@vfile_write_obj.sysread($/.bytesize)).to eq($/)
|
458
|
+
end
|
459
|
+
|
460
|
+
it "should write each arg on a new line" do
|
461
|
+
args = %w(line1 line2 line3)
|
462
|
+
test_str = args.join($/) + $/
|
463
|
+
|
464
|
+
@vfile_write_obj.puts(*args)
|
465
|
+
|
466
|
+
@vfile_write_obj.close
|
467
|
+
@vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
|
468
|
+
|
469
|
+
expect(@vfile_write_obj.sysread(test_str.bytesize)).to eq(test_str)
|
470
|
+
end
|
471
|
+
|
472
|
+
it "should not duplicate separators" do
|
473
|
+
args = %W(line1#{$/} line2#{$/} line3#{$/})
|
474
|
+
test_str = "line1#{$/}line2#{$/}line3#{$/}"
|
475
|
+
|
476
|
+
@vfile_write_obj.puts(*args)
|
477
|
+
|
478
|
+
@vfile_write_obj.close
|
479
|
+
@vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
|
480
|
+
|
481
|
+
expect(@vfile_write_obj.sysread(test_str.bytesize)).to eq(test_str)
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
describe "#readbyte" do
|
486
|
+
it "should return a Fixnum" do
|
487
|
+
expect(@vfile_read_obj.getbyte).to be_kind_of(Fixnum)
|
488
|
+
end
|
489
|
+
|
490
|
+
it "should raise EOFError when at EOF" do
|
491
|
+
@vfile_read_obj.read
|
492
|
+
expect { @vfile_read_obj.readbyte }.to raise_error(EOFError, "end of file reached")
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
describe "#readchar" do
|
497
|
+
it "should return a character of the expected encoding" do
|
498
|
+
expect(@vfile_read_obj.readchar.encoding).to eq(@vfile_read_obj.external_encoding)
|
499
|
+
end
|
500
|
+
|
501
|
+
it "should raise EOFError when at EOF" do
|
502
|
+
@vfile_read_obj.read
|
503
|
+
expect { @vfile_read_obj.readchar }.to raise_error(EOFError, "end of file reached")
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
507
|
+
describe "#readline" do
|
508
|
+
it "should read an entire line by default" do
|
509
|
+
rv = @vfile_read_obj.readline
|
510
|
+
expect(rv[-1]).to eq($/.encode(rv.encoding))
|
511
|
+
end
|
512
|
+
|
513
|
+
it "should raise EOFError when at EOF" do
|
514
|
+
@vfile_read_obj.read
|
515
|
+
expect { @vfile_read_obj.readline }.to raise_error(EOFError, "end of file reached")
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
519
|
+
describe "#readpartial" do
|
520
|
+
it "should do something"
|
521
|
+
end
|
522
|
+
|
523
|
+
describe "#rewind" do
|
524
|
+
it "should return 0" do
|
525
|
+
expect(@vfile_read_obj.rewind).to eq(0)
|
526
|
+
end
|
527
|
+
|
528
|
+
it "should reposition IO position to the start of file" do
|
529
|
+
rv = @vfile_read_obj.sysread(@start_marker.bytesize)
|
530
|
+
expect(rv).to eq(@start_marker)
|
531
|
+
rv = @vfile_read_obj.sysread(@start_marker.bytesize)
|
532
|
+
expect(rv).to_not eq(@start_marker)
|
533
|
+
|
534
|
+
@vfile_read_obj.rewind
|
535
|
+
|
536
|
+
rv = @vfile_read_obj.sysread(@start_marker.bytesize)
|
537
|
+
expect(rv).to eq(@start_marker)
|
538
|
+
end
|
539
|
+
end
|
540
|
+
|
541
|
+
describe "#seek" do
|
542
|
+
it "should raise Errno::EINVAL when attempting to seek before the beginning of the file" do
|
543
|
+
expect do
|
544
|
+
@vfile_read_obj.sysseek(-10, IO::SEEK_CUR)
|
545
|
+
end.to raise_error(
|
546
|
+
Errno::EINVAL, /Invalid argument/
|
547
|
+
)
|
548
|
+
end
|
549
|
+
|
550
|
+
it "should return 0" do
|
551
|
+
offset = @file_size / 2
|
552
|
+
rv = @vfile_read_obj.seek(offset, IO::SEEK_SET)
|
553
|
+
expect(rv).to eq(0)
|
554
|
+
end
|
555
|
+
|
556
|
+
it "should change the read position within the file - IO::SEEK_SET" do
|
557
|
+
@vfile_read_obj.seek(@start_marker.bytesize, IO::SEEK_SET)
|
558
|
+
rv = @vfile_read_obj.sysread(@data1.bytesize) # change to #read
|
559
|
+
expect(rv).to eq(@data1)
|
560
|
+
end
|
561
|
+
|
562
|
+
it "should change the read position within the file - IO::SEEK_CUR" do
|
563
|
+
@vfile_read_obj.seek(@start_marker.bytesize, IO::SEEK_SET)
|
564
|
+
@vfile_read_obj.seek(@data1.bytesize, IO::SEEK_CUR)
|
565
|
+
rv = @vfile_read_obj.sysread(@data2.bytesize) # change to #read
|
566
|
+
expect(rv).to eq(@data2)
|
567
|
+
end
|
568
|
+
|
569
|
+
it "should change the read position within the file - IO::SEEK_END" do
|
570
|
+
@vfile_read_obj.seek(-@end_marker.bytesize, IO::SEEK_END)
|
571
|
+
rv = @vfile_read_obj.sysread(@end_marker.bytesize) # change to #read
|
572
|
+
expect(rv).to eq(@end_marker)
|
573
|
+
end
|
574
|
+
end
|
575
|
+
|
576
|
+
describe "#set_encoding" do
|
577
|
+
before(:each) do
|
578
|
+
@target_external_str = "UTF-16LE"
|
579
|
+
@target_internal_str = "US-ASCII"
|
580
|
+
@target_external_obj = Encoding.find(@target_external_str)
|
581
|
+
@target_internal_obj = Encoding.find(@target_internal_str)
|
582
|
+
|
583
|
+
@vfile_read_test_obj = VirtFS::VFile.new(@full_path, "rb")
|
584
|
+
end
|
585
|
+
|
586
|
+
after(:each) do
|
587
|
+
@vfile_read_test_obj.close
|
588
|
+
end
|
589
|
+
|
590
|
+
it "should return the IO object" do
|
591
|
+
expect(@vfile_read_test_obj.set_encoding(@target_external_str)).to eq(@vfile_read_test_obj)
|
592
|
+
end
|
593
|
+
|
594
|
+
it "should raise ArgumentError when passed 0 args" do
|
595
|
+
expect do
|
596
|
+
@vfile_read_test_obj.set_encoding
|
597
|
+
end.to raise_error(
|
598
|
+
ArgumentError, "wrong number of arguments (0 for 1..2)"
|
599
|
+
)
|
600
|
+
end
|
601
|
+
|
602
|
+
it "should raise ArgumentError when passed more than 2 args" do
|
603
|
+
expect do
|
604
|
+
@vfile_read_test_obj.set_encoding("x", "Y", "Z")
|
605
|
+
end.to raise_error(
|
606
|
+
ArgumentError, "wrong number of arguments (3 for 1..2)"
|
607
|
+
)
|
608
|
+
end
|
609
|
+
|
610
|
+
it "should raise TypeError when passed unexpected types - first arg" do
|
611
|
+
expect do
|
612
|
+
@vfile_read_test_obj.set_encoding(100)
|
613
|
+
end.to raise_error(
|
614
|
+
TypeError, /no implicit conversion of/
|
615
|
+
)
|
616
|
+
end
|
617
|
+
|
618
|
+
it "should raise TypeError when passed unexpected types - second arg" do
|
619
|
+
expect do
|
620
|
+
@vfile_read_test_obj.set_encoding(@target_external_str, 100)
|
621
|
+
end.to raise_error(
|
622
|
+
TypeError, /no implicit conversion of/
|
623
|
+
)
|
624
|
+
end
|
625
|
+
|
626
|
+
context "given encoding objects" do
|
627
|
+
it "should change external and internal encodings" do
|
628
|
+
expect(@vfile_read_test_obj.external_encoding).to_not eq(@target_external_obj)
|
629
|
+
expect(@vfile_read_test_obj.internal_encoding).to_not eq(@target_internal_obj)
|
630
|
+
|
631
|
+
@vfile_read_test_obj.set_encoding(@target_external_obj, @target_internal_obj)
|
632
|
+
|
633
|
+
expect(@vfile_read_test_obj.external_encoding).to eq(@target_external_obj)
|
634
|
+
expect(@vfile_read_test_obj.internal_encoding).to eq(@target_internal_obj)
|
635
|
+
end
|
636
|
+
|
637
|
+
# XXX - Real IO objects don't seem to behave like this.
|
638
|
+
# it "should default internal to external - when internal omitted" do
|
639
|
+
# expect(@vfile_read_test_obj.external_encoding).to_not eq(@target_external_obj)
|
640
|
+
# expect(@vfile_read_test_obj.internal_encoding).to_not eq(@target_external_obj)
|
641
|
+
#
|
642
|
+
# @vfile_read_test_obj.set_encoding(@target_external_obj)
|
643
|
+
#
|
644
|
+
# expect(@vfile_read_test_obj.external_encoding).to eq(@target_external_obj)
|
645
|
+
# expect(@vfile_read_test_obj.internal_encoding).to eq(@target_external_obj)
|
646
|
+
# end
|
647
|
+
end
|
648
|
+
|
649
|
+
context "given strings" do
|
650
|
+
it "should change external and internal encodings" do
|
651
|
+
expect(@vfile_read_test_obj.external_encoding).to_not eq(@target_external_obj)
|
652
|
+
expect(@vfile_read_test_obj.internal_encoding).to_not eq(@target_internal_obj)
|
653
|
+
|
654
|
+
@vfile_read_test_obj.set_encoding(@target_external_str, @target_internal_str)
|
655
|
+
|
656
|
+
expect(@vfile_read_test_obj.external_encoding).to eq(@target_external_obj)
|
657
|
+
expect(@vfile_read_test_obj.internal_encoding).to eq(@target_internal_obj)
|
658
|
+
end
|
659
|
+
|
660
|
+
# XXX - No, it shouldn't.
|
661
|
+
# it "should default internal to external - when internal omitted" do
|
662
|
+
# expect(@vfile_read_test_obj.external_encoding).to_not eq(@target_external_obj)
|
663
|
+
# expect(@vfile_read_test_obj.internal_encoding).to_not eq(@target_external_obj)
|
664
|
+
#
|
665
|
+
# @vfile_read_test_obj.binmode
|
666
|
+
# @vfile_read_test_obj.set_encoding(@target_external_str)
|
667
|
+
#
|
668
|
+
# expect(@vfile_read_test_obj.external_encoding).to eq(@target_external_obj)
|
669
|
+
# expect(@vfile_read_test_obj.internal_encoding).to eq(@target_external_obj)
|
670
|
+
# end
|
671
|
+
end
|
672
|
+
|
673
|
+
context "given mixed types" do
|
674
|
+
it "should work with (Encoding, String)" do
|
675
|
+
expect(@vfile_read_test_obj.external_encoding).to_not eq(@target_external_obj)
|
676
|
+
expect(@vfile_read_test_obj.internal_encoding).to_not eq(@target_internal_obj)
|
677
|
+
|
678
|
+
@vfile_read_test_obj.set_encoding(@target_external_obj, @target_internal_str)
|
679
|
+
|
680
|
+
expect(@vfile_read_test_obj.external_encoding).to eq(@target_external_obj)
|
681
|
+
expect(@vfile_read_test_obj.internal_encoding).to eq(@target_internal_obj)
|
682
|
+
end
|
683
|
+
|
684
|
+
it "should work with (String, Encoding)" do
|
685
|
+
expect(@vfile_read_test_obj.external_encoding).to_not eq(@target_external_obj)
|
686
|
+
expect(@vfile_read_test_obj.internal_encoding).to_not eq(@target_internal_obj)
|
687
|
+
|
688
|
+
@vfile_read_test_obj.set_encoding(@target_external_str, @target_internal_obj)
|
689
|
+
|
690
|
+
expect(@vfile_read_test_obj.external_encoding).to eq(@target_external_obj)
|
691
|
+
expect(@vfile_read_test_obj.internal_encoding).to eq(@target_internal_obj)
|
692
|
+
end
|
693
|
+
end
|
694
|
+
end
|
695
|
+
|
696
|
+
describe "#sync" do
|
697
|
+
it "should return false by default" do
|
698
|
+
expect(@vfile_write_obj.sync).to be false
|
699
|
+
end
|
700
|
+
end
|
701
|
+
|
702
|
+
describe "#sync=" do
|
703
|
+
it "should return the new sync mode" do
|
704
|
+
expect(@vfile_write_obj.sync).to be false
|
705
|
+
expect(@vfile_write_obj.sync = true).to be true
|
706
|
+
end
|
707
|
+
|
708
|
+
it "should change the sync mode" do
|
709
|
+
expect(@vfile_write_obj.sync).to be false
|
710
|
+
expect(@vfile_write_obj.sync = true).to be true
|
711
|
+
expect(@vfile_write_obj.sync).to be true
|
712
|
+
end
|
713
|
+
end
|
714
|
+
|
715
|
+
describe "#write" do
|
716
|
+
it "should return the number of bytes written" do
|
717
|
+
write_str = "0123456789"
|
718
|
+
expect(@vfile_write_obj.write(write_str)).to eq(write_str.bytesize)
|
719
|
+
end
|
720
|
+
|
721
|
+
it "should update the current file position" do
|
722
|
+
write_str = "0123456789"
|
723
|
+
last_pos = @vfile_write_obj.pos
|
724
|
+
(0..9).each do
|
725
|
+
@vfile_write_obj.write(write_str)
|
726
|
+
pos = @vfile_write_obj.pos
|
727
|
+
expect(pos).to eq(last_pos + write_str.bytesize)
|
728
|
+
last_pos = pos
|
729
|
+
end
|
730
|
+
end
|
731
|
+
|
732
|
+
it "should update the size of the file" do
|
733
|
+
write_str = "0123456789"
|
734
|
+
last_size = @vfile_write_obj.size
|
735
|
+
(0..9).each do
|
736
|
+
@vfile_write_obj.write(write_str)
|
737
|
+
size = @vfile_write_obj.size
|
738
|
+
expect(size).to eq(last_size + write_str.bytesize)
|
739
|
+
last_size = size
|
740
|
+
end
|
741
|
+
end
|
742
|
+
|
743
|
+
it "should write data that's readable" do
|
744
|
+
write_str = "0123456789"
|
745
|
+
(0..9).each do
|
746
|
+
@vfile_write_obj.write(write_str)
|
747
|
+
end
|
748
|
+
|
749
|
+
@vfile_write_obj.close
|
750
|
+
@vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
|
751
|
+
|
752
|
+
(0..9).each do
|
753
|
+
expect(@vfile_write_obj.sysread(write_str.bytesize)).to eq(write_str)
|
754
|
+
end
|
755
|
+
|
756
|
+
expect do
|
757
|
+
@vfile_write_obj.sysread(write_str.bytesize)
|
758
|
+
end.to raise_error(
|
759
|
+
EOFError, "end of file reached"
|
760
|
+
)
|
761
|
+
end
|
762
|
+
|
763
|
+
it "should append to an existing file" do
|
764
|
+
write_str = ":NEW END OF FILE"
|
765
|
+
new_end_marker = @end_marker + write_str
|
766
|
+
|
767
|
+
vfile_test_obj = VirtFS::VFile.new(@full_path, "a")
|
768
|
+
vfile_test_obj.write(write_str)
|
769
|
+
vfile_test_obj.close
|
770
|
+
|
771
|
+
fobj = VfsRealFile.new(@full_path, "r")
|
772
|
+
fobj.seek(-new_end_marker.bytesize, IO::SEEK_END)
|
773
|
+
expect(fobj.sysread(new_end_marker.bytesize)).to eq(new_end_marker)
|
774
|
+
fobj.close
|
775
|
+
end
|
776
|
+
|
777
|
+
it "should support read/write" do
|
778
|
+
new_text = "ADDED TEXT\n"
|
779
|
+
|
780
|
+
vfile_test_obj = VirtFS::VFile.new(@full_path, "r+")
|
781
|
+
vfile_test_obj.pos = 0
|
782
|
+
rv = vfile_test_obj.read(@start_marker.bytesize)
|
783
|
+
expect(rv).to eq(@start_marker)
|
784
|
+
|
785
|
+
test_text = rv + new_text
|
786
|
+
|
787
|
+
vfile_test_obj.write(new_text)
|
788
|
+
vfile_test_obj.pos = 0
|
789
|
+
expect(vfile_test_obj.read(test_text.bytesize)).to eq(test_text)
|
790
|
+
vfile_test_obj.close
|
791
|
+
|
792
|
+
fobj = VfsRealFile.new(@full_path, "r")
|
793
|
+
expect(fobj.sysread(test_text.bytesize)).to eq(test_text)
|
794
|
+
fobj.close
|
795
|
+
end
|
796
|
+
end
|
797
|
+
|
798
|
+
describe "#write_nonblock" do
|
799
|
+
it "should do something"
|
800
|
+
end
|
801
|
+
end
|