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.
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,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