virtfs 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +8 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +154 -0
  8. data/Rakefile +5 -0
  9. data/lib/virtfs-nativefs-thick.rb +1 -0
  10. data/lib/virtfs-nativefs-thin.rb +1 -0
  11. data/lib/virtfs.rb +38 -0
  12. data/lib/virtfs/activation.rb +97 -0
  13. data/lib/virtfs/block_io.rb +140 -0
  14. data/lib/virtfs/byte_range.rb +71 -0
  15. data/lib/virtfs/context.rb +300 -0
  16. data/lib/virtfs/context_manager.rb +175 -0
  17. data/lib/virtfs/context_switch_class_methods.rb +96 -0
  18. data/lib/virtfs/delegate_module.rb +40 -0
  19. data/lib/virtfs/dir_instance_delegate.rb +3 -0
  20. data/lib/virtfs/exception.rb +13 -0
  21. data/lib/virtfs/file_instance_delegate.rb +3 -0
  22. data/lib/virtfs/file_modes_and_options.rb +293 -0
  23. data/lib/virtfs/find_class_methods.rb +106 -0
  24. data/lib/virtfs/io_buffer.rb +133 -0
  25. data/lib/virtfs/io_instance_delegate.rb +3 -0
  26. data/lib/virtfs/kernel.rb +146 -0
  27. data/lib/virtfs/nativefs/thick.rb +30 -0
  28. data/lib/virtfs/nativefs/thick/dir_class_methods.rb +38 -0
  29. data/lib/virtfs/nativefs/thick/file_class_methods.rb +178 -0
  30. data/lib/virtfs/nativefs/thin.rb +32 -0
  31. data/lib/virtfs/nativefs/thin/dir.rb +30 -0
  32. data/lib/virtfs/nativefs/thin/dir_class_methods.rb +41 -0
  33. data/lib/virtfs/nativefs/thin/file.rb +112 -0
  34. data/lib/virtfs/nativefs/thin/file_class_methods.rb +181 -0
  35. data/lib/virtfs/protofs/protofs.rb +7 -0
  36. data/lib/virtfs/protofs/protofs_base.rb +12 -0
  37. data/lib/virtfs/protofs/protofs_dir.rb +13 -0
  38. data/lib/virtfs/protofs/protofs_dir_class.rb +31 -0
  39. data/lib/virtfs/protofs/protofs_file.rb +27 -0
  40. data/lib/virtfs/protofs/protofs_file_class.rb +136 -0
  41. data/lib/virtfs/stat.rb +100 -0
  42. data/lib/virtfs/thin_dir_delegator.rb +79 -0
  43. data/lib/virtfs/thin_file_delegator.rb +77 -0
  44. data/lib/virtfs/thin_io_delegator_methods.rb +301 -0
  45. data/lib/virtfs/thin_io_delegator_methods_bufferio.rb +337 -0
  46. data/lib/virtfs/v_dir.rb +238 -0
  47. data/lib/virtfs/v_file.rb +480 -0
  48. data/lib/virtfs/v_io.rb +243 -0
  49. data/lib/virtfs/v_pathname.rb +128 -0
  50. data/lib/virtfs/version.rb +3 -0
  51. data/spec/activate_spec.rb +202 -0
  52. data/spec/chroot_spec.rb +120 -0
  53. data/spec/context_manager_class_spec.rb +246 -0
  54. data/spec/context_manager_instance_spec.rb +255 -0
  55. data/spec/context_spec.rb +335 -0
  56. data/spec/data/UTF-16LE-data.txt +0 -0
  57. data/spec/data/UTF-8-data.txt +212 -0
  58. data/spec/dir_class_spec.rb +506 -0
  59. data/spec/dir_instance_spec.rb +208 -0
  60. data/spec/file_class_spec.rb +2106 -0
  61. data/spec/file_instance_spec.rb +154 -0
  62. data/spec/file_modes_and_options_spec.rb +1556 -0
  63. data/spec/find_spec.rb +142 -0
  64. data/spec/io_bufferio_size_shared_examples.rb +371 -0
  65. data/spec/io_bufferio_size_spec.rb +861 -0
  66. data/spec/io_bufferio_spec.rb +801 -0
  67. data/spec/io_class_spec.rb +145 -0
  68. data/spec/io_instance_spec.rb +516 -0
  69. data/spec/kernel_spec.rb +285 -0
  70. data/spec/mount_spec.rb +186 -0
  71. data/spec/nativefs_local_root_spec.rb +132 -0
  72. data/spec/path_spec.rb +39 -0
  73. data/spec/spec_helper.rb +126 -0
  74. data/tasks/rspec.rake +3 -0
  75. data/tasks/yard.rake +7 -0
  76. data/test/UTF-8-demo.txt +212 -0
  77. data/test/bench.rb +18 -0
  78. data/test/bio_internal_test.rb +45 -0
  79. data/test/delegate_io.rb +31 -0
  80. data/test/delegate_module.rb +62 -0
  81. data/test/encode_test.rb +42 -0
  82. data/test/enoent_test.rb +30 -0
  83. data/test/namespace_test.rb +42 -0
  84. data/test/read_block_valid_encoding.rb +44 -0
  85. data/test/read_test.rb +78 -0
  86. data/test/stream_readers.rb +46 -0
  87. data/test/utf-16-demo.txt +0 -0
  88. data/test/utf8_to_utf16.rb +77 -0
  89. data/test/wrapper_test.rb +34 -0
  90. data/virtfs.gemspec +29 -0
  91. metadata +230 -0
@@ -0,0 +1,145 @@
1
+ require 'spec_helper'
2
+
3
+ describe VirtFS::VIO, "(#{$fs_interface} interface)" do
4
+ before(:all) do
5
+ @temp_file = Tempfile.new("VirtFS-IO")
6
+ @temp_file.write(@start_marker)
7
+ (0..9).each do
8
+ @temp_file.write(@data1)
9
+ @temp_file.write(@data2)
10
+ end
11
+ @temp_file.write(@end_marker)
12
+ @temp_file.close
13
+
14
+ @full_path = @temp_file.path
15
+
16
+ @temp_write = Tempfile.new("VirtFS-IO")
17
+ @temp_write.close
18
+ @write_file_path = @temp_write.path
19
+ end
20
+
21
+ before(:each) do
22
+ reset_context
23
+
24
+ @root = File::SEPARATOR
25
+ @native_fs = nativefs_class.new
26
+ VirtFS.mount(@native_fs, @root)
27
+
28
+ @vfile_read_obj = VirtFS::VFile.new(@full_path, "r")
29
+ @vfile_write_obj = VirtFS::VFile.new(@write_file_path, "w")
30
+ end
31
+
32
+ after(:each) do
33
+ VirtFS.umount(@root)
34
+ end
35
+
36
+ describe ".binread" do
37
+ it "should return the same data as IO.binread - whole file" do
38
+ expect(VirtFS::VIO.binread(@full_path)).to eq(VfsRealIO.binread(@full_path))
39
+ end
40
+
41
+ it "should return the same data as IO.binread - given length" do
42
+ length = 30
43
+ expect(VirtFS::VIO.binread(@full_path, length)).to eq(VfsRealIO.binread(@full_path, length))
44
+ end
45
+
46
+ it "should return the same data as IO.binread - given length and offset" do
47
+ length = 30
48
+ offset = 20
49
+ expect(VirtFS::VIO.binread(@full_path, length, offset)).to eq(VfsRealIO.binread(@full_path, length, offset))
50
+ end
51
+ end
52
+
53
+ describe ".copy_stream" do
54
+ it "should return the number of bytes copied" do
55
+ expect(VirtFS::VIO.copy_stream(@vfile_read_obj, @vfile_write_obj)).to eq(@vfile_read_obj.size)
56
+ end
57
+
58
+ it "should create a file of the same size" do
59
+ VirtFS::VIO.copy_stream(@vfile_read_obj, @vfile_write_obj)
60
+ expect(@vfile_write_obj.size).to eq(@vfile_read_obj.size)
61
+ end
62
+
63
+ it "should create a file with the same contents" do
64
+ VirtFS::VIO.copy_stream(@vfile_read_obj, @vfile_write_obj)
65
+ @vfile_read_obj.rewind
66
+ @vfile_write_obj.reopen(@write_file_path, "r")
67
+ expect(@vfile_write_obj.read).to eq(@vfile_read_obj.read)
68
+ end
69
+ end
70
+
71
+ describe ".foreach" do
72
+ it "should return an enum when no block is given" do
73
+ expect(VirtFS::VIO.foreach(@full_path)).to be_kind_of(Enumerator)
74
+ end
75
+
76
+ it "should return the nil object when block is given" do
77
+ expect(VirtFS::VIO.foreach(@full_path) { true }).to be_nil
78
+ end
79
+
80
+ it "should enumerate the same lines as the standard IO.foreach" do
81
+ expect(VirtFS::VIO.foreach(@full_path).to_a).to match_array(VfsRealIO.foreach(@full_path).to_a)
82
+ end
83
+ end
84
+
85
+ describe ".new" do
86
+ it "should do something"
87
+ end
88
+
89
+ describe ".open" do
90
+ it "should do something"
91
+ end
92
+
93
+ describe ".pipe" do
94
+ it "should do something"
95
+ end
96
+
97
+ describe ".popen" do
98
+ it "should do something"
99
+ end
100
+
101
+ describe ".read" do
102
+ it "should return the same data as IO.read - whole file" do
103
+ expect(VirtFS::VIO.read(@full_path)).to eq(VfsRealIO.read(@full_path))
104
+ end
105
+
106
+ it "should return the same data as IO.read - given length" do
107
+ length = 30
108
+ expect(VirtFS::VIO.read(@full_path, length)).to eq(VfsRealIO.read(@full_path, length))
109
+ end
110
+
111
+ it "should return the same data as IO.read - given length and offset" do
112
+ length = 30
113
+ offset = 20
114
+ expect(VirtFS::VIO.read(@full_path, length, offset)).to eq(VfsRealIO.read(@full_path, length, offset))
115
+ end
116
+ end
117
+
118
+ describe ".readlines" do
119
+ it "should return an Array" do
120
+ expect(VirtFS::VIO.readlines(@full_path)).to be_kind_of(Array)
121
+ end
122
+
123
+ it "should return the same lines as the standard IO.readlines" do
124
+ expect(VirtFS::VIO.readlines(@full_path)).to match_array(VfsRealIO.readlines(@full_path))
125
+ end
126
+ end
127
+
128
+ describe ".select" do
129
+ it "should do something"
130
+ end
131
+
132
+ describe ".sysopen" do
133
+ it "should do something"
134
+ end
135
+
136
+ describe ".try_convert" do
137
+ it "should return nil when not passed an IO object" do
138
+ expect(VirtFS::VIO.try_convert("this is a string")).to be_nil
139
+ end
140
+
141
+ it "should return the IO object when passed an IO object" do
142
+ expect(VirtFS::VIO.try_convert(@vfile_read_obj)).to eq(@vfile_read_obj)
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,516 @@
1
+ require 'spec_helper'
2
+ require 'fcntl'
3
+
4
+ describe VirtFS::VIO, "(#{$fs_interface} interface)" do
5
+ before(:all) do
6
+ @start_marker = "START OF FILE:\n"
7
+ @end_marker = ":END OF FILE"
8
+ @data1 = "0123456789"
9
+ @data2 = "abcdefghijklmnopqrstuvwzyz\n"
10
+
11
+ @temp_file = Tempfile.new("VirtFS-IO")
12
+ @temp_file.write(@start_marker)
13
+ (0..9).each do
14
+ @temp_file.write(@data1)
15
+ @temp_file.write(@data2)
16
+ end
17
+ @temp_file.write(@end_marker)
18
+ @temp_file.close
19
+
20
+ @full_path = @temp_file.path
21
+ @file_size = VfsRealFile.size(@full_path)
22
+
23
+ @temp_write = Tempfile.new("VirtFS-IO")
24
+ @temp_write.close
25
+ @write_file_path = @temp_write.path
26
+
27
+ @temp_rdwr = Tempfile.new("VirtFS-IO")
28
+ @temp_rdwr.close
29
+ @rdwr_file_path = @temp_rdwr.path
30
+
31
+ @binary_encoding = Encoding.find("ASCII-8BIT")
32
+ end
33
+
34
+ before(:each) do
35
+ reset_context
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
+ @vfile_rdwr_obj = VirtFS::VFile.new(@rdwr_file_path, "w+")
44
+ end
45
+
46
+ after(:each) do
47
+ @vfile_read_obj.close unless @vfile_read_obj.closed?
48
+ @vfile_write_obj.close unless @vfile_write_obj.closed?
49
+ @vfile_rdwr_obj.close unless @vfile_rdwr_obj.closed?
50
+ VirtFS.umount(@root)
51
+ end
52
+
53
+ describe "#autoclose=" do
54
+ it "should change the value from true to false" do
55
+ expect(@vfile_read_obj.autoclose?).to be true
56
+ @vfile_read_obj.autoclose = false
57
+ expect(@vfile_read_obj.autoclose?).to be false
58
+ end
59
+
60
+ it "should change the value from true to false - given a 'falsey' value" do
61
+ expect(@vfile_read_obj.autoclose?).to be true
62
+ @vfile_read_obj.autoclose = nil
63
+ expect(@vfile_read_obj.autoclose?).to be false
64
+ end
65
+
66
+ it "should change the value from false to true" do
67
+ @vfile_read_obj.autoclose = false
68
+ expect(@vfile_read_obj.autoclose?).to be false
69
+ @vfile_read_obj.autoclose = true
70
+ expect(@vfile_read_obj.autoclose?).to be true
71
+ end
72
+
73
+ it "should change the value from false to true - given a 'truthy' value" do
74
+ @vfile_read_obj.autoclose = false
75
+ expect(@vfile_read_obj.autoclose?).to be false
76
+ @vfile_read_obj.autoclose = "???"
77
+ expect(@vfile_read_obj.autoclose?).to be true
78
+ end
79
+ end
80
+
81
+ describe "#autoclose?" do
82
+ it "should return the default value of true" do
83
+ expect(@vfile_read_obj.autoclose?).to be true
84
+ end
85
+ end
86
+
87
+ describe "#binmode" do
88
+ it "should return the IO object" do
89
+ expect(@vfile_read_obj.binmode).to eq(@vfile_read_obj)
90
+ end
91
+
92
+ it "should set binmode to true" do
93
+ expect(@vfile_read_obj.binmode?).to be false
94
+ @vfile_read_obj.binmode
95
+ expect(@vfile_read_obj.binmode?).to be true
96
+ end
97
+
98
+ it "should set the external_encoding to binary encoding" do
99
+ expect(@vfile_read_obj.external_encoding).to_not eq(@binary_encoding)
100
+ @vfile_read_obj.binmode
101
+ expect(@vfile_read_obj.external_encoding).to eq(@binary_encoding)
102
+ end
103
+
104
+ it "should set the internal_encoding to nil" do
105
+ # XXX Real File does not seem to change the internal encoding.
106
+ # @vfile_read_obj.set_encoding(":UTF-8")
107
+ # expect(@vfile_read_obj.internal_encoding).to_not be_nil
108
+ @vfile_read_obj.binmode
109
+ expect(@vfile_read_obj.internal_encoding).to be_nil
110
+ end
111
+ end
112
+
113
+ describe "#binmode?" do
114
+ it "should return false by default" do
115
+ expect(@vfile_read_obj.binmode?).to be false
116
+ end
117
+
118
+ it "should return true when in binmode" do
119
+ expect(@vfile_read_obj.binmode?).to be false
120
+ @vfile_read_obj.binmode
121
+ expect(@vfile_read_obj.binmode?).to be true
122
+ end
123
+ end
124
+
125
+ describe "#close" do
126
+ it "should return nil" do
127
+ expect(@vfile_read_obj.close).to be_nil
128
+ end
129
+
130
+ context "should cause subsequent operations to raise IOError" do
131
+ {
132
+ :<< => ["hello"],
133
+ :autoclose= => [true],
134
+ :autoclose? => [],
135
+ :binmode => [],
136
+ :binmode? => [],
137
+ :close => [],
138
+ :close_on_exec? => [],
139
+ :close_on_exec= => [true],
140
+ :close_read => [],
141
+ :close_write => [],
142
+ :each => [],
143
+ :each_byte => [],
144
+ :each_char => [],
145
+ :each_codepoint => [],
146
+ :eof => [],
147
+ :external_encoding => [],
148
+ :fcntl => [0, 1],
149
+ :fdatasync => [],
150
+ :fileno => [],
151
+ :flush => [],
152
+ :fsync => [],
153
+ :getbyte => [],
154
+ :getc => [],
155
+ :gets => [],
156
+ :internal_encoding => [],
157
+ :ioctl => [0, 1],
158
+ :isatty => [],
159
+ :lineno => [],
160
+ :lineno= => [10],
161
+ :pid => [],
162
+ :pos => [],
163
+ :pos= => [0],
164
+ :print => ["string"],
165
+ :printf => ["format"],
166
+ :putc => ["X"],
167
+ :puts => ["string"],
168
+ :read => [10],
169
+ :readbyte => [],
170
+ :readchar => [],
171
+ :readline => [],
172
+ :readlines => [],
173
+ :readpartial => [10],
174
+ :rewind => [],
175
+ :seek => [0],
176
+ :set_encoding => ["encoding"],
177
+ :stat => [],
178
+ :sync => [],
179
+ :sync= => [true],
180
+ :sysread => [10],
181
+ :sysseek => [0],
182
+ :syswrite => ["hello"],
183
+ :ungetbyte => ["x"],
184
+ :ungetc => ["X"],
185
+ :write => ["string"],
186
+ :write_nonblock => ["hello"],
187
+ }.each do |method, args|
188
+ it "should cause subsequent '#{method}' call to raise IOError" do
189
+ @vfile_read_obj.close
190
+ expect { @vfile_read_obj.send(method, *args) {} }.to raise_error(IOError, "closed stream")
191
+ end
192
+ end
193
+ end
194
+ end
195
+
196
+ describe "#close_on_exec?" do
197
+ it "should return true by default" do
198
+ expect(@vfile_read_obj.close_on_exec?).to be true
199
+ end
200
+
201
+ it "should return false when set to false" do
202
+ @vfile_read_obj.close_on_exec = false
203
+ expect(@vfile_read_obj.close_on_exec?).to be false
204
+ end
205
+ end
206
+
207
+ describe "#close_on_exec=" do
208
+ it "should change the close_on_exec setting" do
209
+ coe = @vfile_read_obj.close_on_exec?
210
+ @vfile_read_obj.close_on_exec = !coe
211
+ expect(@vfile_read_obj.close_on_exec?).to be !coe
212
+ end
213
+ end
214
+
215
+ describe "#close_read" do
216
+ it "should raise IOError when called on a closed file" do
217
+ @vfile_read_obj.close
218
+ expect do
219
+ @vfile_read_obj.close_read
220
+ end.to raise_error(IOError, "closed stream")
221
+ end
222
+
223
+ it "should raise IOError when called on a regular file opend rdwr" do
224
+ expect do
225
+ @vfile_rdwr_obj.close_read
226
+ end.to raise_error(IOError, "closing non-duplex IO for reading")
227
+ end
228
+
229
+ it "should raise IOError when called on a file not open for reading" do
230
+ expect do
231
+ @vfile_write_obj.close_read
232
+ end.to raise_error(IOError, "closing non-duplex IO for reading")
233
+ end
234
+
235
+ it "should close a file that's only open for reading" do
236
+ expect(@vfile_read_obj.close_read).to be nil
237
+ expect(@vfile_read_obj.closed?).to be true
238
+ end
239
+ end
240
+
241
+ describe "#close_write" do
242
+ it "should raise IOError when called on a closed file" do
243
+ @vfile_read_obj.close
244
+ expect do
245
+ @vfile_read_obj.close_write
246
+ end.to raise_error(IOError, "closed stream")
247
+ end
248
+
249
+ it "should raise IOError when called on a regular file opend rdwr" do
250
+ expect do
251
+ @vfile_rdwr_obj.close_write
252
+ end.to raise_error(IOError, "closing non-duplex IO for writing")
253
+ end
254
+
255
+ it "should raise IOError when called on a file not open for writing" do
256
+ expect do
257
+ @vfile_read_obj.close_write
258
+ end.to raise_error(IOError, "closing non-duplex IO for writing")
259
+ end
260
+
261
+ it "should close a file that's only open for writing" do
262
+ expect(@vfile_write_obj.close_write).to be nil
263
+ expect(@vfile_write_obj.closed?).to be true
264
+ end
265
+ end
266
+
267
+ describe "#closed?" do
268
+ it "should return false if the file is open" do
269
+ expect(@vfile_read_obj.closed?).to be false
270
+ end
271
+
272
+ it "should return true if the file is closed" do
273
+ @vfile_read_obj.close
274
+ expect(@vfile_read_obj.closed?).to be true
275
+ end
276
+ end
277
+
278
+ describe "#fcntl" do
279
+ it "should return the requested value" do
280
+ expect(@vfile_read_obj.fcntl(Fcntl::F_GETFD, nil)).to be_kind_of(Integer)
281
+ end
282
+ end
283
+
284
+ describe "#fileno" do
285
+ it "should return the integer file number" do
286
+ expect(@vfile_read_obj.fileno).to be_kind_of(Integer)
287
+ end
288
+ end
289
+
290
+ describe "#ioctl" do
291
+ it "should do something"
292
+ end
293
+
294
+ describe "#isatty" do
295
+ it "should return false for a regular file" do
296
+ expect(@vfile_read_obj.isatty).to be false
297
+ end
298
+ end
299
+
300
+ describe "#pid" do
301
+ it "should return nil for a regular file" do
302
+ expect(@vfile_read_obj.pid).to be nil
303
+ end
304
+ end
305
+
306
+ describe "#reopen" do
307
+ it "should return the IO object" do
308
+ expect(@vfile_read_obj.reopen(@vfile_write_obj)).to eq(@vfile_read_obj)
309
+ end
310
+
311
+ it "should take on the attributes of the new IO stream - given IO object" do
312
+ expect(@vfile_read_obj.path).to_not eq(@vfile_write_obj.path)
313
+ expect(@vfile_read_obj.size).to_not eq(@vfile_write_obj.size)
314
+
315
+ @vfile_read_obj.reopen(@vfile_write_obj)
316
+
317
+ expect(@vfile_read_obj.path).to eq(@vfile_write_obj.path)
318
+ expect(@vfile_read_obj.size).to eq(@vfile_write_obj.size)
319
+ end
320
+
321
+ it "should take on the attributes of the new IO stream - given open args" do
322
+ expect(@vfile_read_obj.path).to_not eq(@vfile_write_obj.path)
323
+ expect(@vfile_read_obj.size).to_not eq(@vfile_write_obj.size)
324
+
325
+ @vfile_read_obj.reopen(@write_file_path, "w")
326
+
327
+ expect(@vfile_read_obj.path).to eq(@vfile_write_obj.path)
328
+ expect(@vfile_read_obj.size).to eq(@vfile_write_obj.size)
329
+ end
330
+
331
+ it "should read the same data as the standard File#read - given IO object" do
332
+ rfile_obj = VfsRealFile.new(@full_path, "r")
333
+ @vfile_write_obj.reopen(@vfile_read_obj)
334
+
335
+ read_size = 20
336
+ loop do
337
+ rv1 = @vfile_write_obj.read(read_size)
338
+ rv2 = rfile_obj.read(read_size)
339
+ expect(rv1).to eq(rv2)
340
+ break if rv1.nil? || rv1.empty?
341
+ end
342
+ end
343
+
344
+ it "should read the same data as the standard File#read - given open args" do
345
+ rfile_obj = VfsRealFile.new(@full_path, "r")
346
+ @vfile_write_obj.reopen(@full_path, "r")
347
+
348
+ read_size = 20
349
+ loop do
350
+ rv1 = @vfile_write_obj.read(read_size)
351
+ rv2 = rfile_obj.read(read_size)
352
+ expect(rv1).to eq(rv2)
353
+ break if rv1.nil? || rv1.empty?
354
+ end
355
+ end
356
+ end
357
+
358
+ describe "#stat" do
359
+ it "should return the stat information for the regular file" do
360
+ expect(@vfile_write_obj.stat.symlink?).to be false
361
+ end
362
+ end
363
+
364
+ describe "#sysread" do
365
+ before(:each) do
366
+ @rfile_obj = VfsRealFile.new(@full_path, "r")
367
+ end
368
+
369
+ after(:each) do
370
+ @rfile_obj.close
371
+ end
372
+
373
+ it "should read the number of bytes requested - when EOF not reached" do
374
+ read_size = @file_size / 2
375
+ rv = @vfile_read_obj.sysread(read_size)
376
+ expect(rv.bytesize).to eq(read_size)
377
+ end
378
+
379
+ it "should read data into buffer, when supplied" do
380
+ read_size = @file_size / 2
381
+ rbuf = ""
382
+ rv = @vfile_read_obj.sysread(read_size, rbuf)
383
+ expect(rv).to eq(rbuf)
384
+ end
385
+
386
+ it "should read at most, the size of the file" do
387
+ rv = @vfile_read_obj.sysread(@file_size + 100)
388
+ expect(rv.bytesize).to eq(@file_size)
389
+ end
390
+
391
+ it "should raise EOFError when attempting to read at EOF" do
392
+ @vfile_read_obj.sysread(@file_size)
393
+ expect do
394
+ @vfile_read_obj.sysread(@file_size)
395
+ end.to raise_error(
396
+ EOFError, "end of file reached"
397
+ )
398
+ end
399
+
400
+ it "should read the same data as the standard File#sysread" do
401
+ read_size = 20
402
+ loop do
403
+ begin
404
+ rv1 = @vfile_read_obj.sysread(read_size)
405
+ rv2 = @rfile_obj.sysread(read_size)
406
+ rescue EOFError
407
+ break
408
+ end
409
+ expect(rv1).to eq(rv2)
410
+ end
411
+ end
412
+ end
413
+
414
+ describe "#sysseek" do
415
+ it "should raise Errno::EINVAL when attempting to seek before the beginning of the file" do
416
+ expect do
417
+ @vfile_read_obj.sysseek(-10, IO::SEEK_CUR)
418
+ end.to raise_error(
419
+ Errno::EINVAL, /Invalid argument/
420
+ )
421
+ end
422
+
423
+ it "should return the new offset into the file - IO::SEEK_SET" do
424
+ offset = @file_size / 2
425
+ pos = @vfile_read_obj.sysseek(offset, IO::SEEK_SET)
426
+ expect(pos).to eq(offset)
427
+ end
428
+
429
+ it "should return the new offset into the file - IO::SEEK_CUR" do
430
+ offset = @file_size / 2
431
+ @vfile_read_obj.sysseek(offset, IO::SEEK_SET)
432
+ pos = @vfile_read_obj.sysseek(-10, IO::SEEK_CUR)
433
+ expect(pos).to eq(offset - 10)
434
+ end
435
+
436
+ it "should return the new offset into the file - IO::SEEK_END" do
437
+ pos = @vfile_read_obj.sysseek(-10, IO::SEEK_END)
438
+ expect(pos).to eq(@file_size - 10)
439
+ end
440
+
441
+ it "should change the read position within the file - IO::SEEK_SET" do
442
+ @vfile_read_obj.sysseek(@start_marker.bytesize, IO::SEEK_SET)
443
+ rv = @vfile_read_obj.sysread(@data1.bytesize)
444
+ expect(rv).to eq(@data1)
445
+ end
446
+
447
+ it "should change the read position within the file - IO::SEEK_CUR" do
448
+ @vfile_read_obj.sysseek(@start_marker.bytesize, IO::SEEK_SET)
449
+ @vfile_read_obj.sysseek(@data1.bytesize, IO::SEEK_CUR)
450
+ rv = @vfile_read_obj.sysread(@data2.bytesize)
451
+ expect(rv).to eq(@data2)
452
+ end
453
+
454
+ it "should change the read position within the file - IO::SEEK_END" do
455
+ @vfile_read_obj.sysseek(-@end_marker.bytesize, IO::SEEK_END)
456
+ rv = @vfile_read_obj.sysread(@end_marker.bytesize)
457
+ expect(rv).to eq(@end_marker)
458
+ end
459
+ end
460
+
461
+ describe "#syswrite" do
462
+ it "should return the number of bytes written" do
463
+ write_str = "0123456789"
464
+ expect(@vfile_write_obj.syswrite(write_str)).to eq(write_str.bytesize)
465
+ end
466
+
467
+ it "should update the current file position" do
468
+ write_str = "0123456789"
469
+ last_pos = @vfile_write_obj.pos
470
+ (0..9).each do
471
+ @vfile_write_obj.syswrite(write_str)
472
+ pos = @vfile_write_obj.pos
473
+ expect(pos).to eq(last_pos + write_str.bytesize)
474
+ last_pos = pos
475
+ end
476
+ end
477
+
478
+ it "should update the size of the file" do
479
+ write_str = "0123456789"
480
+ last_size = @vfile_write_obj.size
481
+ (0..9).each do
482
+ @vfile_write_obj.syswrite(write_str)
483
+ size = @vfile_write_obj.size
484
+ expect(size).to eq(last_size + write_str.bytesize)
485
+ last_size = size
486
+ end
487
+ end
488
+
489
+ it "should write data that's readable" do
490
+ write_str = "0123456789"
491
+ (0..9).each do
492
+ @vfile_write_obj.syswrite(write_str)
493
+ end
494
+
495
+ @vfile_write_obj.close
496
+ @vfile_write_obj = VirtFS::VFile.new(@write_file_path, "r")
497
+
498
+ (0..9).each do
499
+ expect(@vfile_write_obj.sysread(write_str.bytesize)).to eq(write_str)
500
+ end
501
+
502
+ expect do
503
+ @vfile_write_obj.sysread(write_str.bytesize)
504
+ end.to raise_error(
505
+ EOFError, "end of file reached"
506
+ )
507
+ end
508
+ end
509
+
510
+ describe "#to_io" do
511
+ it "should return itself" do
512
+ @vfile_read_obj = VirtFS::VFile.new(@full_path, "r")
513
+ expect(@vfile_read_obj.to_io).to eq(@vfile_read_obj)
514
+ end
515
+ end
516
+ end