@@ -245,6 +245,8 @@ def test_upload_chunks_concurrently(shared_bucket, file_data, blobs_to_delete):
245245 chunk_size = 5 * 1024 * 1024 # Minimum supported by XML MPU API
246246 assert os .path .getsize (filename ) > chunk_size # Won't make a good test otherwise
247247
248+ blobs_to_delete .append (upload_blob )
249+
248250 transfer_manager .upload_chunks_concurrently (
249251 filename ,
250252 upload_blob ,
@@ -418,3 +420,58 @@ def test_upload_chunks_concurrently_with_kms(
418420 source_contents = sf .read ()
419421 temp_contents = tmp .read ()
420422 assert source_contents == temp_contents
423+
424+
425+ def test_upload_chunks_concurrently_with_quoted_blob_names (
426+ shared_bucket , file_data , blobs_to_delete
427+ ):
428+ source_file = file_data ["big" ]
429+ filename = source_file ["path" ]
430+ blob_name = "../example_bucket/mpu_file"
431+ upload_blob = shared_bucket .blob (blob_name )
432+ chunk_size = 5 * 1024 * 1024 # Minimum supported by XML MPU API
433+ assert os .path .getsize (filename ) > chunk_size # Won't make a good test otherwise
434+
435+ blobs_to_delete .append (upload_blob )
436+
437+ # If the blob name is not quoted/encoded at all, this will result in a 403.
438+ transfer_manager .upload_chunks_concurrently (
439+ filename , upload_blob , chunk_size = chunk_size , deadline = DEADLINE
440+ )
441+
442+ with tempfile .NamedTemporaryFile () as tmp :
443+ # If the blob name is not quoted correctly, this will result in a 404.
444+ download_blob = shared_bucket .blob (blob_name )
445+ download_blob .download_to_file (tmp )
446+ tmp .seek (0 )
447+
448+ with open (source_file ["path" ], "rb" ) as sf :
449+ source_contents = sf .read ()
450+ temp_contents = tmp .read ()
451+ assert source_contents == temp_contents
452+
453+ # Test emoji names are not mangled.
454+ blob_name = "\U0001f681 " # Helicopter emoji
455+ upload_blob = shared_bucket .blob (blob_name )
456+ chunk_size = 5 * 1024 * 1024 # Minimum supported by XML MPU API
457+ assert os .path .getsize (filename ) > chunk_size # Won't make a good test otherwise
458+
459+ blobs_to_delete .append (upload_blob )
460+
461+ transfer_manager .upload_chunks_concurrently (
462+ filename ,
463+ upload_blob ,
464+ chunk_size = chunk_size ,
465+ deadline = DEADLINE ,
466+ worker_type = transfer_manager .THREAD ,
467+ )
468+
469+ with tempfile .NamedTemporaryFile () as tmp :
470+ download_blob = shared_bucket .blob (blob_name )
471+ download_blob .download_to_file (tmp )
472+ tmp .seek (0 )
473+
474+ with open (source_file ["path" ], "rb" ) as sf :
475+ source_contents = sf .read ()
476+ temp_contents = tmp .read ()
477+ assert source_contents == temp_contents
0 commit comments