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

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

Issue 10199002: Upgrade gsutil to 3.4 (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed comments Created 8 years, 7 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 | Annotate | Revision Log
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.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 TestCopyingDirToBucket(self):
280 """Tests recursively copying 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 TestCopyingDotSlashToBucket(self):
293 """Tests copying ./ to a bucket produces expected naming"""
294 # When running a command like gsutil cp -r . gs://dest we expect the dest
295 # obj names to be of the form gs://dest/abc, not gs://dest/./abc.
296 orig_dir = os.getcwd()
297 for rel_src_dir in ['.', './']:
298 os.chdir(self.src_dir_root)
299 self.RunCommand('cp', ['-R', rel_src_dir, self.dst_bucket_uri.uri])
300 actual = set(str(u) for u in test_util.test_wildcard_iterator(
301 '%s**' % self.dst_bucket_uri.uri).IterUris())
302 expected = set()
303 for file_path in self.all_src_file_paths:
304 start_tmp_pos = (file_path.find(self.src_dir_root)
305 + len(self.src_dir_root))
306 file_path_sans_top_tmp_dir = file_path[start_tmp_pos:]
307 expected.add('%s%s' % (self.dst_bucket_uri.uri,
308 file_path_sans_top_tmp_dir))
309 self.assertEqual(expected, actual)
310 # Clean up/re-set up for next variant iteration.
311 self.TearDownClass()
312 self.SetUpClass()
313 os.chdir(orig_dir)
314
315 def TestCopyingDirContainingOneFileToBucket(self):
316 """Tests copying a directory containing 1 file to a bucket.
317 We test this case to ensure that correct bucket handling isn't dependent
318 on the copy being treated as a multi-source copy.
319 """
320 self.RunCommand('cp', ['-R', '%sdir0%sdir1' %
321 (self.src_dir_root, os.sep),
322 self.dst_bucket_uri.uri])
323 actual = list((str(u) for u in test_util.test_wildcard_iterator(
324 '%s**' % self.dst_bucket_uri.uri).IterUris()))
325 self.assertEqual(1, len(actual))
326 self.assertEqual('%sdir1%snested' % (self.dst_bucket_uri.uri, os.sep),
327 actual[0])
328
329 def TestCopyingBucketToDir(self):
330 """Tests copying from a bucket to a directory"""
331 self.RunCommand('cp', ['-R', self.src_bucket_uri.uri, self.dst_dir_root])
332 actual = set(str(u) for u in test_util.test_wildcard_iterator(
333 '%s**' % self.dst_dir_root).IterUris())
334 expected = set()
335 for uri in self.all_src_obj_uris:
336 expected.add('file://%s%s/%s' % (self.dst_dir_root, uri.bucket_name,
337 uri.object_name))
338 self.assertEqual(expected, actual)
339
340 def TestCopyingBucketToBucket(self):
341 """Tests copying from a bucket-only URI to a bucket"""
342 self.RunCommand('cp', ['-R', self.src_bucket_uri.uri,
343 self.dst_bucket_uri.uri])
344 actual = set(str(u) for u in test_util.test_wildcard_iterator(
345 '%s**' % self.dst_bucket_uri.uri).IterUris())
346 expected = set()
347 for uri in self.all_src_obj_uris:
348 expected.add('%s%s/%s' % (self.dst_bucket_uri.uri, uri.bucket_name,
349 uri.object_name))
350 self.assertEqual(expected, actual)
351
352 """Tests copying from a directory to a directory"""
353 self.RunCommand('cp', ['-R', self.src_dir_root, self.dst_dir_root])
354 actual = set(str(u) for u in test_util.test_wildcard_iterator(
355 '%s**' % self.dst_dir_root).IterUris())
356 expected = set()
357 for file_path in self.all_src_file_paths:
358 start_tmp_pos = file_path.find(self.tmpdir_prefix)
359 file_path_sans_top_tmp_dir = file_path[start_tmp_pos:]
360 expected.add('file://%s%s' % (self.dst_dir_root,
361 file_path_sans_top_tmp_dir))
362 self.assertEqual(expected, actual)
363
364 def TestCopyingFilesAndDirNonRecursive(self):
365 """Tests copying containing files and a directory without -R"""
366 self.RunCommand('cp', ['%s*' % self.src_dir_root, self.dst_dir_root])
367 actual = set(str(u) for u in test_util.test_wildcard_iterator(
368 '%s**' % self.dst_dir_root).IterUris())
369 expected = set(['file://%s%s' % (self.dst_dir_root, f)
370 for f in self.non_nested_file_names])
371 self.assertEqual(expected, actual)
372
373 def TestCopyingFileToDir(self):
374 """Tests copying one file to a directory"""
375 src_file = self.SrcFile('nested')
376 self.RunCommand('cp', [src_file, self.dst_dir_root])
377 actual = list(test_util.test_wildcard_iterator(
378 '%s*' % self.dst_dir_root).IterUris())
379 self.assertEqual(1, len(actual))
380 self.assertEqual('file://%s%s' % (self.dst_dir_root, 'nested'),
381 actual[0].uri)
382
383 def TestCopyingFileToObjectWithConsecutiveSlashes(self):
384 """Tests copying a file to an object containing consecutive slashes"""
385 src_file = self.SrcFile('f0')
386 self.RunCommand('cp', [src_file, '%s/obj' % self.dst_bucket_uri.uri])
387 actual = list(test_util.test_wildcard_iterator(
388 '%s**' % self.dst_bucket_uri.uri).IterUris())
389 self.assertEqual(1, len(actual))
390 self.assertEqual('/obj', actual[0].object_name)
391
392 def TestCopyingCompressedFileToBucket(self):
393 """Tests copying one file with compression to a bucket"""
394 src_file = self.SrcFile('f2.txt')
395 self.RunCommand('cp', ['-z', 'txt', src_file, self.dst_bucket_uri.uri],)
396 actual = list(
397 str(u) for u in test_util.test_wildcard_iterator(
398 '%s*' % self.dst_bucket_uri.uri).IterUris())
399 self.assertEqual(1, len(actual))
400 expected_dst_uri = self.dst_bucket_uri.clone_replace_name('f2.txt')
401 self.assertEqual(expected_dst_uri.uri, actual[0])
402 dst_key = expected_dst_uri.get_key()
403 dst_key.open_read()
404 self.assertEqual('gzip', dst_key.content_encoding)
405
406 def TestCopyingObjectToObject(self):
407 """Tests copying an object to an object"""
408 self.RunCommand('cp', ['%sobj1' % self.src_bucket_uri.uri,
409 self.dst_bucket_uri.uri])
410 actual = list(test_util.test_wildcard_iterator(
411 '%s*' % self.dst_bucket_uri.uri).IterUris())
412 self.assertEqual(1, len(actual))
413 self.assertEqual('obj1', actual[0].object_name)
414
415 def TestCopyingObjsAndFilesToDir(self):
416 """Tests copying objects and files to a directory"""
417 self.RunCommand('cp', ['-R', '%s**' % self.src_bucket_uri.uri,
418 '%s**' % self.src_dir_root, self.dst_dir_root])
419 actual = set(str(u) for u in test_util.test_wildcard_iterator(
420 '%s**' % self.dst_dir_root).IterUris())
421 expected = set()
422 for uri in self.all_src_obj_uris:
423 # Use FinalObjNameComponent here because we expect names to be flattened
424 # when using wildcard copy semantics.
425 expected.add('file://%s%s' % (self.dst_dir_root,
426 self.FinalObjNameComponent(uri)))
427 for file_path in self.nested_child_file_paths:
428 # Use os.path.basename here because we expect names to be flattened when
429 # using wildcard copy semantics.
430 expected.add('file://%s%s' % (self.dst_dir_root,
431 os.path.basename(file_path)))
432 self.assertEqual(expected, actual)
433
434 def TestCopyingObjToDot(self):
435 """Tests that copying an object to . or ./ downloads to correct name"""
436 for final_char in ('/', ''):
437 prev_dir = os.getcwd()
438 os.chdir(self.dst_dir_root)
439 self.RunCommand('cp',
440 ['%sobj1' % self.src_bucket_uri.uri, '.%s' % final_char])
441 actual = set()
442 for dirname, dirnames, filenames in os.walk('.'):
443 for subdirname in dirnames:
444 actual.add(os.path.join(dirname, subdirname))
445 for filename in filenames:
446 actual.add(os.path.join(dirname, filename))
447 expected = set(['./obj1'])
448 self.assertEqual(expected, actual)
449 os.chdir(prev_dir)
450 # Clean up/re-set up for next variant iteration.
451 self.TearDownClass()
452 self.SetUpClass()
453
454 def TestCopyingObjsAndFilesToBucket(self):
455 """Tests copying objects and files to a bucket"""
456 self.RunCommand('cp', ['-R', '%s**' % self.src_bucket_uri.uri,
457 '%s**' % self.src_dir_root, self.dst_bucket_uri.uri])
458 actual = set(str(u) for u in test_util.test_wildcard_iterator(
459 '%s*' % self.dst_bucket_uri.uri).IterUris())
460 expected = set()
461 for uri in self.all_src_obj_uris:
462 # Use FinalObjNameComponent here because we expect names to be flattened
463 # when using wildcard copy semantics.
464 expected.add('%s%s' % (self.dst_bucket_uri.uri,
465 self.FinalObjNameComponent(uri)))
466 for file_path in self.nested_child_file_paths:
467 # Use os.path.basename here because we expect names to be flattened when
468 # using wildcard copy semantics.
469 expected.add('%s%s' % (self.dst_bucket_uri.uri,
470 os.path.basename(file_path)))
471 self.assertEqual(expected, actual)
472
473 def TestAttemptDirCopyWithoutRecursion(self):
474 """Tests copying a directory without -R"""
475 try:
476 self.RunCommand('cp', [self.src_dir_root,
477 self.dst_dir_root])
478 self.fail('Did not get expected CommandException')
479 except CommandException, e:
480 self.assertNotEqual(e.reason.find('No URIs matched'), -1)
481
482 def TestAttemptCopyingProviderOnlySrc(self):
483 """Attempts to copy a src specified as a provider-only URI"""
484 try:
485 self.RunCommand('cp', ['gs://', self.src_bucket_uri.uri])
486 self.fail('Did not get expected CommandException')
487 except CommandException, e:
488 self.assertNotEqual(e.reason.find('provider-only'), -1)
489
490 def TestAttemptCopyingOverlappingSrcDstFile(self):
491 """Attempts to an object atop itself"""
492 obj_uri = test_util.test_storage_uri('%sobj' % self.dst_bucket_uri)
493 self.CreateEmptyObject(obj_uri)
494 try:
495 self.RunCommand('cp', ['%s/f0' % self.src_dir_root,
496 '%s/f0' % self.src_dir_root])
497 self.fail('Did not get expected CommandException')
498 except CommandException, e:
499 self.assertNotEqual(e.reason.find('are the same file - abort'), -1)
500
501 def TestAttemptCopyingToMultiMatchWildcard(self):
502 """Attempts to copy where dst wildcard matches >1 obj"""
503 try:
504 self.RunCommand('cp', ['%sobj0' % self.src_bucket_uri.uri,
505 '%s*' % self.src_bucket_uri.uri])
506 self.fail('Did not get expected CommandException')
507 except CommandException, e:
508 self.assertNotEqual(e.reason.find('must match exactly 1 URI'), -1)
509
510 def TestAttemptCopyingMultiObjsToFile(self):
511 """Attempts to copy multiple objects to a file"""
512 # Use src_dir_root so we can point to an existing file for this test.
513 try:
514 self.RunCommand('cp', ['-R', '%s*' % self.src_bucket_uri.uri,
515 '%sf0' % self.src_dir_root])
516 self.fail('Did not get expected CommandException')
517 except CommandException, e:
518 self.assertNotEqual(e.reason.find('must name a cloud path or '), -2)
519
520 def TestAttemptCopyingWithFileDirConflict(self):
521 """Attempts to copy objects that cause a file/directory conflict"""
522 # Create objects with name conflicts (a/b and a). Use 'dst' bucket because
523 # it gets cleared after each test.
524 self.CreateEmptyObject(test_util.test_storage_uri(
525 '%sa/b' % self.dst_bucket_uri))
526 self.CreateEmptyObject(test_util.test_storage_uri(
527 '%sa' % self.dst_bucket_uri))
528 try:
529 self.RunCommand('cp', ['-R', self.dst_bucket_uri.uri,
530 self.dst_dir_root])
531 self.fail('Did not get expected CommandException')
532 except CommandException, e:
533 self.assertNotEqual(e.reason.find(
534 'exists where a directory needs to be created'), -1)
535
536 def TestAttemptCopyingWithDirFileConflict(self):
537 """Attempts to copy an object that causes a directory/file conflict"""
538 # Create abc in dest dir.
539 os.mkdir('%sabc' % self.dst_dir_root)
540 # Create an object that conflicts with this dest subdir. Use 'dst' bucket
541 # as source because it gets cleared after each test.
542 obj_name = '%sabc' % self.dst_bucket_uri
543 self.CreateEmptyObject(test_util.test_storage_uri(obj_name))
544 try:
545 self.RunCommand('cp', [obj_name, self.dst_dir_root])
546 self.fail('Did not get expected CommandException')
547 except CommandException, e:
548 self.assertNotEqual(e.reason.find(
549 'where the file needs to be created'), -1)
550
551 def TestWildcardMoveWithinBucket(self):
552 """Attempts to move using src wildcard that overlaps dest object.
553 We want to ensure that this doesn't stomp the result data. See the
554 comment starting with 'Expand wildcards before' in commands/mv.py
555 for details.
556 """
557 # Create a single object; use 'dst' bucket because it gets cleared after
558 # each test.
559 self.CreateEmptyObject(
560 test_util.test_storage_uri('%sold' % self.dst_bucket_uri))
561 self.RunCommand('mv', ['%s*' % self.dst_bucket_uri.uri,
562 '%snew' % self.dst_bucket_uri.uri])
563 actual = list(
564 test_util.test_wildcard_iterator(
565 '%s*' % self.dst_bucket_uri.uri).IterUris())
566 self.assertEqual(1, len(actual))
567 self.assertEqual('new', actual[0].object_name)
568
569 def TestCatCommandRuns(self):
570 """Test that the cat command basically runs"""
571 self.RunCommand('cat', ['%sobj1' % self.src_bucket_uri.uri])
572
573 def TestGetAclCommandRuns(self):
574 """Test that the getacl command basically runs"""
575 self.RunCommand('getacl', [self.src_bucket_uri.uri])
576
577 def TestGetDefAclCommandRuns(self):
578 """Test that the getdefacl command basically runs"""
579 self.RunCommand('getacl', [self.src_bucket_uri.uri])
580
581 def TestGetLoggingCommandRuns(self):
582 """Test that the getlogging command basically runs"""
583 self.RunCommand('getlogging', [self.src_bucket_uri.uri])
584
585 def TestHelpCommandDoesntRaise(self):
586 """Test that the help command doesn't raise (sanity checks all help)"""
587 # Unset PAGER if defined, so help output paginating into $PAGER doesn't
588 # cause test to pause.
589 if 'PAGER' in os.environ:
590 del os.environ['PAGER']
591 self.RunCommand('help', [])
592
593 def TestLsNonExistentObjectWithPrefixName(self):
594 """Test ls of non-existent obj that matches prefix of existing objs"""
595 # Use an object name that matches a prefix of other names at that level, to
596 # ensure the ls subdir handling logic doesn't pick up anything extra.
597 output = self.RunCommand('ls', ['%sobj' % self.src_bucket_uri.uri],
598 return_stdout=True)
599 self.assertEqual('', output)
600
601 def TestLsBucketNonRecursive(self):
602 """Test that ls of a bucket returns expected results"""
603 output = self.RunCommand('ls', ['%s*' % self.src_bucket_uri.uri],
604 return_stdout=True)
605 expected = set(x.uri for x in self.all_src_top_level_obj_uris)
606 expected = expected.union(x.uri for x in self.all_src_subdir_obj_uris)
607 expected.add('%ssrc_subdir/:' % self.src_bucket_uri.uri)
608 expected.add('%ssrc_subdir/nested/' % self.src_bucket_uri.uri)
609 expected.add('') # Blank line between subdir listings.
610 actual = set(output.split('\n'))
611 self.assertEqual(expected, actual)
612
613 def TestLsBucketRecursive(self):
614 """Test that ls -R of a bucket returns expected results"""
615 output = self.RunCommand('ls', ['-R', '%s*' % self.src_bucket_uri.uri],
616 return_stdout=True)
617 expected = set(x.uri for x in self.all_src_obj_uris)
618 expected = expected.union(x.uri for x in self.all_src_subdir_obj_uris)
619 expected.add('%ssrc_subdir/:' % self.src_bucket_uri.uri)
620 expected.add('%ssrc_subdir/nested/:' % self.src_bucket_uri.uri)
621 expected.add('') # Blank line between subdir listings.
622 actual = set(output.split('\n'))
623 self.assertEqual(expected, actual)
624
625 def TestLsBucketRecursiveWithLeadingSlashObjectName(self):
626 """Test that ls -R of a bucket with an object that has leading slash"""
627 src_file = self.SrcFile('f0')
628 self.RunCommand('cp', [src_file, '%s/%s' % (self.dst_bucket_uri.uri, 'f0')])
629 output = self.RunCommand('ls', ['-R', '%s*' % self.dst_bucket_uri.uri],
630 return_stdout=True)
631 expected = set(['%s/%s' % (self.dst_bucket_uri.uri, 'f0')])
632 expected.add('') # Blank line between subdir listings.
633 actual = set(output.split('\n'))
634 self.assertEqual(expected, actual)
635
636 def TestLsBucketSubdirNonRecursive(self):
637 """Test that ls of a bucket subdir returns expected results"""
638 output = self.RunCommand('ls', ['%ssrc_subdir' % self.src_bucket_uri.uri],
639 return_stdout=True)
640 expected = set(x.uri for x in self.all_src_subdir_obj_uris)
641 expected = expected.union(x.uri for x in self.all_src_subdir_obj_uris)
642 expected.add('%ssrc_subdir/nested/' % self.src_bucket_uri.uri)
643 expected.add('') # Blank line between subdir listings.
644 actual = set(output.split('\n'))
645 self.assertEqual(expected, actual)
646
647 def TestLsBucketSubdirRecursive(self):
648 """Test that ls -R of a bucket subdir returns expected results"""
649 output = self.RunCommand('ls',
650 ['-R', '%ssrc_subdir' % self.src_bucket_uri.uri],
651 return_stdout=True)
652 expected = set(x.uri for x in self.all_src_subdir_and_below_obj_uris)
653 expected = expected.union(x.uri for x in self.all_src_subdir_obj_uris)
654 expected.add('%ssrc_subdir/:' % self.src_bucket_uri.uri)
655 expected.add('%ssrc_subdir/nested/:' % self.src_bucket_uri.uri)
656 expected.add('') # Blank line between subdir listings.
657 actual = set(output.split('\n'))
658 self.assertEqual(expected, actual)
659
660 def TestMakeBucketsCommand(self):
661 """Test mb on existing bucket"""
662 try:
663 self.RunCommand('mb', [self.dst_bucket_uri.uri])
664 self.fail('Did not get expected StorageCreateError')
665 except boto.exception.StorageCreateError, e:
666 self.assertEqual(e.status, 409)
667
668 def TestRemoveBucketsCommand(self):
669 """Test rb on non-existent bucket"""
670 try:
671 self.RunCommand('rb', ['gs://non_existent_%s' %
672 self.dst_bucket_uri.bucket_name])
673 self.fail('Did not get expected StorageResponseError')
674 except boto.exception.StorageResponseError, e:
675 self.assertEqual(e.status, 404)
676
677 def TestRemoveObjsCommand(self):
678 """Test rm command on non-existent object"""
679 try:
680 self.RunCommand('rm', ['%snon_existent' %
681 self.dst_bucket_uri.uri])
682 self.fail('Did not get expected WildcardException')
683 except StorageResponseError, e:
684 self.assertNotEqual(e.reason.find('Not Found'), -1)
685
686 def TestSetAclOnBucketRuns(self):
687 """Test that the setacl command basically runs"""
688 # We don't test reading back the acl (via getacl command) because at present
689 # MockStorageService doesn't translate canned ACLs into actual ACL XML.
690 self.RunCommand('setacl', ['private', self.src_bucket_uri.uri])
691
692 def TestSetAclOnWildcardNamedBucketRuns(self):
693 """Test that setacl basically runs against wildcard-named bucket"""
694 # We don't test reading back the acl (via getacl command) because at present
695 # MockStorageService doesn't translate canned ACLs into actual ACL XML.
696 uri_str = '%s_s*c' % self.uri_base_str
697 self.RunCommand('setacl', ['private', uri_str])
698
699 def TestSetAclOnObjectRuns(self):
700 """Test that the setacl command basically runs"""
701 self.RunCommand('setacl', ['private', '%s*' % self.src_bucket_uri.uri])
702
703 def TestSetDefAclOnBucketRuns(self):
704 """Test that the setdefacl command basically runs"""
705 self.RunCommand('setdefacl', ['private', self.src_bucket_uri.uri])
706
707 def TestSetDefAclOnObjectFails(self):
708 """Test that the setdefacl command fails when run against an object"""
709 try:
710 self.RunCommand('setdefacl', ['private', '%s*' % self.src_bucket_uri.uri])
711 self.fail('Did not get expected CommandException')
712 except CommandException, e:
713 self.assertNotEqual(e.reason.find('URI must name a bucket'), -1)
714
715 def TestDisableLoggingCommandRuns(self):
716 """Test that the disablelogging command basically runs"""
717 self.RunCommand('disablelogging', [self.src_bucket_uri.uri])
718
719 def TestEnableLoggingCommandRuns(self):
720 """Test that the enablelogging command basically runs"""
721 self.RunCommand('enablelogging', ['-b', 'gs://log_bucket',
722 self.src_bucket_uri.uri])
723
724 # Now that gsutil ver computes a checksum it adds 1-3 seconds to test run
725 # time (for in memory mocked tests that otherwise take ~ 0.1 seconds). Since
726 # it provides very little test value, we're leaving this test commented out.
727 #def TestVerCommmandRuns(self):
728 # """Test that the Ver command basically runs"""
729 # self.RunCommand('ver', [])
730
731 def TestMinusDOptionWorks(self):
732 """Tests using gsutil -D option"""
733 src_file = self.SrcFile('f0')
734 self.RunCommand('cp', [src_file, self.dst_bucket_uri.uri], debug=3)
735 actual = list(test_util.test_wildcard_iterator(
736 '%s*' % self.dst_bucket_uri.uri).IterUris())
737 self.assertEqual(1, len(actual))
738 self.assertEqual('f0', actual[0].object_name)
739
740 def DownloadTestHelper(self, func):
741 """
742 Test resumable download with custom test function to distort downloaded
743 data. We expect an exception to be raised and the dest file to be removed.
744 """
745 object_uri = self.all_src_obj_uris[0].uri
746 try:
747 self.RunCommand('cp', [object_uri, self.tmp_path], test_method=func)
748 self.fail('Did not get expected CommandException')
749 except CommandException:
750 self.assertFalse(os.path.exists(self.tmp_path))
751 except:
752 self.fail('Unexpected exception raised')
753
754 def TestDownloadWithObjectSizeShange(self):
755 """
756 Test resumable download on an object that changes size before the
757 downloaded file's checksum is validated.
758 """
759 def append(fp):
760 """Append a byte at end of an open file and flush contents."""
761 fp.seek(0,2)
762 fp.write('x')
763 fp.flush()
764 self.DownloadTestHelper(append)
765
766 def TestDownloadWithFileContentChange(self):
767 """
768 Tests resumable download on an object where the file content changes
769 before the downloaded file's checksum is validated.
770 """
771 def overwrite(fp):
772 """Overwrite first byte in an open file and flush contents."""
773 fp.seek(0)
774 fp.write('x')
775 fp.flush()
776 self.DownloadTestHelper(overwrite)
777
778 def TestFlatCopyingObjsAndFilesToBucketSubDir(self):
779 """Tests copying flatly listed objects and files to bucket subdir"""
780 # Test with and without final slash on dest subdir.
781 for final_char in ('/', ''):
782 # Set up existing bucket subdir by creating an object in the subdir.
783 self.RunCommand(
784 'cp', ['%sf0' % self.src_dir_root,
785 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
786 self.RunCommand(
787 'cp', ['-R', '%s**' % self.src_bucket_uri.uri,
788 '%s**' % self.src_dir_root,
789 '%sdst_subdir%s' % (self.dst_bucket_uri.uri, final_char)])
790 actual = set(str(u) for u in test_util.test_wildcard_iterator(
791 '%s**' % self.dst_bucket_uri.uri).IterUris())
792 expected = set(['%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
793 for uri in self.all_src_obj_uris:
794 # Use FinalObjNameComponent here because we expect names to be flattened
795 # when using wildcard copy semantics.
796 expected.add('%sdst_subdir/%s' % (self.dst_bucket_uri.uri,
797 self.FinalObjNameComponent(uri)))
798 for file_path in self.nested_child_file_paths:
799 # Use os.path.basename here because we expect names to be flattened when
800 # using wildcard copy semantics.
801 expected.add('%sdst_subdir/%s' % (self.dst_bucket_uri.uri,
802 os.path.basename(file_path)))
803 self.assertEqual(expected, actual)
804 # Clean up/re-set up for next variant iteration.
805 self.TearDownClass()
806 self.SetUpClass()
807
808 def TestRecursiveCopyObjsAndFilesToExistingBucketSubDir(self):
809 """Tests recursive copy of objects and files to existing bucket subdir"""
810 # Test with and without final slash on dest subdir.
811 for final_char in ('/', ''):
812 # Set up existing bucket subdir by creating an object in the subdir.
813 self.RunCommand(
814 'cp', ['%sf0' % self.src_dir_root,
815 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
816 self.RunCommand(
817 'cp', ['-R', '%s' % self.src_bucket_uri.uri,
818 '%s' % self.src_dir_root,
819 '%sdst_subdir%s' % (self.dst_bucket_uri.uri, final_char)])
820 actual = set(str(u) for u in test_util.test_wildcard_iterator(
821 '%s**' % self.dst_bucket_uri.uri).IterUris())
822 expected = set(['%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
823 for uri in self.all_src_obj_uris:
824 expected.add('%sdst_subdir/%s/%s' %
825 (self.dst_bucket_uri.uri, uri.bucket_name, uri.object_name))
826 for file_path in self.all_src_file_paths:
827 start_tmp_pos = file_path.find(self.tmpdir_prefix)
828 file_path_sans_base_dir = file_path[start_tmp_pos:]
829 expected.add('%sdst_subdir/%s' %
830 (self.dst_bucket_uri.uri, file_path_sans_base_dir))
831 self.assertEqual(expected, actual)
832 # Clean up/re-set up for next variant iteration.
833 self.TearDownClass()
834 self.SetUpClass()
835
836 def TestRecursiveCopyObjsAndFilesToNonExistentBucketSubDir(self):
837 """Tests recursive copy of objs + files to non-existent bucket subdir"""
838 # Test with and without final slash on dest subdir.
839 for final_char in ('/', ''):
840 self.RunCommand(
841 'cp', ['-R', '%s' % self.src_bucket_uri.uri,
842 '%s' % self.src_dir_root,
843 '%sdst_subdir%s' % (self.dst_bucket_uri.uri, final_char)])
844 actual = set(str(u) for u in test_util.test_wildcard_iterator(
845 '%s**' % self.dst_bucket_uri.uri).IterUris())
846 expected = set()
847 for uri in self.all_src_obj_uris:
848 expected.add('%sdst_subdir/%s' %
849 (self.dst_bucket_uri.uri, uri.object_name))
850 for file_path in self.all_src_file_paths:
851 start_tmp_pos = file_path.find(self.tmpdir_prefix)
852 file_path_sans_base_dir = (
853 file_path[start_tmp_pos:].partition(os.sep)[-1])
854 expected.add('%sdst_subdir/%s' %
855 (self.dst_bucket_uri.uri, file_path_sans_base_dir))
856 self.assertEqual(expected, actual)
857 # Clean up/re-set up for next variant iteration.
858 self.TearDownClass()
859 self.SetUpClass()
860
861 def TestCopyingBucketSubDirToDir(self):
862 """Tests copying a bucket subdir to a directory"""
863 # Test with and without final slash on dest subdir.
864 for (final_src_char, final_dst_char) in (
865 ('', ''), ('', '/'), ('/', ''), ('/', '/') ):
866 self.RunCommand(
867 'cp', ['-R', '%s%s' % (self.src_bucket_subdir_uri, final_src_char),
868 '%s%s' % (self.dst_dir_root, final_dst_char)])
869 actual = set(str(u) for u in test_util.test_wildcard_iterator(
870 '%s/**' % self.dst_dir_root).IterUris())
871 expected = set()
872 for uri in self.all_src_subdir_and_below_obj_uris:
873 expected.add('file://%s%s' % (self.dst_dir_root, uri.uri.partition(
874 self.src_bucket_uri.uri)[-1]))
875 self.assertEqual(expected, actual)
876 # Clean up/re-set up for next variant iteration.
877 self.TearDownClass()
878 self.SetUpClass()
879
880 def TestCopyingWildcardSpecifiedBucketSubDirToExistingDir(self):
881 """Tests copying a wilcard-specified bucket subdir to a directory"""
882 # Test with and without final slash on dest subdir.
883 for (final_src_char, final_dst_char) in (
884 ('', ''), ('', '/'), ('/', ''), ('/', '/') ):
885 self.RunCommand(
886 'cp', ['-R',
887 '%s%s' % (self.src_bucket_subdir_uri_wildcard, final_src_char),
888 '%s%s' % (self.dst_dir_root, final_dst_char)])
889 actual = set(str(u) for u in test_util.test_wildcard_iterator(
890 '%s/**' % self.dst_dir_root).IterUris())
891 expected = set()
892 for uri in self.all_src_subdir_and_below_obj_uris:
893 expected.add('file://%s%s' % (
894 self.dst_dir_root, uri.uri.partition(self.src_bucket_uri.uri)[-1]))
895 self.assertEqual(expected, actual)
896 # Clean up/re-set up for next variant iteration.
897 self.TearDownClass()
898 self.SetUpClass()
899
900 def TestCopyingBucketSubDirToDirFailsWithoutMinusR(self):
901 """Tests for failure when attempting bucket subdir copy without -R"""
902 try:
903 self.RunCommand(
904 'cp', ['%s' % self.src_bucket_subdir_uri,
905 '%s' % self.dst_dir_root])
906 self.fail('Did not get expected CommandException')
907 except CommandException, e:
908 self.assertNotEqual(e.reason.find('does not exist'), -1)
909
910 def TestCopyingBucketSubDirToBucketSubDir(self):
911 """Tests copying a bucket subdir to another bucket subdir"""
912 # Test with and without final slash on dest subdir.
913 for (final_src_char, final_dst_char) in (
914 ('', ''), ('', '/'), ('/', ''), ('/', '/') ):
915 # Set up existing bucket subdir by creating an object in the subdir.
916 self.RunCommand(
917 'cp', ['%sf0' % self.src_dir_root,
918 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
919 self.RunCommand(
920 'cp', ['-R', '%s%s' % (self.src_bucket_subdir_uri, final_src_char),
921 '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
922 actual = set(str(u) for u in test_util.test_wildcard_iterator(
923 '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
924 expected = set(['%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
925 for uri in self.all_src_subdir_and_below_obj_uris:
926 expected.add(
927 '%s/%s' % (self.dst_bucket_subdir_uri.uri, uri.object_name))
928 self.assertEqual(expected, actual)
929 # Clean up/re-set up for next variant iteration.
930 self.TearDownClass()
931 self.SetUpClass()
932
933 def TestMovingBucketSubDirToBucketSubDir(self):
934 """Tests moving a bucket subdir to another bucket subdir"""
935 # Test with and without final slash on dest subdir.
936 for (final_src_char, final_dst_char) in (
937 ('', ''), ('', '/'), ('/', ''), ('/', '/') ):
938 # Set up existing bucket subdir by creating an object in the subdir.
939 self.RunCommand(
940 'cp', ['%sf0' % self.src_dir_root,
941 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
942 self.RunCommand(
943 'mv', ['%s%s' % (self.src_bucket_subdir_uri, final_src_char),
944 '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
945 actual = set(str(u) for u in test_util.test_wildcard_iterator(
946 '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
947 expected = set(['%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
948 for uri in self.all_src_subdir_and_below_obj_uris:
949 # Unlike the case with copying, with mv we expect renaming to occur
950 # at the level of the src subdir, vs appending that subdir beneath the
951 # dst subdir like is done for copying.
952 expected_name = uri.object_name.replace('src_', 'dst_')
953 expected.add('%s%s' % (self.dst_bucket_uri.uri, expected_name))
954 self.assertEqual(expected, actual)
955 # Clean up/re-set up for next variant iteration.
956 self.TearDownClass()
957 self.SetUpClass()
958
959 def TestCopyingObjectToBucketSubDir(self):
960 """Tests copying an object to a bucket subdir"""
961 # Test with and without final slash on dest subdir.
962 for (final_dst_char) in ('', '/'):
963 # Set up existing bucket subdir by creating an object in the subdir.
964 self.RunCommand(
965 'cp', ['%sf0' % self.src_dir_root,
966 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
967 self.RunCommand(
968 'cp', ['%sobj0' % self.src_bucket_uri,
969 '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
970 actual = set(str(u) for u in test_util.test_wildcard_iterator(
971 '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
972 expected = set([
973 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri,
974 '%sdst_subdir/obj0' % self.dst_bucket_uri.uri])
975 self.assertEqual(expected, actual)
976 # Clean up/re-set up for next variant iteration.
977 self.TearDownClass()
978 self.SetUpClass()
979
980 def TestMovingObjectToBucketSubDir(self):
981 """Tests moving an object to a bucket subdir"""
982 # Test with and without final slash on dest subdir.
983 for (final_dst_char) in ('', '/'):
984 # Set up existing bucket subdir by creating an object in the subdir.
985 self.RunCommand(
986 'cp', ['%sf0' % self.src_dir_root,
987 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
988 self.RunCommand(
989 'mv', ['%sobj0' % self.src_bucket_uri,
990 '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
991 actual = set(str(u) for u in test_util.test_wildcard_iterator(
992 '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
993 expected = set([
994 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri,
995 '%sdst_subdir/obj0' % self.dst_bucket_uri.uri])
996 self.assertEqual(expected, actual)
997 # Clean up/re-set up for next variant iteration.
998 self.TearDownClass()
999 self.SetUpClass()
1000
1001 def TestWildcardSrcSubDirMoveDisallowed(self):
1002 """Tests moving a bucket subdir specified by wildcard is disallowed"""
1003 try:
1004 self.RunCommand(
1005 'mv', ['%s*' % self.src_bucket_subdir_uri,
1006 '%s' % self.dst_bucket_subdir_uri.uri])
1007 self.fail('Did not get expected CommandException')
1008 except CommandException, e:
1009 self.assertNotEqual(e.reason.find('mv command disallows'), -1)
1010
1011 def TestMovingBucketNestedSubDirToBucketNestedSubDir(self):
1012 """Tests moving a bucket nested subdir to another bucket nested subdir"""
1013 # Test with and without final slash on dest subdir.
1014 for (final_src_char, final_dst_char) in (
1015 ('', ''), ('', '/'), ('/', ''), ('/', '/') ):
1016 # Set up existing bucket subdir by creating an object in the subdir.
1017 self.RunCommand(
1018 'cp', ['%sf0' % self.src_dir_root,
1019 '%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
1020 self.RunCommand(
1021 'mv', ['%s%s' % (self.src_bucket_subdir_uri, final_src_char),
1022 '%s%s' % (self.dst_bucket_subdir_uri.uri, final_dst_char)])
1023 actual = set(str(u) for u in test_util.test_wildcard_iterator(
1024 '%s**' % self.dst_bucket_subdir_uri.uri).IterUris())
1025 expected = set(['%sdst_subdir/existing_obj' % self.dst_bucket_uri.uri])
1026 for uri in self.all_src_subdir_and_below_obj_uris:
1027 # Unlike the case with copying, with mv we expect renaming to occur
1028 # at the level of the src subdir, vs appending that subdir beneath the
1029 # dst subdir like is done for copying.
1030 expected_name = uri.object_name.replace('src_', 'dst_')
1031 expected.add('%s%s' % (self.dst_bucket_uri, expected_name))
1032 self.assertEqual(expected, actual)
1033 # Clean up/re-set up for next variant iteration.
1034 self.TearDownClass()
1035 self.SetUpClass()
1036
1037 def TestRemovingBucketSubDir(self):
1038 """Tests removing a bucket subdir"""
1039 # Test with and without final slash on dest subdir.
1040 for final_src_char in ('', '/'):
1041 # Setup: Copy a directory, including subdir, to bucket.
1042 self.RunCommand('cp', ['-R', self.src_dir_root, self.dst_bucket_uri.uri])
1043 src_subdir = self.src_dir_root.split(os.path.sep)[-2]
1044 # Test removing bucket subdir.
1045 self.RunCommand(
1046 'rm', ['-R', '%s%s/dir0%s' %
1047 (self.dst_bucket_uri, src_subdir, final_src_char)])
1048 actual = set(str(u) for u in test_util.test_wildcard_iterator(
1049 '%s**' % self.dst_bucket_uri.uri).IterUris())
1050 expected = set()
1051 for fname in self.non_nested_file_names:
1052 expected.add('%s%s/%s' % (self.dst_bucket_uri.uri, src_subdir, fname))
1053 self.assertEqual(expected, actual)
1054 # Clean up/re-set up for next variant iteration.
1055 self.TearDownClass()
1056 self.SetUpClass()
1057
1058 def TestRecursiveRemoveObjsInBucket(self):
1059 """Tests removing all objects in bucket via rm -R gs://bucket"""
1060 # Test with and without final slash on dest subdir.
1061 for final_src_char in ('', '/'):
1062 # Setup: Copy a directory, including subdir, to bucket.
1063 self.RunCommand('cp', ['-R', self.src_dir_root, self.dst_bucket_uri.uri])
1064 # Test removing all objects via rm -R.
1065 self.RunCommand('rm', ['-R', '%s%s' % (self.dst_bucket_uri,
1066 final_src_char)])
1067 actual = set(str(u) for u in test_util.test_wildcard_iterator(
1068 '%s*' % self.dst_bucket_uri.uri).IterUris())
1069 self.assertEqual(0, len(actual))
1070 # Clean up/re-set up for next variant iteration.
1071 self.TearDownClass()
1072 self.SetUpClass()
1073
1074 def FinalObjNameComponent(self, uri):
1075 """For gs://bucket/abc/def/ghi returns ghi."""
1076 return uri.uri.rpartition('/')[-1]
1077
1078 if __name__ == '__main__':
1079 if sys.version_info[:3] < (2, 5, 1):
1080 sys.exit('These tests must be run on at least Python 2.5.1\n')
1081 test_loader = unittest.TestLoader()
1082 test_loader.testMethodPrefix = 'Test'
1083 suite = test_loader.loadTestsFromTestCase(GsutilCommandTests)
1084 # Seems like there should be a cleaner way to find the test_class.
1085 test_class = suite.__getattribute__('_tests')[0]
1086 # We call SetUpClass() and TearDownClass() ourselves because we
1087 # don't assume the user has Python 2.7 (which supports classmethods
1088 # that do it, with camelCase versions of these names).
1089 try:
1090 print 'Setting up %s...' % test_class.GetSuiteDescription()
1091 test_class.SetUpClass()
1092 print 'Running %s...' % test_class.GetSuiteDescription()
1093 unittest.TextTestRunner(verbosity=2).run(suite)
1094 finally:
1095 print 'Cleaning up after %s...' % test_class.GetSuiteDescription()
1096 test_class.TearDownClass()
1097 print ''
OLDNEW
« no previous file with comments | « third_party/gsutil/gslib/storage_uri_builder.py ('k') | third_party/gsutil/gslib/test_data/test.gif » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698