@@ -14,6 +14,24 @@ def open_file(content)
1414
1515 include TestEOF ::Seek
1616
17+ def test_do_not_mutate_shared_buffers
18+ # Ensure we have two strings that are not embedded but have the same shared
19+ # string reference.
20+ #
21+ # In this case, we must use eval because we need two strings literals that
22+ # are long enough they cannot be embedded, but also contain the same bytes.
23+
24+ a = eval ( "+" +( "x" * 1024 ) . dump )
25+ b = eval ( "+" +( "x" * 1024 ) . dump )
26+
27+ s = StringIO . new ( b )
28+ s . getc
29+ s . ungetc '#'
30+
31+ # We mutated b, so a should not be mutated
32+ assert_equal ( "x" , a [ 0 ] )
33+ end
34+
1735 def test_version
1836 assert_kind_of ( String , StringIO ::VERSION )
1937 end
@@ -46,6 +64,35 @@ def test_null
4664 assert_nil io . gets
4765 io . puts "abc"
4866 assert_nil io . string
67+
68+ # Null device StringIO just drop ungot string
69+ io . ungetc '#'
70+ assert_nil io . getc
71+ end
72+
73+ def test_eof_null
74+ io = StringIO . new ( nil )
75+ assert_predicate io , :eof?
76+ end
77+
78+ def test_pread_null
79+ io = StringIO . new ( nil )
80+ assert_raise ( EOFError ) { io . pread ( 1 , 0 ) }
81+ end
82+
83+ def test_read_null
84+ io = StringIO . new ( nil )
85+ assert_equal "" , io . read ( 0 )
86+ end
87+
88+ def test_seek_null
89+ io = StringIO . new ( nil )
90+ assert_equal ( 0 , io . seek ( 0 , IO ::SEEK_SET ) )
91+ assert_equal ( 0 , io . pos )
92+ assert_equal ( 0 , io . seek ( 0 , IO ::SEEK_CUR ) )
93+ assert_equal ( 0 , io . pos )
94+ assert_equal ( 0 , io . seek ( 0 , IO ::SEEK_END ) ) # This should not segfault
95+ assert_equal ( 0 , io . pos )
4996 end
5097
5198 def test_truncate
@@ -465,6 +512,11 @@ def test_seek
465512 f . close unless f . closed?
466513 end
467514
515+ def test_seek_frozen_string
516+ f = StringIO . new ( -"1234" )
517+ assert_equal ( 0 , f . seek ( 1 ) )
518+ end
519+
468520 def test_each_byte
469521 f = StringIO . new ( "1234" )
470522 a = [ ]
@@ -944,7 +996,7 @@ def test_overflow
944996 intptr_max = RbConfig ::LIMITS [ "INTPTR_MAX" ]
945997 return if intptr_max > StringIO ::MAX_LENGTH
946998 limit = intptr_max - 0x10
947- assert_separately ( %w[ -rstringio ] , "#{ <<-"begin;" } \n #{ <<-"end;" } " )
999+ assert_separately ( %w[ -W0 - rstringio] , "#{ <<-"begin;" } \n #{ <<-"end;" } " )
9481000 begin;
9491001 limit = #{ limit }
9501002 ary = []
@@ -1012,6 +1064,20 @@ def test_coderange_after_overwrite
10121064 assert_predicate ( s . string , :ascii_only? )
10131065 end
10141066
1067+ def test_coderange_after_read_into_buffer
1068+ s = StringIO . new ( "01234567890" . b )
1069+
1070+ buf = "¿Cómo estás? Ça va bien?"
1071+ assert_not_predicate ( buf , :ascii_only? )
1072+
1073+ assert_predicate ( s . string , :ascii_only? )
1074+
1075+ s . read ( 10 , buf )
1076+
1077+ assert_predicate ( buf , :ascii_only? )
1078+ assert_equal '0123456789' , buf
1079+ end
1080+
10151081 require "objspace"
10161082 if ObjectSpace . respond_to? ( :dump ) && ObjectSpace . dump ( eval ( %{"test"} ) ) . include? ( '"chilled":true' ) # Ruby 3.4+ chilled strings
10171083 def test_chilled_string
@@ -1030,6 +1096,13 @@ def test_chilled_string_string_set
10301096 assert_equal ( "test" , io . string )
10311097 assert_same ( chilled_string , io . string )
10321098 end
1099+
1100+ def test_chilled_string_set_enocoding
1101+ chilled_string = eval ( %{""} )
1102+ io = StringIO . new ( chilled_string )
1103+ assert_warning ( "" ) { io . set_encoding ( Encoding ::BINARY ) }
1104+ assert_same ( chilled_string , io . string )
1105+ end
10331106 end
10341107
10351108 private
0 commit comments