@@ -295,7 +295,98 @@ def test_operations_used_in_recursive_download(self):
295295 len (self .operations_called ), 1 , self .operations_called
296296 )
297297 self .assertEqual (self .operations_called [0 ][0 ].name , 'ListObjectsV2' )
298+
299+ def test_for_no_overwrite_flag_when_object_not_exists_on_target (self ):
300+ """Testing when object with different key is successsfully uploaded using no-overwrite"""
301+ full_path = self .files .create_file ('foo.txt' , 'mycontent' )
302+ cmdline = f'{ self .prefix } { full_path } s3://bucket --no-overwrite'
303+ self .parsed_responses = [
304+ {'ETag' : '"c8afdb36c52cf4727836669019e69222"' }
305+ ]
306+ self .run_cmd (cmdline , expected_rc = 0 )
307+ # Verify putObject was called
308+ self .assertEqual (len (self .operations_called ), 1 )
309+ self .assertEqual (self .operations_called [0 ][0 ].name , 'PutObject' )
310+ # Verify the IfNoneMatch condition was set in the request
311+ self .assertEqual (self .operations_called [0 ][1 ]['IfNoneMatch' ], '*' )
312+
313+ def test_for_no_overwrite_flag_when_object_exists_on_target (self ):
314+ """Testing when object already exists using no-overwrite"""
315+ full_path = self .files .create_file ('foo.txt' , 'mycontent' )
316+ cmdline = f'{ self .prefix } { full_path } s3://bucket --no-overwrite'
317+ # Set up the response to simulate a PreconditionFailed error
318+ self .http_response .status_code = 412
319+ self .parsed_responses = [
320+ {
321+ 'Error' : {
322+ 'Code' : 'PreconditionFailed' ,
323+ 'Message' : 'At least one of the pre-conditions you specified did not hold' ,
324+ 'Condition' : 'If-None-match'
325+ }
326+ }
327+ ]
328+ self .run_cmd (cmdline , expected_rc = 0 )
329+ # Verify PutObject was attempted with IfNoneMatch
330+ self .assertEqual (len (self .operations_called ), 1 )
331+ self .assertEqual (self .operations_called [0 ][0 ].name , 'PutObject' )
332+ self .assertEqual (self .operations_called [0 ][1 ]['IfNoneMatch' ], '*' )
298333
334+ def test_for_no_overwrite_flag_multipart_upload_when_object_not_exists_on_target (self ):
335+ """Testing multipart upload with no-overwrite flag when object doesn't exist"""
336+ # Create a large file that will trigger multipart upload
337+ full_path = self .files .create_file ('foo.txt' , 'a' * 10 * (1024 ** 2 ))
338+ cmdline = f'{ self .prefix } { full_path } s3://bucket --no-overwrite'
339+
340+ # Set up responses for multipart upload
341+ self .parsed_responses = [
342+ {'UploadId' : 'foo' }, # CreateMultipartUpload response
343+ {'ETag' : '"foo-1"' }, # UploadPart response
344+ {'ETag' : '"foo-2"' }, # UploadPart response
345+ {} # CompleteMultipartUpload response
346+ ]
347+ self .run_cmd (cmdline , expected_rc = 0 )
348+ # Verify all multipart operations were called
349+ self .assertEqual (len (self .operations_called ), 4 )
350+ self .assertEqual (self .operations_called [0 ][0 ].name , 'CreateMultipartUpload' )
351+ self .assertEqual (self .operations_called [1 ][0 ].name , 'UploadPart' )
352+ self .assertEqual (self .operations_called [2 ][0 ].name , 'UploadPart' )
353+ self .assertEqual (self .operations_called [3 ][0 ].name , 'CompleteMultipartUpload' )
354+ # Verify the IfNoneMatch condition was set in the CompleteMultipartUpload request
355+ self .assertEqual (self .operations_called [3 ][1 ]['IfNoneMatch' ], '*' )
356+
357+ def test_for_no_overwrite_flag_multipart_upload_when_object_exists_on_target (self ):
358+ """Testing multipart upload with no-overwrite flag when object already exist"""
359+ # Create a large file that will trigger multipart upload
360+ full_path = self .files .create_file ('foo.txt' , 'a' * 10 * (1024 ** 2 ))
361+ cmdline = f'{ self .prefix } { full_path } s3://bucket --no-overwrite'
362+ # Set up responses for multipart upload
363+ self .parsed_responses = [
364+ {'UploadId' : 'foo' }, # CreateMultipartUpload response
365+ {'ETag' : '"foo-1"' }, # UploadPart response
366+ {'ETag' : '"foo-2"' }, # UploadPart response
367+ {
368+ 'Error' : {
369+ 'Code' : 'PreconditionFailed' ,
370+ 'Message' : 'At least one of the pre-conditions you specified did not hold' ,
371+ 'Condition' : 'If-None-match'
372+ }
373+ }, # PreconditionFailed error for CompleteMultipart Upload
374+ {} # AbortMultipartUpload response
375+ ]
376+ # Checking for success as file is skipped
377+ self .run_cmd (cmdline , expected_rc = 0 )
378+ # Set up the response to simulate a PreconditionFailed error
379+ self .http_response .status_code = 412
380+ # Verify all multipart operations were called
381+ self .assertEqual (len (self .operations_called ), 5 )
382+ self .assertEqual (self .operations_called [0 ][0 ].name , 'CreateMultipartUpload' )
383+ self .assertEqual (self .operations_called [1 ][0 ].name , 'UploadPart' )
384+ self .assertEqual (self .operations_called [2 ][0 ].name , 'UploadPart' )
385+ self .assertEqual (self .operations_called [3 ][0 ].name , 'CompleteMultipartUpload' )
386+ self .assertEqual (self .operations_called [4 ][0 ].name , 'AbortMultipartUpload' )
387+ # Verify the IfNoneMatch condition was set in the CompleteMultipartUpload request
388+ self .assertEqual (self .operations_called [3 ][1 ]['IfNoneMatch' ], '*' )
389+
299390 def test_dryrun_download (self ):
300391 self .parsed_responses = [self .head_object_response ()]
301392 target = self .files .full_path ('file.txt' )
0 commit comments