1616import os
1717import re
1818import tempfile
19- import time
2019import unittest
2120
2221import pytest
@@ -87,6 +86,7 @@ def setUpModule():
8786
8887
8988def tearDownModule ():
89+ _empty_bucket (Config .TEST_BUCKET )
9090 errors = (exceptions .Conflict , exceptions .TooManyRequests )
9191 retry = RetryErrors (errors , max_tries = 9 )
9292 retry (Config .TEST_BUCKET .delete )(force = True )
@@ -728,30 +728,27 @@ def test_third_level(self):
728728 self .assertEqual (iterator .prefixes , set ())
729729
730730
731- class TestStorageSignURLs (TestStorageFiles ):
732- def setUp ( self ):
733- super ( TestStorageSignURLs , self ). setUp ()
734-
731+ class TestStorageSignURLs (unittest . TestCase ):
732+ BLOB_CONTENT = b"This time for sure, Rocky!"
733+ @ classmethod
734+ def setUpClass ( cls ):
735735 if (
736736 type (Config .CLIENT ._credentials )
737737 is not google .oauth2 .service_account .Credentials
738738 ):
739- self .skipTest ("Signing tests requires a service account credential" )
739+ cls .skipTest ("Signing tests requires a service account credential" )
740740
741- logo_path = self .FILES ["logo" ]["path" ]
742- with open (logo_path , "rb" ) as file_obj :
743- self .LOCAL_FILE = file_obj .read ()
741+ bucket_name = "gcp-signing" + unique_resource_id ()
742+ cls .bucket = Config .CLIENT .create_bucket (bucket_name )
743+ cls .blob = cls .bucket .blob ("README.txt" )
744+ cls .blob .upload_from_string (cls .BLOB_CONTENT )
744745
745- blob = self .bucket .blob ("LogoToSign.jpg" )
746- blob .upload_from_string (self .LOCAL_FILE )
747- self .case_blobs_to_delete .append (blob )
748-
749- def tearDown (self ):
750- errors = (exceptions .TooManyRequests , exceptions .ServiceUnavailable )
746+ @classmethod
747+ def tearDownClass (cls ):
748+ _empty_bucket (cls .bucket )
749+ errors = (exceptions .Conflict , exceptions .TooManyRequests )
751750 retry = RetryErrors (errors , max_tries = 6 )
752- for blob in self .case_blobs_to_delete :
753- if blob .exists ():
754- retry (blob .delete )()
751+ retry (cls .bucket .delete )(force = True )
755752
756753 def _create_signed_list_blobs_url_helper (
757754 self , version , expiration = None , max_age = None , method = "GET"
@@ -798,10 +795,11 @@ def _create_signed_read_url_helper(
798795 expiration = None ,
799796 max_age = None ,
800797 ):
801- blob = self .bucket .blob (blob_name )
802798 if payload is not None :
799+ blob = self .bucket .blob (blob_name )
803800 blob .upload_from_string (payload )
804- self .case_blobs_to_delete .append (blob )
801+ else :
802+ blob = self .blob
805803
806804 if expiration is None and max_age is None :
807805 max_age = 10
@@ -819,7 +817,7 @@ def _create_signed_read_url_helper(
819817 if payload is not None :
820818 self .assertEqual (response .content , payload )
821819 else :
822- self .assertEqual (response .content , self .LOCAL_FILE )
820+ self .assertEqual (response .content , self .BLOB_CONTENT )
823821
824822 def test_create_signed_read_url_v2 (self ):
825823 self ._create_signed_read_url_helper ()
@@ -864,7 +862,8 @@ def _create_signed_delete_url_helper(
864862 if expiration is None and max_age is None :
865863 max_age = 10
866864
867- blob = self .bucket .blob ("LogoToSign.jpg" )
865+ blob = self .bucket .blob ("DELETE_ME.txt" )
866+ blob .upload_from_string (b"DELETE ME!" )
868867
869868 signed_delete_url = blob .generate_signed_url (
870869 expiration = expiration ,
@@ -886,6 +885,68 @@ def test_create_signed_delete_url_v2(self):
886885 def test_create_signed_delete_url_v4 (self ):
887886 self ._create_signed_delete_url_helper (version = "v4" )
888887
888+ def _signed_resumable_upload_url_helper (
889+ self ,
890+ version = "v2" ,
891+ expiration = None ,
892+ max_age = None ,
893+ ):
894+ blob = self .bucket .blob ("cruddy.txt" )
895+ payload = b"DEADBEEF"
896+
897+ if expiration is None and max_age is None :
898+ max_age = 3600
899+
900+ # Initiate the upload using a signed URL.
901+ signed_resumable_upload_url = blob .generate_signed_url (
902+ expiration = expiration ,
903+ max_age = max_age ,
904+ method = "RESUMABLE" ,
905+ client = Config .CLIENT ,
906+ version = version ,
907+ )
908+
909+ post_headers = {"x-goog-resumable" : "start" }
910+ post_response = requests .post (signed_resumable_upload_url , headers = post_headers )
911+ self .assertEqual (post_response .status_code , 201 )
912+
913+ # Finish uploading the body.
914+ location = post_response .headers ["Location" ]
915+ put_headers = {"content-length" : str (len (payload ))}
916+ put_response = requests .put (location , headers = put_headers , data = payload )
917+ self .assertEqual (put_response .status_code , 200 )
918+
919+ # Download using a signed URL and verify.
920+ signed_download_url = blob .generate_signed_url (
921+ expiration = expiration ,
922+ max_age = max_age ,
923+ method = "GET" ,
924+ client = Config .CLIENT ,
925+ version = version ,
926+ )
927+
928+ get_response = requests .get (signed_download_url )
929+ self .assertEqual (get_response .status_code , 200 )
930+ self .assertEqual (get_response .content , payload )
931+
932+ # Finally, delete the blob using a signed URL.
933+ signed_delete_url = blob .generate_signed_url (
934+ expiration = expiration ,
935+ max_age = max_age ,
936+ method = "DELETE" ,
937+ client = Config .CLIENT ,
938+ version = version ,
939+ )
940+
941+ delete_response = requests .delete (signed_delete_url )
942+ self .assertEqual (delete_response .status_code , 204 )
943+
944+ def test_signed_resumable_upload_url_v2 (self ):
945+ self ._signed_resumable_upload_url_helper (version = "v2" )
946+
947+ def test_signed_resumable_upload_url_v4 (self ):
948+ self ._signed_resumable_upload_url_helper (version = "v4" )
949+
889950
890951class TestStorageCompose (TestStorageFiles ):
891952
0 commit comments