From c2999f3cff445a613048e9886e00d06ff214381e Mon Sep 17 00:00:00 2001 From: Danny Hermes Date: Fri, 15 Jan 2016 23:03:41 -0800 Subject: [PATCH 1/2] Making the content length header a string. --- gcloud/connection.py | 3 ++- gcloud/storage/test_batch.py | 8 ++++---- gcloud/test_connection.py | 14 +++++++------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/gcloud/connection.py b/gcloud/connection.py index 16929eec5684..84b4b33bb7d1 100644 --- a/gcloud/connection.py +++ b/gcloud/connection.py @@ -225,7 +225,8 @@ def _make_request(self, method, url, data=None, content_type=None, else: content_length = 0 - headers['Content-Length'] = content_length + # NOTE: str is intended, bytes are sufficient for headers. + headers['Content-Length'] = str(content_length) if content_type: headers['Content-Type'] = content_type diff --git a/gcloud/storage/test_batch.py b/gcloud/storage/test_batch.py index c7664f184034..f50ba4fe153e 100644 --- a/gcloud/storage/test_batch.py +++ b/gcloud/storage/test_batch.py @@ -115,7 +115,7 @@ def test__make_request_GET_normal(self): self.assertEqual(http._requests, []) EXPECTED_HEADERS = [ ('Accept-Encoding', 'gzip'), - ('Content-Length', 0), + ('Content-Length', '0'), ] solo_request, = batch._requests self.assertEqual(solo_request[0], 'GET') @@ -140,7 +140,7 @@ def test__make_request_POST_normal(self): self.assertEqual(http._requests, []) EXPECTED_HEADERS = [ ('Accept-Encoding', 'gzip'), - ('Content-Length', 10), + ('Content-Length', '10'), ] solo_request, = batch._requests self.assertEqual(solo_request[0], 'POST') @@ -165,7 +165,7 @@ def test__make_request_PATCH_normal(self): self.assertEqual(http._requests, []) EXPECTED_HEADERS = [ ('Accept-Encoding', 'gzip'), - ('Content-Length', 10), + ('Content-Length', '10'), ] solo_request, = batch._requests self.assertEqual(solo_request[0], 'PATCH') @@ -190,7 +190,7 @@ def test__make_request_DELETE_normal(self): self.assertEqual(http._requests, []) EXPECTED_HEADERS = [ ('Accept-Encoding', 'gzip'), - ('Content-Length', 0), + ('Content-Length', '0'), ] solo_request, = batch._requests self.assertEqual(solo_request[0], 'DELETE') diff --git a/gcloud/test_connection.py b/gcloud/test_connection.py index 0af98a821f52..2b7ba10af1d8 100644 --- a/gcloud/test_connection.py +++ b/gcloud/test_connection.py @@ -163,7 +163,7 @@ def test__make_request_no_data_no_content_type_no_headers(self): self.assertEqual(http._called_with['body'], None) expected_headers = { 'Accept-Encoding': 'gzip', - 'Content-Length': 0, + 'Content-Length': '0', 'User-Agent': conn.USER_AGENT, } self.assertEqual(http._called_with['headers'], expected_headers) @@ -181,7 +181,7 @@ def test__make_request_w_data_no_extra_headers(self): self.assertEqual(http._called_with['body'], {}) expected_headers = { 'Accept-Encoding': 'gzip', - 'Content-Length': 0, + 'Content-Length': '0', 'Content-Type': 'application/json', 'User-Agent': conn.USER_AGENT, } @@ -200,7 +200,7 @@ def test__make_request_w_extra_headers(self): self.assertEqual(http._called_with['body'], None) expected_headers = { 'Accept-Encoding': 'gzip', - 'Content-Length': 0, + 'Content-Length': '0', 'X-Foo': 'foo', 'User-Agent': conn.USER_AGENT, } @@ -225,7 +225,7 @@ def test_api_request_defaults(self): self.assertEqual(http._called_with['body'], None) expected_headers = { 'Accept-Encoding': 'gzip', - 'Content-Length': 0, + 'Content-Length': '0', 'User-Agent': conn.USER_AGENT, } self.assertEqual(http._called_with['headers'], expected_headers) @@ -274,7 +274,7 @@ def test_api_request_w_query_params(self): self.assertEqual(http._called_with['body'], None) expected_headers = { 'Accept-Encoding': 'gzip', - 'Content-Length': 0, + 'Content-Length': '0', 'User-Agent': conn.USER_AGENT, } self.assertEqual(http._called_with['headers'], expected_headers) @@ -301,7 +301,7 @@ def test_api_request_w_data(self): self.assertEqual(http._called_with['body'], DATAJ) expected_headers = { 'Accept-Encoding': 'gzip', - 'Content-Length': len(DATAJ), + 'Content-Length': str(len(DATAJ)), 'Content-Type': 'application/json', 'User-Agent': conn.USER_AGENT, } @@ -345,7 +345,7 @@ def test_api_request_non_binary_response(self): self.assertEqual(http._called_with['body'], None) expected_headers = { 'Accept-Encoding': 'gzip', - 'Content-Length': 0, + 'Content-Length': '0', 'User-Agent': conn.USER_AGENT, } self.assertEqual(http._called_with['headers'], expected_headers) From 6469d43ad4019ecd4720fabfe3063f8f3b61f189 Mon Sep 17 00:00:00 2001 From: Danny Hermes Date: Fri, 15 Jan 2016 23:14:08 -0800 Subject: [PATCH 2/2] Adding support for pubsub emulator in system test. --- CONTRIBUTING.rst | 22 ++++++++++++++++++++++ system_tests/datastore.py | 15 ++------------- system_tests/pubsub.py | 12 +++++++++++- system_tests/system_test_utils.py | 12 ++++++++++++ 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 9cf55e562724..bc07666d8f61 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -242,6 +242,28 @@ Running System Tests .. _emulators: https://cloud.google.com/sdk/gcloud/reference/beta/emulators/ +- To run the ``pubsub`` system tests with an emulator, first start the + emulator and take note of the process ID:: + + $ gcloud beta emulators pubsub start & + [1] 44444 + + then determine the environment variables needed to interact with + the emulator:: + + $ gcloud beta emulators pubsub env-init + export PUBSUB_EMULATOR_HOST=localhost:8897 + + using these environment variables run the emulator:: + + $ DATASTORE_HOST=http://localhost:8897 \ + > python system_tests/run_system_test.py \ + > --package=pubsub + + and after completion stop the emulator:: + + $ kill 44444 + Test Coverage ------------- diff --git a/system_tests/datastore.py b/system_tests/datastore.py index dbd20dcc87a9..05f3ed1745a1 100644 --- a/system_tests/datastore.py +++ b/system_tests/datastore.py @@ -29,6 +29,7 @@ # repository root is the current directory. from system_tests import clear_datastore from system_tests import populate_datastore +from system_tests.system_test_utils import EmulatorCreds # Isolated namespace so concurrent test runs don't collide. @@ -45,18 +46,6 @@ class Config(object): CLIENT = None -class _EmulatorCreds(object): - """A mock credential object. - - Used to avoid unnecessary token refreshing or reliance on the network - while an emulator is running. - """ - - @staticmethod - def create_scoped_required(): - return False - - def clone_client(client): # Fool the Client constructor to avoid creating a new connection. cloned_client = datastore.Client(project=client.project, @@ -71,7 +60,7 @@ def setUpModule(): client_mod.DATASET = TESTS_DATASET Config.CLIENT = datastore.Client(namespace=TEST_NAMESPACE) else: - credentials = _EmulatorCreds() + credentials = EmulatorCreds() http = httplib2.Http() # Un-authorized. Config.CLIENT = datastore.Client(project=EMULATOR_DATASET, namespace=TEST_NAMESPACE, diff --git a/system_tests/pubsub.py b/system_tests/pubsub.py index c1730ac338d0..3c6b7e5a0e41 100644 --- a/system_tests/pubsub.py +++ b/system_tests/pubsub.py @@ -12,13 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. +import os import time +import httplib2 import unittest2 from gcloud import _helpers +from gcloud.environment_vars import PUBSUB_EMULATOR from gcloud.environment_vars import TESTS_PROJECT from gcloud import pubsub +from system_tests.system_test_utils import EmulatorCreds class Config(object): @@ -32,7 +36,13 @@ class Config(object): def setUpModule(): _helpers.PROJECT = TESTS_PROJECT - Config.CLIENT = pubsub.Client() + if os.getenv(PUBSUB_EMULATOR) is None: + Config.CLIENT = pubsub.Client() + else: + credentials = EmulatorCreds() + http = httplib2.Http() # Un-authorized. + Config.CLIENT = pubsub.Client(credentials=credentials, + http=http) class TestPubsub(unittest2.TestCase): diff --git a/system_tests/system_test_utils.py b/system_tests/system_test_utils.py index 0c8425ea742f..eb7b3b5517bb 100644 --- a/system_tests/system_test_utils.py +++ b/system_tests/system_test_utils.py @@ -34,6 +34,18 @@ """ +class EmulatorCreds(object): + """A mock credential object. + + Used to avoid unnecessary token refreshing or reliance on the network + while an emulator is running. + """ + + @staticmethod + def create_scoped_required(): + return False + + def check_environ(*requirements): missing = []