@@ -38,72 +38,86 @@ def test_ctor(self):
3838 strategy = self ._make_one ()
3939 self .assertIsInstance (strategy , self ._get_target_class ())
4040
41- def test_generate_requests_initial (self ):
41+ def test_generate_requests_initial_new_object (self ):
4242 """
43- Verify the initial request sequence for a new upload.
44- - First request is AppendObjectSpec with state_lookup=False.
45- - Following requests are data chunks.
46- - Final request has finish_write=True.
43+ Verify the initial request sequence for a new upload (WriteObjectSpec).
4744 """
4845 strategy = self ._make_one ()
4946 mock_buffer = io .BytesIO (b"0123456789" )
50- mock_spec = storage_type .AppendObjectSpec (object_ = "test-object" )
47+ # Use WriteObjectSpec for new objects
48+ mock_spec = storage_type .WriteObjectSpec (
49+ resource = storage_type .Object (name = "test-object" )
50+ )
5151 state = {
5252 "write_state" : _WriteState (
5353 mock_spec , chunk_size = 4 , user_buffer = mock_buffer
5454 ),
55- "first_request" : True ,
5655 }
5756
5857 requests = list (strategy .generate_requests (state ))
5958
60- self .assertEqual (requests [0 ].append_object_spec , mock_spec )
59+ # Check first request (Spec)
60+ self .assertEqual (requests [0 ].write_object_spec , mock_spec )
6161 self .assertFalse (requests [0 ].state_lookup )
62- self .assertFalse (requests [0 ].append_object_spec .write_handle )
6362
63+ # Check data chunks
6464 self .assertEqual (requests [1 ].write_offset , 0 )
6565 self .assertEqual (requests [1 ].checksummed_data .content , b"0123" )
6666 self .assertEqual (requests [2 ].write_offset , 4 )
6767 self .assertEqual (requests [2 ].checksummed_data .content , b"4567" )
6868 self .assertEqual (requests [3 ].write_offset , 8 )
6969 self .assertEqual (requests [3 ].checksummed_data .content , b"89" )
7070
71- self .assertEqual (requests [4 ].write_offset , 10 )
72- self .assertTrue (requests [4 ].finish_write )
73-
74- self .assertEqual (len (requests ), 5 )
71+ # Total requests: 1 Spec + 3 Chunks
72+ self .assertEqual (len (requests ), 4 )
7573
76- def test_generate_requests_empty_file (self ):
74+ def test_generate_requests_initial_existing_object (self ):
7775 """
78- Verify the request sequence for an empty file upload.
79- - First request is AppendObjectSpec.
80- - Second and final request has finish_write=True.
76+ Verify the initial request sequence for appending to an existing object (AppendObjectSpec).
8177 """
8278 strategy = self ._make_one ()
83- mock_buffer = io .BytesIO (b"" )
84- mock_spec = storage_type .AppendObjectSpec (object_ = "test-object" )
79+ mock_buffer = io .BytesIO (b"0123" )
80+ # Use AppendObjectSpec for existing objects
81+ mock_spec = storage_type .AppendObjectSpec (
82+ object_ = "test-object" , bucket = "test-bucket"
83+ )
8584 state = {
8685 "write_state" : _WriteState (
8786 mock_spec , chunk_size = 4 , user_buffer = mock_buffer
8887 ),
89- "first_request" : True ,
9088 }
9189
9290 requests = list (strategy .generate_requests (state ))
9391
92+ # Check first request (Spec)
9493 self .assertEqual (requests [0 ].append_object_spec , mock_spec )
9594 self .assertFalse (requests [0 ].state_lookup )
9695
96+ # Check data chunk
9797 self .assertEqual (requests [1 ].write_offset , 0 )
98- self .assertTrue (requests [1 ].finish_write )
98+ self .assertEqual (requests [1 ].checksummed_data .content , b"0123" )
99+
100+ def test_generate_requests_empty_file (self ):
101+ """
102+ Verify request sequence for an empty file. Should just be the Spec.
103+ """
104+ strategy = self ._make_one ()
105+ mock_buffer = io .BytesIO (b"" )
106+ mock_spec = storage_type .AppendObjectSpec (object_ = "test-object" )
107+ state = {
108+ "write_state" : _WriteState (
109+ mock_spec , chunk_size = 4 , user_buffer = mock_buffer
110+ ),
111+ }
112+
113+ requests = list (strategy .generate_requests (state ))
99114
100- self .assertEqual (len (requests ), 2 )
115+ self .assertEqual (len (requests ), 1 )
116+ self .assertEqual (requests [0 ].append_object_spec , mock_spec )
101117
102118 def test_generate_requests_resumption (self ):
103119 """
104120 Verify request sequence when resuming an upload.
105- - First request is AppendObjectSpec with write_handle and state_lookup=True.
106- - Data streaming starts from the persisted_size.
107121 """
108122 strategy = self ._make_one ()
109123 mock_buffer = io .BytesIO (b"0123456789" )
@@ -115,34 +129,26 @@ def test_generate_requests_resumption(self):
115129 write_state .write_handle = storage_type .BidiWriteHandle (handle = b"test-handle" )
116130 mock_buffer .seek (4 )
117131
118- state = {"write_state" : write_state , "first_request" : True }
132+ state = {"write_state" : write_state }
119133
120134 requests = list (strategy .generate_requests (state ))
121135
136+ # Check first request has handle and lookup
122137 self .assertEqual (
123138 requests [0 ].append_object_spec .write_handle .handle , b"test-handle"
124139 )
125140 self .assertTrue (requests [0 ].state_lookup )
126141
142+ # Check data starts from offset 4
127143 self .assertEqual (requests [1 ].write_offset , 4 )
128144 self .assertEqual (requests [1 ].checksummed_data .content , b"4567" )
129145 self .assertEqual (requests [2 ].write_offset , 8 )
130146 self .assertEqual (requests [2 ].checksummed_data .content , b"89" )
131147
132- self .assertEqual (requests [3 ].write_offset , 10 )
133- self .assertTrue (requests [3 ].finish_write )
134-
135- self .assertEqual (len (requests ), 4 )
136-
137148 @pytest .mark .asyncio
138149 async def test_generate_requests_after_failure_and_recovery (self ):
139150 """
140- Verify a complex scenario:
141- 1. Start upload.
142- 2. Receive a persisted_size update.
143- 3. Encounter an error.
144- 4. Recover state.
145- 5. Generate new requests for resumption.
151+ Verify recovery and resumption flow.
146152 """
147153 strategy = self ._make_one ()
148154 mock_buffer = io .BytesIO (b"0123456789abcdef" )
@@ -157,12 +163,11 @@ async def test_generate_requests_after_failure_and_recovery(self):
157163
158164 strategy .update_state_from_response (
159165 storage_type .BidiWriteObjectResponse (
160- persisted_size = 4 , write_handle = b"handle-1"
166+ persisted_size = 4 ,
167+ write_handle = storage_type .BidiWriteHandle (handle = b"handle-1" ),
161168 ),
162169 state ,
163170 )
164- self .assertEqual (write_state .persisted_size , 4 )
165- self .assertEqual (write_state .write_handle , b"handle-1" )
166171
167172 await strategy .recover_state_on_failure (Exception ("network error" ), state )
168173
@@ -172,23 +177,15 @@ async def test_generate_requests_after_failure_and_recovery(self):
172177 requests = list (strategy .generate_requests (state ))
173178
174179 self .assertTrue (requests [0 ].state_lookup )
175- self .assertEqual (requests [0 ].append_object_spec .write_handle , b"handle-1" )
180+ self .assertEqual (
181+ requests [0 ].append_object_spec .write_handle .handle , b"handle-1"
182+ )
176183
177184 self .assertEqual (requests [1 ].write_offset , 4 )
178185 self .assertEqual (requests [1 ].checksummed_data .content , b"4567" )
179- self .assertEqual (requests [2 ].write_offset , 8 )
180- self .assertEqual (requests [2 ].checksummed_data .content , b"89ab" )
181- self .assertEqual (requests [3 ].write_offset , 12 )
182- self .assertEqual (requests [3 ].checksummed_data .content , b"cdef" )
183-
184- self .assertEqual (requests [4 ].write_offset , 16 )
185- self .assertTrue (requests [4 ].finish_write )
186- self .assertEqual (len (requests ), 5 )
187186
188187 def test_update_state_from_response (self ):
189- """
190- Verify that the write state is correctly updated based on server responses.
191- """
188+ """Verify state updates from server responses."""
192189 strategy = self ._make_one ()
193190 mock_buffer = io .BytesIO (b"0123456789" )
194191 mock_spec = storage_type .AppendObjectSpec (object_ = "test-object" )
@@ -232,30 +229,10 @@ def test_update_state_from_response_ignores_smaller_persisted_size(self):
232229
233230 self .assertEqual (write_state .persisted_size , 2048 )
234231
235- @pytest .mark .asyncio
236- async def test_recover_state_on_failure_rewinds_state (self ):
237- """
238- Verify that on failure, the buffer is seeked to persisted_size
239- and bytes_sent is reset.
240- """
241- strategy = self ._make_one ()
242- mock_buffer = mock .MagicMock (spec = io .BytesIO )
243- mock_spec = storage_type .AppendObjectSpec (object_ = "test-object" )
244-
245- write_state = _WriteState (mock_spec , chunk_size = 4 , user_buffer = mock_buffer )
246- write_state .persisted_size = 100
247- write_state .bytes_sent = 200
248- state = {"write_state" : write_state }
249-
250- await strategy .recover_state_on_failure (Exception ("any error" ), state )
251-
252- mock_buffer .seek .assert_called_once_with (100 )
253- self .assertEqual (write_state .bytes_sent , 100 )
254-
255232 @pytest .mark .asyncio
256233 async def test_recover_state_on_failure_handles_redirect (self ):
257234 """
258- Verify that on a redirect error, the routing_token is extracted and stored .
235+ Verify redirection error handling .
259236 """
260237 strategy = self ._make_one ()
261238 mock_buffer = mock .MagicMock (spec = io .BytesIO )
@@ -271,11 +248,11 @@ async def test_recover_state_on_failure_handles_redirect(self):
271248 await strategy .recover_state_on_failure (wrapped_error , state )
272249
273250 self .assertEqual (write_state .routing_token , "new-token-123" )
274- mock_buffer .seek .assert_called_once_with (0 )
275- self .assertEqual (write_state .bytes_sent , 0 )
251+ mock_buffer .seek .assert_called_with (0 )
276252
277253 @pytest .mark .asyncio
278254 async def test_recover_state_on_failure_handles_redirect_with_handle (self ):
255+ """Verify redirection that includes a write handle."""
279256 strategy = self ._make_one ()
280257 mock_buffer = mock .MagicMock (spec = io .BytesIO )
281258 mock_spec = storage_type .AppendObjectSpec (object_ = "test-object" )
@@ -294,8 +271,7 @@ async def test_recover_state_on_failure_handles_redirect_with_handle(self):
294271 self .assertEqual (write_state .routing_token , "new-token-456" )
295272 self .assertEqual (write_state .write_handle , b"redirect-handle" )
296273
297- mock_buffer .seek .assert_called_once_with (0 )
298- self .assertEqual (write_state .bytes_sent , 0 )
274+ mock_buffer .seek .assert_called_with (0 )
299275
300276 def test_generate_requests_sends_crc32c_checksum (self ):
301277 strategy = self ._make_one ()
@@ -305,13 +281,10 @@ def test_generate_requests_sends_crc32c_checksum(self):
305281 "write_state" : _WriteState (
306282 mock_spec , chunk_size = 4 , user_buffer = mock_buffer
307283 ),
308- "first_request" : True ,
309284 }
310285
311286 requests = list (strategy .generate_requests (state ))
312287
313- self .assertEqual (len (requests ), 3 )
314-
315288 expected_crc = google_crc32c .Checksum (b"0123" )
316289 expected_crc_int = int .from_bytes (expected_crc .digest (), "big" )
317290 self .assertEqual (requests [1 ].checksummed_data .crc32c , expected_crc_int )
@@ -323,7 +296,7 @@ def test_generate_requests_with_routing_token(self):
323296
324297 write_state = _WriteState (mock_spec , chunk_size = 4 , user_buffer = mock_buffer )
325298 write_state .routing_token = "redirected-token"
326- state = {"write_state" : write_state , "first_request" : True }
299+ state = {"write_state" : write_state }
327300
328301 requests = list (strategy .generate_requests (state ))
329302
0 commit comments