| Index: third_party/gsutil/gslib/test_commands.py
|
| diff --git a/third_party/gsutil/gslib/test_commands.py b/third_party/gsutil/gslib/test_commands.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..1772afe0f54461f84f6d6cf03cdee8817ba4b1bb
|
| --- /dev/null
|
| +++ b/third_party/gsutil/gslib/test_commands.py
|
| @@ -0,0 +1,1252 @@
|
| +#!/usr/bin/env python
|
| +# Copyright 2010 Google Inc.
|
| +#
|
| +# Permission is hereby granted, free of charge, to any person obtaining a
|
| +# copy of this software and associated documentation files (the
|
| +# "Software"), to deal in the Software without restriction, including
|
| +# without limitation the rights to use, copy, modify, merge, publish, dis-
|
| +# tribute, sublicense, and/or sell copies of the Software, and to permit
|
| +# persons to whom the Software is furnished to do so, subject to the fol-
|
| +# lowing conditions:
|
| +#
|
| +# The above copyright notice and this permission notice shall be included
|
| +# in all copies or substantial portions of the Software.
|
| +#
|
| +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
| +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
|
| +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
| +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
| +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
| +# IN THE SOFTWARE.
|
| +
|
| +"""Tests for gsutil commands.
|
| +The test code in this file runs against an in-memory storage service mock,
|
| +so runs very quickly. This is valuable for testing changes that impact the
|
| +naming rules, since those rules are complex and it's useful to be able to
|
| +make small incremental changes and rerun the tests frequently. Additional
|
| +end-to-end tests (which send traffic to the production Google Cloud Storage
|
| +service) are available via the gsutil test command.
|
| +"""
|
| +
|
| +import os
|
| +import shutil
|
| +import sys
|
| +import tempfile
|
| +import time
|
| +import unittest
|
| +import wildcard_iterator
|
| +
|
| +# Put local libs at front of path so tests will run latest lib code rather
|
| +# than whatever code is found on user's PYTHONPATH.
|
| +sys.path.insert(0, '.')
|
| +sys.path.insert(0, 'boto')
|
| +import boto
|
| +
|
| +from boto.exception import StorageResponseError
|
| +from boto import storage_uri
|
| +from gslib.command_runner import CommandRunner
|
| +from gslib.commands import cp
|
| +from gslib.exception import CommandException
|
| +from gslib import test_util
|
| +from tests.integration.s3.mock_storage_service import MockBucketStorageUri
|
| +
|
| +
|
| +class GsutilCommandTests(unittest.TestCase):
|
| + """gsutil command method test suite"""
|
| +
|
| + # We don't use the gsutil boto config discovery logic here, as it assumes
|
| + # boto is a subdirectory of where the command is running, which is gslib
|
| + # when running these tests. Instead we use a simplified setup:
|
| + gsutil_bin_dir = '.'
|
| + boto_lib_dir = os.path.join(gsutil_bin_dir, 'boto')
|
| + config_file_list = boto.pyami.config.BotoConfigLocations
|
| + # Use "gsutil_test_commands" as a fake UserAgent. This value will never be
|
| + # sent via HTTP because we're using MockStorageService here.
|
| + command_runner = CommandRunner(gsutil_bin_dir, boto_lib_dir, config_file_list,
|
| + "gsutil_test_commands", MockBucketStorageUri)
|
| +
|
| + def GetSuiteDescription(self):
|
| + return 'gsutil command method test suite'
|
| +
|
| + @classmethod
|
| + def tearDown(cls):
|
| + """Deletes any objects or files created by last test run"""
|
| + try:
|
| + for key_uri in test_util.test_wildcard_iterator(
|
| + '%s**' % cls.dst_bucket_uri).IterUris():
|
| + key_uri.delete_key()
|
| + # For some reason trying to catch except
|
| + # wildcard_iterator.WildcardException doesn't work here.
|
| + except Exception:
|
| + # Ignore cleanup failures.
|
| + pass
|
| + # Recursively delete dst dir and then re-create it, so in effect we
|
| + # remove all dirs and files under that directory.
|
| + shutil.rmtree(cls.dst_dir_root)
|
| + os.mkdir(cls.dst_dir_root)
|
| +
|
| + @classmethod
|
| + def SrcFile(cls, fname):
|
| + """Returns path for given test src file"""
|
| + for path in cls.all_src_file_paths:
|
| + if path.find(fname) != -1:
|
| + return path
|
| + raise Exception('SrcFile(%s): no match' % fname)
|
| +
|
| + @classmethod
|
| + def CreateEmptyObject(cls, uri):
|
| + """Creates an empty object for the given StorageUri"""
|
| + key = uri.new_key()
|
| + key.set_contents_from_string('')
|
| +
|
| + @classmethod
|
| + def SetUpClass(cls):
|
| + """Initializes test suite.
|
| +
|
| + Creates a source bucket containing 9 objects, 3 of which live under a
|
| + subdir, 3 of which lives under a nested subdir; a source directory
|
| + containing a subdirectory and file; and a destination bucket and directory.
|
| + """
|
| + cls.uri_base_str = 'gs://gsutil_test_%s' % int(time.time())
|
| + # Use a designated tmpdir prefix to make it easy to find the end of
|
| + # the tmp path.
|
| + cls.tmpdir_prefix = 'tmp_gstest'
|
| +
|
| + # Create the test buckets.
|
| + cls.src_bucket_uri = test_util.test_storage_uri('%s_src' % cls.uri_base_str)
|
| + cls.dst_bucket_uri = test_util.test_storage_uri('%s_dst' % cls.uri_base_str)
|
| + cls.src_bucket_uri.create_bucket()
|
| +
|
| + # Define the src and dest bucket subdir paths. Note that they exclude
|
| + # a slash on the end so we can test handling of bucket subdirs specified
|
| + # both with and without terminating slashes.
|
| + cls.src_bucket_subdir_uri = test_util.test_storage_uri(
|
| + '%s_src/src_subdir' % cls.uri_base_str)
|
| + cls.src_bucket_subdir_uri_wildcard = test_util.test_storage_uri(
|
| + '%s_src/src_sub*' % cls.uri_base_str)
|
| + cls.dst_bucket_subdir_uri = test_util.test_storage_uri(
|
| + '%s_dst/dst_subdir' % cls.uri_base_str)
|
| + cls.dst_bucket_uri.create_bucket()
|
| +
|
| + # Create the test objects in the src bucket.
|
| + cls.all_src_obj_uris = []
|
| + cls.all_src_top_level_obj_uris = []
|
| + cls.all_src_subdir_obj_uris = []
|
| + cls.all_src_subdir_and_below_obj_uris = []
|
| + for i in range(3):
|
| + obj_uri = test_util.test_storage_uri('%sobj%d' % (cls.src_bucket_uri, i))
|
| + cls.CreateEmptyObject(obj_uri)
|
| + cls.all_src_obj_uris.append(obj_uri)
|
| + cls.all_src_top_level_obj_uris.append(obj_uri)
|
| + # Subdir objects
|
| + for i in range(4, 6):
|
| + obj_uri = test_util.test_storage_uri(
|
| + '%s/obj%d' % (cls.src_bucket_subdir_uri, i))
|
| + cls.CreateEmptyObject(obj_uri)
|
| + cls.all_src_obj_uris.append(obj_uri)
|
| + cls.all_src_subdir_obj_uris.append(obj_uri)
|
| + cls.all_src_subdir_and_below_obj_uris.append(obj_uri)
|
| + # Nested subdir objects
|
| + for i in range(7, 9):
|
| + obj_uri = test_util.test_storage_uri(
|
| + '%s/nested/obj%d' % (cls.src_bucket_subdir_uri, i))
|
| + cls.CreateEmptyObject(obj_uri)
|
| + cls.all_src_obj_uris.append(obj_uri)
|
| + cls.all_src_subdir_and_below_obj_uris.append(obj_uri)
|
| +
|
| + # Create the test directories.
|
| + cls.src_dir_root = '%s%s' % (tempfile.mkdtemp(prefix=cls.tmpdir_prefix),
|
| + os.sep)
|
| + nested_subdir = '%sdir0%sdir1' % (cls.src_dir_root, os.sep)
|
| + os.makedirs(nested_subdir)
|
| + cls.dst_dir_root = '%s%s' % (tempfile.mkdtemp(prefix=cls.tmpdir_prefix),
|
| + os.sep)
|
| +
|
| + # Create the test files in the src directory.
|
| + cls.all_src_file_paths = []
|
| + cls.nested_child_file_paths = ['f0', 'f1', 'f2.txt', 'dir0/dir1/nested']
|
| + cls.non_nested_file_names = ['f0', 'f1', 'f2.txt']
|
| + file_names = ['f0', 'f1', 'f2.txt', 'dir0%sdir1%snested' % (os.sep, os.sep)]
|
| + file_paths = ['%s%s' % (cls.src_dir_root, f) for f in file_names]
|
| + for file_path in file_paths:
|
| + f = open(file_path, 'w')
|
| + f.write('test data')
|
| + f.close()
|
| + cls.all_src_file_paths.append(file_path)
|
| + cls.tmp_path = '%s%s' % (cls.src_dir_root, 'tmp0')
|
| +
|
| + cls.created_test_data = True
|
| +
|
| + @classmethod
|
| + def TearDownClass(cls):
|
| + """Cleans up buckets and directories created by SetUpClass"""
|
| +
|
| + if not hasattr(cls, 'created_test_data'):
|
| + return
|
| + # Call cls.tearDown() in case the tests got interrupted, to ensure
|
| + # dst objects and files get deleted.
|
| + cls.tearDown()
|
| + # Now delete src objects and files, and all buckets and dirs.
|
| + try:
|
| + for key_uri in test_util.test_wildcard_iterator(
|
| + '%s**' % cls.src_bucket_uri).IterUris():
|
| + key_uri.delete_key()
|
| + except wildcard_iterator.WildcardException:
|
| + # Ignore cleanup failures.
|
| + pass
|
| + try:
|
| + for key_uri in test_util.test_wildcard_iterator(
|
| + '%s**' % cls.src_dir_root).IterUris():
|
| + key_uri.delete_key()
|
| + except wildcard_iterator.WildcardException:
|
| + # Ignore cleanup failures.
|
| + pass
|
| + cls.src_bucket_uri.delete_bucket()
|
| + cls.dst_bucket_uri.delete_bucket()
|
| + shutil.rmtree(cls.src_dir_root)
|
| + shutil.rmtree(cls.dst_dir_root)
|
| +
|
| +
|
| + def RunCommand(self, command_name, args=None, headers=None, debug=0,
|
| + test_method=None, return_stdout=False):
|
| + """
|
| + Method for calling gslib.command_runner.CommandRunner, passing
|
| + parallel_operations=False for all tests, optionally saving/returning stdout
|
| + output. We run all tests multi-threaded, to exercise those more complicated
|
| + code paths.
|
| + TODO: change to run with parallel_operations=True for all tests. At
|
| + present when you do this it causes many test failures.
|
| +
|
| + Args:
|
| + command_name: The name of the command being run.
|
| + args: Command-line args (arg0 = actual arg, not command name ala bash).
|
| + headers: Dictionary containing optional HTTP headers to pass to boto.
|
| + debug: Debug level to pass in to boto connection (range 0..3).
|
| + parallel_operations: Should command operations be executed in parallel?
|
| + test_method: Optional general purpose method for testing purposes.
|
| + Application and semantics of this method will vary by
|
| + command and test type.
|
| + return_stdout: If true will save and return stdout produced by command.
|
| + """
|
| + sys.stderr.write('\nRunning test of %s %s\n' %
|
| + (command_name, ' '.join(args)))
|
| + if return_stdout:
|
| + # Redirect stdout temporarily, to save output to a file.
|
| + tmpfile = tempfile.mkstemp()[1]
|
| + stdout_sav = sys.stdout
|
| + try:
|
| + fp = open(tmpfile, 'w')
|
| + sys.stdout = fp
|
| + self.command_runner.RunNamedCommand(
|
| + command_name, args=args, headers=headers, debug=debug,
|
| + parallel_operations=False, test_method=test_method)
|
| + finally:
|
| + fp.close()
|
| + sys.stdout = stdout_sav
|
| + output = open(tmpfile, 'r').read()
|
| + os.unlink(tmpfile)
|
| + return output
|
| + else:
|
| + self.command_runner.RunNamedCommand(
|
| + command_name, args=args, headers=headers, debug=debug,
|
| + parallel_operations=False, test_method=test_method)
|
| +
|
| + def TestGetPathBeforeFinalDir(self):
|
| + """Tests _GetPathBeforeFinalDir() (unit test)"""
|
| + self.assertEqual('gs://',
|
| + cp._GetPathBeforeFinalDir(storage_uri('gs://bucket/')))
|
| + self.assertEqual('gs://bucket',
|
| + cp._GetPathBeforeFinalDir(storage_uri('gs://bucket/dir/')))
|
| + self.assertEqual('gs://bucket',
|
| + cp._GetPathBeforeFinalDir(storage_uri('gs://bucket/dir')))
|
| + self.assertEqual('gs://bucket/dir',
|
| + cp._GetPathBeforeFinalDir(
|
| + storage_uri('gs://bucket/dir/obj')))
|
| + self.assertEqual('file://%s' % self.src_dir_root.rstrip('/'),
|
| + cp._GetPathBeforeFinalDir(storage_uri(
|
| + 'file://%sdir0/' % self.src_dir_root)))
|
| +
|
| + def TestCopyingTopLevelFileToBucket(self):
|
| + """Tests copying one top-level file to a bucket"""
|
| + src_file = self.SrcFile('f0')
|
| + self.RunCommand('cp', [src_file, self.dst_bucket_uri.uri])
|
| + actual = list(test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_uri.uri).IterUris())
|
| + self.assertEqual(1, len(actual))
|
| + self.assertEqual('f0', actual[0].object_name)
|
| +
|
| + def TestCopyingAbsolutePathDirToBucket(self):
|
| + """Tests recursively copying absolute path directory to a bucket"""
|
| + self.RunCommand('cp', ['-R', self.src_dir_root, self.dst_bucket_uri.uri])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_uri.uri).IterUris())
|
| + expected = set()
|
| + for file_path in self.all_src_file_paths:
|
| + start_tmp_pos = file_path.find(self.tmpdir_prefix)
|
| + file_path_sans_top_tmp_dir = file_path[start_tmp_pos:]
|
| + expected.add('%s%s' % (self.dst_bucket_uri.uri,
|
| + file_path_sans_top_tmp_dir))
|
| + self.assertEqual(expected, actual)
|
| +
|
| + def TestCopyingRelativePathDirToBucket(self):
|
| + """Tests recursively copying relative directory to a bucket"""
|
| + orig_dir = os.getcwd()
|
| + os.chdir(self.src_dir_root)
|
| + self.RunCommand('cp', ['-R', 'dir0', self.dst_bucket_uri.uri])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_uri.uri).IterUris())
|
| + expected = set()
|
| + for file_path in self.all_src_file_paths:
|
| + start_tmp_pos = file_path.find(self.tmpdir_prefix)
|
| + file_path_sans_top_tmp_dir = file_path[start_tmp_pos:]
|
| + expected.add('%s%s' % (self.dst_bucket_uri.uri, 'dir0/dir1/nested'))
|
| + self.assertEqual(expected, actual)
|
| + os.chdir(orig_dir)
|
| +
|
| + def TestCopyingRelativePathSubDirToBucketSubdirSignifiedByDollarFolderObj(self):
|
| + """Tests recursively copying relative sub-directory to bucket subdir signified by a $folder$ object"""
|
| + orig_dir = os.getcwd()
|
| + os.chdir(self.src_dir_root)
|
| + # Create a $folder$ object to simulate a folder created by GCS manager (or
|
| + # various other tools), which gsutil understands to mean there is a folder into
|
| + # which the object is being copied.
|
| + obj_name = '%sabc_$folder$' % self.dst_bucket_uri
|
| + self.CreateEmptyObject(test_util.test_storage_uri(obj_name))
|
| + self.RunCommand('cp', ['-R', 'dir0/dir1', '%sabc'
|
| + % self.dst_bucket_uri.uri])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_uri.uri).IterUris())
|
| + expected = set([obj_name])
|
| + for file_path in self.all_src_file_paths:
|
| + start_tmp_pos = file_path.find(self.tmpdir_prefix)
|
| + file_path_sans_top_tmp_dir = file_path[start_tmp_pos:]
|
| + expected.add('%sabc/%s' % (self.dst_bucket_uri.uri, 'dir1/nested'))
|
| + self.assertEqual(expected, actual)
|
| + os.chdir(orig_dir)
|
| +
|
| + def TestCopyingRelativePathSubDirToBucketSubdirSignifiedBySlash(self):
|
| + """Tests recursively copying relative sub-directory to bucket subdir signified by a / object"""
|
| + orig_dir = os.getcwd()
|
| + os.chdir(self.src_dir_root)
|
| + self.RunCommand('cp', ['-R', 'dir0/dir1', '%sabc/'
|
| + % self.dst_bucket_uri.uri])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_uri.uri).IterUris())
|
| + expected = set()
|
| + for file_path in self.all_src_file_paths:
|
| + start_tmp_pos = file_path.find(self.tmpdir_prefix)
|
| + file_path_sans_top_tmp_dir = file_path[start_tmp_pos:]
|
| + expected.add('%sabc/%s' % (self.dst_bucket_uri.uri, 'dir1/nested'))
|
| + self.assertEqual(expected, actual)
|
| + os.chdir(orig_dir)
|
| +
|
| + def TestCopyingRelativePathSubDirToBucket(self):
|
| + """Tests recursively copying relative sub-directory to a bucket"""
|
| + orig_dir = os.getcwd()
|
| + os.chdir(self.src_dir_root)
|
| + self.RunCommand('cp', ['-R', 'dir0/dir1', self.dst_bucket_uri.uri])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_uri.uri).IterUris())
|
| + expected = set()
|
| + for file_path in self.all_src_file_paths:
|
| + start_tmp_pos = file_path.find(self.tmpdir_prefix)
|
| + file_path_sans_top_tmp_dir = file_path[start_tmp_pos:]
|
| + expected.add('%s%s' % (self.dst_bucket_uri.uri, 'dir1/nested'))
|
| + self.assertEqual(expected, actual)
|
| + os.chdir(orig_dir)
|
| +
|
| + def TestCopyingDotSlashToBucket(self):
|
| + """Tests copying ./ to a bucket produces expected naming"""
|
| + # When running a command like gsutil cp -r . gs://dest we expect the dest
|
| + # obj names to be of the form gs://dest/abc, not gs://dest/./abc.
|
| + orig_dir = os.getcwd()
|
| + for rel_src_dir in ['.', './']:
|
| + os.chdir(self.src_dir_root)
|
| + self.RunCommand('cp', ['-R', rel_src_dir, self.dst_bucket_uri.uri])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_uri.uri).IterUris())
|
| + expected = set()
|
| + for file_path in self.all_src_file_paths:
|
| + start_tmp_pos = (file_path.find(self.src_dir_root)
|
| + + len(self.src_dir_root))
|
| + file_path_sans_top_tmp_dir = file_path[start_tmp_pos:]
|
| + expected.add('%s%s' % (self.dst_bucket_uri.uri,
|
| + file_path_sans_top_tmp_dir))
|
| + self.assertEqual(expected, actual)
|
| + # Clean up/re-set up for next variant iteration.
|
| + self.TearDownClass()
|
| + self.SetUpClass()
|
| + os.chdir(orig_dir)
|
| +
|
| + def TestCopyingDirContainingOneFileToBucket(self):
|
| + """Tests copying a directory containing 1 file to a bucket.
|
| + We test this case to ensure that correct bucket handling isn't dependent
|
| + on the copy being treated as a multi-source copy.
|
| + """
|
| + self.RunCommand('cp', ['-R', '%sdir0%sdir1' %
|
| + (self.src_dir_root, os.sep),
|
| + self.dst_bucket_uri.uri])
|
| + actual = list((str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_uri.uri).IterUris()))
|
| + self.assertEqual(1, len(actual))
|
| + self.assertEqual('%sdir1%snested' % (self.dst_bucket_uri.uri, os.sep),
|
| + actual[0])
|
| +
|
| + def TestCopyingBucketToDir(self):
|
| + """Tests copying from a bucket to a directory"""
|
| + self.RunCommand('cp', ['-R', self.src_bucket_uri.uri, self.dst_dir_root])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_dir_root).IterUris())
|
| + expected = set()
|
| + for uri in self.all_src_obj_uris:
|
| + expected.add('file://%s%s/%s' % (self.dst_dir_root, uri.bucket_name,
|
| + uri.object_name))
|
| + self.assertEqual(expected, actual)
|
| +
|
| + def TestCopyingBucketToBucket(self):
|
| + """Tests copying from a bucket-only URI to a bucket"""
|
| + self.RunCommand('cp', ['-R', self.src_bucket_uri.uri,
|
| + self.dst_bucket_uri.uri])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_uri.uri).IterUris())
|
| + expected = set()
|
| + for uri in self.all_src_obj_uris:
|
| + expected.add('%s%s/%s' % (self.dst_bucket_uri.uri, uri.bucket_name,
|
| + uri.object_name))
|
| + self.assertEqual(expected, actual)
|
| +
|
| + """Tests copying from a directory to a directory"""
|
| + self.RunCommand('cp', ['-R', self.src_dir_root, self.dst_dir_root])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_dir_root).IterUris())
|
| + expected = set()
|
| + for file_path in self.all_src_file_paths:
|
| + start_tmp_pos = file_path.find(self.tmpdir_prefix)
|
| + file_path_sans_top_tmp_dir = file_path[start_tmp_pos:]
|
| + expected.add('file://%s%s' % (self.dst_dir_root,
|
| + file_path_sans_top_tmp_dir))
|
| + self.assertEqual(expected, actual)
|
| +
|
| + def TestCopyingFilesAndDirNonRecursive(self):
|
| + """Tests copying containing files and a directory without -R"""
|
| + self.RunCommand('cp', ['%s*' % self.src_dir_root, self.dst_dir_root])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_dir_root).IterUris())
|
| + expected = set(['file://%s%s' % (self.dst_dir_root, f)
|
| + for f in self.non_nested_file_names])
|
| + self.assertEqual(expected, actual)
|
| +
|
| + def TestCopyingFileToDir(self):
|
| + """Tests copying one file to a directory"""
|
| + src_file = self.SrcFile('nested')
|
| + self.RunCommand('cp', [src_file, self.dst_dir_root])
|
| + actual = list(test_util.test_wildcard_iterator(
|
| + '%s*' % self.dst_dir_root).IterUris())
|
| + self.assertEqual(1, len(actual))
|
| + self.assertEqual('file://%s%s' % (self.dst_dir_root, 'nested'),
|
| + actual[0].uri)
|
| +
|
| + def TestCopyingFileToObjectWithConsecutiveSlashes(self):
|
| + """Tests copying a file to an object containing consecutive slashes"""
|
| + src_file = self.SrcFile('f0')
|
| + self.RunCommand('cp', [src_file, '%s/obj' % self.dst_bucket_uri.uri])
|
| + actual = list(test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_uri.uri).IterUris())
|
| + self.assertEqual(1, len(actual))
|
| + self.assertEqual('/obj', actual[0].object_name)
|
| +
|
| + def TestCopyingCompressedFileToBucket(self):
|
| + """Tests copying one file with compression to a bucket"""
|
| + src_file = self.SrcFile('f2.txt')
|
| + self.RunCommand('cp', ['-z', 'txt', src_file, self.dst_bucket_uri.uri],)
|
| + actual = list(
|
| + str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s*' % self.dst_bucket_uri.uri).IterUris())
|
| + self.assertEqual(1, len(actual))
|
| + expected_dst_uri = self.dst_bucket_uri.clone_replace_name('f2.txt')
|
| + self.assertEqual(expected_dst_uri.uri, actual[0])
|
| + dst_key = expected_dst_uri.get_key()
|
| + dst_key.open_read()
|
| + self.assertEqual('gzip', dst_key.content_encoding)
|
| +
|
| + def TestCopyingObjectToObject(self):
|
| + """Tests copying an object to an object"""
|
| + self.RunCommand('cp', ['%sobj1' % self.src_bucket_uri.uri,
|
| + self.dst_bucket_uri.uri])
|
| + actual = list(test_util.test_wildcard_iterator(
|
| + '%s*' % self.dst_bucket_uri.uri).IterUris())
|
| + self.assertEqual(1, len(actual))
|
| + self.assertEqual('obj1', actual[0].object_name)
|
| +
|
| + def TestCopyingObjsAndFilesToDir(self):
|
| + """Tests copying objects and files to a directory"""
|
| + self.RunCommand('cp', ['-R', '%s**' % self.src_bucket_uri.uri,
|
| + '%s**' % self.src_dir_root, self.dst_dir_root])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_dir_root).IterUris())
|
| + expected = set()
|
| + for uri in self.all_src_obj_uris:
|
| + # Use FinalObjNameComponent here because we expect names to be flattened
|
| + # when using wildcard copy semantics.
|
| + expected.add('file://%s%s' % (self.dst_dir_root,
|
| + self.FinalObjNameComponent(uri)))
|
| + for file_path in self.nested_child_file_paths:
|
| + # Use os.path.basename here because we expect names to be flattened when
|
| + # using wildcard copy semantics.
|
| + expected.add('file://%s%s' % (self.dst_dir_root,
|
| + os.path.basename(file_path)))
|
| + self.assertEqual(expected, actual)
|
| +
|
| + def TestCopyingObjToDot(self):
|
| + """Tests that copying an object to . or ./ downloads to correct name"""
|
| + for final_char in ('/', ''):
|
| + prev_dir = os.getcwd()
|
| + os.chdir(self.dst_dir_root)
|
| + self.RunCommand('cp',
|
| + ['%sobj1' % self.src_bucket_uri.uri, '.%s' % final_char])
|
| + actual = set()
|
| + for dirname, dirnames, filenames in os.walk('.'):
|
| + for subdirname in dirnames:
|
| + actual.add(os.path.join(dirname, subdirname))
|
| + for filename in filenames:
|
| + actual.add(os.path.join(dirname, filename))
|
| + expected = set(['./obj1'])
|
| + self.assertEqual(expected, actual)
|
| + os.chdir(prev_dir)
|
| + # Clean up/re-set up for next variant iteration.
|
| + self.TearDownClass()
|
| + self.SetUpClass()
|
| +
|
| + def TestCopyingObjsAndFilesToBucket(self):
|
| + """Tests copying objects and files to a bucket"""
|
| + self.RunCommand('cp', ['-R', '%s**' % self.src_bucket_uri.uri,
|
| + '%s**' % self.src_dir_root, self.dst_bucket_uri.uri])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s*' % self.dst_bucket_uri.uri).IterUris())
|
| + expected = set()
|
| + for uri in self.all_src_obj_uris:
|
| + # Use FinalObjNameComponent here because we expect names to be flattened
|
| + # when using wildcard copy semantics.
|
| + expected.add('%s%s' % (self.dst_bucket_uri.uri,
|
| + self.FinalObjNameComponent(uri)))
|
| + for file_path in self.nested_child_file_paths:
|
| + # Use os.path.basename here because we expect names to be flattened when
|
| + # using wildcard copy semantics.
|
| + expected.add('%s%s' % (self.dst_bucket_uri.uri,
|
| + os.path.basename(file_path)))
|
| + self.assertEqual(expected, actual)
|
| +
|
| + def TestAttemptDirCopyWithoutRecursion(self):
|
| + """Tests copying a directory without -R"""
|
| + try:
|
| + self.RunCommand('cp', [self.src_dir_root,
|
| + self.dst_dir_root])
|
| + self.fail('Did not get expected CommandException')
|
| + except CommandException, e:
|
| + self.assertNotEqual(e.reason.find('No URIs matched'), -1)
|
| +
|
| + def TestAttemptCopyingProviderOnlySrc(self):
|
| + """Attempts to copy a src specified as a provider-only URI"""
|
| + try:
|
| + self.RunCommand('cp', ['gs://', self.src_bucket_uri.uri])
|
| + self.fail('Did not get expected CommandException')
|
| + except CommandException, e:
|
| + self.assertNotEqual(e.reason.find('provider-only'), -1)
|
| +
|
| + def TestAttemptCopyingOverlappingSrcDstFile(self):
|
| + """Attempts to an object atop itself"""
|
| + obj_uri = test_util.test_storage_uri('%sobj' % self.dst_bucket_uri)
|
| + self.CreateEmptyObject(obj_uri)
|
| + try:
|
| + self.RunCommand('cp', ['%s/f0' % self.src_dir_root,
|
| + '%s/f0' % self.src_dir_root])
|
| + self.fail('Did not get expected CommandException')
|
| + except CommandException, e:
|
| + self.assertNotEqual(e.reason.find('are the same file - abort'), -1)
|
| +
|
| + def TestAttemptCopyingToMultiMatchWildcard(self):
|
| + """Attempts to copy where dst wildcard matches >1 obj"""
|
| + try:
|
| + self.RunCommand('cp', ['%sobj0' % self.src_bucket_uri.uri,
|
| + '%s*' % self.src_bucket_uri.uri])
|
| + self.fail('Did not get expected CommandException')
|
| + except CommandException, e:
|
| + self.assertNotEqual(e.reason.find('must match exactly 1 URI'), -1)
|
| +
|
| + def TestAttemptCopyingMultiObjsToFile(self):
|
| + """Attempts to copy multiple objects to a file"""
|
| + # Use src_dir_root so we can point to an existing file for this test.
|
| + try:
|
| + self.RunCommand('cp', ['-R', '%s*' % self.src_bucket_uri.uri,
|
| + '%sf0' % self.src_dir_root])
|
| + self.fail('Did not get expected CommandException')
|
| + except CommandException, e:
|
| + self.assertNotEqual(e.reason.find('must name a cloud path or '), -2)
|
| +
|
| + def TestAttemptCopyingWithFileDirConflict(self):
|
| + """Attempts to copy objects that cause a file/directory conflict"""
|
| + # Create objects with name conflicts (a/b and a). Use 'dst' bucket because
|
| + # it gets cleared after each test.
|
| + self.CreateEmptyObject(test_util.test_storage_uri(
|
| + '%sa/b' % self.dst_bucket_uri))
|
| + self.CreateEmptyObject(test_util.test_storage_uri(
|
| + '%sa' % self.dst_bucket_uri))
|
| + try:
|
| + self.RunCommand('cp', ['-R', self.dst_bucket_uri.uri,
|
| + self.dst_dir_root])
|
| + self.fail('Did not get expected CommandException')
|
| + except CommandException, e:
|
| + self.assertNotEqual(e.reason.find(
|
| + 'exists where a directory needs to be created'), -1)
|
| +
|
| + def TestAttemptCopyingWithDirFileConflict(self):
|
| + """Attempts to copy an object that causes a directory/file conflict"""
|
| + # Create abc in dest dir.
|
| + os.mkdir('%sabc' % self.dst_dir_root)
|
| + # Create an object that conflicts with this dest subdir. Use 'dst' bucket
|
| + # as source because it gets cleared after each test.
|
| + obj_name = '%sabc' % self.dst_bucket_uri
|
| + self.CreateEmptyObject(test_util.test_storage_uri(obj_name))
|
| + try:
|
| + self.RunCommand('cp', [obj_name, self.dst_dir_root])
|
| + self.fail('Did not get expected CommandException')
|
| + except CommandException, e:
|
| + self.assertNotEqual(e.reason.find(
|
| + 'where the file needs to be created'), -1)
|
| +
|
| + def TestWildcardMoveWithinBucket(self):
|
| + """Attempts to move using src wildcard that overlaps dest object.
|
| + We want to ensure that this doesn't stomp the result data. See the
|
| + comment starting with 'Expand wildcards before' in commands/mv.py
|
| + for details.
|
| + """
|
| + # Create a single object; use 'dst' bucket because it gets cleared after
|
| + # each test.
|
| + self.CreateEmptyObject(
|
| + test_util.test_storage_uri('%sold' % self.dst_bucket_uri))
|
| + self.RunCommand('mv', ['%s*' % self.dst_bucket_uri.uri,
|
| + '%snew' % self.dst_bucket_uri.uri])
|
| + actual = list(
|
| + test_util.test_wildcard_iterator(
|
| + '%s*' % self.dst_bucket_uri.uri).IterUris())
|
| + self.assertEqual(1, len(actual))
|
| + self.assertEqual('new', actual[0].object_name)
|
| +
|
| + def TestCatCommandRuns(self):
|
| + """Test that the cat command basically runs"""
|
| + self.RunCommand('cat', ['%sobj1' % self.src_bucket_uri.uri])
|
| +
|
| + def TestGetAclCommandRuns(self):
|
| + """Test that the getacl command basically runs"""
|
| + self.RunCommand('getacl', [self.src_bucket_uri.uri])
|
| +
|
| + def TestGetDefAclCommandRuns(self):
|
| + """Test that the getdefacl command basically runs"""
|
| + self.RunCommand('getacl', [self.src_bucket_uri.uri])
|
| +
|
| + def TestGetLoggingCommandRuns(self):
|
| + """Test that the getlogging command basically runs"""
|
| + self.RunCommand('getlogging', [self.src_bucket_uri.uri])
|
| +
|
| + def TestHelpCommandDoesntRaise(self):
|
| + """Test that the help command doesn't raise (sanity checks all help)"""
|
| + # Unset PAGER if defined, so help output paginating into $PAGER doesn't
|
| + # cause test to pause.
|
| + if 'PAGER' in os.environ:
|
| + del os.environ['PAGER']
|
| + self.RunCommand('help', [])
|
| +
|
| + def TestLsNonExistentObjectWithPrefixName(self):
|
| + """Test ls of non-existent obj that matches prefix of existing objs"""
|
| + # Use an object name that matches a prefix of other names at that level, to
|
| + # ensure the ls subdir handling logic doesn't pick up anything extra.
|
| + try:
|
| + output = self.RunCommand('ls', ['%sobj' % self.src_bucket_uri.uri],
|
| + return_stdout=True)
|
| + except CommandException, e:
|
| + self.assertNotEqual(e.reason.find('No such object'), -1)
|
| +
|
| + def TestLsBucketNonRecursive(self):
|
| + """Test that ls of a bucket returns expected results"""
|
| + output = self.RunCommand('ls', ['%s*' % self.src_bucket_uri.uri],
|
| + return_stdout=True)
|
| + expected = set(x.uri for x in self.all_src_top_level_obj_uris)
|
| + expected = expected.union(x.uri for x in self.all_src_subdir_obj_uris)
|
| + expected.add('%ssrc_subdir/:' % self.src_bucket_uri.uri)
|
| + expected.add('%ssrc_subdir/nested/' % self.src_bucket_uri.uri)
|
| + expected.add('') # Blank line between subdir listings.
|
| + actual = set(output.split('\n'))
|
| + self.assertEqual(expected, actual)
|
| +
|
| + def TestLsBucketRecursive(self):
|
| + """Test that ls -R of a bucket returns expected results"""
|
| + output = self.RunCommand('ls', ['-R', '%s*' % self.src_bucket_uri.uri],
|
| + return_stdout=True)
|
| + expected = set(x.uri for x in self.all_src_obj_uris)
|
| + expected = expected.union(x.uri for x in self.all_src_subdir_obj_uris)
|
| + expected.add('%ssrc_subdir/:' % self.src_bucket_uri.uri)
|
| + expected.add('%ssrc_subdir/nested/:' % self.src_bucket_uri.uri)
|
| + expected.add('') # Blank line between subdir listings.
|
| + actual = set(output.split('\n'))
|
| + self.assertEqual(expected, actual)
|
| +
|
| + def TestLsBucketRecursiveWithLeadingSlashObjectName(self):
|
| + """Test that ls -R of a bucket with an object that has leading slash"""
|
| + src_file = self.SrcFile('f0')
|
| + self.RunCommand('cp', [src_file, '%s/%s' % (self.dst_bucket_uri.uri, 'f0')])
|
| + output = self.RunCommand('ls', ['-R', '%s*' % self.dst_bucket_uri.uri],
|
| + return_stdout=True)
|
| + expected = set(['%s/%s' % (self.dst_bucket_uri.uri, 'f0')])
|
| + expected.add('') # Blank line between subdir listings.
|
| + actual = set(output.split('\n'))
|
| + self.assertEqual(expected, actual)
|
| +
|
| + def TestLsBucketSubdirNonRecursive(self):
|
| + """Test that ls of a bucket subdir returns expected results"""
|
| + output = self.RunCommand('ls', ['%ssrc_subdir' % self.src_bucket_uri.uri],
|
| + return_stdout=True)
|
| + expected = set(x.uri for x in self.all_src_subdir_obj_uris)
|
| + expected = expected.union(x.uri for x in self.all_src_subdir_obj_uris)
|
| + expected.add('%ssrc_subdir/nested/' % self.src_bucket_uri.uri)
|
| + expected.add('') # Blank line between subdir listings.
|
| + actual = set(output.split('\n'))
|
| + self.assertEqual(expected, actual)
|
| +
|
| + def TestLsBucketSubdirRecursive(self):
|
| + """Test that ls -R of a bucket subdir returns expected results"""
|
| + for final_char in ('/', ''):
|
| + output = self.RunCommand('ls',
|
| + ['-R', '%ssrc_subdir%s'
|
| + % (self.src_bucket_uri.uri, final_char)],
|
| + return_stdout=True)
|
| + expected = set(x.uri for x in self.all_src_subdir_and_below_obj_uris)
|
| + expected = expected.union(x.uri for x in self.all_src_subdir_obj_uris)
|
| + expected.add('%ssrc_subdir/:' % self.src_bucket_uri.uri)
|
| + expected.add('%ssrc_subdir/nested/:' % self.src_bucket_uri.uri)
|
| + expected.add('') # Blank line between subdir listings.
|
| + actual = set(output.split('\n'))
|
| + self.assertEqual(expected, actual)
|
| +
|
| + def TestMakeBucketsCommand(self):
|
| + """Test mb on existing bucket"""
|
| + try:
|
| + self.RunCommand('mb', [self.dst_bucket_uri.uri])
|
| + self.fail('Did not get expected StorageCreateError')
|
| + except boto.exception.StorageCreateError, e:
|
| + self.assertEqual(e.status, 409)
|
| +
|
| + def TestRemoveBucketsCommand(self):
|
| + """Test rb on non-existent bucket"""
|
| + try:
|
| + self.RunCommand('rb', ['gs://non_existent_%s' %
|
| + self.dst_bucket_uri.bucket_name])
|
| + self.fail('Did not get expected StorageResponseError')
|
| + except boto.exception.StorageResponseError, e:
|
| + self.assertEqual(e.status, 404)
|
| +
|
| + def TestRemoveObjsCommand(self):
|
| + """Test rm command on non-existent object"""
|
| + try:
|
| + self.RunCommand('rm', ['%snon_existent' %
|
| + self.dst_bucket_uri.uri])
|
| + self.fail('Did not get expected WildcardException')
|
| + except StorageResponseError, e:
|
| + self.assertNotEqual(e.reason.find('Not Found'), -1)
|
| +
|
| + def TestSetAclOnBucketRuns(self):
|
| + """Test that the setacl command basically runs"""
|
| + # We don't test reading back the acl (via getacl command) because at present
|
| + # MockStorageService doesn't translate canned ACLs into actual ACL XML.
|
| + self.RunCommand('setacl', ['private', self.src_bucket_uri.uri])
|
| +
|
| + def TestSetAclOnWildcardNamedBucketRuns(self):
|
| + """Test that setacl basically runs against wildcard-named bucket"""
|
| + # We don't test reading back the acl (via getacl command) because at present
|
| + # MockStorageService doesn't translate canned ACLs into actual ACL XML.
|
| + uri_str = '%s_s*c' % self.uri_base_str
|
| + self.RunCommand('setacl', ['private', uri_str])
|
| +
|
| + def TestSetAclOnObjectRuns(self):
|
| + """Test that the setacl command basically runs"""
|
| + self.RunCommand('setacl', ['private', '%s*' % self.src_bucket_uri.uri])
|
| +
|
| + def TestSetDefAclOnBucketRuns(self):
|
| + """Test that the setdefacl command basically runs"""
|
| + self.RunCommand('setdefacl', ['private', self.src_bucket_uri.uri])
|
| +
|
| + def TestSetDefAclOnObjectFails(self):
|
| + """Test that the setdefacl command fails when run against an object"""
|
| + try:
|
| + self.RunCommand('setdefacl', ['private', '%s*' % self.src_bucket_uri.uri])
|
| + self.fail('Did not get expected CommandException')
|
| + except CommandException, e:
|
| + self.assertNotEqual(e.reason.find('URI must name a bucket'), -1)
|
| +
|
| + def TestDisableLoggingCommandRuns(self):
|
| + """Test that the disablelogging command basically runs"""
|
| + self.RunCommand('disablelogging', [self.src_bucket_uri.uri])
|
| +
|
| + def TestEnableLoggingCommandRuns(self):
|
| + """Test that the enablelogging command basically runs"""
|
| + self.RunCommand('enablelogging', ['-b', 'gs://log_bucket',
|
| + self.src_bucket_uri.uri])
|
| +
|
| + # Now that gsutil ver computes a checksum it adds 1-3 seconds to test run
|
| + # time (for in memory mocked tests that otherwise take ~ 0.1 seconds). Since
|
| + # it provides very little test value, we're leaving this test commented out.
|
| + #def TestVerCommmandRuns(self):
|
| + # """Test that the Ver command basically runs"""
|
| + # self.RunCommand('ver', [])
|
| +
|
| + def TestMinusDOptionWorks(self):
|
| + """Tests using gsutil -D option"""
|
| + src_file = self.SrcFile('f0')
|
| + self.RunCommand('cp', [src_file, self.dst_bucket_uri.uri], debug=3)
|
| + actual = list(test_util.test_wildcard_iterator(
|
| + '%s*' % self.dst_bucket_uri.uri).IterUris())
|
| + self.assertEqual(1, len(actual))
|
| + self.assertEqual('f0', actual[0].object_name)
|
| +
|
| + def DownloadTestHelper(self, func):
|
| + """
|
| + Test resumable download with custom test function to distort downloaded
|
| + data. We expect an exception to be raised and the dest file to be removed.
|
| + """
|
| + object_uri = self.all_src_obj_uris[0].uri
|
| + try:
|
| + self.RunCommand('cp', [object_uri, self.tmp_path], test_method=func)
|
| + self.fail('Did not get expected CommandException')
|
| + except CommandException:
|
| + self.assertFalse(os.path.exists(self.tmp_path))
|
| + except:
|
| + self.fail('Unexpected exception raised')
|
| +
|
| + def TestDownloadWithObjectSizeChange(self):
|
| + """
|
| + Test resumable download on an object that changes size before the
|
| + downloaded file's checksum is validated.
|
| + """
|
| + def append(fp):
|
| + """Append a byte at end of an open file and flush contents."""
|
| + fp.seek(0,2)
|
| + fp.write('x')
|
| + fp.flush()
|
| + self.DownloadTestHelper(append)
|
| +
|
| + def TestDownloadWithFileContentChange(self):
|
| + """
|
| + Tests resumable download on an object where the file content changes
|
| + before the downloaded file's checksum is validated.
|
| + """
|
| + def overwrite(fp):
|
| + """Overwrite first byte in an open file and flush contents."""
|
| + fp.seek(0)
|
| + fp.write('x')
|
| + fp.flush()
|
| + self.DownloadTestHelper(overwrite)
|
| +
|
| + def TestFlatCopyingObjsAndFilesToBucketSubDir(self):
|
| + """Tests copying flatly listed objects and files to bucket subdir"""
|
| + # Test with and without final slash on dest subdir.
|
| + for final_char in ('/', ''):
|
| + # Set up existing bucket subdir by creating an object in the subdir.
|
| + self.RunCommand(
|
| + 'cp', ['%sf0' % self.src_dir_root,
|
| + '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
|
| + self.RunCommand(
|
| + 'cp', ['-R', '%s**' % self.src_bucket_uri.uri,
|
| + '%s**' % self.src_dir_root,
|
| + '%sdst_subdir%s' % (self.dst_bucket_uri.uri, final_char)])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_uri.uri).IterUris())
|
| + expected = set(['%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
|
| + for uri in self.all_src_obj_uris:
|
| + # Use FinalObjNameComponent here because we expect names to be flattened
|
| + # when using wildcard copy semantics.
|
| + expected.add('%sdst_subdir/%s' % (self.dst_bucket_uri.uri,
|
| + self.FinalObjNameComponent(uri)))
|
| + for file_path in self.nested_child_file_paths:
|
| + # Use os.path.basename here because we expect names to be flattened when
|
| + # using wildcard copy semantics.
|
| + expected.add('%sdst_subdir/%s' % (self.dst_bucket_uri.uri,
|
| + os.path.basename(file_path)))
|
| + self.assertEqual(expected, actual)
|
| + # Clean up/re-set up for next variant iteration.
|
| + self.TearDownClass()
|
| + self.SetUpClass()
|
| +
|
| + def TestRecursiveCopyObjsAndFilesToExistingBucketSubDir(self):
|
| + """Tests recursive copy of objects and files to existing bucket subdir"""
|
| + # Test with and without final slash on dest subdir.
|
| + for final_char in ('/', ''):
|
| + # Set up existing bucket subdir by creating an object in the subdir.
|
| + self.RunCommand(
|
| + 'cp', ['%sf0' % self.src_dir_root,
|
| + '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
|
| + self.RunCommand(
|
| + 'cp', ['-R', '%s' % self.src_bucket_uri.uri,
|
| + '%s' % self.src_dir_root,
|
| + '%sdst_subdir%s' % (self.dst_bucket_uri.uri, final_char)])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_uri.uri).IterUris())
|
| + expected = set(['%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
|
| + for uri in self.all_src_obj_uris:
|
| + expected.add('%sdst_subdir/%s/%s' %
|
| + (self.dst_bucket_uri.uri, uri.bucket_name, uri.object_name))
|
| + for file_path in self.all_src_file_paths:
|
| + start_tmp_pos = file_path.find(self.tmpdir_prefix)
|
| + file_path_sans_base_dir = file_path[start_tmp_pos:]
|
| + expected.add('%sdst_subdir/%s' %
|
| + (self.dst_bucket_uri.uri, file_path_sans_base_dir))
|
| + self.assertEqual(expected, actual)
|
| + # Clean up/re-set up for next variant iteration.
|
| + self.TearDownClass()
|
| + self.SetUpClass()
|
| +
|
| + def TestRecursiveCopyObjsAndFilesToNonExistentBucketSubDir(self):
|
| + """Tests recursive copy of objs + files to non-existent bucket subdir"""
|
| + # Test with and without final slash on dest subdir.
|
| + self.RunCommand(
|
| + 'cp', ['-R', '%s' % self.src_bucket_uri.uri,
|
| + '%s' % self.src_dir_root,
|
| + '%sdst_subdir' % (self.dst_bucket_uri.uri)])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_uri.uri).IterUris())
|
| + expected = set()
|
| + for uri in self.all_src_obj_uris:
|
| + expected.add('%sdst_subdir/%s' %
|
| + (self.dst_bucket_uri.uri, uri.object_name))
|
| + for file_path in self.all_src_file_paths:
|
| + start_tmp_pos = file_path.find(self.tmpdir_prefix)
|
| + file_path_sans_base_dir = (
|
| + file_path[start_tmp_pos:].partition(os.sep)[-1])
|
| + expected.add('%sdst_subdir/%s' %
|
| + (self.dst_bucket_uri.uri, file_path_sans_base_dir))
|
| + self.assertEqual(expected, actual)
|
| +
|
| + def TestCopyingBucketSubDirToDir(self):
|
| + """Tests copying a bucket subdir to a directory"""
|
| + # Test with and without final slash on dest subdir.
|
| + for (final_src_char, final_dst_char) in (
|
| + ('', ''), ('', '/'), ('/', ''), ('/', '/') ):
|
| + self.RunCommand(
|
| + 'cp', ['-R', '%s%s' % (self.src_bucket_subdir_uri, final_src_char),
|
| + '%s%s' % (self.dst_dir_root, final_dst_char)])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s/**' % self.dst_dir_root).IterUris())
|
| + expected = set()
|
| + for uri in self.all_src_subdir_and_below_obj_uris:
|
| + expected.add('file://%s%s' % (self.dst_dir_root, uri.uri.partition(
|
| + self.src_bucket_uri.uri)[-1]))
|
| + self.assertEqual(expected, actual)
|
| + # Clean up/re-set up for next variant iteration.
|
| + self.TearDownClass()
|
| + self.SetUpClass()
|
| +
|
| + def TestCopyingWildcardSpecifiedBucketSubDirToExistingDir(self):
|
| + """Tests copying a wilcard-specified bucket subdir to a directory"""
|
| + # Test with and without final slash on dest subdir.
|
| + for (final_src_char, final_dst_char) in (
|
| + ('', ''), ('', '/'), ('/', ''), ('/', '/') ):
|
| + self.RunCommand(
|
| + 'cp', ['-R',
|
| + '%s%s' % (self.src_bucket_subdir_uri_wildcard, final_src_char),
|
| + '%s%s' % (self.dst_dir_root, final_dst_char)])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s/**' % self.dst_dir_root).IterUris())
|
| + expected = set()
|
| + for uri in self.all_src_subdir_and_below_obj_uris:
|
| + expected.add('file://%s%s' % (
|
| + self.dst_dir_root, uri.uri.partition(self.src_bucket_uri.uri)[-1]))
|
| + self.assertEqual(expected, actual)
|
| + # Clean up/re-set up for next variant iteration.
|
| + self.TearDownClass()
|
| + self.SetUpClass()
|
| +
|
| + def TestCopyingBucketSubDirToDirFailsWithoutMinusR(self):
|
| + """Tests for failure when attempting bucket subdir copy without -R"""
|
| + try:
|
| + self.RunCommand(
|
| + 'cp', ['%s' % self.src_bucket_subdir_uri,
|
| + '%s' % self.dst_dir_root])
|
| + self.fail('Did not get expected CommandException')
|
| + except CommandException, e:
|
| + self.assertNotEqual(e.reason.find('does not exist'), -1)
|
| +
|
| + def TestCopyingBucketSubDirToBucketSubDir(self):
|
| + """Tests copying a bucket subdir to another bucket subdir"""
|
| + # Test with and without final slash on dest subdir.
|
| + for (final_src_char, final_dst_char) in (
|
| + ('', ''), ('', '/'), ('/', ''), ('/', '/') ):
|
| + # Set up existing bucket subdir by creating an object in the subdir.
|
| + self.RunCommand(
|
| + 'cp', ['%sf0' % self.src_dir_root,
|
| + '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
|
| + self.RunCommand(
|
| + 'cp', ['-R', '%s%s' % (self.src_bucket_subdir_uri, final_src_char),
|
| + '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
|
| + expected = set(['%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
|
| + for uri in self.all_src_subdir_and_below_obj_uris:
|
| + expected.add(
|
| + '%s/%s' % (self.dst_bucket_subdir_uri.uri, uri.object_name))
|
| + self.assertEqual(expected, actual)
|
| + # Clean up/re-set up for next variant iteration.
|
| + self.TearDownClass()
|
| + self.SetUpClass()
|
| +
|
| + def TestMovingBucketSubDirToNonExistentBucketSubDir(self):
|
| + """Tests moving a bucket subdir to a non-existent bucket subdir"""
|
| + # Test with and without final slash on dest subdir.
|
| + for final_src_char in ('', '/'):
|
| + self.RunCommand(
|
| + 'mv', ['%s%s' % (self.src_bucket_subdir_uri, final_src_char),
|
| + '%s' % (self.dst_bucket_subdir_uri.uri)])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
|
| + expected = set([])
|
| + for uri in self.all_src_subdir_and_below_obj_uris:
|
| + # Unlike the case with copying, with mv we expect renaming to occur
|
| + # at the level of the src subdir, vs appending that subdir beneath the
|
| + # dst subdir like is done for copying.
|
| + expected_name = uri.object_name.replace('src_', 'dst_')
|
| + expected.add('%s%s' % (self.dst_bucket_uri.uri, expected_name))
|
| + self.assertEqual(expected, actual)
|
| + # Clean up/re-set up for next variant iteration.
|
| + self.TearDownClass()
|
| + self.SetUpClass()
|
| +
|
| + def TestMovingBucketSubDirToExistingBucketSubDir(self):
|
| + """Tests moving a bucket subdir to a existing bucket subdir"""
|
| + # Test with and without final slash on dest subdir.
|
| + for (final_src_char, final_dst_char) in (
|
| + ('', ''), ('', '/'), ('/', ''), ('/', '/') ):
|
| + # Set up existing bucket subdir by creating an object in the subdir.
|
| + self.RunCommand(
|
| + 'cp', ['%sf0' % self.src_dir_root,
|
| + '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
|
| + self.RunCommand(
|
| + 'mv', ['%s%s' % (self.src_bucket_subdir_uri, final_src_char),
|
| + '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
|
| + expected = set(['%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
|
| + for uri in self.all_src_subdir_and_below_obj_uris:
|
| + expected.add(
|
| + '%s/%s' % (self.dst_bucket_subdir_uri.uri, uri.object_name))
|
| + self.assertEqual(expected, actual)
|
| + # Clean up/re-set up for next variant iteration.
|
| + self.TearDownClass()
|
| + self.SetUpClass()
|
| +
|
| + def TestCopyingObjectToBucketSubDir(self):
|
| + """Tests copying an object to a bucket subdir"""
|
| + # Test with and without final slash on dest subdir.
|
| + for (final_dst_char) in ('', '/'):
|
| + # Set up existing bucket subdir by creating an object in the subdir.
|
| + self.RunCommand(
|
| + 'cp', ['%sf0' % self.src_dir_root,
|
| + '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
|
| + self.RunCommand(
|
| + 'cp', ['%sobj0' % self.src_bucket_uri,
|
| + '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
|
| + expected = set([
|
| + '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri,
|
| + '%sdst_subdir/obj0' % self.dst_bucket_uri.uri])
|
| + self.assertEqual(expected, actual)
|
| + # Clean up/re-set up for next variant iteration.
|
| + self.TearDownClass()
|
| + self.SetUpClass()
|
| +
|
| + def TestCopyingWildcardedFilesToBucketSubDir(self):
|
| + """Tests copying wildcarded files to a bucket subdir"""
|
| + # Test with and without final slash on dest subdir.
|
| + for (final_dst_char) in ('', '/'):
|
| + # Set up existing bucket subdir by creating an object in the subdir.
|
| + self.RunCommand(
|
| + 'cp', ['%sf0' % self.src_dir_root,
|
| + '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
|
| + self.RunCommand(
|
| + 'cp', ['%sf?' % self.src_dir_root,
|
| + '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
|
| + expected = set([
|
| + '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri,
|
| + '%sdst_subdir/f0' % self.dst_bucket_uri.uri,
|
| + '%sdst_subdir/f1' % self.dst_bucket_uri.uri])
|
| + self.assertEqual(expected, actual)
|
| + # Clean up/re-set up for next variant iteration.
|
| + self.TearDownClass()
|
| + self.SetUpClass()
|
| +
|
| + def TestCopyingOneNestedFileToBucketSubDir(self):
|
| + """Tests copying one nested file to a bucket subdir"""
|
| + # Test with and without final slash on dest subdir.
|
| + for (final_dst_char) in ('', '/'):
|
| + # Set up existing bucket subdir by creating an object in the subdir.
|
| + self.RunCommand(
|
| + 'cp', ['%sf0' % self.src_dir_root,
|
| + '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
|
| + self.RunCommand(
|
| + 'cp', ['-r', '%sdir0' % self.src_dir_root,
|
| + '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
|
| + expected = set([
|
| + '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri,
|
| + '%sdst_subdir/dir0/dir1/nested' % self.dst_bucket_uri.uri])
|
| + self.assertEqual(expected, actual)
|
| + # Clean up/re-set up for next variant iteration.
|
| + self.TearDownClass()
|
| + self.SetUpClass()
|
| +
|
| + def TestMovingWildcardedFilesToNonExistentBucketSubDir(self):
|
| + """Tests moving files to a non-existent bucket subdir"""
|
| + # This tests for how we allow users to do something like:
|
| + # gsutil cp *.txt gs://bucket/dir
|
| + # where *.txt matches more than 1 file and gs://bucket/dir
|
| + # doesn't exist as a subdir.
|
| + #
|
| + # Test with and without final slash on dest subdir.
|
| + for (final_dst_char) in ('', '/'):
|
| + # Set up existing bucket subdir by creating an object in the subdir.
|
| + self.RunCommand(
|
| + 'cp', ['%sf0' % self.src_dir_root,
|
| + '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
|
| + # Copy some files into place in dst bucket.
|
| + self.RunCommand(
|
| + 'cp', ['%sf?' % self.src_dir_root,
|
| + '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
|
| + # Now do the move test.
|
| + self.RunCommand(
|
| + 'mv', ['%s/*' % self.dst_bucket_subdir_uri.uri,
|
| + '%s/nonexistent/%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
|
| + expected = set([
|
| + '%sdst_subdir/nonexistent/existing_obj' % self.dst_bucket_uri.uri,
|
| + '%sdst_subdir/nonexistent/f0' % self.dst_bucket_uri.uri,
|
| + '%sdst_subdir/nonexistent/f1' % self.dst_bucket_uri.uri])
|
| + self.assertEqual(expected, actual)
|
| + # Clean up/re-set up for next variant iteration.
|
| + self.TearDownClass()
|
| + self.SetUpClass()
|
| +
|
| + def TestMovingObjectToBucketSubDir(self):
|
| + """Tests moving an object to a bucket subdir"""
|
| + # Test with and without final slash on dest subdir.
|
| + for (final_dst_char) in ('', '/'):
|
| + # Set up existing bucket subdir by creating an object in the subdir.
|
| + self.RunCommand(
|
| + 'cp', ['%sf0' % self.src_dir_root,
|
| + '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
|
| + self.RunCommand(
|
| + 'mv', ['%sobj0' % self.src_bucket_uri,
|
| + '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
|
| + expected = set([
|
| + '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri,
|
| + '%sdst_subdir/obj0' % self.dst_bucket_uri.uri])
|
| + self.assertEqual(expected, actual)
|
| + # Clean up/re-set up for next variant iteration.
|
| + self.TearDownClass()
|
| + self.SetUpClass()
|
| +
|
| + def TestWildcardSrcSubDirMoveDisallowed(self):
|
| + """Tests moving a bucket subdir specified by wildcard is disallowed"""
|
| + try:
|
| + self.RunCommand(
|
| + 'mv', ['%s*' % self.src_bucket_subdir_uri,
|
| + '%s' % self.dst_bucket_subdir_uri.uri])
|
| + self.fail('Did not get expected CommandException')
|
| + except CommandException, e:
|
| + self.assertNotEqual(e.reason.find('mv command disallows naming'), -1)
|
| +
|
| + def TestMovingBucketNestedSubDirToBucketNestedSubDir(self):
|
| + """Tests moving a bucket nested subdir to another bucket nested subdir"""
|
| + # Test with and without final slash on dest subdir.
|
| + for final_src_char in ('', '/'):
|
| + self.RunCommand(
|
| + 'mv', ['%s%s' % (self.src_bucket_subdir_uri, final_src_char),
|
| + '%s' % (self.dst_bucket_subdir_uri.uri)])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
|
| + expected = set([])
|
| + for uri in self.all_src_subdir_and_below_obj_uris:
|
| + # Unlike the case with copying, with mv we expect renaming to occur
|
| + # at the level of the src subdir, vs appending that subdir beneath the
|
| + # dst subdir like is done for copying.
|
| + expected_name = uri.object_name.replace('src_', 'dst_')
|
| + expected.add('%s%s' % (self.dst_bucket_uri, expected_name))
|
| + self.assertEqual(expected, actual)
|
| + # Clean up/re-set up for next variant iteration.
|
| + self.TearDownClass()
|
| + self.SetUpClass()
|
| +
|
| + def TestRemovingBucketSubDir(self):
|
| + """Tests removing a bucket subdir"""
|
| + # Test with and without final slash on dest subdir.
|
| + for final_src_char in ('', '/'):
|
| + # Setup: Copy a directory, including subdir, to bucket.
|
| + self.RunCommand('cp', ['-R', self.src_dir_root, self.dst_bucket_uri.uri])
|
| + src_subdir = self.src_dir_root.split(os.path.sep)[-2]
|
| + # Test removing bucket subdir.
|
| + self.RunCommand(
|
| + 'rm', ['-R', '%s%s/dir0%s' %
|
| + (self.dst_bucket_uri, src_subdir, final_src_char)])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s**' % self.dst_bucket_uri.uri).IterUris())
|
| + expected = set()
|
| + for fname in self.non_nested_file_names:
|
| + expected.add('%s%s/%s' % (self.dst_bucket_uri.uri, src_subdir, fname))
|
| + self.assertEqual(expected, actual)
|
| + # Clean up/re-set up for next variant iteration.
|
| + self.TearDownClass()
|
| + self.SetUpClass()
|
| +
|
| + def TestRecursiveRemoveObjsInBucket(self):
|
| + """Tests removing all objects in bucket via rm -R gs://bucket"""
|
| + # Test with and without final slash on dest subdir.
|
| + for final_src_char in ('', '/'):
|
| + # Setup: Copy a directory, including subdir, to bucket.
|
| + self.RunCommand('cp', ['-R', self.src_dir_root, self.dst_bucket_uri.uri])
|
| + # Test removing all objects via rm -R.
|
| + self.RunCommand('rm', ['-R', '%s%s' % (self.dst_bucket_uri,
|
| + final_src_char)])
|
| + actual = set(str(u) for u in test_util.test_wildcard_iterator(
|
| + '%s*' % self.dst_bucket_uri.uri).IterUris())
|
| + self.assertEqual(0, len(actual))
|
| + # Clean up/re-set up for next variant iteration.
|
| + self.TearDownClass()
|
| + self.SetUpClass()
|
| +
|
| + def FinalObjNameComponent(self, uri):
|
| + """For gs://bucket/abc/def/ghi returns ghi."""
|
| + return uri.uri.rpartition('/')[-1]
|
| +
|
| +if __name__ == '__main__':
|
| + if sys.version_info[:3] < (2, 5, 1):
|
| + sys.exit('These tests must be run on at least Python 2.5.1\n')
|
| + test_loader = unittest.TestLoader()
|
| + test_loader.testMethodPrefix = 'Test'
|
| + suite = test_loader.loadTestsFromTestCase(GsutilCommandTests)
|
| + # Seems like there should be a cleaner way to find the test_class.
|
| + test_class = suite.__getattribute__('_tests')[0]
|
| + # We call SetUpClass() and TearDownClass() ourselves because we
|
| + # don't assume the user has Python 2.7 (which supports classmethods
|
| + # that do it, with camelCase versions of these names).
|
| + try:
|
| + print 'Setting up %s...' % test_class.GetSuiteDescription()
|
| + test_class.SetUpClass()
|
| + print 'Running %s...' % test_class.GetSuiteDescription()
|
| + unittest.TextTestRunner(verbosity=2).run(suite)
|
| + finally:
|
| + print 'Cleaning up after %s...' % test_class.GetSuiteDescription()
|
| + test_class.TearDownClass()
|
| + print ''
|
|
|