* 2022-01-18 [ci skip]
[ruby-80x24.org.git] / test / stringio / test_stringio.rb
blobe0b4504b541b962025206b0f8a34c1bceaf62318
1 # frozen_string_literal: false
2 require 'test/unit'
3 require 'stringio'
4 require "rbconfig/sizeof"
5 require_relative '../ruby/ut_eof'
7 class TestStringIO < Test::Unit::TestCase
8   include TestEOF
9   def open_file(content)
10     f = StringIO.new(content)
11     yield f
12   end
13   alias open_file_rw open_file
15   include TestEOF::Seek
17   def test_initialize
18     assert_kind_of StringIO, StringIO.new
19     assert_kind_of StringIO, StringIO.new('str')
20     assert_kind_of StringIO, StringIO.new('str', 'r+')
21     assert_raise(ArgumentError) { StringIO.new('', 'x') }
22     assert_raise(ArgumentError) { StringIO.new('', 'rx') }
23     assert_raise(ArgumentError) { StringIO.new('', 'rbt') }
24     assert_raise(TypeError) { StringIO.new(nil) }
26     o = Object.new
27     def o.to_str
28       nil
29     end
30     assert_raise(TypeError) { StringIO.new(o) }
32     o = Object.new
33     def o.to_str
34       'str'
35     end
36     assert_kind_of StringIO, StringIO.new(o)
37   end
39   def test_truncate
40     io = StringIO.new("")
41     io.puts "abc"
42     io.truncate(0)
43     io.puts "def"
44     assert_equal("\0\0\0\0def\n", io.string, "[ruby-dev:24190]")
45     assert_raise(Errno::EINVAL) { io.truncate(-1) }
46     io.truncate(10)
47     assert_equal("\0\0\0\0def\n\0\0", io.string)
48   end
50   def test_seek_beyond_eof
51     io = StringIO.new
52     n = 100
53     io.seek(n)
54     io.print "last"
55     assert_equal("\0" * n + "last", io.string, "[ruby-dev:24194]")
56   end
58   def test_overwrite
59     stringio = StringIO.new
60     responses = ['', 'just another ruby', 'hacker']
61     responses.each do |resp|
62       stringio.puts(resp)
63       stringio.rewind
64     end
65     assert_equal("hacker\nother ruby\n", stringio.string, "[ruby-core:3836]")
66   end
68   def test_gets
69     assert_equal(nil, StringIO.new("").gets)
70     assert_equal("\n", StringIO.new("\n").gets)
71     assert_equal("a\n", StringIO.new("a\n").gets)
72     assert_equal("a\n", StringIO.new("a\nb\n").gets)
73     assert_equal("a", StringIO.new("a").gets)
74     assert_equal("a\n", StringIO.new("a\nb").gets)
75     assert_equal("abc\n", StringIO.new("abc\n\ndef\n").gets)
76     assert_equal("abc\n\ndef\n", StringIO.new("abc\n\ndef\n").gets(nil))
77     assert_equal("abc\n\n", StringIO.new("abc\n\ndef\n").gets(""))
78     stringio = StringIO.new("abc\n\ndef\n")
79     assert_equal("abc\n\n", stringio.gets(""))
80     assert_equal("def\n", stringio.gets(""))
81     assert_raise(TypeError){StringIO.new("").gets(1, 1)}
82     assert_nothing_raised {StringIO.new("").gets(nil, nil)}
84     assert_string("", Encoding::UTF_8, StringIO.new("foo").gets(0))
85   end
87   def test_gets_chomp
88     assert_equal(nil, StringIO.new("").gets(chomp: true))
89     assert_equal("", StringIO.new("\n").gets(chomp: true))
90     assert_equal("a", StringIO.new("a\n").gets(chomp: true))
91     assert_equal("a", StringIO.new("a\nb\n").gets(chomp: true))
92     assert_equal("a", StringIO.new("a").gets(chomp: true))
93     assert_equal("a", StringIO.new("a\nb").gets(chomp: true))
94     assert_equal("abc", StringIO.new("abc\n\ndef\n").gets(chomp: true))
95     assert_equal("abc\n\ndef", StringIO.new("abc\n\ndef\n").gets(nil, chomp: true))
96     assert_equal("abc\n", StringIO.new("abc\n\ndef\n").gets("", chomp: true))
97     stringio = StringIO.new("abc\n\ndef\n")
98     assert_equal("abc\n", stringio.gets("", chomp: true))
99     assert_equal("def", stringio.gets("", chomp: true))
101     assert_string("", Encoding::UTF_8, StringIO.new("\n").gets(chomp: true))
102   end
104   def test_gets_chomp_eol
105     assert_equal(nil, StringIO.new("").gets(chomp: true))
106     assert_equal("", StringIO.new("\r\n").gets(chomp: true))
107     assert_equal("a", StringIO.new("a\r\n").gets(chomp: true))
108     assert_equal("a", StringIO.new("a\r\nb\r\n").gets(chomp: true))
109     assert_equal("a", StringIO.new("a").gets(chomp: true))
110     assert_equal("a", StringIO.new("a\r\nb").gets(chomp: true))
111     assert_equal("abc", StringIO.new("abc\r\n\r\ndef\r\n").gets(chomp: true))
112     assert_equal("abc\r\n\r\ndef", StringIO.new("abc\r\n\r\ndef\r\n").gets(nil, chomp: true))
113     assert_equal("abc\r\n", StringIO.new("abc\r\n\r\ndef\r\n").gets("", chomp: true))
114     stringio = StringIO.new("abc\r\n\r\ndef\r\n")
115     assert_equal("abc\r\n", stringio.gets("", chomp: true))
116     assert_equal("def", stringio.gets("", chomp: true))
117   end
119   def test_readlines
120     assert_equal([], StringIO.new("").readlines)
121     assert_equal(["\n"], StringIO.new("\n").readlines)
122     assert_equal(["a\n"], StringIO.new("a\n").readlines)
123     assert_equal(["a\n", "b\n"], StringIO.new("a\nb\n").readlines)
124     assert_equal(["a"], StringIO.new("a").readlines)
125     assert_equal(["a\n", "b"], StringIO.new("a\nb").readlines)
126     assert_equal(["abc\n", "\n", "def\n"], StringIO.new("abc\n\ndef\n").readlines)
127     assert_equal(["abc\n\ndef\n"], StringIO.new("abc\n\ndef\n").readlines(nil), "[ruby-dev:34591]")
128     assert_equal(["abc\n\n", "def\n"], StringIO.new("abc\n\ndef\n").readlines(""))
129   end
131   def test_write
132     s = ""
133     f = StringIO.new(s, "w")
134     f.print("foo")
135     f.close
136     assert_equal("foo", s)
138     f = StringIO.new(s, File::WRONLY)
139     f.print("bar")
140     f.close
141     assert_equal("bar", s)
143     f = StringIO.new(s, "a")
144     o = Object.new
145     def o.to_s; "baz"; end
146     f.print(o)
147     f.close
148     assert_equal("barbaz", s)
149   ensure
150     f.close unless f.closed?
151   end
153   def test_write_nonblock_no_exceptions
154     s = ""
155     f = StringIO.new(s, "w")
156     f.write_nonblock("foo", exception: false)
157     f.close
158     assert_equal("foo", s)
159   end
161   def test_write_nonblock
162     s = ""
163     f = StringIO.new(s, "w")
164     f.write_nonblock("foo")
165     f.close
166     assert_equal("foo", s)
168     f = StringIO.new(s, File::WRONLY)
169     f.write_nonblock("bar")
170     f.close
171     assert_equal("bar", s)
173     f = StringIO.new(s, "a")
174     o = Object.new
175     def o.to_s; "baz"; end
176     f.write_nonblock(o)
177     f.close
178     assert_equal("barbaz", s)
179   ensure
180     f.close unless f.closed?
181   end
183   def test_write_encoding
184     s = "".force_encoding(Encoding::UTF_8)
185     f = StringIO.new(s)
186     f.print("\u{3053 3093 306b 3061 306f ff01}".b)
187     assert_equal(Encoding::UTF_8, s.encoding, "honor the original encoding over ASCII-8BIT")
188   end
190   def test_write_encoding_conversion
191     convertible = "\u{3042}"
192     inconvertible = "\u{1f363}"
193     conversion_encoding = Encoding::Windows_31J
195     s = StringIO.new.set_encoding(conversion_encoding)
196     s.write(convertible)
197     assert_equal(conversion_encoding, s.string.encoding)
199     s = StringIO.new.set_encoding(Encoding::UTF_8)
200     s.write("foo".force_encoding("ISO-8859-1"), convertible)
201     assert_equal(Encoding::UTF_8, s.string.encoding)
203     s = StringIO.new.set_encoding(Encoding::US_ASCII)
204     s.write("foo".force_encoding("US-ASCII"), convertible)
205     assert_equal(Encoding::UTF_8, s.string.encoding)
207     all_assertions do |a|
208       [
209         inconvertible,
210         convertible + inconvertible,
211         [convertible, inconvertible],
212         ["a", inconvertible],
213       ].each do |data|
214         a.for(data.inspect) do
215           s = StringIO.new.set_encoding(conversion_encoding)
216           assert_raise(Encoding::CompatibilityError) do
217             s.write(*data)
218           end
219         end
220       end
221     end
222   end
224   def test_write_integer_overflow
225     f = StringIO.new
226     f.pos = RbConfig::LIMITS["LONG_MAX"]
227     assert_raise(ArgumentError) {
228       f.write("pos + len overflows")
229     }
230   end
232   def test_write_with_multiple_arguments
233     s = ""
234     f = StringIO.new(s, "w")
235     f.write("foo", "bar")
236     f.close
237     assert_equal("foobar", s)
238   ensure
239     f.close unless f.closed?
240   end
242   def test_set_encoding
243     bug10285 = '[ruby-core:65240] [Bug #10285]'
244     f = StringIO.new()
245     f.set_encoding(Encoding::ASCII_8BIT)
246     f.write("quz \x83 mat".b)
247     s = "foo \x97 bar".force_encoding(Encoding::WINDOWS_1252)
248     assert_nothing_raised(Encoding::CompatibilityError, bug10285) {
249       f.write(s)
250     }
251     assert_equal(Encoding::ASCII_8BIT, f.string.encoding, bug10285)
253     bug11827 = '[ruby-core:72189] [Bug #11827]'
254     f = StringIO.new("foo\x83".freeze)
255     assert_nothing_raised(RuntimeError, bug11827) {
256       f.set_encoding(Encoding::ASCII_8BIT)
257     }
258     assert_equal("foo\x83".b, f.gets)
259   end
261   def test_mode_error
262     f = StringIO.new("", "r")
263     assert_raise(IOError) { f.write("foo") }
265     f = StringIO.new("", "w")
266     assert_raise(IOError) { f.read }
268     assert_raise(Errno::EACCES) { StringIO.new("".freeze, "w") }
269     s = ""
270     f = StringIO.new(s, "w")
271     s.freeze
272     assert_raise(IOError) { f.write("foo") }
274     assert_raise(IOError) { StringIO.allocate.read }
275   ensure
276     f.close unless f.closed?
277   end
279   def test_open
280     s = ""
281     StringIO.open("foo") {|f| s = f.read }
282     assert_equal("foo", s)
283   end
285   def test_isatty
286     assert_equal(false, StringIO.new("").isatty)
287   end
289   def test_fsync
290     assert_equal(0, StringIO.new("").fsync)
291   end
293   def test_sync
294     assert_equal(true, StringIO.new("").sync)
295     assert_equal(false, StringIO.new("").sync = false)
296   end
298   def test_set_fcntl
299     assert_raise(NotImplementedError) { StringIO.new("").fcntl }
300   end
302   def test_close
303     f = StringIO.new("")
304     f.close
305     assert_nil(f.close)
307     f = StringIO.new("")
308     f.close_read
309     f.close_write
310     assert_nil(f.close)
311   ensure
312     f.close unless f.closed?
313   end
315   def test_close_read
316     f = StringIO.new("")
317     f.close_read
318     assert_raise(IOError) { f.read }
319     assert_nothing_raised(IOError) {f.close_read}
320     f.close
322     f = StringIO.new("", "w")
323     assert_raise(IOError) { f.close_read }
324     f.close
325   ensure
326     f.close unless f.closed?
327   end
329   def test_close_write
330     f = StringIO.new("")
331     f.close_write
332     assert_raise(IOError) { f.write("foo") }
333     assert_nothing_raised(IOError) {f.close_write}
334     f.close
336     f = StringIO.new("", "r")
337     assert_raise(IOError) { f.close_write }
338     f.close
339   ensure
340     f.close unless f.closed?
341   end
343   def test_closed
344     f = StringIO.new("")
345     assert_equal(false, f.closed?)
346     f.close
347     assert_equal(true, f.closed?)
348   ensure
349     f.close unless f.closed?
350   end
352   def test_closed_read
353     f = StringIO.new("")
354     assert_equal(false, f.closed_read?)
355     f.close_write
356     assert_equal(false, f.closed_read?)
357     f.close_read
358     assert_equal(true, f.closed_read?)
359   ensure
360     f.close unless f.closed?
361   end
363   def test_closed_write
364     f = StringIO.new("")
365     assert_equal(false, f.closed_write?)
366     f.close_read
367     assert_equal(false, f.closed_write?)
368     f.close_write
369     assert_equal(true, f.closed_write?)
370   ensure
371     f.close unless f.closed?
372   end
374   def test_dup
375     f1 = StringIO.new("1234")
376     assert_equal("1", f1.getc)
377     f2 = f1.dup
378     assert_equal("2", f2.getc)
379     assert_equal("3", f1.getc)
380     assert_equal("4", f2.getc)
381     assert_equal(nil, f1.getc)
382     assert_equal(true, f2.eof?)
383     f1.close
384     assert_equal(false, f2.closed?, '[ruby-core:48443]')
385   ensure
386     f1.close unless f1.closed?
387     f2.close unless f2.closed?
388   end
390   def test_lineno
391     f = StringIO.new("foo\nbar\nbaz\n")
392     assert_equal([0, "foo\n"], [f.lineno, f.gets])
393     assert_equal([1, "bar\n"], [f.lineno, f.gets])
394     f.lineno = 1000
395     assert_equal([1000, "baz\n"], [f.lineno, f.gets])
396     assert_equal([1001, nil], [f.lineno, f.gets])
397   ensure
398     f.close unless f.closed?
399   end
401   def test_pos
402     f = StringIO.new("foo\nbar\nbaz\n")
403     assert_equal([0, "foo\n"], [f.pos, f.gets])
404     assert_equal([4, "bar\n"], [f.pos, f.gets])
405     assert_raise(Errno::EINVAL) { f.pos = -1 }
406     f.pos = 1
407     assert_equal([1, "oo\n"], [f.pos, f.gets])
408     assert_equal([4, "bar\n"], [f.pos, f.gets])
409     assert_equal([8, "baz\n"], [f.pos, f.gets])
410     assert_equal([12, nil], [f.pos, f.gets])
411   ensure
412     f.close unless f.closed?
413   end
415   def test_reopen
416     f = StringIO.new("foo\nbar\nbaz\n")
417     assert_equal("foo\n", f.gets)
418     f.reopen("qux\nquux\nquuux\n")
419     assert_equal("qux\n", f.gets)
421     f2 = StringIO.new("")
422     f2.reopen(f)
423     assert_equal("quux\n", f2.gets)
424   ensure
425     f.close unless f.closed?
426   end
428   def test_seek
429     f = StringIO.new("1234")
430     assert_raise(Errno::EINVAL) { f.seek(-1) }
431     f.seek(-1, 2)
432     assert_equal("4", f.getc)
433     assert_raise(Errno::EINVAL) { f.seek(1, 3) }
434     f.close
435     assert_raise(IOError) { f.seek(0) }
436   ensure
437     f.close unless f.closed?
438   end
440   def test_each_byte
441     f = StringIO.new("1234")
442     a = []
443     f.each_byte {|c| a << c }
444     assert_equal(%w(1 2 3 4).map {|c| c.ord }, a)
445   ensure
446     f.close unless f.closed?
447   end
449   def test_each_byte_closed
450     f = StringIO.new("1234")
451     assert_equal("1".ord, f.each_byte {|c| f.close; break c })
452     f = StringIO.new("1234")
453     assert_raise(IOError) do
454       f.each_byte { f.close }
455     end
456   end
458   def test_getbyte
459     f = StringIO.new("1234")
460     assert_equal("1".ord, f.getbyte)
461     assert_equal("2".ord, f.getbyte)
462     assert_equal("3".ord, f.getbyte)
463     assert_equal("4".ord, f.getbyte)
464     assert_equal(nil, f.getbyte)
465   ensure
466     f.close unless f.closed?
467   end
469   def test_ungetbyte
470     s = "foo\nbar\n"
471     t = StringIO.new(s, "r")
472     t.ungetbyte(0x41)
473     assert_equal(0x41, t.getbyte)
474     t.ungetbyte("qux")
475     assert_equal("quxfoo\n", t.gets)
476     t.set_encoding("utf-8")
477     t.ungetbyte(0x89)
478     t.ungetbyte(0x8e)
479     t.ungetbyte("\xe7")
480     t.ungetbyte("\xe7\xb4\x85")
481     assert_equal("\u7d05\u7389bar\n", t.gets)
482     assert_equal("q\u7d05\u7389bar\n", s)
483     t.pos = 1
484     t.ungetbyte("\u{30eb 30d3 30fc}")
485     assert_equal(0, t.pos)
486     assert_equal("\u{30eb 30d3 30fc}\u7d05\u7389bar\n", s)
488     assert_nothing_raised {t.ungetbyte(-1)}
489     assert_nothing_raised {t.ungetbyte(256)}
490     assert_nothing_raised {t.ungetbyte(1<<64)}
491   end
493   def test_ungetc
494     s = "1234"
495     f = StringIO.new(s, "r")
496     assert_nothing_raised { f.ungetc("x") }
497     assert_equal("x", f.getc) # bug? -> it's a feature from 1.9.
498     assert_equal("1", f.getc)
500     s = "1234"
501     f = StringIO.new(s, "r")
502     assert_equal("1", f.getc)
503     f.ungetc("y".ord)
504     assert_equal("y", f.getc)
505     assert_equal("2", f.getc)
507     assert_raise(RangeError) {f.ungetc(0x1ffffff)}
508     assert_raise(RangeError) {f.ungetc(0xffffffffffffff)}
509   ensure
510     f.close unless f.closed?
511   end
513   def test_readchar
514     f = StringIO.new("1234")
515     a = ""
516     assert_raise(EOFError) { loop { a << f.readchar } }
517     assert_equal("1234", a)
518   end
520   def test_readbyte
521     f = StringIO.new("1234")
522     a = []
523     assert_raise(EOFError) { loop { a << f.readbyte } }
524     assert_equal("1234".unpack("C*"), a)
525   end
527   def test_each_char
528     f = StringIO.new("1234")
529     assert_equal(%w(1 2 3 4), f.each_char.to_a)
530   end
532   def test_each_char_closed
533     f = StringIO.new("1234")
534     assert_equal("1", f.each_char {|c| f.close; break c })
535     f = StringIO.new("1234")
536     assert_raise(IOError) do
537       f.each_char { f.close }
538     end
539   end
541   def test_each_codepoint
542     f = StringIO.new("1234")
543     assert_equal([49, 50, 51, 52], f.each_codepoint.to_a)
544   end
546   def test_each_codepoint_closed
547     f = StringIO.new("1234")
548     assert_equal("1".ord, f.each_codepoint {|c| f.close; break c })
549     f = StringIO.new("1234")
550     assert_raise(IOError) do
551       f.each_codepoint { f.close }
552     end
553   end
555   def test_each_codepoint_enumerator
556     io = StringIO.new('你好построить')
558     chinese_part = io.each_codepoint.take(2).pack('U*')
559     russian_part = io.read(40).force_encoding('UTF-8')
561     assert_equal("你好", chinese_part)
562     assert_equal("построить", russian_part)
563   end
565   def test_gets2
566     f = StringIO.new("foo\nbar\nbaz\n")
567     assert_equal("fo", f.gets(2))
569     o = Object.new
570     def o.to_str; "z"; end
571     assert_equal("o\nbar\nbaz", f.gets(o))
573     f = StringIO.new("foo\nbar\nbaz\n")
574     assert_equal("foo\nbar\nbaz", f.gets("az"))
575     f = StringIO.new("a" * 10000 + "zz!")
576     assert_equal("a" * 10000 + "zz", f.gets("zz"))
577     f = StringIO.new("a" * 10000 + "zz!")
578     assert_equal("a" * 10000 + "zz!", f.gets("zzz"))
580     bug4112 = '[ruby-dev:42674]'
581     ["a".encode("utf-16be"), "\u3042"].each do |s|
582       assert_equal(s, StringIO.new(s).gets(1), bug4112)
583       assert_equal(s, StringIO.new(s).gets(nil, 1), bug4112)
584     end
585   end
587   def test_each
588     f = StringIO.new("foo\nbar\nbaz\n")
589     assert_equal(["foo\n", "bar\n", "baz\n"], f.each.to_a)
590     f.rewind
591     assert_equal(["foo", "bar", "baz"], f.each(chomp: true).to_a)
592     f = StringIO.new("foo\nbar\n\nbaz\n")
593     assert_equal(["foo\nbar\n\n", "baz\n"], f.each("").to_a)
594     f.rewind
595     assert_equal(["foo\nbar\n", "baz"], f.each("", chomp: true).to_a)
597     f = StringIO.new("foo\r\nbar\r\n\r\nbaz\r\n")
598     assert_equal(["foo\r\nbar\r\n\r\n", "baz\r\n"], f.each("").to_a)
599     f.rewind
600     assert_equal(["foo\r\nbar\r\n", "baz"], f.each("", chomp: true).to_a)
601   end
603   def test_putc
604     s = ""
605     f = StringIO.new(s, "w")
606     f.putc("1")
607     f.putc("2")
608     f.putc("3")
609     f.close
610     assert_equal("123", s)
612     s = "foo"
613     f = StringIO.new(s, "a")
614     f.putc("1")
615     f.putc("2")
616     f.putc("3")
617     f.close
618     assert_equal("foo123", s)
619   end
621   def test_putc_nonascii
622     s = ""
623     f = StringIO.new(s, "w")
624     f.putc("\u{3042}")
625     f.putc(0x3044)
626     f.close
627     assert_equal("\u{3042}D", s)
629     s = "foo"
630     f = StringIO.new(s, "a")
631     f.putc("\u{3042}")
632     f.putc(0x3044)
633     f.close
634     assert_equal("foo\u{3042}D", s)
635   end
637   def test_read
638     f = StringIO.new("\u3042\u3044")
639     assert_raise(ArgumentError) { f.read(-1) }
640     assert_raise(ArgumentError) { f.read(1, 2, 3) }
641     assert_equal("\u3042\u3044", f.read)
642     assert_nil(f.read(1))
643     f.rewind
644     assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.read(f.size))
646     bug5207 = '[ruby-core:39026]'
647     f.rewind
648     assert_equal("\u3042\u3044", f.read(nil, nil), bug5207)
649     f.rewind
650     s = ""
651     assert_same(s, f.read(nil, s))
652     assert_equal("\u3042\u3044", s, bug5207)
653     f.rewind
654     # not empty buffer
655     s = "0123456789"
656     assert_same(s, f.read(nil, s))
657     assert_equal("\u3042\u3044", s)
659     bug13806 = '[ruby-core:82349] [Bug #13806]'
660     assert_string("", Encoding::UTF_8, f.read, bug13806)
661     assert_string("", Encoding::UTF_8, f.read(nil, nil), bug13806)
662     s.force_encoding(Encoding::US_ASCII)
663     assert_same(s, f.read(nil, s))
664     assert_string("", Encoding::UTF_8, s, bug13806)
665   end
667   def test_readpartial
668     f = StringIO.new("\u3042\u3044")
669     assert_raise(ArgumentError) { f.readpartial(-1) }
670     assert_raise(ArgumentError) { f.readpartial(1, 2, 3) }
671     assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.readpartial(100))
672     f.rewind
673     assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.readpartial(f.size))
674     f.rewind
675     # not empty buffer
676     s = '0123456789'
677     assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.readpartial(f.size, s))
678   end
680   def test_read_nonblock
681     f = StringIO.new("\u3042\u3044")
682     assert_raise(ArgumentError) { f.read_nonblock(-1) }
683     assert_raise(ArgumentError) { f.read_nonblock(1, 2, 3) }
684     assert_equal("\u3042\u3044".force_encoding("BINARY"), f.read_nonblock(100))
685     assert_raise(EOFError) { f.read_nonblock(10) }
686     f.rewind
687     assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.read_nonblock(f.size))
688   end
690   def test_read_nonblock_no_exceptions
691     f = StringIO.new("\u3042\u3044")
692     assert_raise(ArgumentError) { f.read_nonblock(-1, exception: false) }
693     assert_raise(ArgumentError) { f.read_nonblock(1, 2, 3, exception: false) }
694     assert_raise(ArgumentError) { f.read_nonblock }
695     assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.read_nonblock(100, exception: false))
696     assert_equal(nil, f.read_nonblock(10, exception: false))
697     f.rewind
698     assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.read_nonblock(f.size))
699     f.rewind
700     # not empty buffer
701     s = '0123456789'
702     assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.read_nonblock(f.size, s))
703   end
705   def test_sysread
706     f = StringIO.new("sysread \u{30c6 30b9 30c8}")
707     assert_equal "sysread \u{30c6 30b9 30c8}", f.sysread
708     assert_equal "", f.sysread
709     assert_raise(EOFError) { f.sysread(1) }
710     f.rewind
711     assert_equal Encoding::ASCII_8BIT, f.sysread(3).encoding
712   end
714   def test_size
715     f = StringIO.new("1234")
716     assert_equal(4, f.size)
717   end
719   # This test is should in ruby/test_method.rb
720   # However this test depends on stringio library,
721   # we write it here.
722   class C < StringIO
723     alias old_init initialize
724     attr_reader :foo
725     def initialize
726       @foo = :ok
727       old_init
728     end
729   end
731   def test_method
732     assert_equal(:ok, C.new.foo, 'Bug #632 [ruby-core:19282]')
733   end
735   def test_ungetc_pos
736     b = '\\b00010001 \\B00010001 \\b1 \\B1 \\b000100011'
737     s = StringIO.new( b )
738     expected_pos = 0
739     while n = s.getc
740       assert_equal( expected_pos + 1, s.pos )
742       s.ungetc( n )
743       assert_equal( expected_pos, s.pos )
744       assert_equal( n, s.getc )
746       expected_pos += 1
747     end
748   end
750   def test_ungetc_padding
751     s = StringIO.new()
752     s.pos = 2
753     s.ungetc("a")
754     assert_equal("\0""a", s.string)
755     s.pos = 0
756     s.ungetc("b")
757     assert_equal("b""\0""a", s.string)
758   end
760   def test_ungetbyte_pos
761     b = '\\b00010001 \\B00010001 \\b1 \\B1 \\b000100011'
762     s = StringIO.new( b )
763     expected_pos = 0
764     while n = s.getbyte
765       assert_equal( expected_pos + 1, s.pos )
767       s.ungetbyte( n )
768       assert_equal( expected_pos, s.pos )
769       assert_equal( n, s.getbyte )
771       expected_pos += 1
772     end
773   end
775   def test_ungetbyte_padding
776     s = StringIO.new()
777     s.pos = 2
778     s.ungetbyte("a".ord)
779     assert_equal("\0""a", s.string)
780     s.pos = 0
781     s.ungetbyte("b".ord)
782     assert_equal("b""\0""a", s.string)
783   end
785   def test_frozen
786     s = StringIO.new
787     s.freeze
788     bug = '[ruby-core:33648]'
789     exception_class = defined?(FrozenError) ? FrozenError : RuntimeError
790     assert_raise(exception_class, bug) {s.puts("foo")}
791     assert_raise(exception_class, bug) {s.string = "foo"}
792     assert_raise(exception_class, bug) {s.reopen("")}
793   end
795   def test_frozen_string
796     s = StringIO.new("".freeze)
797     bug = '[ruby-core:48530]'
798     assert_raise(IOError, bug) {s.write("foo")}
799     assert_raise(IOError, bug) {s.ungetc("a")}
800     assert_raise(IOError, bug) {s.ungetbyte("a")}
801   end
803   def test_readlines_limit_0
804     assert_raise(ArgumentError, "[ruby-dev:43392]") { StringIO.new.readlines(0) }
805   end
807   def test_each_line_limit_0
808     assert_raise(ArgumentError, "[ruby-dev:43392]") { StringIO.new.each_line(0){} }
809     assert_raise(ArgumentError, "[ruby-dev:43392]") { StringIO.new.each_line("a",0){} }
810   end
812   def test_binmode
813     s = StringIO.new
814     s.set_encoding('utf-8')
815     assert_same s, s.binmode
817     bug_11945 = '[ruby-core:72699] [Bug #11945]'
818     assert_equal Encoding::ASCII_8BIT, s.external_encoding, bug_11945
819   end
821   def test_new_block_warning
822     assert_warn(/does not take block/) do
823       StringIO.new {}
824     end
825   end
827   def test_overflow
828     omit if RbConfig::SIZEOF["void*"] > RbConfig::SIZEOF["long"]
829     limit = RbConfig::LIMITS["INTPTR_MAX"] - 0x10
830     assert_separately(%w[-rstringio], "#{<<-"begin;"}\n#{<<-"end;"}")
831     begin;
832       limit = #{limit}
833       ary = []
834       while true
835         x = "a"*0x100000
836         break if [x].pack("p").unpack("i!")[0] < 0
837         ary << x
838         omit if ary.size > 100
839       end
840       s = StringIO.new(x)
841       s.gets("xxx", limit)
842       assert_equal(0x100000, s.pos)
843     end;
844   end
846   def test_encoding_write
847     s = StringIO.new("", "w:utf-32be")
848     s.print "abc"
849     assert_equal("abc".encode("utf-32be"), s.string)
850   end
852   def test_encoding_read
853     s = StringIO.new("abc".encode("utf-32be"), "r:utf-8")
854     assert_equal("\0\0\0a\0\0\0b\0\0\0c", s.read)
855   end
857   %w/UTF-8 UTF-16BE UTF-16LE UTF-32BE UTF-32LE/.each do |name|
858     define_method("test_strip_bom:#{name}") do
859       text = "\uFEFF\u0100a"
860       content = text.encode(name)
861       result = StringIO.new(content, mode: 'rb:BOM|UTF-8').read
862       assert_equal(Encoding.find(name), result.encoding, name)
863       assert_equal(content[1..-1].b, result.b, name)
865       StringIO.open(content) {|f|
866         assert_equal(Encoding.find(name), f.set_encoding_by_bom)
867       }
868     end
869   end
871   def test_binary_encoding_read_and_default_internal
872     verbose, $VERBOSE = $VERBOSE, nil
873     default_internal = Encoding.default_internal
874     Encoding.default_internal = Encoding::UTF_8
875     $VERBOSE = verbose
876     assert_equal Encoding::BINARY, StringIO.new("Hello".b).read.encoding
877   ensure
878     $VERBOSE = nil
879     Encoding.default_internal = default_internal
880     $VERBOSE = verbose
881   end
883   def assert_string(content, encoding, str, mesg = nil)
884     assert_equal([content, encoding], [str, str.encoding], mesg)
885   end