Skip to content

Commit 2a956e5

Browse files
committed
Add round-trip systest for signed resumable uploads.
1 parent 6e71c29 commit 2a956e5

1 file changed

Lines changed: 83 additions & 22 deletions

File tree

storage/tests/system.py

Lines changed: 83 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import os
1717
import re
1818
import tempfile
19-
import time
2019
import unittest
2120

2221
import pytest
@@ -87,6 +86,7 @@ def setUpModule():
8786

8887

8988
def 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

890951
class TestStorageCompose(TestStorageFiles):
891952

0 commit comments

Comments
 (0)