Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: third_party/gsutil/gslib/test_commands.py

Issue 12042069: Scripts to download files from google storage based on sha1 sums (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Removed gsutil/tests and gsutil/docs Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright 2010 Google Inc.
3 #
4 # Permission is hereby granted, free of charge, to any person obtaining a
5 # copy of this software and associated documentation files (the
6 # "Software"), to deal in the Software without restriction, including
7 # without limitation the rights to use, copy, modify, merge, publish, dis-
8 # tribute, sublicense, and/or sell copies of the Software, and to permit
9 # persons to whom the Software is furnished to do so, subject to the fol-
10 # lowing conditions:
11 #
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
17 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
18 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 # IN THE SOFTWARE.
22
23 """Tests for gsutil commands.
24 The test code in this file runs against an in-memory storage service mock,
25 so runs very quickly. This is valuable for testing changes that impact the
26 naming rules, since those rules are complex and it's useful to be able to
27 make small incremental changes and rerun the tests frequently. Additional
28 end-to-end tests (which send traffic to the production Google Cloud Storage
29 service) are available via the gsutil test command.
30 """
31
32 import os
33 import shutil
34 import sys
35 import tempfile
36 import time
37 import unittest
38 import wildcard_iterator
39
40 # Put local libs at front of path so tests will run latest lib code rather
41 # than whatever code is found on user's PYTHONPATH.
42 sys.path.insert(0, '.')
43 sys.path.insert(0, 'boto')
44 import boto
45
46 from boto.exception import StorageResponseError
47 from boto import storage_uri
48 from gslib.command_runner import CommandRunner
49 from gslib.commands import cp
50 from gslib.exception import CommandException
51 from gslib import test_util
52 from tests.integration.s3.mock_storage_service import MockBucketStorageUri
53
54
55 class GsutilCommandTests(unittest.TestCase):
56 """gsutil command method test suite"""
57
58 # We don't use the gsutil boto config discovery logic here, as it assumes
59 # boto is a subdirectory of where the command is running, which is gslib
60 # when running these tests. Instead we use a simplified setup:
61 gsutil_bin_dir = '.'
62 boto_lib_dir = os.path.join(gsutil_bin_dir, 'boto')
63 config_file_list = boto.pyami.config.BotoConfigLocations
64 # Use "gsutil_test_commands" as a fake UserAgent. This value will never be
65 # sent via HTTP because we're using MockStorageService here.
66 command_runner = CommandRunner(gsutil_bin_dir, boto_lib_dir, config_file_list,
67 "gsutil_test_commands", MockBucketStorageUri)
68
69 def GetSuiteDescription(self):
70 return 'gsutil command method test suite'
71
72 @classmethod
73 def tearDown(cls):
74 """Deletes any objects or files created by last test run"""
75 try:
76 for key_uri in test_util.test_wildcard_iterator(
77 '%s**' % cls.dst_bucket_uri).IterUris():
78 key_uri.delete_key()
79 # For some reason trying to catch except
80 # wildcard_iterator.WildcardException doesn't work here.
81 except Exception:
82 # Ignore cleanup failures.
83 pass
84 # Recursively delete dst dir and then re-create it, so in effect we
85 # remove all dirs and files under that directory.
86 shutil.rmtree(cls.dst_dir_root)
87 os.mkdir(cls.dst_dir_root)
88
89 @classmethod
90 def SrcFile(cls, fname):
91 """Returns path for given test src file"""
92 for path in cls.all_src_file_paths:
93 if path.find(fname) != -1:
94 return path
95 raise Exception('SrcFile(%s): no match' % fname)
96
97 @classmethod
98 def CreateEmptyObject(cls, uri):
99 """Creates an empty object for the given StorageUri"""
100 key = uri.new_key()
101 key.set_contents_from_string('')
102
103 @classmethod
104 def SetUpClass(cls):
105 """Initializes test suite.
106
107 Creates a source bucket containing 9 objects, 3 of which live under a
108 subdir, 3 of which lives under a nested subdir; a source directory
109 containing a subdirectory and file; and a destination bucket and directory.
110 """
111 cls.uri_base_str = 'gs://gsutil_test_%s' % int(time.time())
112 # Use a designated tmpdir prefix to make it easy to find the end of
113 # the tmp path.
114 cls.tmpdir_prefix = 'tmp_gstest'
115
116 # Create the test buckets.
117 cls.src_bucket_uri = test_util.test_storage_uri('%s_src' % cls.uri_base_str)
118 cls.dst_bucket_uri = test_util.test_storage_uri('%s_dst' % cls.uri_base_str)
119 cls.src_bucket_uri.create_bucket()
120
121 # Define the src and dest bucket subdir paths. Note that they exclude
122 # a slash on the end so we can test handling of bucket subdirs specified
123 # both with and without terminating slashes.
124 cls.src_bucket_subdir_uri = test_util.test_storage_uri(
125 '%s_src/src_subdir' % cls.uri_base_str)
126 cls.src_bucket_subdir_uri_wildcard = test_util.test_storage_uri(
127 '%s_src/src_sub*' % cls.uri_base_str)
128 cls.dst_bucket_subdir_uri = test_util.test_storage_uri(
129 '%s_dst/dst_subdir' % cls.uri_base_str)
130 cls.dst_bucket_uri.create_bucket()
131
132 # Create the test objects in the src bucket.
133 cls.all_src_obj_uris = []
134 cls.all_src_top_level_obj_uris = []
135 cls.all_src_subdir_obj_uris = []
136 cls.all_src_subdir_and_below_obj_uris = []
137 for i in range(3):
138 obj_uri = test_util.test_storage_uri('%sobj%d' % (cls.src_bucket_uri, i))
139 cls.CreateEmptyObject(obj_uri)
140 cls.all_src_obj_uris.append(obj_uri)
141 cls.all_src_top_level_obj_uris.append(obj_uri)
142 # Subdir objects
143 for i in range(4, 6):
144 obj_uri = test_util.test_storage_uri(
145 '%s/obj%d' % (cls.src_bucket_subdir_uri, i))
146 cls.CreateEmptyObject(obj_uri)
147 cls.all_src_obj_uris.append(obj_uri)
148 cls.all_src_subdir_obj_uris.append(obj_uri)
149 cls.all_src_subdir_and_below_obj_uris.append(obj_uri)
150 # Nested subdir objects
151 for i in range(7, 9):
152 obj_uri = test_util.test_storage_uri(
153 '%s/nested/obj%d' % (cls.src_bucket_subdir_uri, i))
154 cls.CreateEmptyObject(obj_uri)
155 cls.all_src_obj_uris.append(obj_uri)
156 cls.all_src_subdir_and_below_obj_uris.append(obj_uri)
157
158 # Create the test directories.
159 cls.src_dir_root = '%s%s' % (tempfile.mkdtemp(prefix=cls.tmpdir_prefix),
160 os.sep)
161 nested_subdir = '%sdir0%sdir1' % (cls.src_dir_root, os.sep)
162 os.makedirs(nested_subdir)
163 cls.dst_dir_root = '%s%s' % (tempfile.mkdtemp(prefix=cls.tmpdir_prefix),
164 os.sep)
165
166 # Create the test files in the src directory.
167 cls.all_src_file_paths = []
168 cls.nested_child_file_paths = ['f0', 'f1', 'f2.txt', 'dir0/dir1/nested']
169 cls.non_nested_file_names = ['f0', 'f1', 'f2.txt']
170 file_names = ['f0', 'f1', 'f2.txt', 'dir0%sdir1%snested' % (os.sep, os.sep)]
171 file_paths = ['%s%s' % (cls.src_dir_root, f) for f in file_names]
172 for file_path in file_paths:
173 f = open(file_path, 'w')
174 f.write('test data')
175 f.close()
176 cls.all_src_file_paths.append(file_path)
177 cls.tmp_path = '%s%s' % (cls.src_dir_root, 'tmp0')
178
179 cls.created_test_data = True
180
181 @classmethod
182 def TearDownClass(cls):
183 """Cleans up buckets and directories created by SetUpClass"""
184
185 if not hasattr(cls, 'created_test_data'):
186 return
187 # Call cls.tearDown() in case the tests got interrupted, to ensure
188 # dst objects and files get deleted.
189 cls.tearDown()
190 # Now delete src objects and files, and all buckets and dirs.
191 try:
192 for key_uri in test_util.test_wildcard_iterator(
193 '%s**' % cls.src_bucket_uri).IterUris():
194 key_uri.delete_key()
195 except wildcard_iterator.WildcardException:
196 # Ignore cleanup failures.
197 pass
198 try:
199 for key_uri in test_util.test_wildcard_iterator(
200 '%s**' % cls.src_dir_root).IterUris():
201 key_uri.delete_key()
202 except wildcard_iterator.WildcardException:
203 # Ignore cleanup failures.
204 pass
205 cls.src_bucket_uri.delete_bucket()
206 cls.dst_bucket_uri.delete_bucket()
207 shutil.rmtree(cls.src_dir_root)
208 shutil.rmtree(cls.dst_dir_root)
209
210
211 def RunCommand(self, command_name, args=None, headers=None, debug=0,
212 test_method=None, return_stdout=False):
213 """
214 Method for calling gslib.command_runner.CommandRunner, passing
215 parallel_operations=False for all tests, optionally saving/returning stdout
216 output. We run all tests multi-threaded, to exercise those more complicated
217 code paths.
218 TODO: change to run with parallel_operations=True for all tests. At
219 present when you do this it causes many test failures.
220
221 Args:
222 command_name: The name of the command being run.
223 args: Command-line args (arg0 = actual arg, not command name ala bash).
224 headers: Dictionary containing optional HTTP headers to pass to boto.
225 debug: Debug level to pass in to boto connection (range 0..3).
226 parallel_operations: Should command operations be executed in parallel?
227 test_method: Optional general purpose method for testing purposes.
228 Application and semantics of this method will vary by
229 command and test type.
230 return_stdout: If true will save and return stdout produced by command.
231 """
232 sys.stderr.write('\nRunning test of %s %s\n' %
233 (command_name, ' '.join(args)))
234 if return_stdout:
235 # Redirect stdout temporarily, to save output to a file.
236 tmpfile = tempfile.mkstemp()[1]
237 stdout_sav = sys.stdout
238 try:
239 fp = open(tmpfile, 'w')
240 sys.stdout = fp
241 self.command_runner.RunNamedCommand(
242 command_name, args=args, headers=headers, debug=debug,
243 parallel_operations=False, test_method=test_method)
244 finally:
245 fp.close()
246 sys.stdout = stdout_sav
247 output = open(tmpfile, 'r').read()
248 os.unlink(tmpfile)
249 return output
250 else:
251 self.command_runner.RunNamedCommand(
252 command_name, args=args, headers=headers, debug=debug,
253 parallel_operations=False, test_method=test_method)
254
255 def TestGetPathBeforeFinalDir(self):
256 """Tests _GetPathBeforeFinalDir() (unit test)"""
257 self.assertEqual('gs://',
258 cp._GetPathBeforeFinalDir(storage_uri('gs://bucket/')))
259 self.assertEqual('gs://bucket',
260 cp._GetPathBeforeFinalDir(storage_uri('gs://bucket/dir/')))
261 self.assertEqual('gs://bucket',
262 cp._GetPathBeforeFinalDir(storage_uri('gs://bucket/dir')))
263 self.assertEqual('gs://bucket/dir',
264 cp._GetPathBeforeFinalDir(
265 storage_uri('gs://bucket/dir/obj')))
266 self.assertEqual('file://%s' % self.src_dir_root.rstrip('/'),
267 cp._GetPathBeforeFinalDir(storage_uri(
268 'file://%sdir0/' % self.src_dir_root)))
269
270 def TestCopyingTopLevelFileToBucket(self):
271 """Tests copying one top-level file to a bucket"""
272 src_file = self.SrcFile('f0')
273 self.RunCommand('cp', [src_file, self.dst_bucket_uri.uri])
274 actual = list(test_util.test_wildcard_iterator(
275 '%s**' % self.dst_bucket_uri.uri).IterUris())
276 self.assertEqual(1, len(actual))
277 self.assertEqual('f0', actual[0].object_name)
278
279 def TestCopyingAbsolutePathDirToBucket(self):
280 """Tests recursively copying absolute path directory to a bucket"""
281 self.RunCommand('cp', ['-R', self.src_dir_root, self.dst_bucket_uri.uri])
282 actual = set(str(u) for u in test_util.test_wildcard_iterator(
283 '%s**' % self.dst_bucket_uri.uri).IterUris())
284 expected = set()
285 for file_path in self.all_src_file_paths:
286 start_tmp_pos = file_path.find(self.tmpdir_prefix)
287 file_path_sans_top_tmp_dir = file_path[start_tmp_pos:]
288 expected.add('%s%s' % (self.dst_bucket_uri.uri,
289 file_path_sans_top_tmp_dir))
290 self.assertEqual(expected, actual)
291
292 def TestCopyingRelativePathDirToBucket(self):
293 """Tests recursively copying relative directory to a bucket"""
294 orig_dir = os.getcwd()
295 os.chdir(self.src_dir_root)
296 self.RunCommand('cp', ['-R', 'dir0', self.dst_bucket_uri.uri])
297 actual = set(str(u) for u in test_util.test_wildcard_iterator(
298 '%s**' % self.dst_bucket_uri.uri).IterUris())
299 expected = set()
300 for file_path in self.all_src_file_paths:
301 start_tmp_pos = file_path.find(self.tmpdir_prefix)
302 file_path_sans_top_tmp_dir = file_path[start_tmp_pos:]
303 expected.add('%s%s' % (self.dst_bucket_uri.uri, 'dir0/dir1/nested'))
304 self.assertEqual(expected, actual)
305 os.chdir(orig_dir)
306
307 def TestCopyingRelativePathSubDirToBucketSubdirSignifiedByDollarFolderObj(self ):
308 """Tests recursively copying relative sub-directory to bucket subdir signifi ed by a $folder$ object"""
309 orig_dir = os.getcwd()
310 os.chdir(self.src_dir_root)
311 # Create a $folder$ object to simulate a folder created by GCS manager (or
312 # various other tools), which gsutil understands to mean there is a folder i nto
313 # which the object is being copied.
314 obj_name = '%sabc_$folder$' % self.dst_bucket_uri
315 self.CreateEmptyObject(test_util.test_storage_uri(obj_name))
316 self.RunCommand('cp', ['-R', 'dir0/dir1', '%sabc'
317 % self.dst_bucket_uri.uri])
318 actual = set(str(u) for u in test_util.test_wildcard_iterator(
319 '%s**' % self.dst_bucket_uri.uri).IterUris())
320 expected = set([obj_name])
321 for file_path in self.all_src_file_paths:
322 start_tmp_pos = file_path.find(self.tmpdir_prefix)
323 file_path_sans_top_tmp_dir = file_path[start_tmp_pos:]
324 expected.add('%sabc/%s' % (self.dst_bucket_uri.uri, 'dir1/nested'))
325 self.assertEqual(expected, actual)
326 os.chdir(orig_dir)
327
328 def TestCopyingRelativePathSubDirToBucketSubdirSignifiedBySlash(self):
329 """Tests recursively copying relative sub-directory to bucket subdir signifi ed by a / object"""
330 orig_dir = os.getcwd()
331 os.chdir(self.src_dir_root)
332 self.RunCommand('cp', ['-R', 'dir0/dir1', '%sabc/'
333 % self.dst_bucket_uri.uri])
334 actual = set(str(u) for u in test_util.test_wildcard_iterator(
335 '%s**' % self.dst_bucket_uri.uri).IterUris())
336 expected = set()
337 for file_path in self.all_src_file_paths:
338 start_tmp_pos = file_path.find(self.tmpdir_prefix)
339 file_path_sans_top_tmp_dir = file_path[start_tmp_pos:]
340 expected.add('%sabc/%s' % (self.dst_bucket_uri.uri, 'dir1/nested'))
341 self.assertEqual(expected, actual)
342 os.chdir(orig_dir)
343
344 def TestCopyingRelativePathSubDirToBucket(self):
345 """Tests recursively copying relative sub-directory to a bucket"""
346 orig_dir = os.getcwd()
347 os.chdir(self.src_dir_root)
348 self.RunCommand('cp', ['-R', 'dir0/dir1', self.dst_bucket_uri.uri])
349 actual = set(str(u) for u in test_util.test_wildcard_iterator(
350 '%s**' % self.dst_bucket_uri.uri).IterUris())
351 expected = set()
352 for file_path in self.all_src_file_paths:
353 start_tmp_pos = file_path.find(self.tmpdir_prefix)
354 file_path_sans_top_tmp_dir = file_path[start_tmp_pos:]
355 expected.add('%s%s' % (self.dst_bucket_uri.uri, 'dir1/nested'))
356 self.assertEqual(expected, actual)
357 os.chdir(orig_dir)
358
359 def TestCopyingDotSlashToBucket(self):
360 """Tests copying ./ to a bucket produces expected naming"""
361 # When running a command like gsutil cp -r . gs://dest we expect the dest
362 # obj names to be of the form gs://dest/abc, not gs://dest/./abc.
363 orig_dir = os.getcwd()
364 for rel_src_dir in ['.', './']:
365 os.chdir(self.src_dir_root)
366 self.RunCommand('cp', ['-R', rel_src_dir, self.dst_bucket_uri.uri])
367 actual = set(str(u) for u in test_util.test_wildcard_iterator(
368 '%s**' % self.dst_bucket_uri.uri).IterUris())
369 expected = set()
370 for file_path in self.all_src_file_paths:
371 start_tmp_pos = (file_path.find(self.src_dir_root)
372 + len(self.src_dir_root))
373 file_path_sans_top_tmp_dir = file_path[start_tmp_pos:]
374 expected.add('%s%s' % (self.dst_bucket_uri.uri,
375 file_path_sans_top_tmp_dir))
376 self.assertEqual(expected, actual)
377 # Clean up/re-set up for next variant iteration.
378 self.TearDownClass()
379 self.SetUpClass()
380 os.chdir(orig_dir)
381
382 def TestCopyingDirContainingOneFileToBucket(self):
383 """Tests copying a directory containing 1 file to a bucket.
384 We test this case to ensure that correct bucket handling isn't dependent
385 on the copy being treated as a multi-source copy.
386 """
387 self.RunCommand('cp', ['-R', '%sdir0%sdir1' %
388 (self.src_dir_root, os.sep),
389 self.dst_bucket_uri.uri])
390 actual = list((str(u) for u in test_util.test_wildcard_iterator(
391 '%s**' % self.dst_bucket_uri.uri).IterUris()))
392 self.assertEqual(1, len(actual))
393 self.assertEqual('%sdir1%snested' % (self.dst_bucket_uri.uri, os.sep),
394 actual[0])
395
396 def TestCopyingBucketToDir(self):
397 """Tests copying from a bucket to a directory"""
398 self.RunCommand('cp', ['-R', self.src_bucket_uri.uri, self.dst_dir_root])
399 actual = set(str(u) for u in test_util.test_wildcard_iterator(
400 '%s**' % self.dst_dir_root).IterUris())
401 expected = set()
402 for uri in self.all_src_obj_uris:
403 expected.add('file://%s%s/%s' % (self.dst_dir_root, uri.bucket_name,
404 uri.object_name))
405 self.assertEqual(expected, actual)
406
407 def TestCopyingBucketToBucket(self):
408 """Tests copying from a bucket-only URI to a bucket"""
409 self.RunCommand('cp', ['-R', self.src_bucket_uri.uri,
410 self.dst_bucket_uri.uri])
411 actual = set(str(u) for u in test_util.test_wildcard_iterator(
412 '%s**' % self.dst_bucket_uri.uri).IterUris())
413 expected = set()
414 for uri in self.all_src_obj_uris:
415 expected.add('%s%s/%s' % (self.dst_bucket_uri.uri, uri.bucket_name,
416 uri.object_name))
417 self.assertEqual(expected, actual)
418
419 """Tests copying from a directory to a directory"""
420 self.RunCommand('cp', ['-R', self.src_dir_root, self.dst_dir_root])
421 actual = set(str(u) for u in test_util.test_wildcard_iterator(
422 '%s**' % self.dst_dir_root).IterUris())
423 expected = set()
424 for file_path in self.all_src_file_paths:
425 start_tmp_pos = file_path.find(self.tmpdir_prefix)
426 file_path_sans_top_tmp_dir = file_path[start_tmp_pos:]
427 expected.add('file://%s%s' % (self.dst_dir_root,
428 file_path_sans_top_tmp_dir))
429 self.assertEqual(expected, actual)
430
431 def TestCopyingFilesAndDirNonRecursive(self):
432 """Tests copying containing files and a directory without -R"""
433 self.RunCommand('cp', ['%s*' % self.src_dir_root, self.dst_dir_root])
434 actual = set(str(u) for u in test_util.test_wildcard_iterator(
435 '%s**' % self.dst_dir_root).IterUris())
436 expected = set(['file://%s%s' % (self.dst_dir_root, f)
437 for f in self.non_nested_file_names])
438 self.assertEqual(expected, actual)
439
440 def TestCopyingFileToDir(self):
441 """Tests copying one file to a directory"""
442 src_file = self.SrcFile('nested')
443 self.RunCommand('cp', [src_file, self.dst_dir_root])
444 actual = list(test_util.test_wildcard_iterator(
445 '%s*' % self.dst_dir_root).IterUris())
446 self.assertEqual(1, len(actual))
447 self.assertEqual('file://%s%s' % (self.dst_dir_root, 'nested'),
448 actual[0].uri)
449
450 def TestCopyingFileToObjectWithConsecutiveSlashes(self):
451 """Tests copying a file to an object containing consecutive slashes"""
452 src_file = self.SrcFile('f0')
453 self.RunCommand('cp', [src_file, '%s/obj' % self.dst_bucket_uri.uri])
454 actual = list(test_util.test_wildcard_iterator(
455 '%s**' % self.dst_bucket_uri.uri).IterUris())
456 self.assertEqual(1, len(actual))
457 self.assertEqual('/obj', actual[0].object_name)
458
459 def TestCopyingCompressedFileToBucket(self):
460 """Tests copying one file with compression to a bucket"""
461 src_file = self.SrcFile('f2.txt')
462 self.RunCommand('cp', ['-z', 'txt', src_file, self.dst_bucket_uri.uri],)
463 actual = list(
464 str(u) for u in test_util.test_wildcard_iterator(
465 '%s*' % self.dst_bucket_uri.uri).IterUris())
466 self.assertEqual(1, len(actual))
467 expected_dst_uri = self.dst_bucket_uri.clone_replace_name('f2.txt')
468 self.assertEqual(expected_dst_uri.uri, actual[0])
469 dst_key = expected_dst_uri.get_key()
470 dst_key.open_read()
471 self.assertEqual('gzip', dst_key.content_encoding)
472
473 def TestCopyingObjectToObject(self):
474 """Tests copying an object to an object"""
475 self.RunCommand('cp', ['%sobj1' % self.src_bucket_uri.uri,
476 self.dst_bucket_uri.uri])
477 actual = list(test_util.test_wildcard_iterator(
478 '%s*' % self.dst_bucket_uri.uri).IterUris())
479 self.assertEqual(1, len(actual))
480 self.assertEqual('obj1', actual[0].object_name)
481
482 def TestCopyingObjsAndFilesToDir(self):
483 """Tests copying objects and files to a directory"""
484 self.RunCommand('cp', ['-R', '%s**' % self.src_bucket_uri.uri,
485 '%s**' % self.src_dir_root, self.dst_dir_root])
486 actual = set(str(u) for u in test_util.test_wildcard_iterator(
487 '%s**' % self.dst_dir_root).IterUris())
488 expected = set()
489 for uri in self.all_src_obj_uris:
490 # Use FinalObjNameComponent here because we expect names to be flattened
491 # when using wildcard copy semantics.
492 expected.add('file://%s%s' % (self.dst_dir_root,
493 self.FinalObjNameComponent(uri)))
494 for file_path in self.nested_child_file_paths:
495 # Use os.path.basename here because we expect names to be flattened when
496 # using wildcard copy semantics.
497 expected.add('file://%s%s' % (self.dst_dir_root,
498 os.path.basename(file_path)))
499 self.assertEqual(expected, actual)
500
501 def TestCopyingObjToDot(self):
502 """Tests that copying an object to . or ./ downloads to correct name"""
503 for final_char in ('/', ''):
504 prev_dir = os.getcwd()
505 os.chdir(self.dst_dir_root)
506 self.RunCommand('cp',
507 ['%sobj1' % self.src_bucket_uri.uri, '.%s' % final_char])
508 actual = set()
509 for dirname, dirnames, filenames in os.walk('.'):
510 for subdirname in dirnames:
511 actual.add(os.path.join(dirname, subdirname))
512 for filename in filenames:
513 actual.add(os.path.join(dirname, filename))
514 expected = set(['./obj1'])
515 self.assertEqual(expected, actual)
516 os.chdir(prev_dir)
517 # Clean up/re-set up for next variant iteration.
518 self.TearDownClass()
519 self.SetUpClass()
520
521 def TestCopyingObjsAndFilesToBucket(self):
522 """Tests copying objects and files to a bucket"""
523 self.RunCommand('cp', ['-R', '%s**' % self.src_bucket_uri.uri,
524 '%s**' % self.src_dir_root, self.dst_bucket_uri.uri])
525 actual = set(str(u) for u in test_util.test_wildcard_iterator(
526 '%s*' % self.dst_bucket_uri.uri).IterUris())
527 expected = set()
528 for uri in self.all_src_obj_uris:
529 # Use FinalObjNameComponent here because we expect names to be flattened
530 # when using wildcard copy semantics.
531 expected.add('%s%s' % (self.dst_bucket_uri.uri,
532 self.FinalObjNameComponent(uri)))
533 for file_path in self.nested_child_file_paths:
534 # Use os.path.basename here because we expect names to be flattened when
535 # using wildcard copy semantics.
536 expected.add('%s%s' % (self.dst_bucket_uri.uri,
537 os.path.basename(file_path)))
538 self.assertEqual(expected, actual)
539
540 def TestAttemptDirCopyWithoutRecursion(self):
541 """Tests copying a directory without -R"""
542 try:
543 self.RunCommand('cp', [self.src_dir_root,
544 self.dst_dir_root])
545 self.fail('Did not get expected CommandException')
546 except CommandException, e:
547 self.assertNotEqual(e.reason.find('No URIs matched'), -1)
548
549 def TestAttemptCopyingProviderOnlySrc(self):
550 """Attempts to copy a src specified as a provider-only URI"""
551 try:
552 self.RunCommand('cp', ['gs://', self.src_bucket_uri.uri])
553 self.fail('Did not get expected CommandException')
554 except CommandException, e:
555 self.assertNotEqual(e.reason.find('provider-only'), -1)
556
557 def TestAttemptCopyingOverlappingSrcDstFile(self):
558 """Attempts to an object atop itself"""
559 obj_uri = test_util.test_storage_uri('%sobj' % self.dst_bucket_uri)
560 self.CreateEmptyObject(obj_uri)
561 try:
562 self.RunCommand('cp', ['%s/f0' % self.src_dir_root,
563 '%s/f0' % self.src_dir_root])
564 self.fail('Did not get expected CommandException')
565 except CommandException, e:
566 self.assertNotEqual(e.reason.find('are the same file - abort'), -1)
567
568 def TestAttemptCopyingToMultiMatchWildcard(self):
569 """Attempts to copy where dst wildcard matches >1 obj"""
570 try:
571 self.RunCommand('cp', ['%sobj0' % self.src_bucket_uri.uri,
572 '%s*' % self.src_bucket_uri.uri])
573 self.fail('Did not get expected CommandException')
574 except CommandException, e:
575 self.assertNotEqual(e.reason.find('must match exactly 1 URI'), -1)
576
577 def TestAttemptCopyingMultiObjsToFile(self):
578 """Attempts to copy multiple objects to a file"""
579 # Use src_dir_root so we can point to an existing file for this test.
580 try:
581 self.RunCommand('cp', ['-R', '%s*' % self.src_bucket_uri.uri,
582 '%sf0' % self.src_dir_root])
583 self.fail('Did not get expected CommandException')
584 except CommandException, e:
585 self.assertNotEqual(e.reason.find('must name a cloud path or '), -2)
586
587 def TestAttemptCopyingWithFileDirConflict(self):
588 """Attempts to copy objects that cause a file/directory conflict"""
589 # Create objects with name conflicts (a/b and a). Use 'dst' bucket because
590 # it gets cleared after each test.
591 self.CreateEmptyObject(test_util.test_storage_uri(
592 '%sa/b' % self.dst_bucket_uri))
593 self.CreateEmptyObject(test_util.test_storage_uri(
594 '%sa' % self.dst_bucket_uri))
595 try:
596 self.RunCommand('cp', ['-R', self.dst_bucket_uri.uri,
597 self.dst_dir_root])
598 self.fail('Did not get expected CommandException')
599 except CommandException, e:
600 self.assertNotEqual(e.reason.find(
601 'exists where a directory needs to be created'), -1)
602
603 def TestAttemptCopyingWithDirFileConflict(self):
604 """Attempts to copy an object that causes a directory/file conflict"""
605 # Create abc in dest dir.
606 os.mkdir('%sabc' % self.dst_dir_root)
607 # Create an object that conflicts with this dest subdir. Use 'dst' bucket
608 # as source because it gets cleared after each test.
609 obj_name = '%sabc' % self.dst_bucket_uri
610 self.CreateEmptyObject(test_util.test_storage_uri(obj_name))
611 try:
612 self.RunCommand('cp', [obj_name, self.dst_dir_root])
613 self.fail('Did not get expected CommandException')
614 except CommandException, e:
615 self.assertNotEqual(e.reason.find(
616 'where the file needs to be created'), -1)
617
618 def TestWildcardMoveWithinBucket(self):
619 """Attempts to move using src wildcard that overlaps dest object.
620 We want to ensure that this doesn't stomp the result data. See the
621 comment starting with 'Expand wildcards before' in commands/mv.py
622 for details.
623 """
624 # Create a single object; use 'dst' bucket because it gets cleared after
625 # each test.
626 self.CreateEmptyObject(
627 test_util.test_storage_uri('%sold' % self.dst_bucket_uri))
628 self.RunCommand('mv', ['%s*' % self.dst_bucket_uri.uri,
629 '%snew' % self.dst_bucket_uri.uri])
630 actual = list(
631 test_util.test_wildcard_iterator(
632 '%s*' % self.dst_bucket_uri.uri).IterUris())
633 self.assertEqual(1, len(actual))
634 self.assertEqual('new', actual[0].object_name)
635
636 def TestCatCommandRuns(self):
637 """Test that the cat command basically runs"""
638 self.RunCommand('cat', ['%sobj1' % self.src_bucket_uri.uri])
639
640 def TestGetAclCommandRuns(self):
641 """Test that the getacl command basically runs"""
642 self.RunCommand('getacl', [self.src_bucket_uri.uri])
643
644 def TestGetDefAclCommandRuns(self):
645 """Test that the getdefacl command basically runs"""
646 self.RunCommand('getacl', [self.src_bucket_uri.uri])
647
648 def TestGetLoggingCommandRuns(self):
649 """Test that the getlogging command basically runs"""
650 self.RunCommand('getlogging', [self.src_bucket_uri.uri])
651
652 def TestHelpCommandDoesntRaise(self):
653 """Test that the help command doesn't raise (sanity checks all help)"""
654 # Unset PAGER if defined, so help output paginating into $PAGER doesn't
655 # cause test to pause.
656 if 'PAGER' in os.environ:
657 del os.environ['PAGER']
658 self.RunCommand('help', [])
659
660 def TestLsNonExistentObjectWithPrefixName(self):
661 """Test ls of non-existent obj that matches prefix of existing objs"""
662 # Use an object name that matches a prefix of other names at that level, to
663 # ensure the ls subdir handling logic doesn't pick up anything extra.
664 try:
665 output = self.RunCommand('ls', ['%sobj' % self.src_bucket_uri.uri],
666 return_stdout=True)
667 except CommandException, e:
668 self.assertNotEqual(e.reason.find('No such object'), -1)
669
670 def TestLsBucketNonRecursive(self):
671 """Test that ls of a bucket returns expected results"""
672 output = self.RunCommand('ls', ['%s*' % self.src_bucket_uri.uri],
673 return_stdout=True)
674 expected = set(x.uri for x in self.all_src_top_level_obj_uris)
675 expected = expected.union(x.uri for x in self.all_src_subdir_obj_uris)
676 expected.add('%ssrc_subdir/:' % self.src_bucket_uri.uri)
677 expected.add('%ssrc_subdir/nested/' % self.src_bucket_uri.uri)
678 expected.add('') # Blank line between subdir listings.
679 actual = set(output.split('\n'))
680 self.assertEqual(expected, actual)
681
682 def TestLsBucketRecursive(self):
683 """Test that ls -R of a bucket returns expected results"""
684 output = self.RunCommand('ls', ['-R', '%s*' % self.src_bucket_uri.uri],
685 return_stdout=True)
686 expected = set(x.uri for x in self.all_src_obj_uris)
687 expected = expected.union(x.uri for x in self.all_src_subdir_obj_uris)
688 expected.add('%ssrc_subdir/:' % self.src_bucket_uri.uri)
689 expected.add('%ssrc_subdir/nested/:' % self.src_bucket_uri.uri)
690 expected.add('') # Blank line between subdir listings.
691 actual = set(output.split('\n'))
692 self.assertEqual(expected, actual)
693
694 def TestLsBucketRecursiveWithLeadingSlashObjectName(self):
695 """Test that ls -R of a bucket with an object that has leading slash"""
696 src_file = self.SrcFile('f0')
697 self.RunCommand('cp', [src_file, '%s/%s' % (self.dst_bucket_uri.uri, 'f0')])
698 output = self.RunCommand('ls', ['-R', '%s*' % self.dst_bucket_uri.uri],
699 return_stdout=True)
700 expected = set(['%s/%s' % (self.dst_bucket_uri.uri, 'f0')])
701 expected.add('') # Blank line between subdir listings.
702 actual = set(output.split('\n'))
703 self.assertEqual(expected, actual)
704
705 def TestLsBucketSubdirNonRecursive(self):
706 """Test that ls of a bucket subdir returns expected results"""
707 output = self.RunCommand('ls', ['%ssrc_subdir' % self.src_bucket_uri.uri],
708 return_stdout=True)
709 expected = set(x.uri for x in self.all_src_subdir_obj_uris)
710 expected = expected.union(x.uri for x in self.all_src_subdir_obj_uris)
711 expected.add('%ssrc_subdir/nested/' % self.src_bucket_uri.uri)
712 expected.add('') # Blank line between subdir listings.
713 actual = set(output.split('\n'))
714 self.assertEqual(expected, actual)
715
716 def TestLsBucketSubdirRecursive(self):
717 """Test that ls -R of a bucket subdir returns expected results"""
718 for final_char in ('/', ''):
719 output = self.RunCommand('ls',
720 ['-R', '%ssrc_subdir%s'
721 % (self.src_bucket_uri.uri, final_char)],
722 return_stdout=True)
723 expected = set(x.uri for x in self.all_src_subdir_and_below_obj_uris)
724 expected = expected.union(x.uri for x in self.all_src_subdir_obj_uris)
725 expected.add('%ssrc_subdir/:' % self.src_bucket_uri.uri)
726 expected.add('%ssrc_subdir/nested/:' % self.src_bucket_uri.uri)
727 expected.add('') # Blank line between subdir listings.
728 actual = set(output.split('\n'))
729 self.assertEqual(expected, actual)
730
731 def TestMakeBucketsCommand(self):
732 """Test mb on existing bucket"""
733 try:
734 self.RunCommand('mb', [self.dst_bucket_uri.uri])
735 self.fail('Did not get expected StorageCreateError')
736 except boto.exception.StorageCreateError, e:
737 self.assertEqual(e.status, 409)
738
739 def TestRemoveBucketsCommand(self):
740 """Test rb on non-existent bucket"""
741 try:
742 self.RunCommand('rb', ['gs://non_existent_%s' %
743 self.dst_bucket_uri.bucket_name])
744 self.fail('Did not get expected StorageResponseError')
745 except boto.exception.StorageResponseError, e:
746 self.assertEqual(e.status, 404)
747
748 def TestRemoveObjsCommand(self):
749 """Test rm command on non-existent object"""
750 try:
751 self.RunCommand('rm', ['%snon_existent' %
752 self.dst_bucket_uri.uri])
753 self.fail('Did not get expected WildcardException')
754 except StorageResponseError, e:
755 self.assertNotEqual(e.reason.find('Not Found'), -1)
756
757 def TestSetAclOnBucketRuns(self):
758 """Test that the setacl command basically runs"""
759 # We don't test reading back the acl (via getacl command) because at present
760 # MockStorageService doesn't translate canned ACLs into actual ACL XML.
761 self.RunCommand('setacl', ['private', self.src_bucket_uri.uri])
762
763 def TestSetAclOnWildcardNamedBucketRuns(self):
764 """Test that setacl basically runs against wildcard-named bucket"""
765 # We don't test reading back the acl (via getacl command) because at present
766 # MockStorageService doesn't translate canned ACLs into actual ACL XML.
767 uri_str = '%s_s*c' % self.uri_base_str
768 self.RunCommand('setacl', ['private', uri_str])
769
770 def TestSetAclOnObjectRuns(self):
771 """Test that the setacl command basically runs"""
772 self.RunCommand('setacl', ['private', '%s*' % self.src_bucket_uri.uri])
773
774 def TestSetDefAclOnBucketRuns(self):
775 """Test that the setdefacl command basically runs"""
776 self.RunCommand('setdefacl', ['private', self.src_bucket_uri.uri])
777
778 def TestSetDefAclOnObjectFails(self):
779 """Test that the setdefacl command fails when run against an object"""
780 try:
781 self.RunCommand('setdefacl', ['private', '%s*' % self.src_bucket_uri.uri])
782 self.fail('Did not get expected CommandException')
783 except CommandException, e:
784 self.assertNotEqual(e.reason.find('URI must name a bucket'), -1)
785
786 def TestDisableLoggingCommandRuns(self):
787 """Test that the disablelogging command basically runs"""
788 self.RunCommand('disablelogging', [self.src_bucket_uri.uri])
789
790 def TestEnableLoggingCommandRuns(self):
791 """Test that the enablelogging command basically runs"""
792 self.RunCommand('enablelogging', ['-b', 'gs://log_bucket',
793 self.src_bucket_uri.uri])
794
795 # Now that gsutil ver computes a checksum it adds 1-3 seconds to test run
796 # time (for in memory mocked tests that otherwise take ~ 0.1 seconds). Since
797 # it provides very little test value, we're leaving this test commented out.
798 #def TestVerCommmandRuns(self):
799 # """Test that the Ver command basically runs"""
800 # self.RunCommand('ver', [])
801
802 def TestMinusDOptionWorks(self):
803 """Tests using gsutil -D option"""
804 src_file = self.SrcFile('f0')
805 self.RunCommand('cp', [src_file, self.dst_bucket_uri.uri], debug=3)
806 actual = list(test_util.test_wildcard_iterator(
807 '%s*' % self.dst_bucket_uri.uri).IterUris())
808 self.assertEqual(1, len(actual))
809 self.assertEqual('f0', actual[0].object_name)
810
811 def DownloadTestHelper(self, func):
812 """
813 Test resumable download with custom test function to distort downloaded
814 data. We expect an exception to be raised and the dest file to be removed.
815 """
816 object_uri = self.all_src_obj_uris[0].uri
817 try:
818 self.RunCommand('cp', [object_uri, self.tmp_path], test_method=func)
819 self.fail('Did not get expected CommandException')
820 except CommandException:
821 self.assertFalse(os.path.exists(self.tmp_path))
822 except:
823 self.fail('Unexpected exception raised')
824
825 def TestDownloadWithObjectSizeChange(self):
826 """
827 Test resumable download on an object that changes size before the
828 downloaded file's checksum is validated.
829 """
830 def append(fp):
831 """Append a byte at end of an open file and flush contents."""
832 fp.seek(0,2)
833 fp.write('x')
834 fp.flush()
835 self.DownloadTestHelper(append)
836
837 def TestDownloadWithFileContentChange(self):
838 """
839 Tests resumable download on an object where the file content changes
840 before the downloaded file's checksum is validated.
841 """
842 def overwrite(fp):
843 """Overwrite first byte in an open file and flush contents."""
844 fp.seek(0)
845 fp.write('x')
846 fp.flush()
847 self.DownloadTestHelper(overwrite)
848
849 def TestFlatCopyingObjsAndFilesToBucketSubDir(self):
850 """Tests copying flatly listed objects and files to bucket subdir"""
851 # Test with and without final slash on dest subdir.
852 for final_char in ('/', ''):
853 # Set up existing bucket subdir by creating an object in the subdir.
854 self.RunCommand(
855 'cp', ['%sf0' % self.src_dir_root,
856 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
857 self.RunCommand(
858 'cp', ['-R', '%s**' % self.src_bucket_uri.uri,
859 '%s**' % self.src_dir_root,
860 '%sdst_subdir%s' % (self.dst_bucket_uri.uri, final_char)])
861 actual = set(str(u) for u in test_util.test_wildcard_iterator(
862 '%s**' % self.dst_bucket_uri.uri).IterUris())
863 expected = set(['%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
864 for uri in self.all_src_obj_uris:
865 # Use FinalObjNameComponent here because we expect names to be flattened
866 # when using wildcard copy semantics.
867 expected.add('%sdst_subdir/%s' % (self.dst_bucket_uri.uri,
868 self.FinalObjNameComponent(uri)))
869 for file_path in self.nested_child_file_paths:
870 # Use os.path.basename here because we expect names to be flattened when
871 # using wildcard copy semantics.
872 expected.add('%sdst_subdir/%s' % (self.dst_bucket_uri.uri,
873 os.path.basename(file_path)))
874 self.assertEqual(expected, actual)
875 # Clean up/re-set up for next variant iteration.
876 self.TearDownClass()
877 self.SetUpClass()
878
879 def TestRecursiveCopyObjsAndFilesToExistingBucketSubDir(self):
880 """Tests recursive copy of objects and files to existing bucket subdir"""
881 # Test with and without final slash on dest subdir.
882 for final_char in ('/', ''):
883 # Set up existing bucket subdir by creating an object in the subdir.
884 self.RunCommand(
885 'cp', ['%sf0' % self.src_dir_root,
886 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
887 self.RunCommand(
888 'cp', ['-R', '%s' % self.src_bucket_uri.uri,
889 '%s' % self.src_dir_root,
890 '%sdst_subdir%s' % (self.dst_bucket_uri.uri, final_char)])
891 actual = set(str(u) for u in test_util.test_wildcard_iterator(
892 '%s**' % self.dst_bucket_uri.uri).IterUris())
893 expected = set(['%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
894 for uri in self.all_src_obj_uris:
895 expected.add('%sdst_subdir/%s/%s' %
896 (self.dst_bucket_uri.uri, uri.bucket_name, uri.object_name))
897 for file_path in self.all_src_file_paths:
898 start_tmp_pos = file_path.find(self.tmpdir_prefix)
899 file_path_sans_base_dir = file_path[start_tmp_pos:]
900 expected.add('%sdst_subdir/%s' %
901 (self.dst_bucket_uri.uri, file_path_sans_base_dir))
902 self.assertEqual(expected, actual)
903 # Clean up/re-set up for next variant iteration.
904 self.TearDownClass()
905 self.SetUpClass()
906
907 def TestRecursiveCopyObjsAndFilesToNonExistentBucketSubDir(self):
908 """Tests recursive copy of objs + files to non-existent bucket subdir"""
909 # Test with and without final slash on dest subdir.
910 self.RunCommand(
911 'cp', ['-R', '%s' % self.src_bucket_uri.uri,
912 '%s' % self.src_dir_root,
913 '%sdst_subdir' % (self.dst_bucket_uri.uri)])
914 actual = set(str(u) for u in test_util.test_wildcard_iterator(
915 '%s**' % self.dst_bucket_uri.uri).IterUris())
916 expected = set()
917 for uri in self.all_src_obj_uris:
918 expected.add('%sdst_subdir/%s' %
919 (self.dst_bucket_uri.uri, uri.object_name))
920 for file_path in self.all_src_file_paths:
921 start_tmp_pos = file_path.find(self.tmpdir_prefix)
922 file_path_sans_base_dir = (
923 file_path[start_tmp_pos:].partition(os.sep)[-1])
924 expected.add('%sdst_subdir/%s' %
925 (self.dst_bucket_uri.uri, file_path_sans_base_dir))
926 self.assertEqual(expected, actual)
927
928 def TestCopyingBucketSubDirToDir(self):
929 """Tests copying a bucket subdir to a directory"""
930 # Test with and without final slash on dest subdir.
931 for (final_src_char, final_dst_char) in (
932 ('', ''), ('', '/'), ('/', ''), ('/', '/') ):
933 self.RunCommand(
934 'cp', ['-R', '%s%s' % (self.src_bucket_subdir_uri, final_src_char),
935 '%s%s' % (self.dst_dir_root, final_dst_char)])
936 actual = set(str(u) for u in test_util.test_wildcard_iterator(
937 '%s/**' % self.dst_dir_root).IterUris())
938 expected = set()
939 for uri in self.all_src_subdir_and_below_obj_uris:
940 expected.add('file://%s%s' % (self.dst_dir_root, uri.uri.partition(
941 self.src_bucket_uri.uri)[-1]))
942 self.assertEqual(expected, actual)
943 # Clean up/re-set up for next variant iteration.
944 self.TearDownClass()
945 self.SetUpClass()
946
947 def TestCopyingWildcardSpecifiedBucketSubDirToExistingDir(self):
948 """Tests copying a wilcard-specified bucket subdir to a directory"""
949 # Test with and without final slash on dest subdir.
950 for (final_src_char, final_dst_char) in (
951 ('', ''), ('', '/'), ('/', ''), ('/', '/') ):
952 self.RunCommand(
953 'cp', ['-R',
954 '%s%s' % (self.src_bucket_subdir_uri_wildcard, final_src_char),
955 '%s%s' % (self.dst_dir_root, final_dst_char)])
956 actual = set(str(u) for u in test_util.test_wildcard_iterator(
957 '%s/**' % self.dst_dir_root).IterUris())
958 expected = set()
959 for uri in self.all_src_subdir_and_below_obj_uris:
960 expected.add('file://%s%s' % (
961 self.dst_dir_root, uri.uri.partition(self.src_bucket_uri.uri)[-1]))
962 self.assertEqual(expected, actual)
963 # Clean up/re-set up for next variant iteration.
964 self.TearDownClass()
965 self.SetUpClass()
966
967 def TestCopyingBucketSubDirToDirFailsWithoutMinusR(self):
968 """Tests for failure when attempting bucket subdir copy without -R"""
969 try:
970 self.RunCommand(
971 'cp', ['%s' % self.src_bucket_subdir_uri,
972 '%s' % self.dst_dir_root])
973 self.fail('Did not get expected CommandException')
974 except CommandException, e:
975 self.assertNotEqual(e.reason.find('does not exist'), -1)
976
977 def TestCopyingBucketSubDirToBucketSubDir(self):
978 """Tests copying a bucket subdir to another bucket subdir"""
979 # Test with and without final slash on dest subdir.
980 for (final_src_char, final_dst_char) in (
981 ('', ''), ('', '/'), ('/', ''), ('/', '/') ):
982 # Set up existing bucket subdir by creating an object in the subdir.
983 self.RunCommand(
984 'cp', ['%sf0' % self.src_dir_root,
985 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
986 self.RunCommand(
987 'cp', ['-R', '%s%s' % (self.src_bucket_subdir_uri, final_src_char),
988 '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
989 actual = set(str(u) for u in test_util.test_wildcard_iterator(
990 '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
991 expected = set(['%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
992 for uri in self.all_src_subdir_and_below_obj_uris:
993 expected.add(
994 '%s/%s' % (self.dst_bucket_subdir_uri.uri, uri.object_name))
995 self.assertEqual(expected, actual)
996 # Clean up/re-set up for next variant iteration.
997 self.TearDownClass()
998 self.SetUpClass()
999
1000 def TestMovingBucketSubDirToNonExistentBucketSubDir(self):
1001 """Tests moving a bucket subdir to a non-existent bucket subdir"""
1002 # Test with and without final slash on dest subdir.
1003 for final_src_char in ('', '/'):
1004 self.RunCommand(
1005 'mv', ['%s%s' % (self.src_bucket_subdir_uri, final_src_char),
1006 '%s' % (self.dst_bucket_subdir_uri.uri)])
1007 actual = set(str(u) for u in test_util.test_wildcard_iterator(
1008 '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
1009 expected = set([])
1010 for uri in self.all_src_subdir_and_below_obj_uris:
1011 # Unlike the case with copying, with mv we expect renaming to occur
1012 # at the level of the src subdir, vs appending that subdir beneath the
1013 # dst subdir like is done for copying.
1014 expected_name = uri.object_name.replace('src_', 'dst_')
1015 expected.add('%s%s' % (self.dst_bucket_uri.uri, expected_name))
1016 self.assertEqual(expected, actual)
1017 # Clean up/re-set up for next variant iteration.
1018 self.TearDownClass()
1019 self.SetUpClass()
1020
1021 def TestMovingBucketSubDirToExistingBucketSubDir(self):
1022 """Tests moving a bucket subdir to a existing bucket subdir"""
1023 # Test with and without final slash on dest subdir.
1024 for (final_src_char, final_dst_char) in (
1025 ('', ''), ('', '/'), ('/', ''), ('/', '/') ):
1026 # Set up existing bucket subdir by creating an object in the subdir.
1027 self.RunCommand(
1028 'cp', ['%sf0' % self.src_dir_root,
1029 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
1030 self.RunCommand(
1031 'mv', ['%s%s' % (self.src_bucket_subdir_uri, final_src_char),
1032 '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
1033 actual = set(str(u) for u in test_util.test_wildcard_iterator(
1034 '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
1035 expected = set(['%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
1036 for uri in self.all_src_subdir_and_below_obj_uris:
1037 expected.add(
1038 '%s/%s' % (self.dst_bucket_subdir_uri.uri, uri.object_name))
1039 self.assertEqual(expected, actual)
1040 # Clean up/re-set up for next variant iteration.
1041 self.TearDownClass()
1042 self.SetUpClass()
1043
1044 def TestCopyingObjectToBucketSubDir(self):
1045 """Tests copying an object to a bucket subdir"""
1046 # Test with and without final slash on dest subdir.
1047 for (final_dst_char) in ('', '/'):
1048 # Set up existing bucket subdir by creating an object in the subdir.
1049 self.RunCommand(
1050 'cp', ['%sf0' % self.src_dir_root,
1051 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
1052 self.RunCommand(
1053 'cp', ['%sobj0' % self.src_bucket_uri,
1054 '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
1055 actual = set(str(u) for u in test_util.test_wildcard_iterator(
1056 '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
1057 expected = set([
1058 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri,
1059 '%sdst_subdir/obj0' % self.dst_bucket_uri.uri])
1060 self.assertEqual(expected, actual)
1061 # Clean up/re-set up for next variant iteration.
1062 self.TearDownClass()
1063 self.SetUpClass()
1064
1065 def TestCopyingWildcardedFilesToBucketSubDir(self):
1066 """Tests copying wildcarded files to a bucket subdir"""
1067 # Test with and without final slash on dest subdir.
1068 for (final_dst_char) in ('', '/'):
1069 # Set up existing bucket subdir by creating an object in the subdir.
1070 self.RunCommand(
1071 'cp', ['%sf0' % self.src_dir_root,
1072 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
1073 self.RunCommand(
1074 'cp', ['%sf?' % self.src_dir_root,
1075 '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
1076 actual = set(str(u) for u in test_util.test_wildcard_iterator(
1077 '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
1078 expected = set([
1079 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri,
1080 '%sdst_subdir/f0' % self.dst_bucket_uri.uri,
1081 '%sdst_subdir/f1' % self.dst_bucket_uri.uri])
1082 self.assertEqual(expected, actual)
1083 # Clean up/re-set up for next variant iteration.
1084 self.TearDownClass()
1085 self.SetUpClass()
1086
1087 def TestCopyingOneNestedFileToBucketSubDir(self):
1088 """Tests copying one nested file to a bucket subdir"""
1089 # Test with and without final slash on dest subdir.
1090 for (final_dst_char) in ('', '/'):
1091 # Set up existing bucket subdir by creating an object in the subdir.
1092 self.RunCommand(
1093 'cp', ['%sf0' % self.src_dir_root,
1094 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
1095 self.RunCommand(
1096 'cp', ['-r', '%sdir0' % self.src_dir_root,
1097 '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
1098 actual = set(str(u) for u in test_util.test_wildcard_iterator(
1099 '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
1100 expected = set([
1101 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri,
1102 '%sdst_subdir/dir0/dir1/nested' % self.dst_bucket_uri.uri])
1103 self.assertEqual(expected, actual)
1104 # Clean up/re-set up for next variant iteration.
1105 self.TearDownClass()
1106 self.SetUpClass()
1107
1108 def TestMovingWildcardedFilesToNonExistentBucketSubDir(self):
1109 """Tests moving files to a non-existent bucket subdir"""
1110 # This tests for how we allow users to do something like:
1111 # gsutil cp *.txt gs://bucket/dir
1112 # where *.txt matches more than 1 file and gs://bucket/dir
1113 # doesn't exist as a subdir.
1114 #
1115 # Test with and without final slash on dest subdir.
1116 for (final_dst_char) in ('', '/'):
1117 # Set up existing bucket subdir by creating an object in the subdir.
1118 self.RunCommand(
1119 'cp', ['%sf0' % self.src_dir_root,
1120 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
1121 # Copy some files into place in dst bucket.
1122 self.RunCommand(
1123 'cp', ['%sf?' % self.src_dir_root,
1124 '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
1125 # Now do the move test.
1126 self.RunCommand(
1127 'mv', ['%s/*' % self.dst_bucket_subdir_uri.uri,
1128 '%s/nonexistent/%s' % (self.dst_bucket_subdir_uri.uri, final_ds t_char)])
1129 actual = set(str(u) for u in test_util.test_wildcard_iterator(
1130 '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
1131 expected = set([
1132 '%sdst_subdir/nonexistent/existing_obj' % self.dst_bucket_uri.uri,
1133 '%sdst_subdir/nonexistent/f0' % self.dst_bucket_uri.uri,
1134 '%sdst_subdir/nonexistent/f1' % self.dst_bucket_uri.uri])
1135 self.assertEqual(expected, actual)
1136 # Clean up/re-set up for next variant iteration.
1137 self.TearDownClass()
1138 self.SetUpClass()
1139
1140 def TestMovingObjectToBucketSubDir(self):
1141 """Tests moving an object to a bucket subdir"""
1142 # Test with and without final slash on dest subdir.
1143 for (final_dst_char) in ('', '/'):
1144 # Set up existing bucket subdir by creating an object in the subdir.
1145 self.RunCommand(
1146 'cp', ['%sf0' % self.src_dir_root,
1147 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
1148 self.RunCommand(
1149 'mv', ['%sobj0' % self.src_bucket_uri,
1150 '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
1151 actual = set(str(u) for u in test_util.test_wildcard_iterator(
1152 '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
1153 expected = set([
1154 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri,
1155 '%sdst_subdir/obj0' % self.dst_bucket_uri.uri])
1156 self.assertEqual(expected, actual)
1157 # Clean up/re-set up for next variant iteration.
1158 self.TearDownClass()
1159 self.SetUpClass()
1160
1161 def TestWildcardSrcSubDirMoveDisallowed(self):
1162 """Tests moving a bucket subdir specified by wildcard is disallowed"""
1163 try:
1164 self.RunCommand(
1165 'mv', ['%s*' % self.src_bucket_subdir_uri,
1166 '%s' % self.dst_bucket_subdir_uri.uri])
1167 self.fail('Did not get expected CommandException')
1168 except CommandException, e:
1169 self.assertNotEqual(e.reason.find('mv command disallows naming'), -1)
1170
1171 def TestMovingBucketNestedSubDirToBucketNestedSubDir(self):
1172 """Tests moving a bucket nested subdir to another bucket nested subdir"""
1173 # Test with and without final slash on dest subdir.
1174 for final_src_char in ('', '/'):
1175 self.RunCommand(
1176 'mv', ['%s%s' % (self.src_bucket_subdir_uri, final_src_char),
1177 '%s' % (self.dst_bucket_subdir_uri.uri)])
1178 actual = set(str(u) for u in test_util.test_wildcard_iterator(
1179 '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
1180 expected = set([])
1181 for uri in self.all_src_subdir_and_below_obj_uris:
1182 # Unlike the case with copying, with mv we expect renaming to occur
1183 # at the level of the src subdir, vs appending that subdir beneath the
1184 # dst subdir like is done for copying.
1185 expected_name = uri.object_name.replace('src_', 'dst_')
1186 expected.add('%s%s' % (self.dst_bucket_uri, expected_name))
1187 self.assertEqual(expected, actual)
1188 # Clean up/re-set up for next variant iteration.
1189 self.TearDownClass()
1190 self.SetUpClass()
1191
1192 def TestRemovingBucketSubDir(self):
1193 """Tests removing a bucket subdir"""
1194 # Test with and without final slash on dest subdir.
1195 for final_src_char in ('', '/'):
1196 # Setup: Copy a directory, including subdir, to bucket.
1197 self.RunCommand('cp', ['-R', self.src_dir_root, self.dst_bucket_uri.uri])
1198 src_subdir = self.src_dir_root.split(os.path.sep)[-2]
1199 # Test removing bucket subdir.
1200 self.RunCommand(
1201 'rm', ['-R', '%s%s/dir0%s' %
1202 (self.dst_bucket_uri, src_subdir, final_src_char)])
1203 actual = set(str(u) for u in test_util.test_wildcard_iterator(
1204 '%s**' % self.dst_bucket_uri.uri).IterUris())
1205 expected = set()
1206 for fname in self.non_nested_file_names:
1207 expected.add('%s%s/%s' % (self.dst_bucket_uri.uri, src_subdir, fname))
1208 self.assertEqual(expected, actual)
1209 # Clean up/re-set up for next variant iteration.
1210 self.TearDownClass()
1211 self.SetUpClass()
1212
1213 def TestRecursiveRemoveObjsInBucket(self):
1214 """Tests removing all objects in bucket via rm -R gs://bucket"""
1215 # Test with and without final slash on dest subdir.
1216 for final_src_char in ('', '/'):
1217 # Setup: Copy a directory, including subdir, to bucket.
1218 self.RunCommand('cp', ['-R', self.src_dir_root, self.dst_bucket_uri.uri])
1219 # Test removing all objects via rm -R.
1220 self.RunCommand('rm', ['-R', '%s%s' % (self.dst_bucket_uri,
1221 final_src_char)])
1222 actual = set(str(u) for u in test_util.test_wildcard_iterator(
1223 '%s*' % self.dst_bucket_uri.uri).IterUris())
1224 self.assertEqual(0, len(actual))
1225 # Clean up/re-set up for next variant iteration.
1226 self.TearDownClass()
1227 self.SetUpClass()
1228
1229 def FinalObjNameComponent(self, uri):
1230 """For gs://bucket/abc/def/ghi returns ghi."""
1231 return uri.uri.rpartition('/')[-1]
1232
1233 if __name__ == '__main__':
1234 if sys.version_info[:3] < (2, 5, 1):
1235 sys.exit('These tests must be run on at least Python 2.5.1\n')
1236 test_loader = unittest.TestLoader()
1237 test_loader.testMethodPrefix = 'Test'
1238 suite = test_loader.loadTestsFromTestCase(GsutilCommandTests)
1239 # Seems like there should be a cleaner way to find the test_class.
1240 test_class = suite.__getattribute__('_tests')[0]
1241 # We call SetUpClass() and TearDownClass() ourselves because we
1242 # don't assume the user has Python 2.7 (which supports classmethods
1243 # that do it, with camelCase versions of these names).
1244 try:
1245 print 'Setting up %s...' % test_class.GetSuiteDescription()
1246 test_class.SetUpClass()
1247 print 'Running %s...' % test_class.GetSuiteDescription()
1248 unittest.TextTestRunner(verbosity=2).run(suite)
1249 finally:
1250 print 'Cleaning up after %s...' % test_class.GetSuiteDescription()
1251 test_class.TearDownClass()
1252 print ''
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698