11import os
22import io
3+ import tempfile
34from base64 import b64encode
45from unittest import mock
56
@@ -91,6 +92,51 @@ def test_url(self, filename: str):
9192 self .assertEqual (resumable_uploader .url , "http://tusd.tusdemo.net/files/foo_bar" )
9293 self .assertEqual (resumable_uploader .offset , 10 )
9394
95+ @parametrize (
96+ "filename" ,
97+ [FILEPATH_TEXT , FILEPATH_BINARY ],
98+ )
99+ @responses .activate
100+ def test_url_voided (self , filename : str ):
101+ # Test that voided stored url are cleared
102+ responses .add (
103+ responses .POST ,
104+ self .client .url ,
105+ adding_headers = {"location" : "http://tusd.tusdemo.net/files/foo" },
106+ )
107+ responses .add (
108+ responses .HEAD ,
109+ "http://tusd.tusdemo.net/files/foo" ,
110+ status = 404 ,
111+ )
112+
113+ # Create temporary storage file.
114+ temp_fp = tempfile .NamedTemporaryFile (delete = False )
115+ storage = filestorage .FileStorage (temp_fp .name )
116+ uploader = self .client .uploader (
117+ file_path = filename , store_url = True , url_storage = storage
118+ )
119+
120+ # Conduct only POST creation so that we'd get a storage entry.
121+ uploader .upload (stop_at = - 1 )
122+ key = uploader ._get_fingerprint ()
123+ # First ensure that an entry was created and stored.
124+ self .assertIsNotNone (uploader .url )
125+ self .assertIsNotNone (storage .get_item (key ))
126+
127+ # Now start a new upload, resuming where we left off.
128+ resumed_uploader = self .client .uploader (
129+ file_path = filename , store_url = True , url_storage = storage
130+ )
131+ # HEAD response was 404 so url and storage has to be voided.
132+ self .assertIsNone (resumed_uploader .url )
133+ self .assertIsNone (storage .get_item (key ))
134+
135+ # Remove the temporary storage file.
136+ storage .close ()
137+ temp_fp .close ()
138+ os .remove (temp_fp .name )
139+
94140 def test_request_length (self ):
95141 self .uploader .chunk_size = 200
96142 self .assertEqual (self .uploader .get_request_length (), 200 )
@@ -203,19 +249,19 @@ def test_upload_empty(self):
203249 # Upload URL being set means the POST request was sent and the empty
204250 # file was uploaded without a single PATCH request.
205251 self .assertTrue (uploader .url )
206-
252+
207253 @mock .patch ('tusclient.uploader.uploader.TusRequest' )
208254 def test_upload_checksum (self , request_mock ):
209255 self .mock_request (request_mock )
210256 self .uploader .upload_checksum = True
211257 self .uploader .upload ()
212258 self .assertEqual (self .uploader .offset , self .uploader .get_file_size ())
213-
259+
214260 @parametrize ("chunk_size" , [1 , 2 , 3 , 4 , 5 , 6 ])
215261 @responses .activate
216262 def test_upload_length_deferred (self , chunk_size : int ):
217263 upload_url = f"{ self .client .url } test_upload_length_deferred"
218-
264+
219265 responses .head (
220266 upload_url ,
221267 adding_headers = {"upload-offset" : "0" , "Upload-Defer-Length" : "1" },
@@ -228,7 +274,7 @@ def test_upload_length_deferred(self, chunk_size: int):
228274 )
229275 self .assertTrue (uploader .upload_length_deferred )
230276 self .assertTrue (uploader .stop_at is None )
231-
277+
232278 offset = 0
233279 while not (offset + chunk_size > 5 ):
234280 next_offset = min (offset + chunk_size , 5 )
@@ -245,7 +291,7 @@ def test_upload_length_deferred(self, chunk_size: int):
245291 adding_headers = {"upload-offset" : "5" },
246292 match = [matchers .header_matcher (last_req_headers )],
247293 )
248-
294+
249295 uploader .upload ()
250296 self .assertEqual (uploader .offset , 5 )
251297 self .assertEqual (uploader .stop_at , 5 )
0 commit comments