| Index: tools/telemetry/third_party/gsutilz/gslib/tests/util.py
|
| diff --git a/tools/telemetry/third_party/gsutilz/gslib/tests/util.py b/tools/telemetry/third_party/gsutilz/gslib/tests/util.py
|
| deleted file mode 100644
|
| index 06da870bf8170ff8ee4b39b6ea028da57d0e795b..0000000000000000000000000000000000000000
|
| --- a/tools/telemetry/third_party/gsutilz/gslib/tests/util.py
|
| +++ /dev/null
|
| @@ -1,369 +0,0 @@
|
| -# -*- coding: utf-8 -*-
|
| -# Copyright 2013 Google Inc. All Rights Reserved.
|
| -#
|
| -# Licensed under the Apache License, Version 2.0 (the "License");
|
| -# you may not use this file except in compliance with the License.
|
| -# You may obtain a copy of the License at
|
| -#
|
| -# http://www.apache.org/licenses/LICENSE-2.0
|
| -#
|
| -# Unless required by applicable law or agreed to in writing, software
|
| -# distributed under the License is distributed on an "AS IS" BASIS,
|
| -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -# See the License for the specific language governing permissions and
|
| -# limitations under the License.
|
| -
|
| -from __future__ import absolute_import
|
| -
|
| -from contextlib import contextmanager
|
| -import functools
|
| -import os
|
| -import pkgutil
|
| -import posixpath
|
| -import re
|
| -import tempfile
|
| -import unittest
|
| -import urlparse
|
| -
|
| -import boto
|
| -import gslib.tests as gslib_tests
|
| -
|
| -if not hasattr(unittest.TestCase, 'assertIsNone'):
|
| - # external dependency unittest2 required for Python <= 2.6
|
| - import unittest2 as unittest # pylint: disable=g-import-not-at-top
|
| -
|
| -# Flags for running different types of tests.
|
| -RUN_INTEGRATION_TESTS = True
|
| -RUN_UNIT_TESTS = True
|
| -RUN_S3_TESTS = False
|
| -
|
| -PARALLEL_COMPOSITE_UPLOAD_TEST_CONFIG = '/tmp/.boto.parallel_upload_test_config'
|
| -
|
| -
|
| -def _HasS3Credentials():
|
| - return (boto.config.get('Credentials', 'aws_access_key_id', None) and
|
| - boto.config.get('Credentials', 'aws_secret_access_key', None))
|
| -
|
| -HAS_S3_CREDS = _HasS3Credentials()
|
| -
|
| -
|
| -def _HasGSHost():
|
| - return boto.config.get('Credentials', 'gs_host', None) is not None
|
| -
|
| -HAS_GS_HOST = _HasGSHost()
|
| -
|
| -
|
| -def _UsingJSONApi():
|
| - return boto.config.get('GSUtil', 'prefer_api', 'json').upper() != 'XML'
|
| -
|
| -USING_JSON_API = _UsingJSONApi()
|
| -
|
| -
|
| -def _ArgcompleteAvailable():
|
| - argcomplete = None
|
| - try:
|
| - # pylint: disable=g-import-not-at-top
|
| - import argcomplete
|
| - except ImportError:
|
| - pass
|
| - return argcomplete is not None
|
| -
|
| -ARGCOMPLETE_AVAILABLE = _ArgcompleteAvailable()
|
| -
|
| -
|
| -def _NormalizeURI(uri):
|
| - """Normalizes the path component of a URI.
|
| -
|
| - Args:
|
| - uri: URI to normalize.
|
| -
|
| - Returns:
|
| - Normalized URI.
|
| -
|
| - Examples:
|
| - gs://foo//bar -> gs://foo/bar
|
| - gs://foo/./bar -> gs://foo/bar
|
| - """
|
| - # Note: we have to do this dance of changing gs:// to file:// because on
|
| - # Windows, the urlparse function won't work with URL schemes that are not
|
| - # known. urlparse('gs://foo/bar') on Windows turns into:
|
| - # scheme='gs', netloc='', path='//foo/bar'
|
| - # while on non-Windows platforms, it turns into:
|
| - # scheme='gs', netloc='foo', path='/bar'
|
| - uri = uri.replace('gs://', 'file://')
|
| - parsed = list(urlparse.urlparse(uri))
|
| - parsed[2] = posixpath.normpath(parsed[2])
|
| - if parsed[2].startswith('//'):
|
| - # The normpath function doesn't change '//foo' -> '/foo' by design.
|
| - parsed[2] = parsed[2][1:]
|
| - unparsed = urlparse.urlunparse(parsed)
|
| - unparsed = unparsed.replace('file://', 'gs://')
|
| - return unparsed
|
| -
|
| -
|
| -def GenerationFromURI(uri):
|
| - """Returns a the generation for a StorageUri.
|
| -
|
| - Args:
|
| - uri: boto.storage_uri.StorageURI object to get the URI from.
|
| -
|
| - Returns:
|
| - Generation string for the URI.
|
| - """
|
| - if not (uri.generation or uri.version_id):
|
| - if uri.scheme == 's3': return 'null'
|
| - return uri.generation or uri.version_id
|
| -
|
| -
|
| -def ObjectToURI(obj, *suffixes):
|
| - """Returns the storage URI string for a given StorageUri or file object.
|
| -
|
| - Args:
|
| - obj: The object to get the URI from. Can be a file object, a subclass of
|
| - boto.storage_uri.StorageURI, or a string. If a string, it is assumed to
|
| - be a local on-disk path.
|
| - *suffixes: Suffixes to append. For example, ObjectToUri(bucketuri, 'foo')
|
| - would return the URI for a key name 'foo' inside the given
|
| - bucket.
|
| -
|
| - Returns:
|
| - Storage URI string.
|
| - """
|
| - if isinstance(obj, file):
|
| - return 'file://%s' % os.path.abspath(os.path.join(obj.name, *suffixes))
|
| - if isinstance(obj, basestring):
|
| - return 'file://%s' % os.path.join(obj, *suffixes)
|
| - uri = obj.uri
|
| - if suffixes:
|
| - uri = _NormalizeURI('/'.join([uri] + list(suffixes)))
|
| -
|
| - # Storage URIs shouldn't contain a trailing slash.
|
| - if uri.endswith('/'):
|
| - uri = uri[:-1]
|
| - return uri
|
| -
|
| -# The mock storage service comes from the Boto library, but it is not
|
| -# distributed with Boto when installed as a package. To get around this, we
|
| -# copy the file to gslib/tests/mock_storage_service.py when building the gsutil
|
| -# package. Try and import from both places here.
|
| -# pylint: disable=g-import-not-at-top
|
| -try:
|
| - from gslib.tests import mock_storage_service
|
| -except ImportError:
|
| - try:
|
| - from boto.tests.integration.s3 import mock_storage_service
|
| - except ImportError:
|
| - try:
|
| - from tests.integration.s3 import mock_storage_service
|
| - except ImportError:
|
| - import mock_storage_service
|
| -
|
| -
|
| -class GSMockConnection(mock_storage_service.MockConnection):
|
| -
|
| - def __init__(self, *args, **kwargs):
|
| - kwargs['provider'] = 'gs'
|
| - self.debug = 0
|
| - super(GSMockConnection, self).__init__(*args, **kwargs)
|
| -
|
| -mock_connection = GSMockConnection()
|
| -
|
| -
|
| -class GSMockBucketStorageUri(mock_storage_service.MockBucketStorageUri):
|
| -
|
| - def connect(self, access_key_id=None, secret_access_key=None):
|
| - return mock_connection
|
| -
|
| - def compose(self, components, headers=None):
|
| - """Dummy implementation to allow parallel uploads with tests."""
|
| - return self.new_key()
|
| -
|
| -
|
| -TEST_BOTO_REMOVE_SECTION = 'TestRemoveSection'
|
| -
|
| -
|
| -def _SetBotoConfig(section, name, value, revert_list):
|
| - """Sets boto configuration temporarily for testing.
|
| -
|
| - SetBotoConfigForTest and SetBotoConfigFileForTest should be called by tests
|
| - instead of this function. Those functions will ensure that the configuration
|
| - is reverted to its original setting using _RevertBotoConfig.
|
| -
|
| - Args:
|
| - section: Boto config section to set
|
| - name: Boto config name to set
|
| - value: Value to set
|
| - revert_list: List for tracking configs to revert.
|
| - """
|
| - prev_value = boto.config.get(section, name, None)
|
| - if not boto.config.has_section(section):
|
| - revert_list.append((section, TEST_BOTO_REMOVE_SECTION, None))
|
| - boto.config.add_section(section)
|
| - revert_list.append((section, name, prev_value))
|
| - if value is None:
|
| - boto.config.remove_option(section, name)
|
| - else:
|
| - boto.config.set(section, name, value)
|
| -
|
| -
|
| -def _RevertBotoConfig(revert_list):
|
| - """Reverts boto config modifications made by _SetBotoConfig.
|
| -
|
| - Args:
|
| - revert_list: List of boto config modifications created by calls to
|
| - _SetBotoConfig.
|
| - """
|
| - sections_to_remove = []
|
| - for section, name, value in revert_list:
|
| - if value is None:
|
| - if name == TEST_BOTO_REMOVE_SECTION:
|
| - sections_to_remove.append(section)
|
| - else:
|
| - boto.config.remove_option(section, name)
|
| - else:
|
| - boto.config.set(section, name, value)
|
| - for section in sections_to_remove:
|
| - boto.config.remove_section(section)
|
| -
|
| -
|
| -def PerformsFileToObjectUpload(func):
|
| - """Decorator indicating that a test uploads from a local file to an object.
|
| -
|
| - This forces the test to run once normally, and again with special boto
|
| - config settings that will ensure that the test follows the parallel composite
|
| - upload code path.
|
| -
|
| - Args:
|
| - func: Function to wrap.
|
| -
|
| - Returns:
|
| - Wrapped function.
|
| - """
|
| - @functools.wraps(func)
|
| - def Wrapper(*args, **kwargs):
|
| - # Run the test normally once.
|
| - func(*args, **kwargs)
|
| -
|
| - # Try again, forcing parallel composite uploads.
|
| - with SetBotoConfigForTest([
|
| - ('GSUtil', 'parallel_composite_upload_threshold', '1'),
|
| - ('GSUtil', 'check_hashes', 'always')]):
|
| - func(*args, **kwargs)
|
| -
|
| - return Wrapper
|
| -
|
| -
|
| -@contextmanager
|
| -def SetBotoConfigForTest(boto_config_list):
|
| - """Sets the input list of boto configs for the duration of a 'with' clause.
|
| -
|
| - Args:
|
| - boto_config_list: list of tuples of:
|
| - (boto config section to set, boto config name to set, value to set)
|
| -
|
| - Yields:
|
| - Once after config is set.
|
| - """
|
| - revert_configs = []
|
| - tmp_filename = None
|
| - try:
|
| - tmp_fd, tmp_filename = tempfile.mkstemp(prefix='gsutil-temp-cfg')
|
| - os.close(tmp_fd)
|
| - for boto_config in boto_config_list:
|
| - _SetBotoConfig(boto_config[0], boto_config[1], boto_config[2],
|
| - revert_configs)
|
| - with open(tmp_filename, 'w') as tmp_file:
|
| - boto.config.write(tmp_file)
|
| -
|
| - with SetBotoConfigFileForTest(tmp_filename):
|
| - yield
|
| - finally:
|
| - _RevertBotoConfig(revert_configs)
|
| - if tmp_filename:
|
| - try:
|
| - os.remove(tmp_filename)
|
| - except OSError:
|
| - pass
|
| -
|
| -
|
| -@contextmanager
|
| -def SetEnvironmentForTest(env_variable_dict):
|
| - """Sets OS environment variables for a single test."""
|
| -
|
| - def _ApplyDictToEnvironment(dict_to_apply):
|
| - for k, v in dict_to_apply.iteritems():
|
| - old_values[k] = os.environ.get(k)
|
| - if v is not None:
|
| - os.environ[k] = v
|
| - elif k in os.environ:
|
| - del os.environ[k]
|
| -
|
| - old_values = {}
|
| - for k in env_variable_dict:
|
| - old_values[k] = os.environ.get(k)
|
| -
|
| - try:
|
| - _ApplyDictToEnvironment(env_variable_dict)
|
| - yield
|
| - finally:
|
| - _ApplyDictToEnvironment(old_values)
|
| -
|
| -
|
| -@contextmanager
|
| -def SetBotoConfigFileForTest(boto_config_path):
|
| - """Sets a given file as the boto config file for a single test."""
|
| - # Setup for entering "with" block.
|
| - try:
|
| - old_boto_config_env_variable = os.environ['BOTO_CONFIG']
|
| - boto_config_was_set = True
|
| - except KeyError:
|
| - boto_config_was_set = False
|
| - os.environ['BOTO_CONFIG'] = boto_config_path
|
| -
|
| - try:
|
| - yield
|
| - finally:
|
| - # Teardown for exiting "with" block.
|
| - if boto_config_was_set:
|
| - os.environ['BOTO_CONFIG'] = old_boto_config_env_variable
|
| - else:
|
| - os.environ.pop('BOTO_CONFIG', None)
|
| -
|
| -
|
| -def GetTestNames():
|
| - """Returns a list of the names of the test modules in gslib.tests."""
|
| - matcher = re.compile(r'^test_(?P<name>.*)$')
|
| - names = []
|
| - for _, modname, _ in pkgutil.iter_modules(gslib_tests.__path__):
|
| - m = matcher.match(modname)
|
| - if m:
|
| - names.append(m.group('name'))
|
| - return names
|
| -
|
| -
|
| -@contextmanager
|
| -def WorkingDirectory(new_working_directory):
|
| - """Changes the working directory for the duration of a 'with' call.
|
| -
|
| - Args:
|
| - new_working_directory: The directory to switch to before executing wrapped
|
| - code. A None value indicates that no switching is necessary.
|
| -
|
| - Yields:
|
| - Once after working directory has been changed.
|
| - """
|
| - prev_working_directory = None
|
| - try:
|
| - prev_working_directory = os.getcwd()
|
| - except OSError:
|
| - # This can happen if the current working directory no longer exists.
|
| - pass
|
| -
|
| - if new_working_directory:
|
| - os.chdir(new_working_directory)
|
| -
|
| - try:
|
| - yield
|
| - finally:
|
| - if new_working_directory and prev_working_directory:
|
| - os.chdir(prev_working_directory)
|
|
|