Skip to content

Commit

Permalink
Implementing storage regression tests to match gcloud-node.
Browse files Browse the repository at this point in the history
Note meant to be merged. Some missing features were
uncovered or hard to use APIs and I want to discuss here
and then map out the plan (i.e. how to break this up).
  • Loading branch information
dhermes committed Nov 3, 2014
1 parent f33e557 commit fb3b3ba
Show file tree
Hide file tree
Showing 13 changed files with 315 additions and 22 deletions.
3 changes: 3 additions & 0 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,10 @@ Running Regression Tests
so you'll need to provide some environment variables to facilitate
authentication to your project:

- ``GCLOUD_TESTS_PROJECT_ID``: Developers Console project ID (e.g.
bamboo-shift-455).
- ``GCLOUD_TESTS_DATASET_ID``: The name of the dataset your tests connect to.
This is typically the same as ``GCLOUD_TESTS_PROJECT_ID``.
- ``GCLOUD_TESTS_CLIENT_EMAIL``: The email for the service account you're
authenticating with
- ``GCLOUD_TESTS_KEY_FILE``: The path to an encrypted key file.
Expand Down
3 changes: 2 additions & 1 deletion gcloud/storage/bucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,8 @@ def upload_file(self, filename, key=None):
if key is None:
key = os.path.basename(filename)
key = self.new_key(key)
return key.set_contents_from_filename(filename)
key.upload_from_filename(filename)
return key

def upload_file_object(self, file_obj, key=None):
"""Shortcut method to upload a file object into this bucket.
Expand Down
10 changes: 8 additions & 2 deletions gcloud/storage/iterator.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ class Iterator(object):
:type path: string
:param path: The path to query for the list of items.
"""
def __init__(self, connection, path):
def __init__(self, connection, path, extra_params=None):
self.connection = connection
self.path = path
self.page_number = 0
self.next_page_token = None
self.extra_params = extra_params

def __iter__(self):
"""Iterate through the list of items."""
Expand All @@ -69,8 +70,13 @@ def get_query_params(self):
:rtype: dict or None
:returns: A dictionary of query parameters or None if there are none.
"""
result = None
if self.next_page_token:
return {'pageToken': self.next_page_token}
result = {'pageToken': self.next_page_token}
if self.extra_params is not None:
result = result or {}
result.update(self.extra_params)
return result

def get_next_page_response(self):
"""Requests the next page from the path provided.
Expand Down
11 changes: 6 additions & 5 deletions gcloud/storage/key.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,9 @@ def upload_from_string(self, data, content_type='text/plain'):
"""
string_buffer = StringIO()
string_buffer.write(data)
self.set_contents_from_file(file_obj=string_buffer, rewind=True,
size=string_buffer.len,
content_type=content_type)
self.upload_from_file(file_obj=string_buffer, rewind=True,
size=string_buffer.len,
content_type=content_type)
return self

# NOTE: Alias for boto-like API.
Expand Down Expand Up @@ -465,10 +465,11 @@ class _KeyIterator(Iterator):
:type bucket: :class:`gcloud.storage.bucket.Bucket`
:param bucket: The bucket from which to list keys.
"""
def __init__(self, bucket):
def __init__(self, bucket, extra_params=None):
self.bucket = bucket
super(_KeyIterator, self).__init__(
connection=bucket.connection, path=bucket.path + '/o')
connection=bucket.connection, path=bucket.path + '/o',
extra_params=extra_params)

def get_items_from_response(self, response):
"""Factory method, yields :class:`.storage.key.Key` items from response.
Expand Down
6 changes: 4 additions & 2 deletions gcloud/storage/test_bucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,9 @@ def __init__(self, bucket, name):
self._bucket = bucket
self._name = name

def set_contents_from_filename(self, filename):
def upload_from_filename(self, filename):
_uploaded.append((self._bucket, self._name, filename))

bucket = self._makeOne()
with _Monkey(MUT, Key=_Key):
bucket.upload_file(FILENAME)
Expand All @@ -354,8 +355,9 @@ def __init__(self, bucket, name):
self._bucket = bucket
self._name = name

def set_contents_from_filename(self, filename):
def upload_from_filename(self, filename):
_uploaded.append((self._bucket, self._name, filename))

bucket = self._makeOne()
with _Monkey(MUT, Key=_Key):
bucket.upload_file(FILENAME, KEY)
Expand Down
7 changes: 7 additions & 0 deletions gcloud/storage/test_iterator.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ def test_get_query_params_w_token(self):
self.assertEqual(iterator.get_query_params(),
{'pageToken': TOKEN})

def test_get_query_params_extra_params(self):
connection = _Connection()
PATH = '/foo'
extra_params = {'key': 'val'}
iterator = self._makeOne(connection, PATH, extra_params=extra_params)
self.assertEqual(iterator.get_query_params(), extra_params)

def test_get_next_page_response_new_no_token_in_response(self):
PATH = '/foo'
TOKEN = 'token'
Expand Down
Binary file added regression/data/CloudPlatform_128px_Retina.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added regression/data/five-mb-file.zip
Binary file not shown.
3 changes: 2 additions & 1 deletion regression/local_test_setup.sample
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export GCLOUD_TESTS_DATASET_ID="my-dataset"
export GCLOUD_TESTS_PROJECT_ID="my-project"
export GCLOUD_TESTS_DATASET_ID=${GCLOUD_TESTS_PROJECT_ID}
export GCLOUD_TESTS_CLIENT_EMAIL="some-account@developer.gserviceaccount.com"
export GCLOUD_TESTS_KEY_FILE="path.key"
39 changes: 30 additions & 9 deletions regression/regression_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,58 @@
import sys

from gcloud import datastore
from gcloud import storage


# Defaults from shell environ. May be None.
PROJECT_ID = os.getenv('GCLOUD_TESTS_PROJECT_ID')
DATASET_ID = os.getenv('GCLOUD_TESTS_DATASET_ID')
CLIENT_EMAIL = os.getenv('GCLOUD_TESTS_CLIENT_EMAIL')
KEY_FILENAME = os.getenv('GCLOUD_TESTS_KEY_FILE')
DATASETS = {}
CACHED_RETURN_VALS = {}

ENVIRON_ERROR_MSG = """\
To run the regression tests, you need to set some environment variables.
Please check the Contributing guide for instructions.
"""


def get_environ():
if DATASET_ID is None or CLIENT_EMAIL is None or KEY_FILENAME is None:
print >> sys.stderr, ENVIRON_ERROR_MSG
sys.exit(1)
def get_environ(require_datastore=False, require_storage=False):
if require_datastore:
if DATASET_ID is None or CLIENT_EMAIL is None or KEY_FILENAME is None:
print >> sys.stderr, ENVIRON_ERROR_MSG
sys.exit(1)

if require_storage:
if PROJECT_ID is None or CLIENT_EMAIL is None or KEY_FILENAME is None:
print >> sys.stderr, ENVIRON_ERROR_MSG
sys.exit(1)

return {
'project_id': PROJECT_ID,
'dataset_id': DATASET_ID,
'client_email': CLIENT_EMAIL,
'key_filename': KEY_FILENAME,
}


def get_dataset():
environ = get_environ()
environ = get_environ(require_datastore=True)
get_dataset_args = (environ['dataset_id'], environ['client_email'],
environ['key_filename'])
if get_dataset_args not in DATASETS:
key = ('get_dataset', get_dataset_args)
if key not in CACHED_RETURN_VALS:
# Cache return value for the environment.
CACHED_RETURN_VALS[key] = datastore.get_dataset(*get_dataset_args)
return CACHED_RETURN_VALS[key]


def get_storage_connection():
environ = get_environ(require_storage=True)
get_connection_args = (environ['project_id'], environ['client_email'],
environ['key_filename'])
key = ('get_storage_connection', get_connection_args)
if key not in CACHED_RETURN_VALS:
# Cache return value for the environment.
DATASETS[get_dataset_args] = datastore.get_dataset(*get_dataset_args)
return DATASETS[get_dataset_args]
CACHED_RETURN_VALS[key] = storage.get_connection(*get_connection_args)
return CACHED_RETURN_VALS[key]
7 changes: 5 additions & 2 deletions regression/run_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def get_parser():
parser = argparse.ArgumentParser(
description='GCloud test runner against actual project.')
parser.add_argument('--package', dest='package',
choices=('datastore',),
choices=('datastore', 'storage'),
default='datastore', help='Package to be tested.')
return parser

Expand All @@ -27,7 +27,10 @@ def main():
parser = get_parser()
args = parser.parse_args()
# Make sure environ is set before running test.
regression_utils.get_environ()
if args.package == 'datastore':
regression_utils.get_environ(require_datastore=True)
elif args.package == 'storage':
regression_utils.get_environ(require_storage=True)
test_result = run_module_tests(args.package)
if not test_result.wasSuccessful():
sys.exit(1)
Expand Down
Loading

0 comments on commit fb3b3ba

Please sign in to comment.