@@ -17,13 +17,23 @@ def test_accepts_ios_and_strings
1717 assert_equal "Hello world!" , io . read
1818 end
1919
20- def test_fails_if_io_is_neither_string_nor_io
20+ def test_rejects_invalid_io_types
2121 error = assert_raises ( ArgumentError ) { HTTP ::FormData ::CompositeIO . new ( %i[ hello world ] ) }
2222
2323 assert_includes error . message , ":hello"
2424 assert_includes error . message , "is neither a String nor an IO object"
2525 end
2626
27+ def test_error_message_contains_inspect
28+ obj = Object . new
29+ def obj . inspect = "INVALID_IO_INSPECT"
30+ def obj . to_s = "INVALID_IO_TO_S"
31+
32+ error = assert_raises ( ArgumentError ) { HTTP ::FormData ::CompositeIO . new ( [ obj ] ) }
33+
34+ assert_includes error . message , "INVALID_IO_INSPECT"
35+ end
36+
2737 def test_reads_all_data
2838 assert_equal "Hello world!" , @composite_io . read
2939 end
@@ -35,13 +45,13 @@ def test_reads_partial_data
3545 assert_equal "world!" , @composite_io . read ( 6 )
3646 end
3747
38- def test_returns_empty_string_when_no_data_retrieved
48+ def test_returns_empty_string_when_exhausted_without_length
3949 @composite_io . read
4050
4151 assert_equal "" , @composite_io . read
4252 end
4353
44- def test_returns_nil_when_no_partial_data_retrieved
54+ def test_returns_nil_when_exhausted_with_length
4555 @composite_io . read
4656
4757 assert_nil @composite_io . read ( 3 )
@@ -72,15 +82,15 @@ def test_fills_buffer_with_retrieved_content
7282 assert_equal "world!" , outbuf
7383 end
7484
75- def test_returns_nil_when_no_partial_data_retrieved_with_buffer
85+ def test_clears_buffer_when_exhausted_with_length
7686 outbuf = +"content"
7787 @composite_io . read
7888
7989 assert_nil @composite_io . read ( 3 , outbuf )
8090 assert_equal "" , outbuf
8191 end
8292
83- def test_returns_data_in_binary_encoding
93+ def test_returns_binary_encoding
8494 io = HTTP ::FormData ::CompositeIO . new ( %w[ Janko Marohnić ] )
8595
8696 assert_equal Encoding ::BINARY , io . read ( 5 ) . encoding
@@ -109,90 +119,62 @@ def test_rewinds_all_ios
109119 assert_equal "Hello world!" , @composite_io . read
110120 end
111121
112- def test_returns_sum_of_all_io_sizes
122+ def test_size_returns_sum_of_all_ios
113123 assert_equal 12 , @composite_io . size
114124 end
115125
116- def test_returns_zero_when_no_ios
117- empty = HTTP ::FormData ::CompositeIO . new ( [ ] )
118-
119- assert_equal 0 , empty . size
126+ def test_size_returns_zero_for_empty
127+ assert_equal 0 , HTTP ::FormData ::CompositeIO . new ( [ ] ) . size
120128 end
121129
122- # --- Kill mutations for CompositeIO#initialize ---
123-
124- # Kill: replacing io.is_a?(String) with nil/false/self.is_a?(String)/io.instance_of?(String)
125- # Verify that a String subclass is also converted to StringIO
126- def test_initialize_converts_string_subclass_to_io
127- str_subclass = Class . new ( String )
128- io = HTTP ::FormData ::CompositeIO . new ( [ str_subclass . new ( "hello" ) ] )
130+ # String subclass is also converted to StringIO
131+ def test_accepts_string_subclass
132+ io = HTTP ::FormData ::CompositeIO . new ( [ Class . new ( String ) . new ( "hello" ) ] )
129133
130134 assert_equal "hello" , io . read
131135 end
132136
133- # Kill: replacing io.respond_to?(:read) with nil/false
134- # Verify that an object responding to :read is accepted as-is
135- def test_initialize_accepts_custom_io_object
137+ # Object responding to :read is accepted as-is
138+ def test_accepts_custom_io_object
136139 custom_io = Class . new do
137- def initialize
138- @done = false
139- end
140+ def initialize = @done = false
140141
141142 def read ( length = nil , outbuf = nil )
142143 if @done
143144 length ? nil : ""
144145 else
145146 @done = true
146147 result = +"custom"
147- if outbuf
148- outbuf . replace ( result )
149- outbuf
150- else
151- result
152- end
148+ outbuf ? outbuf . replace ( result ) : result
153149 end
154150 end
155151
156152 def size = 6
157-
158- def rewind
159- @done = false
160- end
153+ def rewind = @done = false
161154 end . new
162155
163- io = HTTP ::FormData ::CompositeIO . new ( [ custom_io ] )
164-
165- assert_equal "custom" , io . read
156+ assert_equal "custom" , HTTP ::FormData ::CompositeIO . new ( [ custom_io ] ) . read
166157 end
167158
168- # Kill: @index = 0 replaced with @index = nil or removed
169- def test_initialize_starts_reading_from_beginning
170- io = HTTP ::FormData ::CompositeIO . new ( %w[ abc def ] )
171-
172- assert_equal "a" , io . read ( 1 )
159+ def test_starts_reading_from_beginning
160+ assert_equal "a" , HTTP ::FormData ::CompositeIO . new ( %w[ abc def ] ) . read ( 1 )
173161 end
174162
175- # Kill: @buffer = "".b replaced with something else
176- def test_read_partial_uses_internal_buffer_correctly
163+ def test_reads_across_io_boundaries
177164 io = HTTP ::FormData ::CompositeIO . new ( %w[ abc def ] )
178165
179166 assert_equal "ab" , io . read ( 2 )
180167 assert_equal "cd" , io . read ( 2 )
181168 assert_equal "ef" , io . read ( 2 )
182169 end
183170
184- # Kill: replacing current_io with nil or other mutation
185- def test_current_io_returns_nil_after_all_read
171+ def test_returns_nil_after_all_read_with_length
186172 io = HTTP ::FormData ::CompositeIO . new ( [ "a" ] )
187173 io . read
188174
189175 assert_nil io . read ( 1 )
190176 end
191177
192- # --- Kill mutations for CompositeIO#read ---
193-
194- # Kill: data unless length && data.empty? — various mutations
195- # When reading all with no length and there IS data
196178 def test_read_without_length_returns_string
197179 io = HTTP ::FormData ::CompositeIO . new ( [ "hello" ] )
198180 result = io . read
@@ -201,48 +183,15 @@ def test_read_without_length_returns_string
201183 assert_equal "hello" , result
202184 end
203185
204- # When reading all with no length and NO data left
205- def test_read_without_length_returns_empty_string_when_exhausted
206- io = HTTP ::FormData ::CompositeIO . new ( [ "hello" ] )
207- io . read
208- result = io . read
209-
210- assert_instance_of String , result
211- assert_equal "" , result
212- end
213-
214- # When reading with length and NO data left
215- def test_read_with_length_returns_nil_when_exhausted
216- io = HTTP ::FormData ::CompositeIO . new ( [ "hello" ] )
217- io . read
218- result = io . read ( 5 )
219-
220- assert_nil result
221- end
222-
223- # --- Kill mutations for CompositeIO#readpartial ---
224-
225- # Kill: chunk && !chunk.empty? mutations
226- # Read across IO boundary with exact length
227- def test_readpartial_advances_through_ios
228- io = HTTP ::FormData ::CompositeIO . new ( %w[ ab cd ef ] )
229-
230- assert_equal "abcdef" , io . read
186+ def test_advances_through_ios
187+ assert_equal "abcdef" , HTTP ::FormData ::CompositeIO . new ( %w[ ab cd ef ] ) . read
231188 end
232189
233- # Kill: chunk = current_io.read(max_length, @buffer) mutations
234- def test_readpartial_with_empty_io_in_middle
235- io = HTTP ::FormData ::CompositeIO . new ( [ "ab" , "" , "cd" ] )
236-
237- assert_equal "abcd" , io . read
190+ def test_skips_empty_io_in_middle
191+ assert_equal "abcd" , HTTP ::FormData ::CompositeIO . new ( [ "ab" , "" , "cd" ] ) . read
238192 end
239193
240- # --- Kill mutations for CompositeIO#read_chunks ---
241-
242- # Kill: next if length.nil? replaced with other
243- # Kill: length -= chunk.bytesize mutations
244- # Kill: break if length.zero? mutations
245- def test_read_chunks_respects_length_exactly
194+ def test_respects_length_exactly
246195 io = HTTP ::FormData ::CompositeIO . new ( %w[ abcdef ghijkl ] )
247196
248197 assert_equal "abc" , io . read ( 3 )
@@ -252,14 +201,13 @@ def test_read_chunks_respects_length_exactly
252201 assert_nil io . read ( 1 )
253202 end
254203
255- def test_read_chunks_length_spanning_ios
204+ def test_length_spanning_ios
256205 io = HTTP ::FormData ::CompositeIO . new ( %w[ ab cd ef ] )
257206
258207 assert_equal "abcd" , io . read ( 4 )
259208 assert_equal "ef" , io . read ( 4 )
260209 end
261210
262- # Kill: read with outbuf and no length
263211 def test_read_all_with_outbuf
264212 outbuf = +""
265213 io = HTTP ::FormData ::CompositeIO . new ( [ "hello" , " " , "world" ] )
@@ -270,7 +218,6 @@ def test_read_all_with_outbuf
270218 assert_same result , outbuf
271219 end
272220
273- # Verify outbuf is cleared before use
274221 def test_read_with_outbuf_clears_previous_content
275222 outbuf = +"previous content"
276223 io = HTTP ::FormData ::CompositeIO . new ( [ "new" ] )
@@ -279,25 +226,12 @@ def test_read_with_outbuf_clears_previous_content
279226 assert_equal "new" , outbuf
280227 end
281228
282- # Kill: outbuf.clear.force_encoding(Encoding::BINARY) -> outbuf.clear
283- # Verify that outbuf encoding is forced to binary
284- def test_read_with_utf8_outbuf_returns_binary_encoding
229+ def test_outbuf_encoding_forced_to_binary
285230 outbuf = +"hello"
286231 outbuf . force_encoding ( Encoding ::UTF_8 )
287232 io = HTTP ::FormData ::CompositeIO . new ( %w[ Marohnić ] )
288233 io . read ( 5 , outbuf )
289234
290235 assert_equal Encoding ::BINARY , outbuf . encoding
291236 end
292-
293- # Kill: error message mutation — io.inspect vs io vs nil vs self.inspect
294- def test_error_message_contains_inspect_of_invalid_io
295- obj = Object . new
296- def obj . inspect = "INVALID_IO_INSPECT"
297- def obj . to_s = "INVALID_IO_TO_S"
298-
299- error = assert_raises ( ArgumentError ) { HTTP ::FormData ::CompositeIO . new ( [ obj ] ) }
300-
301- assert_includes error . message , "INVALID_IO_INSPECT"
302- end
303237end
0 commit comments