@@ -124,7 +124,11 @@ def test__write_to_stream_with_hash_check_fail(self, checksum):
124
124
msg = download_mod ._CHECKSUM_MISMATCH .format (
125
125
EXAMPLE_URL , bad_checksum , good_checksum , checksum_type = checksum .upper ()
126
126
)
127
- assert error .args [0 ] == msg
127
+ assert msg in error .args [0 ]
128
+ assert (
129
+ f"The download request read { download ._bytes_downloaded } bytes of data."
130
+ in error .args [0 ]
131
+ )
128
132
129
133
# Check mocks.
130
134
response .__enter__ .assert_called_once_with ()
@@ -186,6 +190,29 @@ def test__write_to_stream_with_invalid_checksum_type(self):
186
190
error = exc_info .value
187
191
assert error .args [0 ] == "checksum must be ``'md5'``, ``'crc32c'`` or ``None``"
188
192
193
+ @pytest .mark .parametrize ("checksum" , ["md5" , "crc32c" ])
194
+ def test__write_to_stream_incomplete_read (self , checksum ):
195
+ stream = io .BytesIO ()
196
+ download = download_mod .Download (EXAMPLE_URL , stream = stream , checksum = checksum )
197
+
198
+ chunk1 = b"first chunk"
199
+ mock_full_content_length = len (chunk1 ) + 123
200
+ headers = {"x-goog-stored-content-length" : mock_full_content_length }
201
+ bad_checksum = "d3JvbmcgbiBtYWRlIHVwIQ=="
202
+ header_value = "crc32c={bad},md5={bad}" .format (bad = bad_checksum )
203
+ headers [_helpers ._HASH_HEADER ] = header_value
204
+ response = _mock_response (chunks = [chunk1 ], headers = headers )
205
+
206
+ with pytest .raises (ConnectionError ) as exc_info :
207
+ download ._write_to_stream (response )
208
+
209
+ assert not download .finished
210
+ error = exc_info .value
211
+ assert (
212
+ f"The download request read { download ._bytes_downloaded } bytes of data."
213
+ in error .args [0 ]
214
+ )
215
+
189
216
def _consume_helper (
190
217
self ,
191
218
stream = None ,
@@ -304,7 +331,11 @@ def test_consume_with_stream_hash_check_fail(self, checksum):
304
331
msg = download_mod ._CHECKSUM_MISMATCH .format (
305
332
EXAMPLE_URL , bad_checksum , good_checksum , checksum_type = checksum .upper ()
306
333
)
307
- assert error .args [0 ] == msg
334
+ assert msg in error .args [0 ]
335
+ assert (
336
+ f"The download request read { download ._bytes_downloaded } bytes of data."
337
+ in error .args [0 ]
338
+ )
308
339
309
340
# Check mocks.
310
341
transport .request .assert_called_once_with (
@@ -599,7 +630,11 @@ def test__write_to_stream_with_hash_check_fail(self, checksum):
599
630
msg = download_mod ._CHECKSUM_MISMATCH .format (
600
631
EXAMPLE_URL , bad_checksum , good_checksum , checksum_type = checksum .upper ()
601
632
)
602
- assert error .args [0 ] == msg
633
+ assert msg in error .args [0 ]
634
+ assert (
635
+ f"The download request read { download ._bytes_downloaded } bytes of data."
636
+ in error .args [0 ]
637
+ )
603
638
604
639
# Check mocks.
605
640
response .__enter__ .assert_called_once_with ()
@@ -632,6 +667,31 @@ def test__write_to_stream_with_invalid_checksum_type(self):
632
667
error = exc_info .value
633
668
assert error .args [0 ] == "checksum must be ``'md5'``, ``'crc32c'`` or ``None``"
634
669
670
+ @pytest .mark .parametrize ("checksum" , ["md5" , "crc32c" ])
671
+ def test__write_to_stream_incomplete_read (self , checksum ):
672
+ stream = io .BytesIO ()
673
+ download = download_mod .RawDownload (
674
+ EXAMPLE_URL , stream = stream , checksum = checksum
675
+ )
676
+
677
+ chunk1 = b"first chunk"
678
+ mock_full_content_length = len (chunk1 ) + 123
679
+ headers = {"x-goog-stored-content-length" : mock_full_content_length }
680
+ bad_checksum = "d3JvbmcgbiBtYWRlIHVwIQ=="
681
+ header_value = "crc32c={bad},md5={bad}" .format (bad = bad_checksum )
682
+ headers [_helpers ._HASH_HEADER ] = header_value
683
+ response = _mock_raw_response (chunks = [chunk1 ], headers = headers )
684
+
685
+ with pytest .raises (ConnectionError ) as exc_info :
686
+ download ._write_to_stream (response )
687
+
688
+ assert not download .finished
689
+ error = exc_info .value
690
+ assert (
691
+ f"The download request read { download ._bytes_downloaded } bytes of data."
692
+ in error .args [0 ]
693
+ )
694
+
635
695
def _consume_helper (
636
696
self ,
637
697
stream = None ,
@@ -754,7 +814,11 @@ def test_consume_with_stream_hash_check_fail(self, checksum):
754
814
msg = download_mod ._CHECKSUM_MISMATCH .format (
755
815
EXAMPLE_URL , bad_checksum , good_checksum , checksum_type = checksum .upper ()
756
816
)
757
- assert error .args [0 ] == msg
817
+ assert msg in error .args [0 ]
818
+ assert (
819
+ f"The download request read { download ._bytes_downloaded } bytes of data."
820
+ in error .args [0 ]
821
+ )
758
822
759
823
# Check mocks.
760
824
transport .request .assert_called_once_with (
0 commit comments