fake_io 0.1.0
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.
- checksums.yaml +7 -0
- data/.document +3 -0
- data/.github/workflows/ruby.yml +28 -0
- data/.gitignore +5 -0
- data/.rspec +1 -0
- data/.yardopts +1 -0
- data/ChangeLog.md +8 -0
- data/Gemfile +16 -0
- data/LICENSE.txt +20 -0
- data/README.md +93 -0
- data/Rakefile +13 -0
- data/fake_io.gemspec +61 -0
- data/gemspec.yml +20 -0
- data/lib/fake_io/version.rb +4 -0
- data/lib/fake_io.rb +1213 -0
- data/spec/classes/test_io.rb +36 -0
- data/spec/fake_io_spec.rb +1212 -0
- data/spec/spec_helper.rb +4 -0
- metadata +81 -0
@@ -0,0 +1,1212 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fake_io'
|
3
|
+
|
4
|
+
require 'classes/test_io'
|
5
|
+
|
6
|
+
describe FakeIO do
|
7
|
+
let(:chunks) { ["one\n", "two\nthree\n", "four\n"] }
|
8
|
+
let(:string) { chunks.join }
|
9
|
+
let(:bytes) { chunks.join.each_byte.to_a }
|
10
|
+
let(:chars) { chunks.join.each_char.to_a }
|
11
|
+
let(:lines) { chunks.join.each_line.to_a }
|
12
|
+
|
13
|
+
subject { TestIO.new(chunks) }
|
14
|
+
|
15
|
+
describe "#initialize" do
|
16
|
+
it "should open the IO stream" do
|
17
|
+
expect(subject).not_to be_closed
|
18
|
+
end
|
19
|
+
|
20
|
+
it "must default #autoclose? to true" do
|
21
|
+
expect(subject.autoclose?).to be(true)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "must default #close_on_exec? to true" do
|
25
|
+
expect(subject.close_on_exec?).to be(true)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should set the file descriptor returned by io_open" do
|
29
|
+
expect(subject.fileno).to eq(3)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "must set #pos to 0" do
|
33
|
+
expect(subject.pos).to eq(0)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "must set #lineno to 0" do
|
37
|
+
expect(subject.lineno).to eq(0)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "must set #eof to false" do
|
41
|
+
expect(subject.eof).to be(false)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "must default #tty? to false" do
|
45
|
+
expect(subject.tty?).to be(false)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "must default #pid to nil" do
|
49
|
+
expect(subject.pid).to be(nil)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "must default #sync to false" do
|
53
|
+
expect(subject.sync).to be(false)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "must default #external_encoding to Encoding.default_external" do
|
57
|
+
expect(subject.external_encoding).to eq(Encoding.default_external)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#advise" do
|
62
|
+
it "must return nil" do
|
63
|
+
expect(subject.advise(:normal,0,0)).to be(nil)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "#autoclose=" do
|
68
|
+
let(:autoclose) { false }
|
69
|
+
|
70
|
+
before { subject.autoclose = autoclose }
|
71
|
+
|
72
|
+
it "must set #autoclose?" do
|
73
|
+
expect(subject.autoclose?).to be(autoclose)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#autoclose?" do
|
78
|
+
it "must return true by default" do
|
79
|
+
expect(subject.autoclose?).to be(true)
|
80
|
+
end
|
81
|
+
|
82
|
+
context "when #autoclose= is set to false" do
|
83
|
+
before { subject.autoclose = false }
|
84
|
+
|
85
|
+
it "must return false" do
|
86
|
+
expect(subject.autoclose?).to be(false)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "#close_on_exec=" do
|
92
|
+
let(:close_on_exec) { false }
|
93
|
+
|
94
|
+
before { subject.close_on_exec = close_on_exec }
|
95
|
+
|
96
|
+
it "must set #close_on_exec?" do
|
97
|
+
expect(subject.close_on_exec?).to be(close_on_exec)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "#close_on_exec?" do
|
102
|
+
it "must return true by default" do
|
103
|
+
expect(subject.close_on_exec?).to be(true)
|
104
|
+
end
|
105
|
+
|
106
|
+
context "when #close_on_exec= is set to false" do
|
107
|
+
before { subject.close_on_exec = false }
|
108
|
+
|
109
|
+
it "must return false" do
|
110
|
+
expect(subject.close_on_exec?).to be(false)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "#binmode" do
|
116
|
+
before { subject.binmode }
|
117
|
+
|
118
|
+
it "must cause #binmode? to return true" do
|
119
|
+
expect(subject.binmode?).to be(true)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "#binmode?" do
|
124
|
+
it "must return false by default" do
|
125
|
+
expect(subject.binmode?).to be(false)
|
126
|
+
end
|
127
|
+
|
128
|
+
context "when binmode is set" do
|
129
|
+
before { subject.binmode }
|
130
|
+
|
131
|
+
it "must return true" do
|
132
|
+
expect(subject.binmode?).to be(true)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "#isatty" do
|
138
|
+
it "must return false by default" do
|
139
|
+
expect(subject.isatty).to be(false)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe "#tty?" do
|
144
|
+
it "must return false by default" do
|
145
|
+
expect(subject.tty?).to be(false)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "#set_encoding" do
|
150
|
+
context "when given a single String" do
|
151
|
+
let(:string) { 'ASCII' }
|
152
|
+
|
153
|
+
before { subject.set_encoding(string) }
|
154
|
+
|
155
|
+
it "must set the #external_encoding" do
|
156
|
+
expect(subject.external_encoding).to eq(Encoding.find(string))
|
157
|
+
end
|
158
|
+
|
159
|
+
it "must not set the #internal_encoding" do
|
160
|
+
expect(subject.internal_encoding).to be(nil)
|
161
|
+
end
|
162
|
+
|
163
|
+
context "and the String contains a ':'" do
|
164
|
+
let(:ext_enc) { 'UTF-8' }
|
165
|
+
let(:int_enc) { 'ASCII' }
|
166
|
+
let(:string) { "#{ext_enc}:#{int_enc}" }
|
167
|
+
|
168
|
+
it "must set the #external_encoding" do
|
169
|
+
expect(subject.external_encoding).to eq(Encoding.find(ext_enc))
|
170
|
+
end
|
171
|
+
|
172
|
+
it "must set the #internal_encoding" do
|
173
|
+
expect(subject.internal_encoding).to eq(Encoding.find(int_enc))
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context "and the String contains a ','" do
|
178
|
+
let(:ext_enc) { 'UTF-8' }
|
179
|
+
let(:int_enc) { 'ASCII' }
|
180
|
+
let(:string) { "#{ext_enc},#{int_enc}" }
|
181
|
+
|
182
|
+
it "must set the #external_encoding" do
|
183
|
+
expect(subject.external_encoding).to eq(Encoding.find(ext_enc))
|
184
|
+
end
|
185
|
+
|
186
|
+
it "must set the #internal_encoding" do
|
187
|
+
expect(subject.internal_encoding).to eq(Encoding.find(int_enc))
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
context "when given a single Encoding object" do
|
193
|
+
let(:encoding) { Encoding::ASCII }
|
194
|
+
|
195
|
+
before { subject.set_encoding(encoding) }
|
196
|
+
|
197
|
+
it "must set the #external_encoding" do
|
198
|
+
expect(subject.external_encoding).to eq(encoding)
|
199
|
+
end
|
200
|
+
|
201
|
+
it "must not set the #internal_encoding" do
|
202
|
+
expect(subject.internal_encoding).to be(nil)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
context "when given two Encoding objects" do
|
207
|
+
let(:external_encoding) { Encoding::UTF_8 }
|
208
|
+
let(:internal_encoding) { Encoding::ASCII }
|
209
|
+
|
210
|
+
before { subject.set_encoding(external_encoding,internal_encoding) }
|
211
|
+
|
212
|
+
it "must set the #external_encoding" do
|
213
|
+
expect(subject.external_encoding).to eq(external_encoding)
|
214
|
+
end
|
215
|
+
|
216
|
+
it "must set the #internal_encoding" do
|
217
|
+
expect(subject.internal_encoding).to eq(internal_encoding)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
context "when given another Object besides a String or an Encoding" do
|
222
|
+
it do
|
223
|
+
expect {
|
224
|
+
subject.set_encoding(Object.new)
|
225
|
+
}.to raise_error(TypeError,"argument must be a String or Encoding object")
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context "when no arguments are given" do
|
230
|
+
it do
|
231
|
+
expect {
|
232
|
+
subject.set_encoding
|
233
|
+
}.to raise_error(ArgumentError,"wrong number of arguments (given 0, expected 1..3)")
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
context "when given more than three arguments" do
|
238
|
+
it do
|
239
|
+
expect {
|
240
|
+
subject.set_encoding(
|
241
|
+
Encoding::ASCII,
|
242
|
+
Encoding::ASCII,
|
243
|
+
Encoding::ASCII,
|
244
|
+
Encoding::ASCII
|
245
|
+
)
|
246
|
+
}.to raise_error(ArgumentError,"wrong number of arguments (given 4, expected 1..3)")
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
describe "#set_encoding_by_bom" do
|
252
|
+
class TestBOM
|
253
|
+
|
254
|
+
include FakeIO
|
255
|
+
|
256
|
+
def initialize(data)
|
257
|
+
@data = data
|
258
|
+
super()
|
259
|
+
end
|
260
|
+
|
261
|
+
private
|
262
|
+
|
263
|
+
def io_read
|
264
|
+
if (data = @data)
|
265
|
+
@data = nil
|
266
|
+
return data
|
267
|
+
else
|
268
|
+
raise(EOFError,"end of stream")
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
end
|
273
|
+
|
274
|
+
subject { TestBOM.new(data) }
|
275
|
+
|
276
|
+
before { subject.set_encoding_by_bom }
|
277
|
+
|
278
|
+
context "when the first byte is 0x00" do
|
279
|
+
context "and the second byte is 0x00" do
|
280
|
+
context "and the thrid byte is 0xFE" do
|
281
|
+
context "and the fourth byte is 0xFF" do
|
282
|
+
let(:data) do
|
283
|
+
"\x00\x00\xFE\xFFhello".force_encoding(Encoding::ASCII_8BIT)
|
284
|
+
end
|
285
|
+
|
286
|
+
let(:encoding) { Encoding::UTF_32BE }
|
287
|
+
|
288
|
+
it "must set #external_encoding to Encoding::UTF_32BE" do
|
289
|
+
expect(subject.external_encoding).to eq(encoding)
|
290
|
+
end
|
291
|
+
|
292
|
+
it "must consume the BOM bytes" do
|
293
|
+
expect(subject.read).to eq(
|
294
|
+
data.byteslice(4..).force_encoding(encoding)
|
295
|
+
)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
context "but the fourth byte is not 0xFF" do
|
300
|
+
let(:data) do
|
301
|
+
"\x00\x00\xFEXhello".force_encoding(Encoding::ASCII_8BIT)
|
302
|
+
end
|
303
|
+
|
304
|
+
it "must not set #external_encoding" do
|
305
|
+
expect(subject.external_encoding).to be(
|
306
|
+
Encoding.default_external
|
307
|
+
)
|
308
|
+
end
|
309
|
+
|
310
|
+
it "must put the bytes back into the read buffer" do
|
311
|
+
expect(subject.read).to eq(
|
312
|
+
data.force_encoding(subject.external_encoding)
|
313
|
+
)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
context "but EOF is reached" do
|
318
|
+
let(:data) do
|
319
|
+
"\x00\x00\xFE".force_encoding(Encoding::ASCII_8BIT)
|
320
|
+
end
|
321
|
+
|
322
|
+
it "must not set #external_encoding" do
|
323
|
+
expect(subject.external_encoding).to be(
|
324
|
+
Encoding.default_external
|
325
|
+
)
|
326
|
+
end
|
327
|
+
|
328
|
+
it "must put the bytes back into the read buffer" do
|
329
|
+
expect(subject.read).to eq(
|
330
|
+
data.force_encoding(subject.external_encoding)
|
331
|
+
)
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
context "but the third byte is not 0xFE" do
|
337
|
+
let(:data) do
|
338
|
+
"\x00\x00XXhello".force_encoding(Encoding::ASCII_8BIT)
|
339
|
+
end
|
340
|
+
|
341
|
+
it "must not set #external_encoding" do
|
342
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
343
|
+
end
|
344
|
+
|
345
|
+
it "must put the bytes back into the read buffer" do
|
346
|
+
expect(subject.read).to eq(
|
347
|
+
data.force_encoding(subject.external_encoding)
|
348
|
+
)
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
context "but EOF is reached" do
|
353
|
+
let(:data) do
|
354
|
+
"\x00\x00".force_encoding(Encoding::ASCII_8BIT)
|
355
|
+
end
|
356
|
+
|
357
|
+
it "must not set #external_encoding" do
|
358
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
359
|
+
end
|
360
|
+
|
361
|
+
it "must put the bytes back into the read buffer" do
|
362
|
+
expect(subject.read).to eq(
|
363
|
+
data.force_encoding(subject.external_encoding)
|
364
|
+
)
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
context "but the second byte is not 0x00" do
|
370
|
+
let(:data) do
|
371
|
+
"\x00XXXhello".force_encoding(Encoding::ASCII_8BIT)
|
372
|
+
end
|
373
|
+
|
374
|
+
it "must not set #external_encoding" do
|
375
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
376
|
+
end
|
377
|
+
|
378
|
+
it "must put the bytes back into the read buffer" do
|
379
|
+
expect(subject.read).to eq(
|
380
|
+
data.force_encoding(subject.external_encoding)
|
381
|
+
)
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
context "but EOF is reached" do
|
386
|
+
let(:data) do
|
387
|
+
"\x00".force_encoding(Encoding::ASCII_8BIT)
|
388
|
+
end
|
389
|
+
|
390
|
+
it "must not set #external_encoding" do
|
391
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
392
|
+
end
|
393
|
+
|
394
|
+
it "must put the bytes back into the read buffer" do
|
395
|
+
expect(subject.read).to eq(
|
396
|
+
data.force_encoding(subject.external_encoding)
|
397
|
+
)
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
context "but the first byte is not 0x00" do
|
403
|
+
let(:data) do
|
404
|
+
"XXXXhello".force_encoding(Encoding::ASCII_8BIT)
|
405
|
+
end
|
406
|
+
|
407
|
+
it "must not set #external_encoding" do
|
408
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
409
|
+
end
|
410
|
+
|
411
|
+
it "must put the bytes back into the read buffer" do
|
412
|
+
expect(subject.read).to eq(
|
413
|
+
data.force_encoding(subject.external_encoding)
|
414
|
+
)
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
context "when the first byte is 0x28" do
|
419
|
+
context "and the second byte is 0x2F" do
|
420
|
+
context "and the third byte is 0x76" do
|
421
|
+
let(:data) do
|
422
|
+
"\x28\x2F\x76hello".force_encoding(Encoding::ASCII_8BIT)
|
423
|
+
end
|
424
|
+
|
425
|
+
let(:encoding) { Encoding::UTF_7 }
|
426
|
+
|
427
|
+
it "must set #external_encoding to Encoding::UTF_7" do
|
428
|
+
expect(subject.external_encoding).to eq(encoding)
|
429
|
+
end
|
430
|
+
|
431
|
+
it "must consume the BOM bytes" do
|
432
|
+
pending "Cannot convert from UTF-8 to UTF-7"
|
433
|
+
|
434
|
+
expect(subject.read).to eq(
|
435
|
+
data.byteslice(2..).force_encoding(encoding)
|
436
|
+
)
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
context "but the third byte is not 0x76" do
|
441
|
+
let(:data) do
|
442
|
+
"\x28\x2FXhello".force_encoding(Encoding::ASCII_8BIT)
|
443
|
+
end
|
444
|
+
|
445
|
+
it "must not set #external_encoding" do
|
446
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
447
|
+
end
|
448
|
+
|
449
|
+
it "must put the bytes back into the read buffer" do
|
450
|
+
expect(subject.read).to eq(
|
451
|
+
data.force_encoding(subject.external_encoding)
|
452
|
+
)
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
context "but EOF is reached" do
|
457
|
+
let(:data) do
|
458
|
+
"\x28\x2F".force_encoding(Encoding::ASCII_8BIT)
|
459
|
+
end
|
460
|
+
|
461
|
+
it "must not set #external_encoding" do
|
462
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
463
|
+
end
|
464
|
+
|
465
|
+
it "must put the bytes back into the read buffer" do
|
466
|
+
expect(subject.read).to eq(
|
467
|
+
data.force_encoding(subject.external_encoding)
|
468
|
+
)
|
469
|
+
end
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
context "but the second byte is not 0x2F" do
|
474
|
+
let(:data) do
|
475
|
+
"\x28XXhello".force_encoding(Encoding::ASCII_8BIT)
|
476
|
+
end
|
477
|
+
|
478
|
+
it "must not set #external_encoding" do
|
479
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
480
|
+
end
|
481
|
+
|
482
|
+
it "must put the bytes back into the read buffer" do
|
483
|
+
expect(subject.read).to eq(
|
484
|
+
data.force_encoding(subject.external_encoding)
|
485
|
+
)
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
context "but EOF is reached" do
|
490
|
+
let(:data) do
|
491
|
+
"\x28".force_encoding(Encoding::ASCII_8BIT)
|
492
|
+
end
|
493
|
+
|
494
|
+
it "must not set #external_encoding" do
|
495
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
496
|
+
end
|
497
|
+
|
498
|
+
it "must put the bytes back into the read buffer" do
|
499
|
+
expect(subject.read).to eq(
|
500
|
+
data.force_encoding(subject.external_encoding)
|
501
|
+
)
|
502
|
+
end
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
context "but the first byte is not 0x2F" do
|
507
|
+
let(:data) do
|
508
|
+
"XXXhello".force_encoding(Encoding::ASCII_8BIT)
|
509
|
+
end
|
510
|
+
|
511
|
+
it "must not set #external_encoding" do
|
512
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
513
|
+
end
|
514
|
+
|
515
|
+
it "must put the bytes back into the read buffer" do
|
516
|
+
expect(subject.read).to eq(
|
517
|
+
data.force_encoding(subject.external_encoding)
|
518
|
+
)
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
context "when the first byte is 0xEF" do
|
523
|
+
context "and the second byte is 0xBB" do
|
524
|
+
context "and the third byte is 0xBF" do
|
525
|
+
let(:data) do
|
526
|
+
"\xEF\xBB\xBFhello".force_encoding(Encoding::ASCII_8BIT)
|
527
|
+
end
|
528
|
+
|
529
|
+
let(:encoding) { Encoding::UTF_8 }
|
530
|
+
|
531
|
+
it "must set #external_encoding to Encoding::UTF_8" do
|
532
|
+
expect(subject.external_encoding).to eq(encoding)
|
533
|
+
end
|
534
|
+
|
535
|
+
it "must consume the BOM bytes" do
|
536
|
+
expect(subject.read).to eq(
|
537
|
+
data.byteslice(3..).force_encoding(encoding)
|
538
|
+
)
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
context "but the third byte is not 0xBF" do
|
543
|
+
let(:data) do
|
544
|
+
"\xEF\xBBXhello".force_encoding(Encoding::ASCII_8BIT)
|
545
|
+
end
|
546
|
+
|
547
|
+
it "must not set #external_encoding" do
|
548
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
549
|
+
end
|
550
|
+
|
551
|
+
it "must put the bytes back into the read buffer" do
|
552
|
+
expect(subject.read).to eq(
|
553
|
+
data.force_encoding(subject.external_encoding)
|
554
|
+
)
|
555
|
+
end
|
556
|
+
end
|
557
|
+
|
558
|
+
context "but EOF is reached" do
|
559
|
+
let(:data) do
|
560
|
+
"\xEF\xBB".force_encoding(Encoding::ASCII_8BIT)
|
561
|
+
end
|
562
|
+
|
563
|
+
it "must not set #external_encoding" do
|
564
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
565
|
+
end
|
566
|
+
|
567
|
+
it "must put the bytes back into the read buffer" do
|
568
|
+
expect(subject.read).to eq(
|
569
|
+
data.force_encoding(subject.external_encoding)
|
570
|
+
)
|
571
|
+
end
|
572
|
+
end
|
573
|
+
end
|
574
|
+
|
575
|
+
context "but the second byte is not 0xBB" do
|
576
|
+
let(:data) do
|
577
|
+
"\xEFXXhello".force_encoding(Encoding::ASCII_8BIT)
|
578
|
+
end
|
579
|
+
|
580
|
+
it "must not set #external_encoding" do
|
581
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
582
|
+
end
|
583
|
+
|
584
|
+
it "must put the bytes back into the read buffer" do
|
585
|
+
expect(subject.read).to eq(
|
586
|
+
data.force_encoding(subject.external_encoding)
|
587
|
+
)
|
588
|
+
end
|
589
|
+
end
|
590
|
+
|
591
|
+
context "but EOF is reached" do
|
592
|
+
let(:data) do
|
593
|
+
"\xEF".force_encoding(Encoding::ASCII_8BIT)
|
594
|
+
end
|
595
|
+
|
596
|
+
it "must not set #external_encoding" do
|
597
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
598
|
+
end
|
599
|
+
|
600
|
+
it "must put the bytes back into the read buffer" do
|
601
|
+
expect(subject.read).to eq(
|
602
|
+
data.force_encoding(subject.external_encoding)
|
603
|
+
)
|
604
|
+
end
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
608
|
+
context "but the first byte is not 0xEF" do
|
609
|
+
let(:data) do
|
610
|
+
"XXXhello".force_encoding(Encoding::ASCII_8BIT)
|
611
|
+
end
|
612
|
+
|
613
|
+
it "must not set #external_encoding" do
|
614
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
615
|
+
end
|
616
|
+
|
617
|
+
it "must put the bytes back into the read buffer" do
|
618
|
+
expect(subject.read).to eq(
|
619
|
+
data.force_encoding(subject.external_encoding)
|
620
|
+
)
|
621
|
+
end
|
622
|
+
end
|
623
|
+
|
624
|
+
context "when the first byte is 0xFE" do
|
625
|
+
context "and the second byte is 0xFF" do
|
626
|
+
let(:data) do
|
627
|
+
"\xFE\xFFhello".force_encoding(Encoding::ASCII_8BIT)
|
628
|
+
end
|
629
|
+
|
630
|
+
let(:encoding) { Encoding::UTF_16BE }
|
631
|
+
|
632
|
+
it "must set #external_encoding to Encoding::UTF_16BE" do
|
633
|
+
expect(subject.external_encoding).to eq(encoding)
|
634
|
+
end
|
635
|
+
|
636
|
+
it "must consume the BOM bytes" do
|
637
|
+
expect(subject.read).to eq(
|
638
|
+
data.byteslice(2..).force_encoding(encoding)
|
639
|
+
)
|
640
|
+
end
|
641
|
+
end
|
642
|
+
|
643
|
+
context "but the second byte is not 0xFF" do
|
644
|
+
let(:data) do
|
645
|
+
"\xFEXhello".force_encoding(Encoding::ASCII_8BIT)
|
646
|
+
end
|
647
|
+
|
648
|
+
it "must not set #external_encoding" do
|
649
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
650
|
+
end
|
651
|
+
|
652
|
+
it "must put the bytes back into the read buffer" do
|
653
|
+
expect(subject.read).to eq(
|
654
|
+
data.force_encoding(subject.external_encoding)
|
655
|
+
)
|
656
|
+
end
|
657
|
+
end
|
658
|
+
|
659
|
+
context "but EOF is reached" do
|
660
|
+
let(:data) do
|
661
|
+
"\xFE".force_encoding(Encoding::ASCII_8BIT)
|
662
|
+
end
|
663
|
+
|
664
|
+
it "must not set #external_encoding" do
|
665
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
666
|
+
end
|
667
|
+
|
668
|
+
it "must put the bytes back into the read buffer" do
|
669
|
+
expect(subject.read).to eq(
|
670
|
+
data.force_encoding(subject.external_encoding)
|
671
|
+
)
|
672
|
+
end
|
673
|
+
end
|
674
|
+
end
|
675
|
+
|
676
|
+
context "but the first byte is not 0xFE" do
|
677
|
+
let(:data) do
|
678
|
+
"XXhello".force_encoding(Encoding::ASCII_8BIT)
|
679
|
+
end
|
680
|
+
|
681
|
+
it "must not set #external_encoding" do
|
682
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
683
|
+
end
|
684
|
+
|
685
|
+
it "must put the bytes back into the read buffer" do
|
686
|
+
expect(subject.read).to eq(
|
687
|
+
data.force_encoding(subject.external_encoding)
|
688
|
+
)
|
689
|
+
end
|
690
|
+
end
|
691
|
+
|
692
|
+
context "but EOF is reached" do
|
693
|
+
let(:data) do
|
694
|
+
"".force_encoding(Encoding::ASCII_8BIT)
|
695
|
+
end
|
696
|
+
|
697
|
+
it "must not set #external_encoding" do
|
698
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
699
|
+
end
|
700
|
+
end
|
701
|
+
|
702
|
+
context "when the first byte is 0xFF" do
|
703
|
+
context "and the second byte is 0xFE" do
|
704
|
+
let(:data) do
|
705
|
+
"\xFF\xFEhello".force_encoding(Encoding::ASCII_8BIT)
|
706
|
+
end
|
707
|
+
|
708
|
+
let(:encoding) { Encoding::UTF_16LE }
|
709
|
+
|
710
|
+
it "must set #external_encoding to Encoding::UTF_16LE" do
|
711
|
+
expect(subject.external_encoding).to eq(encoding)
|
712
|
+
end
|
713
|
+
|
714
|
+
it "must consume the BOM bytes" do
|
715
|
+
expect(subject.read).to eq(
|
716
|
+
data.byteslice(2..).force_encoding(encoding)
|
717
|
+
)
|
718
|
+
end
|
719
|
+
end
|
720
|
+
|
721
|
+
context "but the second byte is not 0xFE" do
|
722
|
+
let(:data) do
|
723
|
+
"\xFFXhello".force_encoding(Encoding::ASCII_8BIT)
|
724
|
+
end
|
725
|
+
|
726
|
+
it "must not set #external_encoding" do
|
727
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
728
|
+
end
|
729
|
+
|
730
|
+
it "must put the bytes back into the read buffer" do
|
731
|
+
expect(subject.read).to eq(
|
732
|
+
data.force_encoding(subject.external_encoding)
|
733
|
+
)
|
734
|
+
end
|
735
|
+
end
|
736
|
+
|
737
|
+
context "but EOF is reached" do
|
738
|
+
let(:data) do
|
739
|
+
"\xFF".force_encoding(Encoding::ASCII_8BIT)
|
740
|
+
end
|
741
|
+
|
742
|
+
it "must not set #external_encoding" do
|
743
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
744
|
+
end
|
745
|
+
|
746
|
+
it "must put the bytes back into the read buffer" do
|
747
|
+
expect(subject.read).to eq(
|
748
|
+
data.force_encoding(subject.external_encoding)
|
749
|
+
)
|
750
|
+
end
|
751
|
+
end
|
752
|
+
end
|
753
|
+
|
754
|
+
context "but the first byte is not 0xFF" do
|
755
|
+
let(:data) do
|
756
|
+
"XXhello".force_encoding(Encoding::ASCII_8BIT)
|
757
|
+
end
|
758
|
+
|
759
|
+
it "must not set #external_encoding" do
|
760
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
761
|
+
end
|
762
|
+
|
763
|
+
it "must put the bytes back into the read buffer" do
|
764
|
+
expect(subject.read).to eq(
|
765
|
+
data.force_encoding(subject.external_encoding)
|
766
|
+
)
|
767
|
+
end
|
768
|
+
end
|
769
|
+
|
770
|
+
context "but EOF is reached" do
|
771
|
+
let(:data) { "".force_encoding(Encoding::ASCII_8BIT) }
|
772
|
+
|
773
|
+
it "must not set #external_encoding" do
|
774
|
+
expect(subject.external_encoding).to be(Encoding.default_external)
|
775
|
+
end
|
776
|
+
end
|
777
|
+
end
|
778
|
+
|
779
|
+
describe "#each_chunk" do
|
780
|
+
it "should read each block of data" do
|
781
|
+
expect(subject.each_chunk.to_a).to eq(chunks)
|
782
|
+
end
|
783
|
+
|
784
|
+
it "must set the encoding of the String to Encoding.default_external" do
|
785
|
+
expect(subject.each_chunk.first.encoding).to eq(Encoding.default_external)
|
786
|
+
end
|
787
|
+
|
788
|
+
context "when #external_encoding diffs from Encoding.default_external" do
|
789
|
+
let(:external_encoding) { Encoding::ASCII_8BIT }
|
790
|
+
|
791
|
+
before { subject.external_encoding = external_encoding }
|
792
|
+
|
793
|
+
it "must set the encoding of the String to #external_encoding" do
|
794
|
+
expect(subject.each_chunk.first.encoding).to eq(subject.external_encoding)
|
795
|
+
end
|
796
|
+
end
|
797
|
+
|
798
|
+
it "must set #eof to true at the end" do
|
799
|
+
expect(subject.eof).to be(false)
|
800
|
+
|
801
|
+
subject.each_chunk { |chunk| }
|
802
|
+
|
803
|
+
expect(subject.eof).to be(true)
|
804
|
+
end
|
805
|
+
|
806
|
+
context "when #io_read raises an EOFError" do
|
807
|
+
it "must set #eof to true" do
|
808
|
+
allow(subject).to receive(:io_read).and_raise(EOFError)
|
809
|
+
expect(subject.eof).to be(false)
|
810
|
+
|
811
|
+
subject.each_chunk { |chunk| }
|
812
|
+
|
813
|
+
expect(subject.eof).to be(true)
|
814
|
+
end
|
815
|
+
end
|
816
|
+
end
|
817
|
+
|
818
|
+
describe "#read" do
|
819
|
+
context "when no length is given" do
|
820
|
+
it "should read all of the data" do
|
821
|
+
expect(subject.read).to eq(string)
|
822
|
+
end
|
823
|
+
|
824
|
+
it "must set the encoding of the String to Encoding.default_external" do
|
825
|
+
expect(subject.read.encoding).to eq(Encoding.default_external)
|
826
|
+
end
|
827
|
+
|
828
|
+
it "must advance #pos by the number of bytes read" do
|
829
|
+
previous_pos = subject.pos
|
830
|
+
read_data = subject.read
|
831
|
+
|
832
|
+
expect(subject.pos - previous_pos).to eq(read_data.bytesize)
|
833
|
+
end
|
834
|
+
|
835
|
+
context "when #external_encoding diffs from Encoding.default_external" do
|
836
|
+
let(:external_encoding) { Encoding::ASCII_8BIT }
|
837
|
+
|
838
|
+
before { subject.external_encoding = external_encoding }
|
839
|
+
|
840
|
+
it "must set the encoding of the String to #external_encoding" do
|
841
|
+
expect(subject.read.encoding).to eq(subject.external_encoding)
|
842
|
+
end
|
843
|
+
end
|
844
|
+
|
845
|
+
context "and when a buffer is also given" do
|
846
|
+
let(:buffer) { String.new }
|
847
|
+
|
848
|
+
it "must append the all read bytes to the buffer" do
|
849
|
+
subject.read(nil,buffer)
|
850
|
+
|
851
|
+
expect(buffer).to eq(string)
|
852
|
+
end
|
853
|
+
end
|
854
|
+
end
|
855
|
+
|
856
|
+
context "when a length is given" do
|
857
|
+
it "should read partial sections of the data" do
|
858
|
+
expect(subject.read(3)).to eq(string[0,3])
|
859
|
+
expect(subject.read(1)).to eq(string[3,1])
|
860
|
+
end
|
861
|
+
|
862
|
+
it "should read individual blocks of data" do
|
863
|
+
expect(subject.read(4)).to eq(string[0,4])
|
864
|
+
end
|
865
|
+
|
866
|
+
it "must advance #pos by the number of bytes read" do
|
867
|
+
previous_pos = subject.pos
|
868
|
+
length = 4
|
869
|
+
read_data = subject.read(length)
|
870
|
+
|
871
|
+
expect(subject.pos - previous_pos).to eq(length)
|
872
|
+
end
|
873
|
+
|
874
|
+
context "but the data is UTF-8" do
|
875
|
+
let(:chunks) { ["Σὲ ", "γνωρίζω ἀπὸ", " τὴν κόψη"] }
|
876
|
+
|
877
|
+
it "must read exactly N bytes, not N chars" do
|
878
|
+
expect(subject.read(1)).to eq(string.byteslice(0,1))
|
879
|
+
end
|
880
|
+
end
|
881
|
+
|
882
|
+
context "and when a buffer is also given" do
|
883
|
+
let(:buffer) { String.new }
|
884
|
+
|
885
|
+
it "must append the read bytes to the buffer" do
|
886
|
+
subject.read(3,buffer)
|
887
|
+
subject.read(1,buffer)
|
888
|
+
|
889
|
+
expect(buffer).to eq(string[0,3 + 1])
|
890
|
+
end
|
891
|
+
end
|
892
|
+
end
|
893
|
+
end
|
894
|
+
|
895
|
+
describe "#readpartial" do
|
896
|
+
let(:length) { 3 }
|
897
|
+
|
898
|
+
it "must read at most N bytes" do
|
899
|
+
expect(subject.readpartial(length).length).to eq(length)
|
900
|
+
end
|
901
|
+
|
902
|
+
it "must set the encoding of the String to Encoding.default_external" do
|
903
|
+
expect(subject.readpartial(length).encoding).to eq(Encoding.default_external)
|
904
|
+
end
|
905
|
+
|
906
|
+
context "when #external_encoding diffs from Encoding.default_external" do
|
907
|
+
let(:external_encoding) { Encoding::ASCII_8BIT }
|
908
|
+
|
909
|
+
before { subject.external_encoding = external_encoding }
|
910
|
+
|
911
|
+
it "must set the encoding of the String to #external_encoding" do
|
912
|
+
expect(subject.readpartial(length).encoding).to eq(subject.external_encoding)
|
913
|
+
end
|
914
|
+
end
|
915
|
+
|
916
|
+
context "when also given a buffer" do
|
917
|
+
let(:buffer) { String.new }
|
918
|
+
|
919
|
+
it "must append the read bytes to the buffer" do
|
920
|
+
subject.readpartial(length,buffer)
|
921
|
+
subject.readpartial(length,buffer)
|
922
|
+
|
923
|
+
expect(buffer).to eq(string[0,length * 2])
|
924
|
+
end
|
925
|
+
end
|
926
|
+
end
|
927
|
+
|
928
|
+
describe "#getbyte" do
|
929
|
+
it "should get byte" do
|
930
|
+
expect(subject.getbyte).to eq(bytes.first)
|
931
|
+
end
|
932
|
+
end
|
933
|
+
|
934
|
+
describe "#gets" do
|
935
|
+
it "should get a line" do
|
936
|
+
expect(subject.gets).to eq(lines.first)
|
937
|
+
end
|
938
|
+
|
939
|
+
it "must set the encoding of the String to Encoding.default_external" do
|
940
|
+
expect(subject.gets.encoding).to eq(Encoding.default_external)
|
941
|
+
end
|
942
|
+
|
943
|
+
context "when #external_encoding diffs from Encoding.default_external" do
|
944
|
+
let(:external_encoding) { Encoding::ASCII_8BIT }
|
945
|
+
|
946
|
+
before { subject.external_encoding = external_encoding }
|
947
|
+
|
948
|
+
it "must set the encoding of the String to #external_encoding" do
|
949
|
+
expect(subject.gets.encoding).to eq(subject.external_encoding)
|
950
|
+
end
|
951
|
+
end
|
952
|
+
end
|
953
|
+
|
954
|
+
describe "#readbyte" do
|
955
|
+
it "should read bytes" do
|
956
|
+
expect(subject.readbyte).to eq(bytes.first)
|
957
|
+
end
|
958
|
+
end
|
959
|
+
|
960
|
+
describe "#getc" do
|
961
|
+
it "should get a character" do
|
962
|
+
expect(subject.getc).to eq(chars.first)
|
963
|
+
end
|
964
|
+
|
965
|
+
it "must set the encoding of the String to Encoding.default_external" do
|
966
|
+
expect(subject.getc.encoding).to eq(Encoding.default_external)
|
967
|
+
end
|
968
|
+
|
969
|
+
context "when #external_encoding diffs from Encoding.default_external" do
|
970
|
+
let(:external_encoding) { Encoding::ASCII_8BIT }
|
971
|
+
|
972
|
+
before { subject.external_encoding = external_encoding }
|
973
|
+
|
974
|
+
it "must set the encoding of the String to #external_encoding" do
|
975
|
+
expect(subject.getc.encoding).to eq(subject.external_encoding)
|
976
|
+
end
|
977
|
+
end
|
978
|
+
end
|
979
|
+
|
980
|
+
describe "#readchar" do
|
981
|
+
it "should read a char" do
|
982
|
+
expect(subject.readchar).to eq(chars.first)
|
983
|
+
end
|
984
|
+
|
985
|
+
it "must set the encoding of the String to Encoding.default_external" do
|
986
|
+
expect(subject.readchar.encoding).to eq(Encoding.default_external)
|
987
|
+
end
|
988
|
+
|
989
|
+
context "when #external_encoding diffs from Encoding.default_external" do
|
990
|
+
let(:external_encoding) { Encoding::ASCII_8BIT }
|
991
|
+
|
992
|
+
before { subject.external_encoding = external_encoding }
|
993
|
+
|
994
|
+
it "must set the encoding of the String to #external_encoding" do
|
995
|
+
expect(subject.readchar.encoding).to eq(subject.external_encoding)
|
996
|
+
end
|
997
|
+
end
|
998
|
+
end
|
999
|
+
|
1000
|
+
describe "#ungetc" do
|
1001
|
+
it "should un-get characters back into the IO stream" do
|
1002
|
+
data = subject.read(4)
|
1003
|
+
data.each_char.reverse_each { |c| subject.ungetc(c) }
|
1004
|
+
|
1005
|
+
expect(subject.read(4)).to eq(data)
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
it "must decrement #pos" do
|
1009
|
+
data = subject.read(4)
|
1010
|
+
previous_pos = subject.pos
|
1011
|
+
char = data.chars.last
|
1012
|
+
|
1013
|
+
subject.ungetc(char)
|
1014
|
+
|
1015
|
+
expect(previous_pos - subject.pos).to eq(char.bytesize)
|
1016
|
+
end
|
1017
|
+
end
|
1018
|
+
|
1019
|
+
describe "#readline" do
|
1020
|
+
it "should read a line" do
|
1021
|
+
expect(subject.readline).to eq(lines.first)
|
1022
|
+
end
|
1023
|
+
|
1024
|
+
it "must set the encoding of the String to Encoding.default_external" do
|
1025
|
+
expect(subject.readline.encoding).to eq(Encoding.default_external)
|
1026
|
+
end
|
1027
|
+
|
1028
|
+
context "when #external_encoding diffs from Encoding.default_external" do
|
1029
|
+
let(:external_encoding) { Encoding::ASCII_8BIT }
|
1030
|
+
|
1031
|
+
before { subject.external_encoding = external_encoding }
|
1032
|
+
|
1033
|
+
it "must set the encoding of the String to #external_encoding" do
|
1034
|
+
expect(subject.readline.encoding).to eq(subject.external_encoding)
|
1035
|
+
end
|
1036
|
+
end
|
1037
|
+
end
|
1038
|
+
|
1039
|
+
describe "#readlines" do
|
1040
|
+
it "should read all lines" do
|
1041
|
+
expect(subject.readlines).to eq(lines)
|
1042
|
+
end
|
1043
|
+
|
1044
|
+
it "must set the encoding of the String to Encoding.default_external" do
|
1045
|
+
expect(subject.readlines.map(&:encoding)).to all(eq(Encoding.default_external))
|
1046
|
+
end
|
1047
|
+
|
1048
|
+
context "when #external_encoding diffs from Encoding.default_external" do
|
1049
|
+
let(:external_encoding) { Encoding::ASCII_8BIT }
|
1050
|
+
|
1051
|
+
before { subject.external_encoding = external_encoding }
|
1052
|
+
|
1053
|
+
it "must set the encoding of the String to #external_encoding" do
|
1054
|
+
expect(subject.readlines.map(&:encoding)).to all(eq(subject.external_encoding))
|
1055
|
+
end
|
1056
|
+
end
|
1057
|
+
end
|
1058
|
+
|
1059
|
+
describe "#each_byte" do
|
1060
|
+
it "should read each byte of data" do
|
1061
|
+
expect(subject.each_byte.to_a).to eq(bytes)
|
1062
|
+
end
|
1063
|
+
end
|
1064
|
+
|
1065
|
+
describe "#each_char" do
|
1066
|
+
context "when a block is given" do
|
1067
|
+
it "must yield each read char of the data" do
|
1068
|
+
expect { |b|
|
1069
|
+
subject.each_char(&b)
|
1070
|
+
}.to yield_successive_args(*chars)
|
1071
|
+
end
|
1072
|
+
end
|
1073
|
+
|
1074
|
+
context "when no block is given" do
|
1075
|
+
it "must return an Enumerator that read each char of data" do
|
1076
|
+
expect(subject.each_char.to_a).to eq(chars)
|
1077
|
+
end
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
it "must set the encoding of the String to Encoding.default_external" do
|
1081
|
+
expect(subject.each_char.map(&:encoding)).to all(eq(Encoding.default_external))
|
1082
|
+
end
|
1083
|
+
|
1084
|
+
context "when #external_encoding diffs from Encoding.default_external" do
|
1085
|
+
let(:external_encoding) { Encoding::ASCII_8BIT }
|
1086
|
+
|
1087
|
+
before { subject.external_encoding = external_encoding }
|
1088
|
+
|
1089
|
+
it "must set the encoding of the String to #external_encoding" do
|
1090
|
+
expect(subject.each_char.map(&:encoding)).to all(eq(subject.external_encoding))
|
1091
|
+
end
|
1092
|
+
end
|
1093
|
+
end
|
1094
|
+
|
1095
|
+
describe "#each_line" do
|
1096
|
+
it "should read each line of data" do
|
1097
|
+
expect(subject.each_line.to_a).to eq(lines)
|
1098
|
+
end
|
1099
|
+
|
1100
|
+
it "must set the encoding of the String to Encoding.default_external" do
|
1101
|
+
expect(subject.each_line.map(&:encoding)).to all(eq(Encoding.default_external))
|
1102
|
+
end
|
1103
|
+
|
1104
|
+
context "when #external_encoding diffs from Encoding.default_external" do
|
1105
|
+
let(:external_encoding) { Encoding::ASCII_8BIT }
|
1106
|
+
|
1107
|
+
before { subject.external_encoding = external_encoding }
|
1108
|
+
|
1109
|
+
it "must set the encoding of the String to #external_encoding" do
|
1110
|
+
expect(subject.each_line.map(&:encoding)).to all(eq(subject.external_encoding))
|
1111
|
+
end
|
1112
|
+
end
|
1113
|
+
end
|
1114
|
+
|
1115
|
+
describe "#write" do
|
1116
|
+
let(:data) { "foo" }
|
1117
|
+
|
1118
|
+
it "must call #io_write with the data" do
|
1119
|
+
expect(subject).to receive(:io_write).with(data)
|
1120
|
+
|
1121
|
+
subject.write(data)
|
1122
|
+
end
|
1123
|
+
|
1124
|
+
context "when the given data is not a String" do
|
1125
|
+
let(:data) { :foo }
|
1126
|
+
|
1127
|
+
it "must convert the data to a String before calling #io_write" do
|
1128
|
+
expect(subject).to receive(:io_write).with(data.to_s)
|
1129
|
+
|
1130
|
+
subject.write(data)
|
1131
|
+
end
|
1132
|
+
end
|
1133
|
+
|
1134
|
+
context "when #internal_encoding is not nil" do
|
1135
|
+
let(:internal_encoding) { Encoding::ASCII_8BIT }
|
1136
|
+
let(:encoded_data) { data.encode(internal_encoding) }
|
1137
|
+
|
1138
|
+
before { subject.internal_encoding = internal_encoding }
|
1139
|
+
|
1140
|
+
it "it must convert the given data to #internal_encoding before calling #io_write" do
|
1141
|
+
expect(data).to receive(:force_encoding).with(internal_encoding).and_return(encoded_data)
|
1142
|
+
expect(subject).to receive(:io_write).with(encoded_data)
|
1143
|
+
|
1144
|
+
subject.write(data)
|
1145
|
+
end
|
1146
|
+
end
|
1147
|
+
|
1148
|
+
context "when the object is not opened for writing" do
|
1149
|
+
before { subject.close_write }
|
1150
|
+
|
1151
|
+
it do
|
1152
|
+
expect {
|
1153
|
+
subject.write(data)
|
1154
|
+
}.to raise_error(IOError,"closed for writing")
|
1155
|
+
end
|
1156
|
+
end
|
1157
|
+
end
|
1158
|
+
|
1159
|
+
describe "#to_io" do
|
1160
|
+
it "must return self" do
|
1161
|
+
expect(subject.to_io).to be(subject)
|
1162
|
+
end
|
1163
|
+
end
|
1164
|
+
|
1165
|
+
describe "#inspect" do
|
1166
|
+
let(:fd) { subject.instance_variable_get('@fd') }
|
1167
|
+
|
1168
|
+
it "must return the inspected object as a string, including the @fd" do
|
1169
|
+
expect(subject.inspect).to eq("#<#{subject.class}: #{fd}>")
|
1170
|
+
end
|
1171
|
+
end
|
1172
|
+
|
1173
|
+
context "when running under Ruby 2.x" do
|
1174
|
+
if RUBY_VERSION < '3.'
|
1175
|
+
it "must define #bytes" do
|
1176
|
+
expect(subject).to respond_to(:bytes)
|
1177
|
+
end
|
1178
|
+
|
1179
|
+
it "must define #chars" do
|
1180
|
+
expect(subject).to respond_to(:chars)
|
1181
|
+
end
|
1182
|
+
|
1183
|
+
it "must define #codepoints" do
|
1184
|
+
expect(subject).to respond_to(:codepoints)
|
1185
|
+
end
|
1186
|
+
|
1187
|
+
it "must define #lines" do
|
1188
|
+
expect(subject).to respond_to(:lines)
|
1189
|
+
end
|
1190
|
+
end
|
1191
|
+
end
|
1192
|
+
|
1193
|
+
context "when running under Ruby 3.x" do
|
1194
|
+
if RUBY_VERSION > '3.'
|
1195
|
+
it "must not define #bytes" do
|
1196
|
+
expect(subject).to_not respond_to(:bytes)
|
1197
|
+
end
|
1198
|
+
|
1199
|
+
it "must not define #chars" do
|
1200
|
+
expect(subject).to_not respond_to(:chars)
|
1201
|
+
end
|
1202
|
+
|
1203
|
+
it "must not define #codepoints" do
|
1204
|
+
expect(subject).to_not respond_to(:codepoints)
|
1205
|
+
end
|
1206
|
+
|
1207
|
+
it "must not define #lines" do
|
1208
|
+
expect(subject).to_not respond_to(:lines)
|
1209
|
+
end
|
1210
|
+
end
|
1211
|
+
end
|
1212
|
+
end
|