ruby_smb 3.0.6 → 3.1.2

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 (140) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/examples/file_server.rb +8 -1
  4. data/examples/virtual_file_server.rb +143 -0
  5. data/lib/ruby_smb/client/encryption.rb +16 -4
  6. data/lib/ruby_smb/client/negotiation.rb +10 -8
  7. data/lib/ruby_smb/fscc/file_information/file_access_information.rb +15 -0
  8. data/lib/ruby_smb/fscc/file_information/file_alignment_information.rb +45 -0
  9. data/lib/ruby_smb/fscc/file_information/file_all_information.rb +23 -0
  10. data/lib/ruby_smb/fscc/file_information/file_basic_information.rb +20 -0
  11. data/lib/ruby_smb/fscc/file_information/file_both_directory_information.rb +3 -3
  12. data/lib/ruby_smb/fscc/file_information/file_directory_information.rb +3 -3
  13. data/lib/ruby_smb/fscc/file_information/file_ea_information.rb +1 -0
  14. data/lib/ruby_smb/fscc/file_information/file_full_directory_information.rb +3 -3
  15. data/lib/ruby_smb/fscc/file_information/file_id_both_directory_information.rb +3 -3
  16. data/lib/ruby_smb/fscc/file_information/file_id_full_directory_information.rb +3 -3
  17. data/lib/ruby_smb/fscc/file_information/file_internal_information.rb +15 -0
  18. data/lib/ruby_smb/fscc/file_information/file_mode_information.rb +29 -0
  19. data/lib/ruby_smb/fscc/file_information/file_name_information.rb +16 -0
  20. data/lib/ruby_smb/fscc/file_information/file_names_information.rb +1 -1
  21. data/lib/ruby_smb/fscc/file_information/file_normalized_name_information.rb +16 -0
  22. data/lib/ruby_smb/fscc/file_information/file_position_information.rb +15 -0
  23. data/lib/ruby_smb/fscc/file_information/file_rename_information.rb +1 -1
  24. data/lib/ruby_smb/fscc/file_information/file_standard_information.rb +20 -0
  25. data/lib/ruby_smb/fscc/file_information/file_stream_information.rb +3 -0
  26. data/lib/ruby_smb/fscc/file_information.rb +43 -6
  27. data/lib/ruby_smb/fscc/file_system_information/file_fs_attribute_information.rb +1 -0
  28. data/lib/ruby_smb/fscc/file_system_information/file_fs_volume_information.rb +1 -0
  29. data/lib/ruby_smb/fscc/file_system_information.rb +4 -0
  30. data/lib/ruby_smb/gss/provider/ntlm.rb +20 -3
  31. data/lib/ruby_smb/gss/provider.rb +10 -1
  32. data/lib/ruby_smb/server/server_client/encryption.rb +66 -0
  33. data/lib/ruby_smb/server/server_client/negotiation.rb +14 -3
  34. data/lib/ruby_smb/server/server_client/session_setup.rb +21 -4
  35. data/lib/ruby_smb/server/server_client/share_io.rb +17 -0
  36. data/lib/ruby_smb/server/server_client/tree_connect.rb +40 -3
  37. data/lib/ruby_smb/server/server_client.rb +156 -38
  38. data/lib/ruby_smb/server/session.rb +5 -1
  39. data/lib/ruby_smb/server/share/provider/disk/file_system.rb +28 -0
  40. data/lib/ruby_smb/server/share/provider/disk/processor/close.rb +46 -0
  41. data/lib/ruby_smb/server/share/provider/disk/processor/create.rb +143 -0
  42. data/lib/ruby_smb/server/share/provider/disk/processor/query.rb +359 -0
  43. data/lib/ruby_smb/server/share/provider/disk/processor/read.rb +70 -0
  44. data/lib/ruby_smb/server/share/provider/disk/processor.rb +223 -0
  45. data/lib/ruby_smb/server/share/provider/disk.rb +12 -418
  46. data/lib/ruby_smb/server/share/provider/pipe.rb +2 -2
  47. data/lib/ruby_smb/server/share/provider/processor.rb +16 -0
  48. data/lib/ruby_smb/server/share/provider/virtual_disk/virtual_file.rb +85 -0
  49. data/lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb +196 -0
  50. data/lib/ruby_smb/server/share/provider/virtual_disk/virtual_stat.rb +175 -0
  51. data/lib/ruby_smb/server/share/provider/virtual_disk.rb +116 -0
  52. data/lib/ruby_smb/server/share/provider.rb +1 -0
  53. data/lib/ruby_smb/server.rb +13 -3
  54. data/lib/ruby_smb/signing.rb +18 -4
  55. data/lib/ruby_smb/smb1/commands.rb +1 -0
  56. data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +11 -1
  57. data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +1 -1
  58. data/lib/ruby_smb/smb1/packet/read_andx_response.rb +5 -4
  59. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +12 -4
  60. data/lib/ruby_smb/smb1/packet/trans2/data_block.rb +9 -1
  61. data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +52 -51
  62. data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +37 -37
  63. data/lib/ruby_smb/smb1/packet/trans2/find_information_level/find_file_both_directory_info.rb +48 -0
  64. data/lib/ruby_smb/smb1/packet/trans2/find_information_level.rb +28 -15
  65. data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +51 -51
  66. data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +36 -36
  67. data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +40 -39
  68. data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +40 -40
  69. data/lib/ruby_smb/smb1/packet/trans2/query_file_information_request.rb +60 -0
  70. data/lib/ruby_smb/smb1/packet/trans2/query_file_information_response.rb +59 -0
  71. data/lib/ruby_smb/smb1/packet/trans2/query_fs_information_level/query_fs_attribute_info.rb +31 -0
  72. data/lib/ruby_smb/smb1/packet/trans2/query_fs_information_level.rb +40 -0
  73. data/lib/ruby_smb/smb1/packet/trans2/query_fs_information_request.rb +46 -0
  74. data/lib/ruby_smb/smb1/packet/trans2/query_fs_information_response.rb +59 -0
  75. data/lib/ruby_smb/smb1/packet/trans2/query_information_level/query_file_basic_info.rb +23 -0
  76. data/lib/ruby_smb/smb1/packet/trans2/query_information_level/query_file_standard_info.rb +22 -0
  77. data/lib/ruby_smb/smb1/packet/trans2/query_information_level.rb +62 -0
  78. data/lib/ruby_smb/smb1/packet/trans2/query_path_information_request.rb +65 -0
  79. data/lib/ruby_smb/smb1/packet/trans2/query_path_information_response.rb +59 -0
  80. data/lib/ruby_smb/smb1/packet/trans2/request.rb +24 -8
  81. data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +4 -4
  82. data/lib/ruby_smb/smb1/packet/trans2/response.rb +29 -20
  83. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +42 -42
  84. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +23 -23
  85. data/lib/ruby_smb/smb1/packet/trans2/subcommands.rb +23 -5
  86. data/lib/ruby_smb/smb1/packet/trans2.rb +4 -0
  87. data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +4 -1
  88. data/lib/ruby_smb/smb2/negotiate_context.rb +10 -1
  89. data/lib/ruby_smb/smb2/packet/transform_header.rb +7 -7
  90. data/lib/ruby_smb/smb2/tree.rb +1 -0
  91. data/lib/ruby_smb/smb2.rb +1 -0
  92. data/lib/ruby_smb/version.rb +1 -1
  93. data/spec/lib/ruby_smb/client_spec.rb +31 -8
  94. data/spec/lib/ruby_smb/fscc/file_information/file_access_information_spec.rb +21 -0
  95. data/spec/lib/ruby_smb/fscc/file_information/file_alignment_information_spec.rb +21 -0
  96. data/spec/lib/ruby_smb/fscc/file_information/file_all_information_spec.rb +61 -0
  97. data/spec/lib/ruby_smb/fscc/file_information/file_basic_information_spec.rb +41 -0
  98. data/spec/lib/ruby_smb/fscc/file_information/file_both_directory_information_spec.rb +59 -10
  99. data/spec/lib/ruby_smb/fscc/file_information/file_directory_information_spec.rb +30 -12
  100. data/spec/lib/ruby_smb/fscc/file_information/file_ea_information_spec.rb +21 -0
  101. data/spec/lib/ruby_smb/fscc/file_information/file_full_directory_information_spec.rb +30 -12
  102. data/spec/lib/ruby_smb/fscc/file_information/file_id_both_directory_information_spec.rb +63 -10
  103. data/spec/lib/ruby_smb/fscc/file_information/file_id_full_directory_information_spec.rb +30 -12
  104. data/spec/lib/ruby_smb/fscc/file_information/file_internal_information_spec.rb +21 -0
  105. data/spec/lib/ruby_smb/fscc/file_information/file_mode_information_spec.rb +21 -0
  106. data/spec/lib/ruby_smb/fscc/file_information/file_name_information_spec.rb +44 -0
  107. data/spec/lib/ruby_smb/fscc/file_information/file_names_information_spec.rb +30 -12
  108. data/spec/lib/ruby_smb/fscc/file_information/file_network_open_information_spec.rb +51 -0
  109. data/spec/lib/ruby_smb/fscc/file_information/file_normalized_name_information_spec.rb +44 -0
  110. data/spec/lib/ruby_smb/fscc/file_information/file_position_information_spec.rb +21 -0
  111. data/spec/lib/ruby_smb/fscc/file_information/file_rename_information_spec.rb +1 -1
  112. data/spec/lib/ruby_smb/fscc/file_information/file_standard_information_spec.rb +41 -0
  113. data/spec/lib/ruby_smb/fscc/file_information/file_stream_information_spec.rb +51 -0
  114. data/spec/lib/ruby_smb/fscc/file_information_spec.rb +14 -0
  115. data/spec/lib/ruby_smb/fscc/file_system_information/file_fs_attribute_information_spec.rb +46 -0
  116. data/spec/lib/ruby_smb/fscc/file_system_information/file_fs_volume_information_spec.rb +51 -0
  117. data/spec/lib/ruby_smb/fscc/file_system_information_spec.rb +14 -0
  118. data/spec/lib/ruby_smb/server/server_client_spec.rb +15 -0
  119. data/spec/lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname_spec.rb +581 -0
  120. data/spec/lib/ruby_smb/server/share/provider/virtual_disk/virtual_stat_spec.rb +207 -0
  121. data/spec/lib/ruby_smb/server/share/provider/virtual_disk_spec.rb +122 -0
  122. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_request_spec.rb +2 -2
  123. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +36 -2
  124. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_request_spec.rb +2 -2
  125. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +35 -1
  126. data/spec/lib/ruby_smb/smb1/packet/trans2/query_file_information_request_spec.rb +74 -0
  127. data/spec/lib/ruby_smb/smb1/packet/trans2/query_file_information_response_spec.rb +96 -0
  128. data/spec/lib/ruby_smb/smb1/packet/trans2/query_fs_information_request_spec.rb +62 -0
  129. data/spec/lib/ruby_smb/smb1/packet/trans2/query_fs_information_response_spec.rb +88 -0
  130. data/spec/lib/ruby_smb/smb1/packet/trans2/query_path_information_request_spec.rb +79 -0
  131. data/spec/lib/ruby_smb/smb1/packet/trans2/query_path_information_response_spec.rb +96 -0
  132. data/spec/lib/ruby_smb/smb1/packet/trans2/request_spec.rb +2 -2
  133. data/spec/lib/ruby_smb/smb1/packet/trans2/response_spec.rb +3 -3
  134. data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_request_spec.rb +3 -2
  135. data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_response_spec.rb +7 -2
  136. data/spec/lib/ruby_smb/smb1/tree_spec.rb +3 -3
  137. data/spec/lib/ruby_smb/smb2/packet/transform_header_spec.rb +2 -2
  138. data.tar.gz.sig +0 -0
  139. metadata +88 -2
  140. metadata.gz.sig +0 -0
@@ -0,0 +1,581 @@
1
+ RSpec.shared_context 'existing common' do
2
+ describe '#atime' do
3
+ it 'is a Time instance' do
4
+ expect(virtual_pathname.atime).to be_a Time
5
+ end
6
+ end
7
+
8
+ describe '#birthtime' do
9
+ it 's a Time instance' do
10
+ expect(virtual_pathname.birthtime).to be_a Time
11
+ end
12
+ end
13
+
14
+ describe '#blockdev?' do
15
+ it 'returns false' do
16
+ expect(virtual_pathname.blockdev?).to be false
17
+ end
18
+ end
19
+
20
+ describe '#chardev?' do
21
+ it 'returns false' do
22
+ expect(virtual_pathname.chardev?).to be false
23
+ end
24
+ end
25
+
26
+ describe '#ctime' do
27
+ it 'is a Time instance' do
28
+ expect(virtual_pathname.ctime).to be_a Time
29
+ end
30
+ end
31
+
32
+ describe '#exist?' do
33
+ it 'returns true' do
34
+ expect(virtual_pathname.exist?).to be true
35
+ end
36
+ end
37
+
38
+ describe '#grpowned?' do
39
+ it 'returns true' do
40
+ expect(virtual_pathname.grpowned?).to be true
41
+ end
42
+ end
43
+
44
+ describe '#mtime' do
45
+ it 'is a Time instance' do
46
+ expect(virtual_pathname.mtime).to be_a Time
47
+ end
48
+ end
49
+
50
+ describe '#owned?' do
51
+ it 'returns true' do
52
+ expect(virtual_pathname.owned?).to be true
53
+ end
54
+ end
55
+
56
+ describe '#pipe?' do
57
+ it 'returns false' do
58
+ expect(virtual_pathname.pipe?).to be false
59
+ end
60
+ end
61
+
62
+ describe '#readable?' do
63
+ it 'returns true' do
64
+ expect(virtual_pathname.readable?).to be true
65
+ end
66
+ end
67
+
68
+ describe '#setgid?' do
69
+ it 'returns false' do
70
+ expect(virtual_pathname.setgid?).to be false
71
+ end
72
+ end
73
+
74
+ describe '#setuid?' do
75
+ it 'returns false' do
76
+ expect(virtual_pathname.setuid?).to be false
77
+ end
78
+ end
79
+
80
+ describe '#size' do
81
+ it 'returns 0' do
82
+ expect(virtual_pathname.size).to be 0
83
+ end
84
+ end
85
+
86
+ describe '#socket?' do
87
+ it 'returns false' do
88
+ expect(virtual_pathname.socket?).to be false
89
+ end
90
+ end
91
+
92
+ describe '#stat' do
93
+ it 'is a VirtualStat instance' do
94
+ expect(virtual_pathname.stat).to be_a RubySMB::Server::Share::Provider::VirtualDisk::VirtualStat
95
+ end
96
+ end
97
+
98
+ describe '#sticky?' do
99
+ it 'returns false' do
100
+ expect(virtual_pathname.sticky?).to be false
101
+ end
102
+ end
103
+
104
+ describe '#symlink?' do
105
+ it 'returns false' do
106
+ expect(virtual_pathname.symlink?).to be false
107
+ end
108
+ end
109
+
110
+ describe '#world_readable?' do
111
+ it 'returns true' do
112
+ expect(virtual_pathname.world_readable?).to be true
113
+ end
114
+ end
115
+
116
+ describe '#world_writable?' do
117
+ it 'returns false' do
118
+ expect(virtual_pathname.world_writable?).to be false
119
+ end
120
+ end
121
+
122
+ describe '#writable?' do
123
+ it 'returns true' do
124
+ expect(virtual_pathname.writable?).to be true
125
+ end
126
+ end
127
+ end
128
+
129
+ RSpec.describe RubySMB::Server::Share::Provider::VirtualDisk::VirtualPathname do
130
+ let(:path) { 'path' }
131
+ let(:leaf_path) { File.join(path, 'leaf') }
132
+ subject(:virtual_pathname) { described_class.new({}, path) }
133
+
134
+ it { is_expected.to respond_to :atime }
135
+ it { is_expected.to respond_to :birthtime }
136
+ it { is_expected.to respond_to :blockdev? }
137
+ it { is_expected.to respond_to :chardev? }
138
+ it { is_expected.to respond_to :ctime }
139
+ it { is_expected.to respond_to :directory? }
140
+ it { is_expected.to respond_to :executable? }
141
+ it { is_expected.to respond_to :file? }
142
+ it { is_expected.to respond_to :ftype }
143
+ it { is_expected.to respond_to :grpowned? }
144
+ it { is_expected.to respond_to :mtime }
145
+ it { is_expected.to respond_to :owned? }
146
+ it { is_expected.to respond_to :pipe? }
147
+ it { is_expected.to respond_to :readable? }
148
+ it { is_expected.to respond_to :setgid? }
149
+ it { is_expected.to respond_to :setuid? }
150
+ it { is_expected.to respond_to :size }
151
+ it { is_expected.to respond_to :socket? }
152
+ it { is_expected.to respond_to :sticky? }
153
+ it { is_expected.to respond_to :symlink? }
154
+ it { is_expected.to respond_to :world_readable? }
155
+ it { is_expected.to respond_to :world_writable? }
156
+ it { is_expected.to respond_to :writable? }
157
+ it { is_expected.to respond_to :zero? }
158
+
159
+ describe '.basename' do
160
+ # class methods return strings, instance methods return a new object
161
+ it 'returns a String' do
162
+ expect(described_class.basename('')).to be_a String
163
+ end
164
+ end
165
+
166
+ describe '.cleanpath' do
167
+ # class methods return strings, instance methods return a new object
168
+ it 'returns a String' do
169
+ expect(described_class.cleanpath('')).to be_a String
170
+ end
171
+
172
+ it 'normalizes relative paths' do
173
+ expect(described_class.cleanpath('')).to eq '.'
174
+ expect(described_class.cleanpath('.')).to eq '.'
175
+ expect(described_class.cleanpath('./')).to eq '.'
176
+ expect(described_class.cleanpath('./.')).to eq '.'
177
+ end
178
+
179
+ it 'normalizes absolute paths' do
180
+ expect(described_class.cleanpath('/')).to eq '/'
181
+ expect(described_class.cleanpath('/.')).to eq '/'
182
+ expect(described_class.cleanpath('/..')).to eq '/'
183
+ expect(described_class.cleanpath('/test/..')).to eq '/'
184
+ expect(described_class.cleanpath('/test/../')).to eq '/'
185
+ end
186
+ end
187
+
188
+ describe '.dirname' do
189
+ # class methods return strings, instance methods return a new object
190
+ it 'returns a String' do
191
+ expect(described_class.dirname('')).to be_a String
192
+ end
193
+ end
194
+ describe '#initialize' do
195
+ it 'defaults to existing' do
196
+ expect(virtual_pathname.exist?).to be true
197
+ end
198
+
199
+ it 'defaults to being a directory' do
200
+ expect(virtual_pathname.directory?).to be true
201
+ end
202
+
203
+ it 'defaults to having a stat object' do
204
+ expect(virtual_pathname.stat).to be_truthy
205
+ end
206
+
207
+ it 'throws an exception when stat is specified with exist? false' do
208
+ expect { described_class.new({}, path, exist?: false, stat: true) }.to raise_error(ArgumentError)
209
+ end
210
+
211
+ it 'accepts a VirtualStat object' do
212
+ stat = RubySMB::Server::Share::Provider::VirtualDisk::VirtualStat.new
213
+ expect(RubySMB::Server::Share::Provider::VirtualDisk::VirtualStat).to_not receive(:new)
214
+ inst = described_class.new({}, path, stat: stat)
215
+ expect(inst.stat).to be stat
216
+ end
217
+
218
+ it 'accepts a VirtualStat Hash' do
219
+ stat = { size: rand(0xFFFF) }
220
+ expect(RubySMB::Server::Share::Provider::VirtualDisk::VirtualStat).to receive(:new).and_call_original
221
+ inst = described_class.new({}, path, stat: stat)
222
+ expect(inst.stat).to_not be stat
223
+ expect(inst.stat).to be_a RubySMB::Server::Share::Provider::VirtualDisk::VirtualStat
224
+ expect(inst.stat.size).to eq stat[:size]
225
+ end
226
+ end
227
+
228
+ describe '#dirname' do
229
+ it 'returns a new object' do
230
+ expect(virtual_pathname.dirname).to be_a described_class
231
+ end
232
+ end
233
+
234
+ describe '#extname' do
235
+ it 'returns a String' do
236
+ expect(virtual_pathname.extname).to be_a String
237
+ end
238
+ end
239
+
240
+ describe '#join' do
241
+ it 'returns a new object' do
242
+ joined = virtual_pathname.join(leaf_path)
243
+ expect(joined).to be_a described_class
244
+ expect(joined).to_not eq virtual_pathname
245
+ end
246
+ end
247
+
248
+ describe '#split' do
249
+ it 'returns an array of two objects' do
250
+ split = virtual_pathname.split
251
+ expect(split.length).to be 2
252
+ expect(split[0]).to be_a described_class
253
+ expect(split[1]).to be_a described_class
254
+ end
255
+ end
256
+
257
+ describe '#to_s' do
258
+ it 'returns a string representation' do
259
+ expect(virtual_pathname.to_s).to be_a String
260
+ end
261
+ end
262
+
263
+ context 'when it is an absolute path' do
264
+ subject(:virtual_pathname) { described_class.new({}, "#{File::SEPARATOR}testing") }
265
+
266
+ describe '#absolute?' do
267
+ it 'returns true' do
268
+ expect(virtual_pathname.absolute?).to be true
269
+ end
270
+ end
271
+
272
+ describe '#relative?' do
273
+ it 'returns false' do
274
+ expect(virtual_pathname.relative?).to be false
275
+ end
276
+ end
277
+ end
278
+
279
+ context 'when it is a relative path' do
280
+ subject(:virtual_pathname) { described_class.new({}, ".#{File::SEPARATOR}testing") }
281
+
282
+ describe '#absolute?' do
283
+ it 'returns false' do
284
+ expect(virtual_pathname.absolute?).to be false
285
+ end
286
+ end
287
+
288
+ describe '#relative?' do
289
+ it 'returns true' do
290
+ expect(virtual_pathname.relative?).to be true
291
+ end
292
+ end
293
+ end
294
+
295
+ context 'when it is an existing directory' do
296
+ let(:virtual_fs) { Hash.new }
297
+ subject(:virtual_pathname) { described_class.new(virtual_fs, path, exist?: true, stat: { directory?: true }) }
298
+
299
+ include_context 'existing common'
300
+
301
+ context 'that is empty' do
302
+ describe '#children' do
303
+ it 'returns an empty array' do
304
+ expect(virtual_pathname.children).to be_a Array
305
+ expect(virtual_pathname.children).to be_empty
306
+ end
307
+ end
308
+
309
+ describe '#entries' do
310
+ it 'calls #children with_directories=false)' do
311
+ expect(virtual_pathname).to receive(:children).with(false).and_call_original
312
+ virtual_pathname.entries
313
+ end
314
+
315
+ it 'returns an empty array' do
316
+ expect(virtual_pathname.entries).to be_a Array
317
+ expect(virtual_pathname.entries).to be_empty
318
+ end
319
+ end
320
+ end
321
+
322
+ context 'that is populated' do
323
+ before(:each) do
324
+ virtual_fs[leaf_path] = described_class.new(virtual_fs, leaf_path)
325
+ end
326
+
327
+ describe '#children' do
328
+ context 'when with_directories is true' do
329
+ it 'returns an array of children' do
330
+ expect(virtual_pathname.children(true)).to be_a Array
331
+ expect(virtual_pathname.children(true)).to_not be_empty
332
+ child = virtual_pathname.children(true).first
333
+ expect(child).to be_a described_class
334
+ expect(child.to_s).to eq leaf_path
335
+ end
336
+ end
337
+
338
+ context 'when with_directories is false' do
339
+ it 'returns an array of children' do
340
+ expect(virtual_pathname.children(false)).to be_a Array
341
+ expect(virtual_pathname.children(false)).to_not be_empty
342
+ child = virtual_pathname.children(false).last
343
+ expect(child).to be_a described_class
344
+ expect(child.to_s).to eq File.basename(leaf_path)
345
+ end
346
+ end
347
+ end
348
+
349
+ describe '#entries' do
350
+ it 'calls #children with_directories=false)' do
351
+ expect(virtual_pathname).to receive(:children).with(false).and_call_original
352
+ virtual_pathname.entries
353
+ end
354
+
355
+ it 'returns an array of children' do
356
+ expect(virtual_pathname.entries).to be_a Array
357
+ expect(virtual_pathname.entries).to_not be_empty
358
+ child = virtual_pathname.entries.last
359
+ expect(child).to be_a described_class
360
+ expect(child.to_s).to eq File.basename(leaf_path)
361
+ end
362
+ end
363
+ end
364
+
365
+ describe '#executable?' do
366
+ it 'returns true' do
367
+ expect(virtual_pathname.executable?).to be true
368
+ end
369
+ end
370
+
371
+ describe '#ftype' do
372
+ it 'returns directory' do
373
+ expect(virtual_pathname.ftype).to eq 'directory'
374
+ end
375
+ end
376
+
377
+ describe '#zero?' do
378
+ it 'returns false' do
379
+ expect(virtual_pathname.zero?).to be false
380
+ end
381
+ end
382
+ end
383
+
384
+ context 'when it is an existing file' do
385
+ subject(:virtual_pathname) { described_class.new({}, path, exist?: true, stat: { file?: true }) }
386
+
387
+ include_context 'existing common'
388
+
389
+ describe '#children' do
390
+ it 'raises Errno::ENOTDIR' do
391
+ expect { virtual_pathname.children }.to raise_error(Errno::ENOTDIR)
392
+ end
393
+ end
394
+
395
+ describe '#entries' do
396
+ it 'raises Errno::ENOTDIR' do
397
+ expect { virtual_pathname.entries }.to raise_error(Errno::ENOTDIR)
398
+ end
399
+ end
400
+
401
+ describe '#executable?' do
402
+ it 'returns false' do
403
+ expect(virtual_pathname.executable?).to be false
404
+ end
405
+ end
406
+
407
+ describe '#ftype' do
408
+ it 'returns file' do
409
+ expect(virtual_pathname.ftype).to eq 'file'
410
+ end
411
+ end
412
+
413
+ describe '#zero?' do
414
+ it 'returns true' do
415
+ expect(virtual_pathname.zero?).to be true
416
+ end
417
+ end
418
+ end
419
+
420
+ context 'when it does not exist' do
421
+ # every attribute is tested to ensure they behave just like a Pathname object that doesn't exist
422
+ subject(:virtual_pathname) { described_class.new({}, path, exist?: false) }
423
+
424
+ describe '#atime' do
425
+ it 'raises Errno::ENOENT' do
426
+ expect { virtual_pathname.atime }.to raise_error(Errno::ENOENT)
427
+ end
428
+ end
429
+
430
+ describe '#birthtime' do
431
+ it 'raises Errno::ENOENT' do
432
+ expect { virtual_pathname.birthtime }.to raise_error(Errno::ENOENT)
433
+ end
434
+ end
435
+
436
+ describe '#blockdev?' do
437
+ it 'returns false' do
438
+ expect(virtual_pathname.blockdev?).to be false
439
+ end
440
+ end
441
+
442
+ describe '#chardev?' do
443
+ it 'returns false' do
444
+ expect(virtual_pathname.chardev?).to be false
445
+ end
446
+ end
447
+
448
+ describe '#ctime' do
449
+ it 'raises Errno::ENOENT' do
450
+ expect { virtual_pathname.ctime }.to raise_error(Errno::ENOENT)
451
+ end
452
+ end
453
+
454
+ describe '#directory?' do
455
+ it 'returns false' do
456
+ expect(virtual_pathname.directory?).to be false
457
+ end
458
+ end
459
+
460
+ describe '#executable?' do
461
+ it 'returns false' do
462
+ expect(virtual_pathname.executable?).to be false
463
+ end
464
+ end
465
+
466
+ describe '#exist?' do
467
+ it 'returns false' do
468
+ expect(virtual_pathname.exist?).to be false
469
+ end
470
+ end
471
+
472
+ describe '#file?' do
473
+ it 'returns false' do
474
+ expect(virtual_pathname.file?).to be false
475
+ end
476
+ end
477
+
478
+ describe '#ftype' do
479
+ it 'raises Errno::ENOENT' do
480
+ expect { virtual_pathname.ftype }.to raise_error(Errno::ENOENT)
481
+ end
482
+ end
483
+
484
+ describe '#grpowned?' do
485
+ it 'returns false' do
486
+ expect(virtual_pathname.grpowned?).to be false
487
+ end
488
+ end
489
+
490
+ describe '#mtime' do
491
+ it 'raises Errno::ENOENT' do
492
+ expect { virtual_pathname.mtime }.to raise_error(Errno::ENOENT)
493
+ end
494
+ end
495
+
496
+ describe '#owned?' do
497
+ it 'returns false' do
498
+ expect(virtual_pathname.owned?).to be false
499
+ end
500
+ end
501
+
502
+ describe '#pipe?' do
503
+ it 'returns false' do
504
+ expect(virtual_pathname.pipe?).to be false
505
+ end
506
+ end
507
+
508
+ describe '#readable?' do
509
+ it 'returns false' do
510
+ expect(virtual_pathname.readable?).to be false
511
+ end
512
+ end
513
+
514
+ describe '#setgid?' do
515
+ it 'returns false' do
516
+ expect(virtual_pathname.setgid?).to be false
517
+ end
518
+ end
519
+
520
+ describe '#setuid?' do
521
+ it 'returns false' do
522
+ expect(virtual_pathname.setuid?).to be false
523
+ end
524
+ end
525
+
526
+ describe '#size' do
527
+ it 'raises Errno::ENOENT' do
528
+ expect { virtual_pathname.size }.to raise_error(Errno::ENOENT)
529
+ end
530
+ end
531
+
532
+ describe '#socket?' do
533
+ it 'returns false' do
534
+ expect(virtual_pathname.socket?).to be false
535
+ end
536
+ end
537
+
538
+ describe '#stat' do
539
+ it 'raises Errno::ENOENT' do
540
+ expect { virtual_pathname.stat }.to raise_error(Errno::ENOENT)
541
+ end
542
+ end
543
+
544
+ describe '#sticky?' do
545
+ it 'returns false' do
546
+ expect(virtual_pathname.sticky?).to be false
547
+ end
548
+ end
549
+
550
+ describe '#symlink?' do
551
+ it 'returns false' do
552
+ expect(virtual_pathname.symlink?).to be false
553
+ end
554
+ end
555
+
556
+ describe '#world_readable?' do
557
+ it 'returns nil' do
558
+ expect(virtual_pathname.world_readable?).to be_nil
559
+ end
560
+ end
561
+
562
+ describe '#world_writable?' do
563
+ it 'returns nil' do
564
+ expect(virtual_pathname.world_writable?).to be_nil
565
+ end
566
+ end
567
+
568
+ describe '#writable?' do
569
+ it 'returns false' do
570
+ expect(virtual_pathname.writable?).to be false
571
+ end
572
+ end
573
+
574
+ describe '#zero?' do
575
+ it 'returns false' do
576
+ expect(virtual_pathname.zero?).to be false
577
+ end
578
+ end
579
+ end
580
+ end
581
+