| OLD | NEW |
| (Empty) |
| 1 # -*- coding: utf-8 -*- | |
| 2 # Copyright 2010 Google Inc. All Rights Reserved. | |
| 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 """Tests for parallel uploads ported from gsutil naming tests. | |
| 23 | |
| 24 Currently, the mock storage service is not thread-safe and therefore not | |
| 25 suitable for multiprocess/multithreaded testing. Since parallel composite | |
| 26 uploads necessarily create at least one worker thread outside of main, | |
| 27 these tests are present in this file as temporary (slower) integration tests | |
| 28 to provide validation for parallel composite uploads until a thread-safe | |
| 29 mock storage service rewrite. | |
| 30 | |
| 31 Tests for relative paths are not included as integration_testcase does not | |
| 32 support modifying the current working directory. | |
| 33 """ | |
| 34 | |
| 35 import os | |
| 36 | |
| 37 import gslib.tests.testcase as testcase | |
| 38 from gslib.tests.util import ObjectToURI as suri | |
| 39 from gslib.tests.util import PerformsFileToObjectUpload | |
| 40 from gslib.util import Retry | |
| 41 | |
| 42 | |
| 43 class TestParallelCp(testcase.GsUtilIntegrationTestCase): | |
| 44 """Unit tests for gsutil naming logic.""" | |
| 45 | |
| 46 @PerformsFileToObjectUpload | |
| 47 def testCopyingTopLevelFileToBucket(self): | |
| 48 """Tests copying one top-level file to a bucket.""" | |
| 49 src_file = self.CreateTempFile(file_name='f0') | |
| 50 dst_bucket_uri = self.CreateBucket() | |
| 51 self.RunGsUtil(['cp', src_file, suri(dst_bucket_uri)]) | |
| 52 | |
| 53 lines = self.AssertNObjectsInBucket(dst_bucket_uri, 1) | |
| 54 self.assertEqual(suri(dst_bucket_uri, 'f0'), lines[0]) | |
| 55 | |
| 56 @PerformsFileToObjectUpload | |
| 57 def testCopyingMultipleFilesToBucket(self): | |
| 58 """Tests copying multiple files to a bucket.""" | |
| 59 src_file0 = self.CreateTempFile(file_name='f0') | |
| 60 src_file1 = self.CreateTempFile(file_name='f1') | |
| 61 dst_bucket_uri = self.CreateBucket() | |
| 62 self.RunGsUtil(['cp', src_file0, src_file1, suri(dst_bucket_uri)]) | |
| 63 | |
| 64 lines = self.AssertNObjectsInBucket(dst_bucket_uri, 2) | |
| 65 self.assertEqual(suri(dst_bucket_uri, 'f0'), lines[0]) | |
| 66 self.assertEqual(suri(dst_bucket_uri, 'f1'), lines[1]) | |
| 67 | |
| 68 @PerformsFileToObjectUpload | |
| 69 def testCopyingNestedFileToBucketSubdir(self): | |
| 70 """Tests copying a nested file to a bucket subdir. | |
| 71 | |
| 72 Tests that we correctly translate local FS-specific delimiters ('\' on | |
| 73 Windows) to bucket delimiter (/). | |
| 74 """ | |
| 75 tmpdir = self.CreateTempDir() | |
| 76 subdir = os.path.join(tmpdir, 'subdir') | |
| 77 os.mkdir(subdir) | |
| 78 src_file = self.CreateTempFile(tmpdir=tmpdir, file_name='obj', contents='') | |
| 79 dst_bucket_uri = self.CreateBucket() | |
| 80 # Make an object under subdir so next copy will treat subdir as a subdir. | |
| 81 self.RunGsUtil(['cp', src_file, suri(dst_bucket_uri, 'subdir/a')]) | |
| 82 self.RunGsUtil(['cp', src_file, suri(dst_bucket_uri, 'subdir')]) | |
| 83 | |
| 84 lines = self.AssertNObjectsInBucket(dst_bucket_uri, 2) | |
| 85 self.assertEqual(suri(dst_bucket_uri, 'subdir/a'), lines[0]) | |
| 86 self.assertEqual(suri(dst_bucket_uri, 'subdir/obj'), lines[1]) | |
| 87 | |
| 88 @PerformsFileToObjectUpload | |
| 89 def testCopyingAbsolutePathDirToBucket(self): | |
| 90 """Tests recursively copying absolute path directory to a bucket.""" | |
| 91 dst_bucket_uri = self.CreateBucket() | |
| 92 src_dir_root = self.CreateTempDir(test_files=[ | |
| 93 'f0', 'f1', 'f2.txt', ('dir0', 'dir1', 'nested')]) | |
| 94 self.RunGsUtil(['cp', '-R', src_dir_root, suri(dst_bucket_uri)]) | |
| 95 src_tmpdir = os.path.split(src_dir_root)[1] | |
| 96 | |
| 97 lines = self.AssertNObjectsInBucket(dst_bucket_uri, 4) | |
| 98 self.assertEqual(suri(dst_bucket_uri, src_tmpdir, | |
| 99 'dir0', 'dir1', 'nested'), lines[0]) | |
| 100 self.assertEqual(suri(dst_bucket_uri, src_tmpdir, 'f0'), lines[1]) | |
| 101 self.assertEqual(suri(dst_bucket_uri, src_tmpdir, 'f1'), lines[2]) | |
| 102 self.assertEqual(suri(dst_bucket_uri, src_tmpdir, 'f2.txt'), lines[3]) | |
| 103 | |
| 104 @PerformsFileToObjectUpload | |
| 105 def testCopyingDirContainingOneFileToBucket(self): | |
| 106 """Tests copying a directory containing 1 file to a bucket. | |
| 107 | |
| 108 We test this case to ensure that correct bucket handling isn't dependent | |
| 109 on the copy being treated as a multi-source copy. | |
| 110 """ | |
| 111 dst_bucket_uri = self.CreateBucket() | |
| 112 src_dir = self.CreateTempDir(test_files=[('dir0', 'dir1', 'foo')]) | |
| 113 self.RunGsUtil(['cp', '-R', os.path.join(src_dir, 'dir0', 'dir1'), | |
| 114 suri(dst_bucket_uri)]) | |
| 115 | |
| 116 lines = self.AssertNObjectsInBucket(dst_bucket_uri, 1) | |
| 117 self.assertEqual(suri(dst_bucket_uri, 'dir1', 'foo'), lines[0]) | |
| 118 | |
| 119 @PerformsFileToObjectUpload | |
| 120 def testCopyingFileToObjectWithConsecutiveSlashes(self): | |
| 121 """Tests copying a file to an object containing consecutive slashes.""" | |
| 122 src_file = self.CreateTempFile(file_name='f0') | |
| 123 dst_bucket_uri = self.CreateBucket() | |
| 124 self.RunGsUtil(['cp', src_file, suri(dst_bucket_uri) + '//obj']) | |
| 125 | |
| 126 lines = self.AssertNObjectsInBucket(dst_bucket_uri, 1) | |
| 127 self.assertEqual(suri(dst_bucket_uri) + '//obj', lines[0]) | |
| 128 | |
| 129 @PerformsFileToObjectUpload | |
| 130 def testCopyingObjsAndFilesToBucket(self): | |
| 131 """Tests copying objects and files to a bucket.""" | |
| 132 src_bucket_uri = self.CreateBucket() | |
| 133 self.CreateObject(src_bucket_uri, object_name='f1', contents='foo') | |
| 134 src_dir = self.CreateTempDir(test_files=['f2']) | |
| 135 dst_bucket_uri = self.CreateBucket() | |
| 136 self.RunGsUtil(['cp', '-R', suri(src_bucket_uri, '**'), | |
| 137 '%s%s**' % (src_dir, os.sep), suri(dst_bucket_uri)]) | |
| 138 | |
| 139 lines = self.AssertNObjectsInBucket(dst_bucket_uri, 2) | |
| 140 self.assertEqual(suri(dst_bucket_uri, 'f1'), lines[0]) | |
| 141 self.assertEqual(suri(dst_bucket_uri, 'f2'), lines[1]) | |
| 142 | |
| 143 @PerformsFileToObjectUpload | |
| 144 def testCopyingSubdirRecursiveToNonexistentSubdir(self): | |
| 145 """Tests copying a directory with a single file recursively to a bucket. | |
| 146 | |
| 147 The file should end up in a new bucket subdirectory with the file's | |
| 148 directory structure starting below the recursive copy point, as in Unix cp. | |
| 149 | |
| 150 Example: | |
| 151 filepath: dir1/dir2/foo | |
| 152 cp -r dir1 dir3 | |
| 153 Results in dir3/dir2/foo being created. | |
| 154 """ | |
| 155 src_dir = self.CreateTempDir() | |
| 156 self.CreateTempFile(tmpdir=src_dir + '/dir1/dir2', file_name='foo') | |
| 157 dst_bucket_uri = self.CreateBucket() | |
| 158 self.RunGsUtil(['cp', '-R', src_dir + '/dir1', | |
| 159 suri(dst_bucket_uri, 'dir3')]) | |
| 160 | |
| 161 lines = self.AssertNObjectsInBucket(dst_bucket_uri, 1) | |
| 162 self.assertEqual(suri(dst_bucket_uri, 'dir3/dir2/foo'), lines[0]) | |
| 163 | |
| 164 @PerformsFileToObjectUpload | |
| 165 def testCopyingWildcardedFilesToBucketSubDir(self): | |
| 166 """Tests copying wildcarded files to a bucket subdir.""" | |
| 167 # Test with and without final slash on dest subdir. | |
| 168 for final_dst_char in ('', '/'): | |
| 169 dst_bucket_uri = self.CreateBucket() | |
| 170 self.CreateObject(dst_bucket_uri, object_name='subdir0/existing', | |
| 171 contents='foo') | |
| 172 self.CreateObject(dst_bucket_uri, object_name='subdir1/existing', | |
| 173 contents='foo') | |
| 174 src_dir = self.CreateTempDir(test_files=['f0', 'f1', 'f2']) | |
| 175 | |
| 176 for i in range(2): | |
| 177 self.RunGsUtil( | |
| 178 ['cp', os.path.join(src_dir, 'f?'), | |
| 179 suri(dst_bucket_uri, 'subdir%d' % i) + final_dst_char]) | |
| 180 | |
| 181 @Retry(AssertionError, tries=3, timeout_secs=1) | |
| 182 def _Check1(): | |
| 183 """Validate files were copied to the correct destinations.""" | |
| 184 stdout = self.RunGsUtil(['ls', suri(dst_bucket_uri, 'subdir%d' % i, | |
| 185 '**')], | |
| 186 return_stdout=True) | |
| 187 lines = stdout.split('\n') | |
| 188 self.assertEqual(5, len(lines)) | |
| 189 self.assertEqual(suri(dst_bucket_uri, 'subdir%d' % i, 'existing'), | |
| 190 lines[0]) | |
| 191 self.assertEqual(suri(dst_bucket_uri, 'subdir%d' % i, 'f0'), lines[1]) | |
| 192 self.assertEqual(suri(dst_bucket_uri, 'subdir%d' % i, 'f1'), lines[2]) | |
| 193 self.assertEqual(suri(dst_bucket_uri, 'subdir%d' % i, 'f2'), lines[3]) | |
| 194 _Check1() | |
| 195 | |
| 196 @PerformsFileToObjectUpload | |
| 197 def testCopyingOneNestedFileToBucketSubDir(self): | |
| 198 """Tests copying one nested file to a bucket subdir.""" | |
| 199 # Test with and without final slash on dest subdir. | |
| 200 for final_dst_char in ('', '/'): | |
| 201 | |
| 202 dst_bucket_uri = self.CreateBucket() | |
| 203 self.CreateObject(dst_bucket_uri, object_name='d0/placeholder', | |
| 204 contents='foo') | |
| 205 self.CreateObject(dst_bucket_uri, object_name='d1/placeholder', | |
| 206 contents='foo') | |
| 207 | |
| 208 for i in range(2): | |
| 209 src_dir = self.CreateTempDir(test_files=[('d3', 'd4', 'nested', 'f1')]) | |
| 210 self.RunGsUtil(['cp', '-r', suri(src_dir, 'd3'), | |
| 211 suri(dst_bucket_uri, 'd%d' % i) + final_dst_char]) | |
| 212 | |
| 213 lines = self.AssertNObjectsInBucket(dst_bucket_uri, 4) | |
| 214 self.assertEqual(suri(dst_bucket_uri, 'd0', 'd3', 'd4', 'nested', 'f1'), | |
| 215 lines[0]) | |
| 216 self.assertEqual(suri(dst_bucket_uri, 'd0', 'placeholder'), lines[1]) | |
| 217 self.assertEqual(suri(dst_bucket_uri, 'd1', 'd3', 'd4', 'nested', 'f1'), | |
| 218 lines[2]) | |
| 219 self.assertEqual(suri(dst_bucket_uri, 'd1', 'placeholder'), lines[3]) | |
| 220 | |
| OLD | NEW |