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