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,243 @@
1
+ module VirtFS
2
+ # VirtFS IO representation - implements the core Ruby IO methods, dispatching
3
+ # to underlying mounted VirtFS filesystems
4
+ #
5
+ class VIO # rubocop:disable ClassLength
6
+ include IOInstanceDelegate
7
+
8
+ VfsRealIO.constants.each { |cn| const_set(cn, VfsRealIO.const_get(cn)) }
9
+
10
+ # VFile initializer
11
+ #
12
+ # @param io_obj [VirtFS::FS::IO] handle to filesystem specific io obj
13
+ #
14
+ def initialize(io_obj)
15
+ __setobj__(io_obj)
16
+ end
17
+
18
+ #
19
+ # Some methods need to return the IO object. Methods in the delegator
20
+ # object can't do that, so we intercept them and do it here.
21
+ #
22
+
23
+ def <<(obj)
24
+ super
25
+ self
26
+ end
27
+
28
+ def binmode
29
+ super
30
+ self
31
+ end
32
+
33
+ def reopen(*args)
34
+ __setobj__(super)
35
+ self
36
+ end
37
+
38
+ def set_encoding(*args) # rubocop:disable Style/AccessorMethodName
39
+ super
40
+ self
41
+ end
42
+
43
+ def to_io
44
+ self
45
+ end
46
+
47
+ # Class methods
48
+ class << self
49
+ # Read specified number of bytes from file
50
+ #
51
+ # @param f [String] file to ready
52
+ # @param length [Integer] number of bytes to read
53
+ # @param offset [Integer] position to start reading at
54
+ #
55
+ # @return [Array<Byte>] bytes read from file (up to length size)
56
+ def binread(f, length = nil, offset = 0)
57
+ VFile.open(f, "rb") do |fobj|
58
+ fobj.pos = offset
59
+ return fobj.read unless length
60
+ return fobj.read(length)
61
+ end
62
+ end
63
+
64
+ # def binwrite()
65
+
66
+ # Copy stream from source to destination
67
+ #
68
+ # @param from [String] file stream to copy
69
+ # @param to [String] file stream to copy to
70
+ # @param max_length [Integer] max number of bytes to copy
71
+ # @param offset [Integer] position to start coying from
72
+ def copy_stream(from, to, max_length = nil, offset = 0) # rubocop:disable CyclomaticComplexity
73
+ from_file = from.is_a?(VIO) ? from : VFile.open(from, "rb")
74
+ to_file = to.is_a?(VIO) ? to : VFile.open(to, "wb") # rubocop:disable SpaceAroundOperators
75
+ return copy_from_to(from_file, to_file, max_length, offset)
76
+ ensure
77
+ from_file.close unless from_file.nil? || from.is_a?(VIO)
78
+ to_file.close unless to_file.nil? || to.is_a?(VIO) # rubocop:disable SpaceAroundOperators
79
+ end
80
+
81
+ # Invoke block for each file matching pattern
82
+ #
83
+ # IO.foreach( portname, separator=$/ <, options> ) { | line | . . . } -> nil
84
+ # IO.foreach( portname, limit <, options> ) { | line | . . . } -> nil
85
+ # IO.foreach( portname, separator, limit <, options> ) { | line | . . . } -> nil
86
+ #
87
+ def foreach(portname, *args, &block)
88
+ return VfsRealIO.foreach(portname, *args) unless filename?(portname)
89
+ return to_enum(__method__, portname, *args) unless block_given?
90
+
91
+ separator, limit, options = parse_args(args)
92
+
93
+ VFile.open(portname, "r", options) do |fobj|
94
+ fobj.each(separator, limit, &block)
95
+ end
96
+ nil
97
+ end
98
+
99
+ def pipe(*args, &block)
100
+ # XXX - should wrap VfsRealIO objects in common delegator class
101
+ # so is_a? and kind_of? will work with all IO objects.
102
+ VfsRealIO.pipe(*args, &block) # TODO: wrap returned read and write IO
103
+ end
104
+
105
+ def popen(*args, &block)
106
+ VfsRealIO.popen(*args, &block) # TODO: wrap returned IO
107
+ end
108
+
109
+ def read(portname, *args)
110
+ return VfsRealIO.read(portname, *args) unless filename?(portname)
111
+
112
+ length, offset, options = length_offset_options(args)
113
+
114
+ VFile.open(portname, "r", options) do |fobj|
115
+ fobj.pos = offset
116
+ return fobj.read unless length
117
+ return fobj.read(length)
118
+ end
119
+ end
120
+
121
+ def readlines(portname, *args)
122
+ return VfsRealIO.readlines(portname, *args) unless filename?(portname)
123
+ foreach(portname, *args).to_a
124
+ end
125
+
126
+ def select(*args)
127
+ VfsRealIO.select(*args)
128
+ end
129
+
130
+ def sysopen(*args)
131
+ VfsRealIO.sysopen(*args)
132
+ end
133
+
134
+ def try_convert(obj)
135
+ return nil unless obj.respond_to?(:to_io)
136
+ obj.to_io # TODO: wrap?
137
+ end
138
+
139
+ # Instantiate IO instance.
140
+ #
141
+ # @param integer_fd [Integer] file descriptor
142
+ # @param mode [String] mode to open IO instance
143
+ # @param hash_options options to forward to IO initialiezr
144
+ #
145
+ def new(integer_fd, mode = "r", hash_options = {})
146
+ #
147
+ # Directly instantiating an IO instance (not through File)
148
+ # will return a standard IO object.
149
+ #
150
+ fs_obj = VfsRealIO.new(integer_fd, mode, hash_options)
151
+ obj = allocate
152
+ obj.send(:initialize, fs_obj)
153
+ obj
154
+ end
155
+ alias_method :for_fd, :new
156
+
157
+ # Open IO Instance and invoke block w/ it before closing
158
+ #
159
+ # @see #new
160
+ def open(*args)
161
+ io_obj = new(*args) # IO.new or File.new
162
+ return io_obj unless block_given?
163
+ begin
164
+ return yield(io_obj)
165
+ ensure
166
+ io_obj.close
167
+ end
168
+ end
169
+
170
+ private
171
+
172
+ def filename?(portname)
173
+ portname[0] != "|"
174
+ end
175
+
176
+ # separator, limit, options
177
+ def parse_args(args)
178
+ separator = $RS
179
+ limit = nil
180
+ options = {}
181
+
182
+ while (arg = args.shift)
183
+ if arg.is_a?(String)
184
+ separator = arg
185
+ elsif arg.is_a?(Numeric)
186
+ limit = arg
187
+ elsif arg.is_a?(Hash)
188
+ options = arg
189
+ end
190
+ end
191
+ return separator, limit, options
192
+ end
193
+
194
+ def length_offset_options(args) # rubocop:disable AbcSize, PerceivedComplexity, CyclomaticComplexity
195
+ case args.length
196
+ when 0
197
+ return nil, 0, {}
198
+ when 1
199
+ return args[0].to_int, 0, {} if args[0].respond_to?(:to_int)
200
+ return nil, 0, args[0].to_hash if args[0].respond_to?(:to_hash)
201
+ int_type_error(args[0])
202
+ when 2
203
+ int_type_error(args[0]) unless args[0].respond_to?(:to_int)
204
+ return args[0].to_int, args[1].to_int, {} if args[1].respond_to?(:to_int)
205
+ return args[0].to_int, 0, args[1].to_hash if args[1].respond_to?(:to_hash)
206
+ int_type_error(args[1])
207
+ when 3
208
+ int_type_error(args[0]) unless args[0].respond_to?(:to_int)
209
+ int_type_error(args[1]) unless args[1].respond_to?(:to_int)
210
+ return args[0].to_int, args[1].to_int, args[2].to_hash if args[2].respond_to?(:to_hash)
211
+ hash_type_error(args[2])
212
+ else
213
+ raise ArgumentError, "wrong number of arguments (5+ for 1..4)"
214
+ end
215
+ end
216
+
217
+ def int_type_error(arg)
218
+ raise TypeError, "no implicit conversion from #{arg.class.name} to integer"
219
+ end
220
+
221
+ def hash_type_error(arg)
222
+ raise TypeError, "no implicit conversion from #{arg.class.name} to Hash"
223
+ end
224
+
225
+ def copy_from_to(from, to, length, offset)
226
+ chunk_size = 1024
227
+ bytes_written = 0
228
+
229
+ from.pos = offset
230
+ while (rv = from.read(chunk_size))
231
+ if length && bytes_written + rv.bytesize > length
232
+ len = length - bytes_written
233
+ to.write(rv[0, len])
234
+ break
235
+ end
236
+ to.write(rv)
237
+ bytes_written += rv.bytesize
238
+ end
239
+ bytes_written
240
+ end
241
+ end # class methods
242
+ end
243
+ end
@@ -0,0 +1,128 @@
1
+ module VirtFS
2
+ class VPathname < VfsRealPathname
3
+ def self.getwd
4
+ new(::Dir.getwd)
5
+ end
6
+
7
+ def self.pwd
8
+ getwd
9
+ end
10
+
11
+ def self.glob(*args)
12
+ return ::Dir.glob(args).collect { |p| new(p) } unless block_given?
13
+ ::Dir.glob(*args).each { |p| yield(new(p)) }
14
+ end
15
+
16
+ # absolute?
17
+ # ascend
18
+
19
+ def atime
20
+ ::File.atime(to_path)
21
+ end
22
+
23
+ # basename
24
+
25
+ def binread(*args)
26
+ ::File.binread(to_path, *args)
27
+ end
28
+
29
+ # binwrite
30
+ # birthtime
31
+ # blockdev?
32
+ # chardev?
33
+ # children
34
+ # chmod
35
+ # chown
36
+ # cleanpath
37
+ # ctime
38
+ # delete
39
+ # descend
40
+ # directory?
41
+ # dirname
42
+ # each_child
43
+ # each_entry
44
+ # each_filename
45
+ # each_line
46
+ # empty?
47
+ # entries
48
+ # eql?
49
+ # executable?
50
+ # executable_real?
51
+ # exist?
52
+
53
+ def expand_path(dirstring = nil)
54
+ return self if absolute?
55
+ self.class.new(::File.expand_path(to_path, dirstring))
56
+ end
57
+
58
+ # extname
59
+
60
+ def file?
61
+ ::File.file?(to_path)
62
+ end
63
+
64
+ # find
65
+ # fnmatch
66
+ # fnmatch?
67
+ # freeze
68
+ # ftype
69
+ # grpowned?
70
+ # join
71
+ # lchmod
72
+ # lchown
73
+ # lstat
74
+ # make_link
75
+ # make_symlink
76
+ # mkdir
77
+ # mkpath
78
+ # mountpoint?
79
+ # mtime
80
+ # open
81
+ # opendir
82
+ # owned?
83
+ # parent
84
+ # pipe?
85
+
86
+ def read(*args)
87
+ ::File.open(to_path, "r") { |f| return f.read(*args) }
88
+ end
89
+
90
+ # readable?
91
+ # readable_real?
92
+ # readlines
93
+ # readlink
94
+ # realdirpath
95
+ # realpath
96
+ # relative?
97
+ # relative_path_from
98
+ # rename
99
+ # rmdir
100
+ # rmtree
101
+ # root?
102
+ # setgid?
103
+ # setuid?
104
+ # size
105
+ # size?
106
+ # socket?
107
+ # split
108
+ # stat
109
+ # sticky?
110
+ # sub
111
+ # sub_ext
112
+ # symlink?
113
+ # sysopen
114
+ # taint
115
+ # to_path
116
+ # to_s
117
+ # truncate
118
+ # unlink
119
+ # untaint
120
+ # utime
121
+ # world_readable?
122
+ # world_writable?
123
+ # writable?
124
+ # writable_real?
125
+ # write
126
+ # zero?
127
+ end
128
+ end
@@ -0,0 +1,3 @@
1
+ module VirtFS
2
+ VERSION = "0.0.1" unless const_defined?(:VERSION)
3
+ end
@@ -0,0 +1,202 @@
1
+ require 'spec_helper'
2
+
3
+ describe VirtFS, " - activation (#{$fs_interface} interface)" do
4
+ before(:each) do
5
+ reset_context
6
+ @root = File::SEPARATOR
7
+ @native_fs = nativefs_class.new
8
+ VirtFS.mount(@native_fs, @root)
9
+ end
10
+
11
+ after(:each) do
12
+ VirtFS.deactivate! if VirtFS.activated?
13
+ VirtFS.umount(@root) if VirtFS.mounted?(@root)
14
+ end
15
+
16
+ it "should save reference to standard Dir class" do
17
+ expect(Object.const_defined?(:VfsRealDir)).to be true
18
+ expect(VfsRealDir).to eq(Dir)
19
+ end
20
+
21
+ it "should save reference to standard File class" do
22
+ expect(Object.const_defined?(:VfsRealFile)).to be true
23
+ expect(VfsRealFile).to eq(File)
24
+ end
25
+
26
+ it "should save reference to standard IO class" do
27
+ expect(Object.const_defined?(:VfsRealIO)).to be true
28
+ expect(VfsRealIO).to eq(IO)
29
+ end
30
+
31
+ it "should define VirtFS class" do
32
+ expect(Object.const_defined?(:VirtFS)).to be true
33
+ end
34
+
35
+ it "should define VirtFS::VDir class" do
36
+ expect(VirtFS.const_defined?(:VDir)).to be true
37
+ end
38
+
39
+ it "should define VirtFS::VFile class" do
40
+ expect(VirtFS.const_defined?(:File)).to be true
41
+ end
42
+
43
+ it "should define VirtFS::VIO class" do
44
+ expect(VirtFS.const_defined?(:IO)).to be true
45
+ end
46
+
47
+ describe ".activate!" do
48
+ it "should cause .activated? to return true" do
49
+ expect(VirtFS.activated?).to be false
50
+ VirtFS.activate!
51
+ expect(VirtFS.activated?).to be true
52
+ end
53
+
54
+ it "should set standard Dir class to VirtFS::Dir" do
55
+ expect(Dir).to eq(VfsRealDir)
56
+ VirtFS.activate!
57
+ expect(Dir).to eq(VirtFS::VDir)
58
+ end
59
+
60
+ it "should set standard File class to VirtFS::File" do
61
+ expect(File).to eq(VfsRealFile)
62
+ VirtFS.activate!
63
+ expect(File).to eq(VirtFS::VFile)
64
+ end
65
+
66
+ it "should set standard IO class to VirtFS::IO" do
67
+ expect(IO).to eq(VfsRealIO)
68
+ VirtFS.activate!
69
+ expect(IO).to eq(VirtFS::VIO)
70
+ end
71
+ end
72
+
73
+ describe ".deactivate!" do
74
+ before(:each) do
75
+ VirtFS.activate!
76
+ end
77
+
78
+ after(:each) do
79
+ VirtFS.deactivate! if VirtFS.activated?
80
+ end
81
+
82
+ it "should cause .activated? to return false" do
83
+ expect(VirtFS.activated?).to be true
84
+ VirtFS.deactivate!
85
+ expect(VirtFS.activated?).to be false
86
+ end
87
+
88
+ it "should set standard Dir class to VfsRealDir" do
89
+ expect(Dir).to eq(VirtFS::VDir)
90
+ VirtFS.deactivate!
91
+ expect(Dir).to eq(VfsRealDir)
92
+ end
93
+
94
+ it "should set standard File class to VfsRealFile" do
95
+ expect(File).to eq(VirtFS::VFile)
96
+ VirtFS.deactivate!
97
+ expect(File).to eq(VfsRealFile)
98
+ end
99
+
100
+ it "should set standard IO class to VfsRealDir" do
101
+ expect(IO).to eq(VirtFS::VIO)
102
+ VirtFS.deactivate!
103
+ expect(IO).to eq(VfsRealIO)
104
+ end
105
+ end
106
+
107
+ describe ".with" do
108
+ after(:each) do
109
+ VirtFS.deactivate! if VirtFS.activated?
110
+ end
111
+
112
+ it "should only be activated within block - when not activated initially" do
113
+ expect(VirtFS.activated?).to be false
114
+ VirtFS.with { expect(VirtFS.activated?).to be true }
115
+ expect(VirtFS.activated?).to be false
116
+ end
117
+
118
+ it "should remain activated - when activated initially" do
119
+ VirtFS.activate!
120
+ expect(VirtFS.activated?).to be true
121
+ VirtFS.with { expect(VirtFS.activated?).to be true }
122
+ expect(VirtFS.activated?).to be true
123
+ end
124
+ end
125
+
126
+ describe ".without" do
127
+ after(:each) do
128
+ VirtFS.deactivate! if VirtFS.activated?
129
+ end
130
+
131
+ it "should only be deactivated within block - when activated initially" do
132
+ VirtFS.activate!
133
+ expect(VirtFS.activated?).to be true
134
+ VirtFS.without { expect(VirtFS.activated?).to be false }
135
+ expect(VirtFS.activated?).to be true
136
+ end
137
+
138
+ it "should remain deactivated - when deactivated initially" do
139
+ expect(VirtFS.activated?).to be false
140
+ VirtFS.without { expect(VirtFS.activated?).to be false }
141
+ expect(VirtFS.activated?).to be false
142
+ end
143
+ end
144
+
145
+ describe "Dir objects" do
146
+ it "should identify as standard Dir - when not activated" do
147
+ Dir.open(__dir__) do |dir|
148
+ expect(dir).to be_kind_of(Dir)
149
+ expect(dir).to be_kind_of(VfsRealDir)
150
+ expect(dir).not_to be_kind_of(VirtFS::VDir)
151
+ end
152
+ end
153
+
154
+ it "should identify as VirtFS Dir - when activated" do
155
+ VirtFS.with do
156
+ Dir.open(__dir__) do |dir|
157
+ expect(dir).to be_kind_of(Dir)
158
+ expect(dir).to be_kind_of(VirtFS::VDir)
159
+ expect(dir).not_to be_kind_of(VfsRealDir)
160
+ end
161
+ end
162
+ end
163
+ end
164
+
165
+ describe "File objects" do
166
+ it "should identify as standard File - when not activated" do
167
+ File.open(__FILE__) do |file|
168
+ expect(file).to be_kind_of(File)
169
+ expect(file).to be_kind_of(VfsRealFile)
170
+ expect(file).not_to be_kind_of(VirtFS::VFile)
171
+ end
172
+ end
173
+
174
+ it "should identify as standard IO - when not activated" do
175
+ File.open(__FILE__) do |file|
176
+ expect(file).to be_kind_of(IO)
177
+ expect(file).to be_kind_of(VfsRealIO)
178
+ expect(file).not_to be_kind_of(VirtFS::VIO)
179
+ end
180
+ end
181
+
182
+ it "should identify as VirtFS File - when activated" do
183
+ VirtFS.with do
184
+ File.open(__FILE__) do |file|
185
+ expect(file).to be_kind_of(File)
186
+ expect(file).to be_kind_of(VirtFS::VFile)
187
+ expect(file).not_to be_kind_of(VfsRealFile)
188
+ end
189
+ end
190
+ end
191
+
192
+ it "should identify as VirtFS IO - when activated" do
193
+ VirtFS.with do
194
+ File.open(__FILE__) do |file|
195
+ expect(file).to be_kind_of(IO)
196
+ expect(file).to be_kind_of(VirtFS::VIO)
197
+ expect(file).not_to be_kind_of(VfsRealIO)
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end