OLD | NEW |
1 # -*- coding: utf-8 -*- | 1 # -*- coding: utf-8 -*- |
2 # Copyright 2014 Google Inc. All Rights Reserved. | 2 # Copyright 2014 Google Inc. All Rights Reserved. |
3 # | 3 # |
4 # Licensed under the Apache License, Version 2.0 (the "License"); | 4 # Licensed under the Apache License, Version 2.0 (the "License"); |
5 # you may not use this file except in compliance with the License. | 5 # you may not use this file except in compliance with the License. |
6 # You may obtain a copy of the License at | 6 # You may obtain a copy of the License at |
7 # | 7 # |
8 # http://www.apache.org/licenses/LICENSE-2.0 | 8 # http://www.apache.org/licenses/LICENSE-2.0 |
9 # | 9 # |
10 # Unless required by applicable law or agreed to in writing, software | 10 # Unless required by applicable law or agreed to in writing, software |
11 # distributed under the License is distributed on an "AS IS" BASIS, | 11 # distributed under the License is distributed on an "AS IS" BASIS, |
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 # See the License for the specific language governing permissions and | 13 # See the License for the specific language governing permissions and |
14 # limitations under the License. | 14 # limitations under the License. |
15 """Integration tests for rsync command.""" | 15 """Integration tests for rsync command.""" |
16 | 16 |
17 import os | 17 import os |
18 | 18 |
19 import crcmod | 19 import crcmod |
20 | 20 |
21 import gslib.tests.testcase as testcase | 21 import gslib.tests.testcase as testcase |
22 from gslib.tests.testcase.integration_testcase import SkipForS3 | 22 from gslib.tests.testcase.integration_testcase import SkipForS3 |
23 from gslib.tests.util import ObjectToURI as suri | 23 from gslib.tests.util import ObjectToURI as suri |
24 from gslib.tests.util import PerformsFileToObjectUpload | 24 from gslib.tests.util import SequentialAndParallelTransfer |
25 from gslib.tests.util import SetBotoConfigForTest | 25 from gslib.tests.util import SetBotoConfigForTest |
26 from gslib.tests.util import unittest | 26 from gslib.tests.util import unittest |
27 from gslib.util import IS_WINDOWS | 27 from gslib.util import IS_WINDOWS |
28 from gslib.util import Retry | 28 from gslib.util import Retry |
29 from gslib.util import UsingCrcmodExtension | 29 from gslib.util import UsingCrcmodExtension |
30 | 30 |
31 NO_CHANGES = 'Building synchronization state...\nStarting synchronization\n' | 31 NO_CHANGES = 'Building synchronization state...\nStarting synchronization\n' |
32 | 32 |
33 | 33 |
34 def _TailSet(start_point, listing): | 34 def _TailSet(start_point, listing): |
35 """Returns set of object name tails. | 35 """Returns set of object name tails. |
36 | 36 |
37 Tails can be compared between source and dest, past the point at which rsync | 37 Tails can be compared between source and dest, past the point at which rsync |
38 was done. For example if test ran rsync gs://bucket1/dir gs://bucket2/dir2, | 38 was done. For example if test ran rsync gs://bucket1/dir gs://bucket2/dir2, |
39 the tails for listings from bucket1 would start after "dir", while the tails | 39 the tails for listings from bucket1 would start after "dir", while the tails |
40 for listings from bucket2 would start after "dir2". | 40 for listings from bucket2 would start after "dir2". |
41 | 41 |
42 Args: | 42 Args: |
43 start_point: The target of the rsync command, e.g., for the above command it | 43 start_point: The target of the rsync command, e.g., for the above command it |
44 would be gs://bucket1/dir for the bucket1 listing results and | 44 would be gs://bucket1/dir for the bucket1 listing results and |
45 gs://bucket2/dir2 for the bucket2 listing results. | 45 gs://bucket2/dir2 for the bucket2 listing results. |
46 listing: The listing over which to compute tail. | 46 listing: The listing over which to compute tail. |
47 | 47 |
48 Returns: | 48 Returns: |
49 Object name tails. | 49 Object name tails. |
50 """ | 50 """ |
51 return set(l[len(start_point):] for l in listing.strip().split('\n')) | 51 return set(l[len(start_point):] for l in listing.strip().split('\n')) |
52 | 52 |
| 53 |
53 # TODO: Add inspection to the retry wrappers in this test suite where the state | 54 # TODO: Add inspection to the retry wrappers in this test suite where the state |
54 # at the end of a retry block is depended upon by subsequent tests (since | 55 # at the end of a retry block is depended upon by subsequent tests (since |
55 # listing content can vary depending on which backend server is reached until | 56 # listing content can vary depending on which backend server is reached until |
56 # eventual consistency is reached). | 57 # eventual consistency is reached). |
57 # TODO: Remove retry wrappers and AssertNObjectsInBucket calls if GCS ever | 58 # TODO: Remove retry wrappers and AssertNObjectsInBucket calls if GCS ever |
58 # supports strong listing consistency. | 59 # supports strong listing consistency. |
59 class TestRsync(testcase.GsUtilIntegrationTestCase): | 60 class TestRsync(testcase.GsUtilIntegrationTestCase): |
60 """Integration tests for rsync command.""" | 61 """Integration tests for rsync command.""" |
61 | 62 |
62 @staticmethod | 63 @staticmethod |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 # Note: The tests below exercise the cases | 106 # Note: The tests below exercise the cases |
106 # {src_dir, src_bucket} X {dst_dir, dst_bucket}. We use gsutil rsync -d for | 107 # {src_dir, src_bucket} X {dst_dir, dst_bucket}. We use gsutil rsync -d for |
107 # all the cases but then have just one test without -d (test_bucket_to_bucket) | 108 # all the cases but then have just one test without -d (test_bucket_to_bucket) |
108 # as representative of handling without the -d option. This provides | 109 # as representative of handling without the -d option. This provides |
109 # reasonable test coverage because the -d handling it src/dest URI-type | 110 # reasonable test coverage because the -d handling it src/dest URI-type |
110 # independent, and keeps the test case combinations more manageable. | 111 # independent, and keeps the test case combinations more manageable. |
111 | 112 |
112 def test_bucket_to_bucket(self): | 113 def test_bucket_to_bucket(self): |
113 """Tests that flat and recursive rsync between 2 buckets works correctly.""" | 114 """Tests that flat and recursive rsync between 2 buckets works correctly.""" |
114 # Create 2 buckets with 1 overlapping object, 1 extra object at root level | 115 # Create 2 buckets with 1 overlapping object, 1 extra object at root level |
115 # in each, and 1 extra object 1 level down in each. Make the overlapping | 116 # in each, and 1 extra object 1 level down in each, where one of the objects |
116 # objects named the same but with different content, to test that we detect | 117 # starts with "." to test that we don't skip those objects. Make the |
117 # and properly copy in that case. | 118 # overlapping objects named the same but with different content, to test |
| 119 # that we detect and properly copy in that case. |
118 bucket1_uri = self.CreateBucket() | 120 bucket1_uri = self.CreateBucket() |
119 bucket2_uri = self.CreateBucket() | 121 bucket2_uri = self.CreateBucket() |
120 self.CreateObject(bucket_uri=bucket1_uri, object_name='obj1', | 122 self.CreateObject(bucket_uri=bucket1_uri, object_name='obj1', |
121 contents='obj1') | 123 contents='obj1') |
122 self.CreateObject(bucket_uri=bucket1_uri, object_name='obj2', | 124 self.CreateObject(bucket_uri=bucket1_uri, object_name='.obj2', |
123 contents='obj2') | 125 contents='.obj2') |
124 self.CreateObject(bucket_uri=bucket1_uri, object_name='subdir/obj3', | 126 self.CreateObject(bucket_uri=bucket1_uri, object_name='subdir/obj3', |
125 contents='subdir/obj3') | 127 contents='subdir/obj3') |
126 self.CreateObject(bucket_uri=bucket2_uri, object_name='obj2', | 128 self.CreateObject(bucket_uri=bucket2_uri, object_name='.obj2', |
127 contents='OBJ2') | 129 contents='.OBJ2') |
128 self.CreateObject(bucket_uri=bucket2_uri, object_name='obj4', | 130 self.CreateObject(bucket_uri=bucket2_uri, object_name='obj4', |
129 contents='obj4') | 131 contents='obj4') |
130 self.CreateObject(bucket_uri=bucket2_uri, object_name='subdir/obj5', | 132 self.CreateObject(bucket_uri=bucket2_uri, object_name='subdir/obj5', |
131 contents='subdir/obj5') | 133 contents='subdir/obj5') |
132 | 134 |
133 # Use @Retry as hedge against bucket listing eventual consistency. | 135 # Use @Retry as hedge against bucket listing eventual consistency. |
134 @Retry(AssertionError, tries=3, timeout_secs=1) | 136 @Retry(AssertionError, tries=3, timeout_secs=1) |
135 def _Check1(): | 137 def _Check1(): |
136 """Tests rsync works as expected.""" | 138 """Tests rsync works as expected.""" |
137 self.RunGsUtil(['rsync', suri(bucket1_uri), suri(bucket2_uri)]) | 139 self.RunGsUtil(['rsync', suri(bucket1_uri), suri(bucket2_uri)]) |
138 listing1 = _TailSet(suri(bucket1_uri), self._FlatListBucket(bucket1_uri)) | 140 listing1 = _TailSet(suri(bucket1_uri), self._FlatListBucket(bucket1_uri)) |
139 listing2 = _TailSet(suri(bucket2_uri), self._FlatListBucket(bucket2_uri)) | 141 listing2 = _TailSet(suri(bucket2_uri), self._FlatListBucket(bucket2_uri)) |
140 # First bucket should have un-altered content. | 142 # First bucket should have un-altered content. |
141 self.assertEquals(listing1, set(['/obj1', '/obj2', '/subdir/obj3'])) | 143 self.assertEquals(listing1, set(['/obj1', '/.obj2', '/subdir/obj3'])) |
142 # Second bucket should have new objects added from source bucket (without | 144 # Second bucket should have new objects added from source bucket (without |
143 # removing extraneeous object found in dest bucket), and without the | 145 # removing extraneeous object found in dest bucket), and without the |
144 # subdir objects synchronized. | 146 # subdir objects synchronized. |
145 self.assertEquals(listing2, | 147 self.assertEquals(listing2, |
146 set(['/obj1', '/obj2', '/obj4', '/subdir/obj5'])) | 148 set(['/obj1', '/.obj2', '/obj4', '/subdir/obj5'])) |
147 # Assert that the src/dest objects that had same length but different | 149 # Assert that the src/dest objects that had same length but different |
148 # content were correctly synchronized (bucket to bucket sync uses | 150 # content were correctly synchronized (bucket to bucket sync uses |
149 # checksums). | 151 # checksums). |
150 self.assertEquals('obj2', self.RunGsUtil( | 152 self.assertEquals('.obj2', self.RunGsUtil( |
151 ['cat', suri(bucket1_uri, 'obj2')], return_stdout=True)) | 153 ['cat', suri(bucket1_uri, '.obj2')], return_stdout=True)) |
152 self.assertEquals('obj2', self.RunGsUtil( | 154 self.assertEquals('.obj2', self.RunGsUtil( |
153 ['cat', suri(bucket2_uri, 'obj2')], return_stdout=True)) | 155 ['cat', suri(bucket2_uri, '.obj2')], return_stdout=True)) |
154 _Check1() | 156 _Check1() |
155 | 157 |
156 # Use @Retry as hedge against bucket listing eventual consistency. | 158 # Use @Retry as hedge against bucket listing eventual consistency. |
157 @Retry(AssertionError, tries=3, timeout_secs=1) | 159 @Retry(AssertionError, tries=3, timeout_secs=1) |
158 def _Check2(): | 160 def _Check2(): |
159 # Check that re-running the same rsync command causes no more changes. | 161 # Check that re-running the same rsync command causes no more changes. |
160 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 162 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
161 ['rsync', suri(bucket1_uri), suri(bucket2_uri)], return_stderr=True)) | 163 ['rsync', suri(bucket1_uri), suri(bucket2_uri)], return_stderr=True)) |
162 _Check2() | 164 _Check2() |
163 | 165 |
164 # Now add and remove some objects in each bucket and test rsync -r. | 166 # Now add and remove some objects in each bucket and test rsync -r. |
165 self.CreateObject(bucket_uri=bucket1_uri, object_name='obj6', | 167 self.CreateObject(bucket_uri=bucket1_uri, object_name='obj6', |
166 contents='obj6') | 168 contents='obj6') |
167 self.CreateObject(bucket_uri=bucket2_uri, object_name='obj7', | 169 self.CreateObject(bucket_uri=bucket2_uri, object_name='obj7', |
168 contents='obj7') | 170 contents='obj7') |
169 self.RunGsUtil(['rm', suri(bucket1_uri, 'obj1')]) | 171 self.RunGsUtil(['rm', suri(bucket1_uri, 'obj1')]) |
170 self.RunGsUtil(['rm', suri(bucket2_uri, 'obj2')]) | 172 self.RunGsUtil(['rm', suri(bucket2_uri, '.obj2')]) |
171 | 173 |
172 # Use @Retry as hedge against bucket listing eventual consistency. | 174 # Use @Retry as hedge against bucket listing eventual consistency. |
173 @Retry(AssertionError, tries=3, timeout_secs=1) | 175 @Retry(AssertionError, tries=3, timeout_secs=1) |
174 def _Check3(): | 176 def _Check3(): |
175 self.RunGsUtil(['rsync', '-r', suri(bucket1_uri), suri(bucket2_uri)]) | 177 self.RunGsUtil(['rsync', '-r', suri(bucket1_uri), suri(bucket2_uri)]) |
176 listing1 = _TailSet(suri(bucket1_uri), self._FlatListBucket(bucket1_uri)) | 178 listing1 = _TailSet(suri(bucket1_uri), self._FlatListBucket(bucket1_uri)) |
177 listing2 = _TailSet(suri(bucket2_uri), self._FlatListBucket(bucket2_uri)) | 179 listing2 = _TailSet(suri(bucket2_uri), self._FlatListBucket(bucket2_uri)) |
178 # First bucket should have un-altered content. | 180 # First bucket should have un-altered content. |
179 self.assertEquals(listing1, set(['/obj2', '/obj6', '/subdir/obj3'])) | 181 self.assertEquals(listing1, set(['/.obj2', '/obj6', '/subdir/obj3'])) |
180 # Second bucket should have objects tha were newly added to first bucket | 182 # Second bucket should have objects tha were newly added to first bucket |
181 # (wihout removing extraneous dest bucket objects), and without the | 183 # (wihout removing extraneous dest bucket objects), and without the |
182 # subdir objects synchronized. | 184 # subdir objects synchronized. |
183 self.assertEquals(listing2, set(['/obj1', '/obj2', '/obj4', '/obj6', | 185 self.assertEquals(listing2, set(['/obj1', '/.obj2', '/obj4', '/obj6', |
184 '/obj7', '/subdir/obj3', | 186 '/obj7', '/subdir/obj3', |
185 '/subdir/obj5'])) | 187 '/subdir/obj5'])) |
186 _Check3() | 188 _Check3() |
187 | 189 |
188 # Use @Retry as hedge against bucket listing eventual consistency. | 190 # Use @Retry as hedge against bucket listing eventual consistency. |
189 @Retry(AssertionError, tries=3, timeout_secs=1) | 191 @Retry(AssertionError, tries=3, timeout_secs=1) |
190 def _Check4(): | 192 def _Check4(): |
191 # Check that re-running the same rsync command causes no more changes. | 193 # Check that re-running the same rsync command causes no more changes. |
192 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 194 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
193 ['rsync', '-r', suri(bucket1_uri), suri(bucket2_uri)], | 195 ['rsync', '-r', suri(bucket1_uri), suri(bucket2_uri)], |
194 return_stderr=True)) | 196 return_stderr=True)) |
195 _Check4() | 197 _Check4() |
196 | 198 |
197 def test_bucket_to_bucket_minus_d(self): | 199 def test_bucket_to_bucket_minus_d(self): |
198 """Tests that flat and recursive rsync between 2 buckets works correctly.""" | 200 """Tests that flat and recursive rsync between 2 buckets works correctly.""" |
199 # Create 2 buckets with 1 overlapping object, 1 extra object at root level | 201 # Create 2 buckets with 1 overlapping object, 1 extra object at root level |
200 # in each, and 1 extra object 1 level down in each. Make the overlapping | 202 # in each, and 1 extra object 1 level down in each, where one of the objects |
201 # objects named the same but with different content, to test that we detect | 203 # starts with "." to test that we don't skip those objects. Make the |
202 # and properly copy in that case. | 204 # overlapping objects named the same but with different content, to test |
| 205 # that we detect and properly copy in that case. |
203 bucket1_uri = self.CreateBucket() | 206 bucket1_uri = self.CreateBucket() |
204 bucket2_uri = self.CreateBucket() | 207 bucket2_uri = self.CreateBucket() |
205 self.CreateObject(bucket_uri=bucket1_uri, object_name='obj1', | 208 self.CreateObject(bucket_uri=bucket1_uri, object_name='obj1', |
206 contents='obj1') | 209 contents='obj1') |
207 self.CreateObject(bucket_uri=bucket1_uri, object_name='obj2', | 210 self.CreateObject(bucket_uri=bucket1_uri, object_name='.obj2', |
208 contents='obj2') | 211 contents='.obj2') |
209 self.CreateObject(bucket_uri=bucket1_uri, object_name='subdir/obj3', | 212 self.CreateObject(bucket_uri=bucket1_uri, object_name='subdir/obj3', |
210 contents='subdir/obj3') | 213 contents='subdir/obj3') |
211 self.CreateObject(bucket_uri=bucket2_uri, object_name='obj2', | 214 self.CreateObject(bucket_uri=bucket2_uri, object_name='.obj2', |
212 contents='OBJ2') | 215 contents='.OBJ2') |
213 self.CreateObject(bucket_uri=bucket2_uri, object_name='obj4', | 216 self.CreateObject(bucket_uri=bucket2_uri, object_name='obj4', |
214 contents='obj4') | 217 contents='obj4') |
215 self.CreateObject(bucket_uri=bucket2_uri, object_name='subdir/obj5', | 218 self.CreateObject(bucket_uri=bucket2_uri, object_name='subdir/obj5', |
216 contents='subdir/obj5') | 219 contents='subdir/obj5') |
217 | 220 |
218 # Use @Retry as hedge against bucket listing eventual consistency. | 221 # Use @Retry as hedge against bucket listing eventual consistency. |
219 @Retry(AssertionError, tries=3, timeout_secs=1) | 222 @Retry(AssertionError, tries=3, timeout_secs=1) |
220 def _Check1(): | 223 def _Check1(): |
221 """Tests rsync works as expected.""" | 224 """Tests rsync works as expected.""" |
222 self.RunGsUtil(['rsync', '-d', suri(bucket1_uri), suri(bucket2_uri)]) | 225 self.RunGsUtil(['rsync', '-d', suri(bucket1_uri), suri(bucket2_uri)]) |
223 listing1 = _TailSet(suri(bucket1_uri), self._FlatListBucket(bucket1_uri)) | 226 listing1 = _TailSet(suri(bucket1_uri), self._FlatListBucket(bucket1_uri)) |
224 listing2 = _TailSet(suri(bucket2_uri), self._FlatListBucket(bucket2_uri)) | 227 listing2 = _TailSet(suri(bucket2_uri), self._FlatListBucket(bucket2_uri)) |
225 # First bucket should have un-altered content. | 228 # First bucket should have un-altered content. |
226 self.assertEquals(listing1, set(['/obj1', '/obj2', '/subdir/obj3'])) | 229 self.assertEquals(listing1, set(['/obj1', '/.obj2', '/subdir/obj3'])) |
227 # Second bucket should have content like first bucket but without the | 230 # Second bucket should have content like first bucket but without the |
228 # subdir objects synchronized. | 231 # subdir objects synchronized. |
229 self.assertEquals(listing2, set(['/obj1', '/obj2', '/subdir/obj5'])) | 232 self.assertEquals(listing2, set(['/obj1', '/.obj2', '/subdir/obj5'])) |
230 # Assert that the src/dest objects that had same length but different | 233 # Assert that the src/dest objects that had same length but different |
231 # content were correctly synchronized (bucket to bucket sync uses | 234 # content were correctly synchronized (bucket to bucket sync uses |
232 # checksums). | 235 # checksums). |
233 self.assertEquals('obj2', self.RunGsUtil( | 236 self.assertEquals('.obj2', self.RunGsUtil( |
234 ['cat', suri(bucket1_uri, 'obj2')], return_stdout=True)) | 237 ['cat', suri(bucket1_uri, '.obj2')], return_stdout=True)) |
235 self.assertEquals('obj2', self.RunGsUtil( | 238 self.assertEquals('.obj2', self.RunGsUtil( |
236 ['cat', suri(bucket2_uri, 'obj2')], return_stdout=True)) | 239 ['cat', suri(bucket2_uri, '.obj2')], return_stdout=True)) |
237 _Check1() | 240 _Check1() |
238 | 241 |
239 # Use @Retry as hedge against bucket listing eventual consistency. | 242 # Use @Retry as hedge against bucket listing eventual consistency. |
240 @Retry(AssertionError, tries=3, timeout_secs=1) | 243 @Retry(AssertionError, tries=3, timeout_secs=1) |
241 def _Check2(): | 244 def _Check2(): |
242 # Check that re-running the same rsync command causes no more changes. | 245 # Check that re-running the same rsync command causes no more changes. |
243 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 246 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
244 ['rsync', '-d', suri(bucket1_uri), suri(bucket2_uri)], | 247 ['rsync', '-d', suri(bucket1_uri), suri(bucket2_uri)], |
245 return_stderr=True)) | 248 return_stderr=True)) |
246 _Check2() | 249 _Check2() |
247 | 250 |
248 # Now add and remove some objects in each bucket and test rsync -r. | 251 # Now add and remove some objects in each bucket and test rsync -r. |
249 self.CreateObject(bucket_uri=bucket1_uri, object_name='obj6', | 252 self.CreateObject(bucket_uri=bucket1_uri, object_name='obj6', |
250 contents='obj6') | 253 contents='obj6') |
251 self.CreateObject(bucket_uri=bucket2_uri, object_name='obj7', | 254 self.CreateObject(bucket_uri=bucket2_uri, object_name='obj7', |
252 contents='obj7') | 255 contents='obj7') |
253 self.RunGsUtil(['rm', suri(bucket1_uri, 'obj1')]) | 256 self.RunGsUtil(['rm', suri(bucket1_uri, 'obj1')]) |
254 self.RunGsUtil(['rm', suri(bucket2_uri, 'obj2')]) | 257 self.RunGsUtil(['rm', suri(bucket2_uri, '.obj2')]) |
255 | 258 |
256 # Use @Retry as hedge against bucket listing eventual consistency. | 259 # Use @Retry as hedge against bucket listing eventual consistency. |
257 @Retry(AssertionError, tries=3, timeout_secs=1) | 260 @Retry(AssertionError, tries=3, timeout_secs=1) |
258 def _Check3(): | 261 def _Check3(): |
259 self.RunGsUtil(['rsync', '-d', '-r', | 262 self.RunGsUtil(['rsync', '-d', '-r', |
260 suri(bucket1_uri), suri(bucket2_uri)]) | 263 suri(bucket1_uri), suri(bucket2_uri)]) |
261 listing1 = _TailSet(suri(bucket1_uri), self._FlatListBucket(bucket1_uri)) | 264 listing1 = _TailSet(suri(bucket1_uri), self._FlatListBucket(bucket1_uri)) |
262 listing2 = _TailSet(suri(bucket2_uri), self._FlatListBucket(bucket2_uri)) | 265 listing2 = _TailSet(suri(bucket2_uri), self._FlatListBucket(bucket2_uri)) |
263 # First bucket should have un-altered content. | 266 # First bucket should have un-altered content. |
264 self.assertEquals(listing1, set(['/obj2', '/obj6', '/subdir/obj3'])) | 267 self.assertEquals(listing1, set(['/.obj2', '/obj6', '/subdir/obj3'])) |
265 # Second bucket should have content like first bucket but without the | 268 # Second bucket should have content like first bucket but without the |
266 # subdir objects synchronized. | 269 # subdir objects synchronized. |
267 self.assertEquals(listing2, set(['/obj2', '/obj6', '/subdir/obj3'])) | 270 self.assertEquals(listing2, set(['/.obj2', '/obj6', '/subdir/obj3'])) |
268 _Check3() | 271 _Check3() |
269 | 272 |
270 # Use @Retry as hedge against bucket listing eventual consistency. | 273 # Use @Retry as hedge against bucket listing eventual consistency. |
271 @Retry(AssertionError, tries=3, timeout_secs=1) | 274 @Retry(AssertionError, tries=3, timeout_secs=1) |
272 def _Check4(): | 275 def _Check4(): |
273 # Check that re-running the same rsync command causes no more changes. | 276 # Check that re-running the same rsync command causes no more changes. |
274 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 277 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
275 ['rsync', '-d', '-r', suri(bucket1_uri), suri(bucket2_uri)], | 278 ['rsync', '-d', '-r', suri(bucket1_uri), suri(bucket2_uri)], |
276 return_stderr=True)) | 279 return_stderr=True)) |
277 _Check4() | 280 _Check4() |
278 | 281 |
279 # Test sequential upload as well as parallel composite upload case. | 282 # Test sequential upload as well as parallel composite upload case. |
280 @PerformsFileToObjectUpload | 283 @SequentialAndParallelTransfer |
281 @unittest.skipUnless(UsingCrcmodExtension(crcmod), | 284 @unittest.skipUnless(UsingCrcmodExtension(crcmod), |
282 'Test requires fast crcmod.') | 285 'Test requires fast crcmod.') |
283 def test_dir_to_bucket_minus_d(self): | 286 def test_dir_to_bucket_minus_d(self): |
284 """Tests that flat and recursive rsync dir to bucket works correctly.""" | 287 """Tests that flat and recursive rsync dir to bucket works correctly.""" |
285 # Create dir and bucket with 1 overlapping object, 1 extra object at root | 288 # Create dir and bucket with 1 overlapping object, 1 extra object at root |
286 # level in each, and 1 extra object 1 level down in each. Make the | 289 # level in each, and 1 extra object 1 level down in each, where one of the |
| 290 # objects starts with "." to test that we don't skip those objects. Make the |
287 # overlapping objects named the same but with different content, to test | 291 # overlapping objects named the same but with different content, to test |
288 # that we detect and properly copy in that case. | 292 # that we detect and properly copy in that case. |
289 tmpdir = self.CreateTempDir() | 293 tmpdir = self.CreateTempDir() |
290 subdir = os.path.join(tmpdir, 'subdir') | 294 subdir = os.path.join(tmpdir, 'subdir') |
291 os.mkdir(subdir) | 295 os.mkdir(subdir) |
292 bucket_uri = self.CreateBucket() | 296 bucket_uri = self.CreateBucket() |
293 self.CreateTempFile(tmpdir=tmpdir, file_name='obj1', contents='obj1') | 297 self.CreateTempFile(tmpdir=tmpdir, file_name='obj1', contents='obj1') |
294 self.CreateTempFile(tmpdir=tmpdir, file_name='obj2', contents='obj2') | 298 self.CreateTempFile(tmpdir=tmpdir, file_name='.obj2', contents='.obj2') |
295 self.CreateTempFile(tmpdir=subdir, file_name='obj3', contents='subdir/obj3') | 299 self.CreateTempFile(tmpdir=subdir, file_name='obj3', contents='subdir/obj3') |
296 self.CreateObject(bucket_uri=bucket_uri, object_name='obj2', | 300 self.CreateObject(bucket_uri=bucket_uri, object_name='.obj2', |
297 contents='OBJ2') | 301 contents='.OBJ2') |
298 self.CreateObject(bucket_uri=bucket_uri, object_name='obj4', | 302 self.CreateObject(bucket_uri=bucket_uri, object_name='obj4', |
299 contents='obj4') | 303 contents='obj4') |
300 self.CreateObject(bucket_uri=bucket_uri, object_name='subdir/obj5', | 304 self.CreateObject(bucket_uri=bucket_uri, object_name='subdir/obj5', |
301 contents='subdir/obj5') | 305 contents='subdir/obj5') |
302 | 306 |
303 # Need to make sure the bucket listing is caught-up, otherwise the | 307 # Need to make sure the bucket listing is caught-up, otherwise the |
304 # first rsync may not see obj2 and overwrite it. | 308 # first rsync may not see .obj2 and overwrite it. |
305 self.AssertNObjectsInBucket(bucket_uri, 3) | 309 self.AssertNObjectsInBucket(bucket_uri, 3) |
306 | 310 |
307 # Use @Retry as hedge against bucket listing eventual consistency. | 311 # Use @Retry as hedge against bucket listing eventual consistency. |
308 @Retry(AssertionError, tries=3, timeout_secs=1) | 312 @Retry(AssertionError, tries=3, timeout_secs=1) |
309 def _Check1(): | 313 def _Check1(): |
310 """Tests rsync works as expected.""" | 314 """Tests rsync works as expected.""" |
311 self.RunGsUtil(['rsync', '-d', tmpdir, suri(bucket_uri)]) | 315 self.RunGsUtil(['rsync', '-d', tmpdir, suri(bucket_uri)]) |
312 listing1 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) | 316 listing1 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) |
313 listing2 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) | 317 listing2 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) |
314 # Dir should have un-altered content. | 318 # Dir should have un-altered content. |
315 self.assertEquals(listing1, set(['/obj1', '/obj2', '/subdir/obj3'])) | 319 self.assertEquals(listing1, set(['/obj1', '/.obj2', '/subdir/obj3'])) |
316 # Bucket should have content like dir but without the subdir objects | 320 # Bucket should have content like dir but without the subdir objects |
317 # synchronized. | 321 # synchronized. |
318 self.assertEquals(listing2, set(['/obj1', '/obj2', '/subdir/obj5'])) | 322 self.assertEquals(listing2, set(['/obj1', '/.obj2', '/subdir/obj5'])) |
319 # Assert that the src/dest objects that had same length but different | 323 # Assert that the src/dest objects that had same length but different |
320 # content were not synchronized (dir to bucket sync doesn't use checksums | 324 # content were not synchronized (dir to bucket sync doesn't use checksums |
321 # unless you specify -c). | 325 # unless you specify -c). |
322 with open(os.path.join(tmpdir, 'obj2')) as f: | 326 with open(os.path.join(tmpdir, '.obj2')) as f: |
323 self.assertEquals('obj2', '\n'.join(f.readlines())) | 327 self.assertEquals('.obj2', '\n'.join(f.readlines())) |
324 self.assertEquals('OBJ2', self.RunGsUtil( | 328 self.assertEquals('.OBJ2', self.RunGsUtil( |
325 ['cat', suri(bucket_uri, 'obj2')], return_stdout=True)) | 329 ['cat', suri(bucket_uri, '.obj2')], return_stdout=True)) |
326 _Check1() | 330 _Check1() |
327 | 331 |
328 # Use @Retry as hedge against bucket listing eventual consistency. | 332 # Use @Retry as hedge against bucket listing eventual consistency. |
329 @Retry(AssertionError, tries=3, timeout_secs=1) | 333 @Retry(AssertionError, tries=3, timeout_secs=1) |
330 def _Check2(): | 334 def _Check2(): |
331 # Check that re-running the same rsync command causes no more changes. | 335 # Check that re-running the same rsync command causes no more changes. |
332 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 336 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
333 ['rsync', '-d', tmpdir, suri(bucket_uri)], return_stderr=True)) | 337 ['rsync', '-d', tmpdir, suri(bucket_uri)], return_stderr=True)) |
334 _Check2() | 338 _Check2() |
335 | 339 |
336 # Now rerun the sync with the -c option. | 340 # Now rerun the sync with the -c option. |
337 # Use @Retry as hedge against bucket listing eventual consistency. | 341 # Use @Retry as hedge against bucket listing eventual consistency. |
338 @Retry(AssertionError, tries=3, timeout_secs=1) | 342 @Retry(AssertionError, tries=3, timeout_secs=1) |
339 def _Check3(): | 343 def _Check3(): |
340 """Tests rsync -c works as expected.""" | 344 """Tests rsync -c works as expected.""" |
341 self.RunGsUtil(['rsync', '-d', '-c', tmpdir, suri(bucket_uri)]) | 345 self.RunGsUtil(['rsync', '-d', '-c', tmpdir, suri(bucket_uri)]) |
342 listing1 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) | 346 listing1 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) |
343 listing2 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) | 347 listing2 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) |
344 # Dir should have un-altered content. | 348 # Dir should have un-altered content. |
345 self.assertEquals(listing1, set(['/obj1', '/obj2', '/subdir/obj3'])) | 349 self.assertEquals(listing1, set(['/obj1', '/.obj2', '/subdir/obj3'])) |
346 # Bucket should have content like dir but without the subdir objects | 350 # Bucket should have content like dir but without the subdir objects |
347 # synchronized. | 351 # synchronized. |
348 self.assertEquals(listing2, set(['/obj1', '/obj2', '/subdir/obj5'])) | 352 self.assertEquals(listing2, set(['/obj1', '/.obj2', '/subdir/obj5'])) |
349 # Assert that the src/dest objects that had same length but different | 353 # Assert that the src/dest objects that had same length but different |
350 # content were synchronized (dir to bucket sync with -c uses checksums). | 354 # content were synchronized (dir to bucket sync with -c uses checksums). |
351 with open(os.path.join(tmpdir, 'obj2')) as f: | 355 with open(os.path.join(tmpdir, '.obj2')) as f: |
352 self.assertEquals('obj2', '\n'.join(f.readlines())) | 356 self.assertEquals('.obj2', '\n'.join(f.readlines())) |
353 self.assertEquals('obj2', self.RunGsUtil( | 357 self.assertEquals('.obj2', self.RunGsUtil( |
354 ['cat', suri(bucket_uri, 'obj2')], return_stdout=True)) | 358 ['cat', suri(bucket_uri, '.obj2')], return_stdout=True)) |
355 _Check3() | 359 _Check3() |
356 | 360 |
357 # Use @Retry as hedge against bucket listing eventual consistency. | 361 # Use @Retry as hedge against bucket listing eventual consistency. |
358 @Retry(AssertionError, tries=3, timeout_secs=1) | 362 @Retry(AssertionError, tries=3, timeout_secs=1) |
359 def _Check4(): | 363 def _Check4(): |
360 # Check that re-running the same rsync command causes no more changes. | 364 # Check that re-running the same rsync command causes no more changes. |
361 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 365 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
362 ['rsync', '-d', '-c', tmpdir, suri(bucket_uri)], return_stderr=True)) | 366 ['rsync', '-d', '-c', tmpdir, suri(bucket_uri)], return_stderr=True)) |
363 _Check4() | 367 _Check4() |
364 | 368 |
365 # Now add and remove some objects in dir and bucket and test rsync -r. | 369 # Now add and remove some objects in dir and bucket and test rsync -r. |
366 self.CreateTempFile(tmpdir=tmpdir, file_name='obj6', contents='obj6') | 370 self.CreateTempFile(tmpdir=tmpdir, file_name='obj6', contents='obj6') |
367 self.CreateObject(bucket_uri=bucket_uri, object_name='obj7', | 371 self.CreateObject(bucket_uri=bucket_uri, object_name='obj7', |
368 contents='obj7') | 372 contents='obj7') |
369 os.unlink(os.path.join(tmpdir, 'obj1')) | 373 os.unlink(os.path.join(tmpdir, 'obj1')) |
370 self.RunGsUtil(['rm', suri(bucket_uri, 'obj2')]) | 374 self.RunGsUtil(['rm', suri(bucket_uri, '.obj2')]) |
371 | 375 |
372 # Use @Retry as hedge against bucket listing eventual consistency. | 376 # Use @Retry as hedge against bucket listing eventual consistency. |
373 @Retry(AssertionError, tries=3, timeout_secs=1) | 377 @Retry(AssertionError, tries=3, timeout_secs=1) |
374 def _Check5(): | 378 def _Check5(): |
375 self.RunGsUtil(['rsync', '-d', '-r', tmpdir, suri(bucket_uri)]) | 379 self.RunGsUtil(['rsync', '-d', '-r', tmpdir, suri(bucket_uri)]) |
376 listing1 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) | 380 listing1 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) |
377 listing2 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) | 381 listing2 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) |
378 # Dir should have un-altered content. | 382 # Dir should have un-altered content. |
379 self.assertEquals(listing1, set(['/obj2', '/obj6', '/subdir/obj3'])) | 383 self.assertEquals(listing1, set(['/.obj2', '/obj6', '/subdir/obj3'])) |
380 # Bucket should have content like dir but without the subdir objects | 384 # Bucket should have content like dir but without the subdir objects |
381 # synchronized. | 385 # synchronized. |
382 self.assertEquals(listing2, set(['/obj2', '/obj6', '/subdir/obj3'])) | 386 self.assertEquals(listing2, set(['/.obj2', '/obj6', '/subdir/obj3'])) |
383 _Check5() | 387 _Check5() |
384 | 388 |
385 # Use @Retry as hedge against bucket listing eventual consistency. | 389 # Use @Retry as hedge against bucket listing eventual consistency. |
386 @Retry(AssertionError, tries=3, timeout_secs=1) | 390 @Retry(AssertionError, tries=3, timeout_secs=1) |
387 def _Check6(): | 391 def _Check6(): |
388 # Check that re-running the same rsync command causes no more changes. | 392 # Check that re-running the same rsync command causes no more changes. |
389 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 393 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
390 ['rsync', '-d', '-r', tmpdir, suri(bucket_uri)], return_stderr=True)) | 394 ['rsync', '-d', '-r', tmpdir, suri(bucket_uri)], return_stderr=True)) |
391 _Check6() | 395 _Check6() |
392 | 396 |
393 @unittest.skipUnless(UsingCrcmodExtension(crcmod), | 397 @unittest.skipUnless(UsingCrcmodExtension(crcmod), |
394 'Test requires fast crcmod.') | 398 'Test requires fast crcmod.') |
395 def test_dir_to_dir_minus_d(self): | 399 def test_dir_to_dir_minus_d(self): |
396 """Tests that flat and recursive rsync dir to dir works correctly.""" | 400 """Tests that flat and recursive rsync dir to dir works correctly.""" |
397 # Create 2 dirs with 1 overlapping file, 1 extra file at root | 401 # Create 2 dirs with 1 overlapping file, 1 extra file at root |
398 # level in each, and 1 extra file 1 level down in each. Make the | 402 # level in each, and 1 extra file 1 level down in each, where one of the |
| 403 # objects starts with "." to test that we don't skip those objects. Make the |
399 # overlapping files named the same but with different content, to test | 404 # overlapping files named the same but with different content, to test |
400 # that we detect and properly copy in that case. | 405 # that we detect and properly copy in that case. |
401 tmpdir1 = self.CreateTempDir() | 406 tmpdir1 = self.CreateTempDir() |
402 tmpdir2 = self.CreateTempDir() | 407 tmpdir2 = self.CreateTempDir() |
403 subdir1 = os.path.join(tmpdir1, 'subdir1') | 408 subdir1 = os.path.join(tmpdir1, 'subdir1') |
404 subdir2 = os.path.join(tmpdir2, 'subdir2') | 409 subdir2 = os.path.join(tmpdir2, 'subdir2') |
405 os.mkdir(subdir1) | 410 os.mkdir(subdir1) |
406 os.mkdir(subdir2) | 411 os.mkdir(subdir2) |
407 self.CreateTempFile(tmpdir=tmpdir1, file_name='obj1', contents='obj1') | 412 self.CreateTempFile(tmpdir=tmpdir1, file_name='obj1', contents='obj1') |
408 self.CreateTempFile(tmpdir=tmpdir1, file_name='obj2', contents='obj2') | 413 self.CreateTempFile(tmpdir=tmpdir1, file_name='.obj2', contents='.obj2') |
409 self.CreateTempFile( | 414 self.CreateTempFile( |
410 tmpdir=subdir1, file_name='obj3', contents='subdir1/obj3') | 415 tmpdir=subdir1, file_name='obj3', contents='subdir1/obj3') |
411 self.CreateTempFile(tmpdir=tmpdir2, file_name='obj2', contents='OBJ2') | 416 self.CreateTempFile(tmpdir=tmpdir2, file_name='.obj2', contents='.OBJ2') |
412 self.CreateTempFile(tmpdir=tmpdir2, file_name='obj4', contents='obj4') | 417 self.CreateTempFile(tmpdir=tmpdir2, file_name='obj4', contents='obj4') |
413 self.CreateTempFile( | 418 self.CreateTempFile( |
414 tmpdir=subdir2, file_name='obj5', contents='subdir2/obj5') | 419 tmpdir=subdir2, file_name='obj5', contents='subdir2/obj5') |
415 | 420 |
416 self.RunGsUtil(['rsync', '-d', tmpdir1, tmpdir2]) | 421 self.RunGsUtil(['rsync', '-d', tmpdir1, tmpdir2]) |
417 listing1 = _TailSet(tmpdir1, self._FlatListDir(tmpdir1)) | 422 listing1 = _TailSet(tmpdir1, self._FlatListDir(tmpdir1)) |
418 listing2 = _TailSet(tmpdir2, self._FlatListDir(tmpdir2)) | 423 listing2 = _TailSet(tmpdir2, self._FlatListDir(tmpdir2)) |
419 # dir1 should have un-altered content. | 424 # dir1 should have un-altered content. |
420 self.assertEquals(listing1, set(['/obj1', '/obj2', '/subdir1/obj3'])) | 425 self.assertEquals(listing1, set(['/obj1', '/.obj2', '/subdir1/obj3'])) |
421 # dir2 should have content like dir1 but without the subdir1 objects | 426 # dir2 should have content like dir1 but without the subdir1 objects |
422 # synchronized. | 427 # synchronized. |
423 self.assertEquals(listing2, set(['/obj1', '/obj2', '/subdir2/obj5'])) | 428 self.assertEquals(listing2, set(['/obj1', '/.obj2', '/subdir2/obj5'])) |
424 # Assert that the src/dest objects that had same length but different | 429 # Assert that the src/dest objects that had same length but different |
425 # checksums were not synchronized (dir to dir sync doesn't use checksums | 430 # checksums were not synchronized (dir to dir sync doesn't use checksums |
426 # unless you specify -c). | 431 # unless you specify -c). |
427 with open(os.path.join(tmpdir1, 'obj2')) as f: | 432 with open(os.path.join(tmpdir1, '.obj2')) as f: |
428 self.assertEquals('obj2', '\n'.join(f.readlines())) | 433 self.assertEquals('.obj2', '\n'.join(f.readlines())) |
429 with open(os.path.join(tmpdir2, 'obj2')) as f: | 434 with open(os.path.join(tmpdir2, '.obj2')) as f: |
430 self.assertEquals('OBJ2', '\n'.join(f.readlines())) | 435 self.assertEquals('.OBJ2', '\n'.join(f.readlines())) |
431 | 436 |
432 # Use @Retry as hedge against bucket listing eventual consistency. | 437 # Use @Retry as hedge against bucket listing eventual consistency. |
433 @Retry(AssertionError, tries=3, timeout_secs=1) | 438 @Retry(AssertionError, tries=3, timeout_secs=1) |
434 def _Check1(): | 439 def _Check1(): |
435 # Check that re-running the same rsync command causes no more changes. | 440 # Check that re-running the same rsync command causes no more changes. |
436 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 441 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
437 ['rsync', '-d', tmpdir1, tmpdir2], return_stderr=True)) | 442 ['rsync', '-d', tmpdir1, tmpdir2], return_stderr=True)) |
438 _Check1() | 443 _Check1() |
439 | 444 |
440 # Now rerun the sync with the -c option. | 445 # Now rerun the sync with the -c option. |
441 self.RunGsUtil(['rsync', '-d', '-c', tmpdir1, tmpdir2]) | 446 self.RunGsUtil(['rsync', '-d', '-c', tmpdir1, tmpdir2]) |
442 listing1 = _TailSet(tmpdir1, self._FlatListDir(tmpdir1)) | 447 listing1 = _TailSet(tmpdir1, self._FlatListDir(tmpdir1)) |
443 listing2 = _TailSet(tmpdir2, self._FlatListDir(tmpdir2)) | 448 listing2 = _TailSet(tmpdir2, self._FlatListDir(tmpdir2)) |
444 # dir1 should have un-altered content. | 449 # dir1 should have un-altered content. |
445 self.assertEquals(listing1, set(['/obj1', '/obj2', '/subdir1/obj3'])) | 450 self.assertEquals(listing1, set(['/obj1', '/.obj2', '/subdir1/obj3'])) |
446 # dir2 should have content like dir but without the subdir objects | 451 # dir2 should have content like dir but without the subdir objects |
447 # synchronized. | 452 # synchronized. |
448 self.assertEquals(listing2, set(['/obj1', '/obj2', '/subdir2/obj5'])) | 453 self.assertEquals(listing2, set(['/obj1', '/.obj2', '/subdir2/obj5'])) |
449 # Assert that the src/dest objects that had same length but different | 454 # Assert that the src/dest objects that had same length but different |
450 # content were synchronized (dir to dir sync with -c uses checksums). | 455 # content were synchronized (dir to dir sync with -c uses checksums). |
451 with open(os.path.join(tmpdir1, 'obj2')) as f: | 456 with open(os.path.join(tmpdir1, '.obj2')) as f: |
452 self.assertEquals('obj2', '\n'.join(f.readlines())) | 457 self.assertEquals('.obj2', '\n'.join(f.readlines())) |
453 with open(os.path.join(tmpdir1, 'obj2')) as f: | 458 with open(os.path.join(tmpdir1, '.obj2')) as f: |
454 self.assertEquals('obj2', '\n'.join(f.readlines())) | 459 self.assertEquals('.obj2', '\n'.join(f.readlines())) |
455 | 460 |
456 # Use @Retry as hedge against bucket listing eventual consistency. | 461 # Use @Retry as hedge against bucket listing eventual consistency. |
457 @Retry(AssertionError, tries=3, timeout_secs=1) | 462 @Retry(AssertionError, tries=3, timeout_secs=1) |
458 def _Check2(): | 463 def _Check2(): |
459 # Check that re-running the same rsync command causes no more changes. | 464 # Check that re-running the same rsync command causes no more changes. |
460 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 465 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
461 ['rsync', '-d', '-c', tmpdir1, tmpdir2], return_stderr=True)) | 466 ['rsync', '-d', '-c', tmpdir1, tmpdir2], return_stderr=True)) |
462 _Check2() | 467 _Check2() |
463 | 468 |
464 # Now add and remove some objects in both dirs and test rsync -r. | 469 # Now add and remove some objects in both dirs and test rsync -r. |
465 self.CreateTempFile(tmpdir=tmpdir1, file_name='obj6', contents='obj6') | 470 self.CreateTempFile(tmpdir=tmpdir1, file_name='obj6', contents='obj6') |
466 self.CreateTempFile(tmpdir=tmpdir2, file_name='obj7', contents='obj7') | 471 self.CreateTempFile(tmpdir=tmpdir2, file_name='obj7', contents='obj7') |
467 os.unlink(os.path.join(tmpdir1, 'obj1')) | 472 os.unlink(os.path.join(tmpdir1, 'obj1')) |
468 os.unlink(os.path.join(tmpdir2, 'obj2')) | 473 os.unlink(os.path.join(tmpdir2, '.obj2')) |
469 | 474 |
470 self.RunGsUtil(['rsync', '-d', '-r', tmpdir1, tmpdir2]) | 475 self.RunGsUtil(['rsync', '-d', '-r', tmpdir1, tmpdir2]) |
471 listing1 = _TailSet(tmpdir1, self._FlatListDir(tmpdir1)) | 476 listing1 = _TailSet(tmpdir1, self._FlatListDir(tmpdir1)) |
472 listing2 = _TailSet(tmpdir2, self._FlatListDir(tmpdir2)) | 477 listing2 = _TailSet(tmpdir2, self._FlatListDir(tmpdir2)) |
473 # dir1 should have un-altered content. | 478 # dir1 should have un-altered content. |
474 self.assertEquals(listing1, set(['/obj2', '/obj6', '/subdir1/obj3'])) | 479 self.assertEquals(listing1, set(['/.obj2', '/obj6', '/subdir1/obj3'])) |
475 # dir2 should have content like dir but without the subdir objects | 480 # dir2 should have content like dir but without the subdir objects |
476 # synchronized. | 481 # synchronized. |
477 self.assertEquals(listing2, set(['/obj2', '/obj6', '/subdir1/obj3'])) | 482 self.assertEquals(listing2, set(['/.obj2', '/obj6', '/subdir1/obj3'])) |
478 | 483 |
479 # Use @Retry as hedge against bucket listing eventual consistency. | 484 # Use @Retry as hedge against bucket listing eventual consistency. |
480 @Retry(AssertionError, tries=3, timeout_secs=1) | 485 @Retry(AssertionError, tries=3, timeout_secs=1) |
481 def _Check3(): | 486 def _Check3(): |
482 # Check that re-running the same rsync command causes no more changes. | 487 # Check that re-running the same rsync command causes no more changes. |
483 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 488 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
484 ['rsync', '-d', '-r', tmpdir1, tmpdir2], return_stderr=True)) | 489 ['rsync', '-d', '-r', tmpdir1, tmpdir2], return_stderr=True)) |
485 _Check3() | 490 _Check3() |
486 | 491 |
487 def test_dir_to_dir_minus_d_more_files_than_bufsize(self): | 492 def test_dir_to_dir_minus_d_more_files_than_bufsize(self): |
(...skipping 23 matching lines...) Expand all Loading... |
511 # Check that re-running the same rsync command causes no more changes. | 516 # Check that re-running the same rsync command causes no more changes. |
512 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 517 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
513 ['rsync', '-d', tmpdir1, tmpdir2], return_stderr=True)) | 518 ['rsync', '-d', tmpdir1, tmpdir2], return_stderr=True)) |
514 _Check() | 519 _Check() |
515 | 520 |
516 @unittest.skipUnless(UsingCrcmodExtension(crcmod), | 521 @unittest.skipUnless(UsingCrcmodExtension(crcmod), |
517 'Test requires fast crcmod.') | 522 'Test requires fast crcmod.') |
518 def test_bucket_to_dir_minus_d(self): | 523 def test_bucket_to_dir_minus_d(self): |
519 """Tests that flat and recursive rsync bucket to dir works correctly.""" | 524 """Tests that flat and recursive rsync bucket to dir works correctly.""" |
520 # Create bucket and dir with 1 overlapping object, 1 extra object at root | 525 # Create bucket and dir with 1 overlapping object, 1 extra object at root |
521 # level in each, and 1 extra object 1 level down in each. Make the | 526 # level in each, and 1 extra object 1 level down in each, where one of the |
| 527 # objects starts with "." to test that we don't skip those objects. Make the |
522 # overlapping objects named the same but with different content, to test | 528 # overlapping objects named the same but with different content, to test |
523 # that we detect and properly copy in that case. | 529 # that we detect and properly copy in that case. |
524 bucket_uri = self.CreateBucket() | 530 bucket_uri = self.CreateBucket() |
525 tmpdir = self.CreateTempDir() | 531 tmpdir = self.CreateTempDir() |
526 subdir = os.path.join(tmpdir, 'subdir') | 532 subdir = os.path.join(tmpdir, 'subdir') |
527 os.mkdir(subdir) | 533 os.mkdir(subdir) |
528 self.CreateObject(bucket_uri=bucket_uri, object_name='obj1', | 534 self.CreateObject(bucket_uri=bucket_uri, object_name='obj1', |
529 contents='obj1') | 535 contents='obj1') |
530 self.CreateObject(bucket_uri=bucket_uri, object_name='obj2', | 536 self.CreateObject(bucket_uri=bucket_uri, object_name='.obj2', |
531 contents='obj2') | 537 contents='.obj2') |
532 self.CreateObject(bucket_uri=bucket_uri, object_name='subdir/obj3', | 538 self.CreateObject(bucket_uri=bucket_uri, object_name='subdir/obj3', |
533 contents='subdir/obj3') | 539 contents='subdir/obj3') |
534 self.CreateTempFile(tmpdir=tmpdir, file_name='obj2', contents='OBJ2') | 540 self.CreateTempFile(tmpdir=tmpdir, file_name='.obj2', contents='.OBJ2') |
535 self.CreateTempFile(tmpdir=tmpdir, file_name='obj4', contents='obj4') | 541 self.CreateTempFile(tmpdir=tmpdir, file_name='obj4', contents='obj4') |
536 self.CreateTempFile(tmpdir=subdir, file_name='obj5', contents='subdir/obj5') | 542 self.CreateTempFile(tmpdir=subdir, file_name='obj5', contents='subdir/obj5') |
537 | 543 |
538 # Use @Retry as hedge against bucket listing eventual consistency. | 544 # Use @Retry as hedge against bucket listing eventual consistency. |
539 @Retry(AssertionError, tries=3, timeout_secs=1) | 545 @Retry(AssertionError, tries=3, timeout_secs=1) |
540 def _Check1(): | 546 def _Check1(): |
541 """Tests rsync works as expected.""" | 547 """Tests rsync works as expected.""" |
542 self.RunGsUtil(['rsync', '-d', suri(bucket_uri), tmpdir]) | 548 self.RunGsUtil(['rsync', '-d', suri(bucket_uri), tmpdir]) |
543 listing1 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) | 549 listing1 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) |
544 listing2 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) | 550 listing2 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) |
545 # Bucket should have un-altered content. | 551 # Bucket should have un-altered content. |
546 self.assertEquals(listing1, set(['/obj1', '/obj2', '/subdir/obj3'])) | 552 self.assertEquals(listing1, set(['/obj1', '/.obj2', '/subdir/obj3'])) |
547 # Dir should have content like bucket but without the subdir objects | 553 # Dir should have content like bucket but without the subdir objects |
548 # synchronized. | 554 # synchronized. |
549 self.assertEquals(listing2, set(['/obj1', '/obj2', '/subdir/obj5'])) | 555 self.assertEquals(listing2, set(['/obj1', '/.obj2', '/subdir/obj5'])) |
550 # Assert that the src/dest objects that had same length but different | 556 # Assert that the src/dest objects that had same length but different |
551 # content were not synchronized (bucket to dir sync doesn't use checksums | 557 # content were not synchronized (bucket to dir sync doesn't use checksums |
552 # unless you specify -c). | 558 # unless you specify -c). |
553 self.assertEquals('obj2', self.RunGsUtil( | 559 self.assertEquals('.obj2', self.RunGsUtil( |
554 ['cat', suri(bucket_uri, 'obj2')], return_stdout=True)) | 560 ['cat', suri(bucket_uri, '.obj2')], return_stdout=True)) |
555 with open(os.path.join(tmpdir, 'obj2')) as f: | 561 with open(os.path.join(tmpdir, '.obj2')) as f: |
556 self.assertEquals('OBJ2', '\n'.join(f.readlines())) | 562 self.assertEquals('.OBJ2', '\n'.join(f.readlines())) |
557 _Check1() | 563 _Check1() |
558 | 564 |
559 # Use @Retry as hedge against bucket listing eventual consistency. | 565 # Use @Retry as hedge against bucket listing eventual consistency. |
560 @Retry(AssertionError, tries=3, timeout_secs=1) | 566 @Retry(AssertionError, tries=3, timeout_secs=1) |
561 def _Check2(): | 567 def _Check2(): |
562 # Check that re-running the same rsync command causes no more changes. | 568 # Check that re-running the same rsync command causes no more changes. |
563 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 569 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
564 ['rsync', '-d', suri(bucket_uri), tmpdir], return_stderr=True)) | 570 ['rsync', '-d', suri(bucket_uri), tmpdir], return_stderr=True)) |
565 _Check2() | 571 _Check2() |
566 | 572 |
567 # Now rerun the sync with the -c option. | 573 # Now rerun the sync with the -c option. |
568 # Use @Retry as hedge against bucket listing eventual consistency. | 574 # Use @Retry as hedge against bucket listing eventual consistency. |
569 @Retry(AssertionError, tries=3, timeout_secs=1) | 575 @Retry(AssertionError, tries=3, timeout_secs=1) |
570 def _Check3(): | 576 def _Check3(): |
571 """Tests rsync -c works as expected.""" | 577 """Tests rsync -c works as expected.""" |
572 self.RunGsUtil(['rsync', '-d', '-c', suri(bucket_uri), tmpdir]) | 578 self.RunGsUtil(['rsync', '-d', '-c', suri(bucket_uri), tmpdir]) |
573 listing1 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) | 579 listing1 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) |
574 listing2 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) | 580 listing2 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) |
575 # Bucket should have un-altered content. | 581 # Bucket should have un-altered content. |
576 self.assertEquals(listing1, set(['/obj1', '/obj2', '/subdir/obj3'])) | 582 self.assertEquals(listing1, set(['/obj1', '/.obj2', '/subdir/obj3'])) |
577 # Dir should have content like bucket but without the subdir objects | 583 # Dir should have content like bucket but without the subdir objects |
578 # synchronized. | 584 # synchronized. |
579 self.assertEquals(listing2, set(['/obj1', '/obj2', '/subdir/obj5'])) | 585 self.assertEquals(listing2, set(['/obj1', '/.obj2', '/subdir/obj5'])) |
580 # Assert that the src/dest objects that had same length but different | 586 # Assert that the src/dest objects that had same length but different |
581 # content were synchronized (bucket to dir sync with -c uses checksums). | 587 # content were synchronized (bucket to dir sync with -c uses checksums). |
582 self.assertEquals('obj2', self.RunGsUtil( | 588 self.assertEquals('.obj2', self.RunGsUtil( |
583 ['cat', suri(bucket_uri, 'obj2')], return_stdout=True)) | 589 ['cat', suri(bucket_uri, '.obj2')], return_stdout=True)) |
584 with open(os.path.join(tmpdir, 'obj2')) as f: | 590 with open(os.path.join(tmpdir, '.obj2')) as f: |
585 self.assertEquals('obj2', '\n'.join(f.readlines())) | 591 self.assertEquals('.obj2', '\n'.join(f.readlines())) |
586 _Check3() | 592 _Check3() |
587 | 593 |
588 # Use @Retry as hedge against bucket listing eventual consistency. | 594 # Use @Retry as hedge against bucket listing eventual consistency. |
589 @Retry(AssertionError, tries=3, timeout_secs=1) | 595 @Retry(AssertionError, tries=3, timeout_secs=1) |
590 def _Check4(): | 596 def _Check4(): |
591 # Check that re-running the same rsync command causes no more changes. | 597 # Check that re-running the same rsync command causes no more changes. |
592 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 598 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
593 ['rsync', '-d', '-c', suri(bucket_uri), tmpdir], return_stderr=True)) | 599 ['rsync', '-d', '-c', suri(bucket_uri), tmpdir], return_stderr=True)) |
594 _Check4() | 600 _Check4() |
595 | 601 |
596 # Now add and remove some objects in dir and bucket and test rsync -r. | 602 # Now add and remove some objects in dir and bucket and test rsync -r. |
597 self.CreateObject(bucket_uri=bucket_uri, object_name='obj6', | 603 self.CreateObject(bucket_uri=bucket_uri, object_name='obj6', |
598 contents='obj6') | 604 contents='obj6') |
599 self.CreateTempFile(tmpdir=tmpdir, file_name='obj7', contents='obj7') | 605 self.CreateTempFile(tmpdir=tmpdir, file_name='obj7', contents='obj7') |
600 self.RunGsUtil(['rm', suri(bucket_uri, 'obj1')]) | 606 self.RunGsUtil(['rm', suri(bucket_uri, 'obj1')]) |
601 os.unlink(os.path.join(tmpdir, 'obj2')) | 607 os.unlink(os.path.join(tmpdir, '.obj2')) |
602 | 608 |
603 # Use @Retry as hedge against bucket listing eventual consistency. | 609 # Use @Retry as hedge against bucket listing eventual consistency. |
604 @Retry(AssertionError, tries=3, timeout_secs=1) | 610 @Retry(AssertionError, tries=3, timeout_secs=1) |
605 def _Check5(): | 611 def _Check5(): |
606 self.RunGsUtil(['rsync', '-d', '-r', suri(bucket_uri), tmpdir]) | 612 self.RunGsUtil(['rsync', '-d', '-r', suri(bucket_uri), tmpdir]) |
607 listing1 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) | 613 listing1 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) |
608 listing2 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) | 614 listing2 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) |
609 # Bucket should have un-altered content. | 615 # Bucket should have un-altered content. |
610 self.assertEquals(listing1, set(['/obj2', '/obj6', '/subdir/obj3'])) | 616 self.assertEquals(listing1, set(['/.obj2', '/obj6', '/subdir/obj3'])) |
611 # Dir should have content like bucket but without the subdir objects | 617 # Dir should have content like bucket but without the subdir objects |
612 # synchronized. | 618 # synchronized. |
613 self.assertEquals(listing2, set(['/obj2', '/obj6', '/subdir/obj3'])) | 619 self.assertEquals(listing2, set(['/.obj2', '/obj6', '/subdir/obj3'])) |
614 _Check5() | 620 _Check5() |
615 | 621 |
616 # Use @Retry as hedge against bucket listing eventual consistency. | 622 # Use @Retry as hedge against bucket listing eventual consistency. |
617 @Retry(AssertionError, tries=3, timeout_secs=1) | 623 @Retry(AssertionError, tries=3, timeout_secs=1) |
618 def _Check6(): | 624 def _Check6(): |
619 # Check that re-running the same rsync command causes no more changes. | 625 # Check that re-running the same rsync command causes no more changes. |
620 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 626 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
621 ['rsync', '-d', '-r', suri(bucket_uri), tmpdir], return_stderr=True)) | 627 ['rsync', '-d', '-r', suri(bucket_uri), tmpdir], return_stderr=True)) |
622 _Check6() | 628 _Check6() |
623 | 629 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 def _Check1(): | 682 def _Check1(): |
677 """Tests rsync works as expected.""" | 683 """Tests rsync works as expected.""" |
678 output = self.RunGsUtil( | 684 output = self.RunGsUtil( |
679 ['rsync', '-d', '-r', suri(bucket_uri), tmpdir], return_stderr=True) | 685 ['rsync', '-d', '-r', suri(bucket_uri), tmpdir], return_stderr=True) |
680 listing1 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) | 686 listing1 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) |
681 listing2 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) | 687 listing2 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) |
682 # Bucket should have un-altered content. | 688 # Bucket should have un-altered content. |
683 self.assertEquals(listing1, set(['/obj1', '//'])) | 689 self.assertEquals(listing1, set(['/obj1', '//'])) |
684 # Bucket should not have the placeholder object. | 690 # Bucket should not have the placeholder object. |
685 self.assertEquals(listing2, set(['/obj1'])) | 691 self.assertEquals(listing2, set(['/obj1'])) |
686 # Stdout should report what happened. | |
687 self.assertRegexpMatches(output, r'.*Skipping cloud sub-directory.*') | |
688 _Check1() | 692 _Check1() |
689 | 693 |
690 @unittest.skipIf(IS_WINDOWS, 'os.symlink() is not available on Windows.') | 694 @unittest.skipIf(IS_WINDOWS, 'os.symlink() is not available on Windows.') |
691 def test_rsync_minus_d_minus_e(self): | 695 def test_rsync_minus_d_minus_e(self): |
692 """Tests that rsync -e ignores symlinks.""" | 696 """Tests that rsync -e ignores symlinks.""" |
693 tmpdir = self.CreateTempDir() | 697 tmpdir = self.CreateTempDir() |
694 subdir = os.path.join(tmpdir, 'subdir') | 698 subdir = os.path.join(tmpdir, 'subdir') |
695 os.mkdir(subdir) | 699 os.mkdir(subdir) |
696 bucket_uri = self.CreateBucket() | 700 bucket_uri = self.CreateBucket() |
697 fpath1 = self.CreateTempFile( | 701 fpath1 = self.CreateTempFile( |
698 tmpdir=tmpdir, file_name='obj1', contents='obj1') | 702 tmpdir=tmpdir, file_name='obj1', contents='obj1') |
699 self.CreateTempFile(tmpdir=tmpdir, file_name='obj2', contents='obj2') | 703 self.CreateTempFile(tmpdir=tmpdir, file_name='.obj2', contents='.obj2') |
700 self.CreateTempFile(tmpdir=subdir, file_name='obj3', contents='subdir/obj3') | 704 self.CreateTempFile(tmpdir=subdir, file_name='obj3', contents='subdir/obj3') |
701 good_symlink_path = os.path.join(tmpdir, 'symlink1') | 705 good_symlink_path = os.path.join(tmpdir, 'symlink1') |
702 os.symlink(fpath1, good_symlink_path) | 706 os.symlink(fpath1, good_symlink_path) |
703 # Make a symlink that points to a non-existent path to test that -e also | 707 # Make a symlink that points to a non-existent path to test that -e also |
704 # handles that case. | 708 # handles that case. |
705 bad_symlink_path = os.path.join(tmpdir, 'symlink2') | 709 bad_symlink_path = os.path.join(tmpdir, 'symlink2') |
706 os.symlink(os.path.join('/', 'non-existent'), bad_symlink_path) | 710 os.symlink(os.path.join('/', 'non-existent'), bad_symlink_path) |
707 self.CreateObject(bucket_uri=bucket_uri, object_name='obj2', | 711 self.CreateObject(bucket_uri=bucket_uri, object_name='.obj2', |
708 contents='OBJ2') | 712 contents='.OBJ2') |
709 self.CreateObject(bucket_uri=bucket_uri, object_name='obj4', | 713 self.CreateObject(bucket_uri=bucket_uri, object_name='obj4', |
710 contents='obj4') | 714 contents='obj4') |
711 self.CreateObject(bucket_uri=bucket_uri, object_name='subdir/obj5', | 715 self.CreateObject(bucket_uri=bucket_uri, object_name='subdir/obj5', |
712 contents='subdir/obj5') | 716 contents='subdir/obj5') |
713 | 717 |
714 # Use @Retry as hedge against bucket listing eventual consistency. | 718 # Use @Retry as hedge against bucket listing eventual consistency. |
715 @Retry(AssertionError, tries=3, timeout_secs=1) | 719 @Retry(AssertionError, tries=3, timeout_secs=1) |
716 def _Check1(): | 720 def _Check1(): |
717 """Ensure listings match the commented expectations.""" | 721 """Ensure listings match the commented expectations.""" |
718 self.RunGsUtil(['rsync', '-d', '-e', tmpdir, suri(bucket_uri)]) | 722 self.RunGsUtil(['rsync', '-d', '-e', tmpdir, suri(bucket_uri)]) |
719 listing1 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) | 723 listing1 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) |
720 listing2 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) | 724 listing2 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) |
721 # Dir should have un-altered content. | 725 # Dir should have un-altered content. |
722 self.assertEquals( | 726 self.assertEquals( |
723 listing1, | 727 listing1, |
724 set(['/obj1', '/obj2', '/subdir/obj3', '/symlink1', '/symlink2'])) | 728 set(['/obj1', '/.obj2', '/subdir/obj3', '/symlink1', '/symlink2'])) |
725 # Bucket should have content like dir but without the symlink, and | 729 # Bucket should have content like dir but without the symlink, and |
726 # without subdir objects synchronized. | 730 # without subdir objects synchronized. |
727 self.assertEquals(listing2, set(['/obj1', '/obj2', '/subdir/obj5'])) | 731 self.assertEquals(listing2, set(['/obj1', '/.obj2', '/subdir/obj5'])) |
728 _Check1() | 732 _Check1() |
729 | 733 |
730 # Now remove invalid symlink and run without -e, and see that symlink gets | 734 # Now remove invalid symlink and run without -e, and see that symlink gets |
731 # copied (as file to which it points). Use @Retry as hedge against bucket | 735 # copied (as file to which it points). Use @Retry as hedge against bucket |
732 # listing eventual consistency. | 736 # listing eventual consistency. |
733 os.unlink(bad_symlink_path) | 737 os.unlink(bad_symlink_path) |
734 @Retry(AssertionError, tries=3, timeout_secs=1) | 738 @Retry(AssertionError, tries=3, timeout_secs=1) |
735 def _Check2(): | 739 def _Check2(): |
736 """Tests rsync works as expected.""" | 740 """Tests rsync works as expected.""" |
737 self.RunGsUtil(['rsync', '-d', tmpdir, suri(bucket_uri)]) | 741 self.RunGsUtil(['rsync', '-d', tmpdir, suri(bucket_uri)]) |
738 listing1 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) | 742 listing1 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) |
739 listing2 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) | 743 listing2 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) |
740 # Dir should have un-altered content. | 744 # Dir should have un-altered content. |
741 self.assertEquals( | 745 self.assertEquals( |
742 listing1, set(['/obj1', '/obj2', '/subdir/obj3', '/symlink1'])) | 746 listing1, set(['/obj1', '/.obj2', '/subdir/obj3', '/symlink1'])) |
743 # Bucket should have content like dir but without the symlink, and | 747 # Bucket should have content like dir but without the symlink, and |
744 # without subdir objects synchronized. | 748 # without subdir objects synchronized. |
745 self.assertEquals( | 749 self.assertEquals( |
746 listing2, set(['/obj1', '/obj2', '/subdir/obj5', '/symlink1'])) | 750 listing2, set(['/obj1', '/.obj2', '/subdir/obj5', '/symlink1'])) |
747 self.assertEquals('obj1', self.RunGsUtil( | 751 self.assertEquals('obj1', self.RunGsUtil( |
748 ['cat', suri(bucket_uri, 'symlink1')], return_stdout=True)) | 752 ['cat', suri(bucket_uri, 'symlink1')], return_stdout=True)) |
749 _Check2() | 753 _Check2() |
750 | 754 |
751 # Use @Retry as hedge against bucket listing eventual consistency. | 755 # Use @Retry as hedge against bucket listing eventual consistency. |
752 @Retry(AssertionError, tries=3, timeout_secs=1) | 756 @Retry(AssertionError, tries=3, timeout_secs=1) |
753 def _Check3(): | 757 def _Check3(): |
754 # Check that re-running the same rsync command causes no more changes. | 758 # Check that re-running the same rsync command causes no more changes. |
755 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 759 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
756 ['rsync', '-d', tmpdir, suri(bucket_uri)], return_stderr=True)) | 760 ['rsync', '-d', tmpdir, suri(bucket_uri)], return_stderr=True)) |
757 _Check3() | 761 _Check3() |
758 | 762 |
759 @SkipForS3('S3 does not support composite objects') | 763 @SkipForS3('S3 does not support composite objects') |
760 def test_bucket_to_bucket_minus_d_with_composites(self): | 764 def test_bucket_to_bucket_minus_d_with_composites(self): |
761 """Tests that rsync works with composite objects (which don't have MD5s).""" | 765 """Tests that rsync works with composite objects (which don't have MD5s).""" |
762 bucket1_uri = self.CreateBucket() | 766 bucket1_uri = self.CreateBucket() |
763 bucket2_uri = self.CreateBucket() | 767 bucket2_uri = self.CreateBucket() |
764 self.CreateObject(bucket_uri=bucket1_uri, object_name='obj1', | 768 self.CreateObject(bucket_uri=bucket1_uri, object_name='obj1', |
765 contents='obj1') | 769 contents='obj1') |
766 self.CreateObject(bucket_uri=bucket1_uri, object_name='obj2', | 770 self.CreateObject(bucket_uri=bucket1_uri, object_name='.obj2', |
767 contents='obj2') | 771 contents='.obj2') |
768 self.RunGsUtil( | 772 self.RunGsUtil( |
769 ['compose', suri(bucket1_uri, 'obj1'), suri(bucket1_uri, 'obj2'), | 773 ['compose', suri(bucket1_uri, 'obj1'), suri(bucket1_uri, '.obj2'), |
770 suri(bucket1_uri, 'obj3')]) | 774 suri(bucket1_uri, 'obj3')]) |
771 self.CreateObject(bucket_uri=bucket2_uri, object_name='obj2', | 775 self.CreateObject(bucket_uri=bucket2_uri, object_name='.obj2', |
772 contents='OBJ2') | 776 contents='.OBJ2') |
773 self.CreateObject(bucket_uri=bucket2_uri, object_name='obj4', | 777 self.CreateObject(bucket_uri=bucket2_uri, object_name='obj4', |
774 contents='obj4') | 778 contents='obj4') |
775 | 779 |
776 # Use @Retry as hedge against bucket listing eventual consistency. | 780 # Use @Retry as hedge against bucket listing eventual consistency. |
777 @Retry(AssertionError, tries=3, timeout_secs=1) | 781 @Retry(AssertionError, tries=3, timeout_secs=1) |
778 def _Check1(): | 782 def _Check1(): |
779 self.RunGsUtil(['rsync', '-d', suri(bucket1_uri), suri(bucket2_uri)]) | 783 self.RunGsUtil(['rsync', '-d', suri(bucket1_uri), suri(bucket2_uri)]) |
780 listing1 = _TailSet(suri(bucket1_uri), self._FlatListBucket(bucket1_uri)) | 784 listing1 = _TailSet(suri(bucket1_uri), self._FlatListBucket(bucket1_uri)) |
781 listing2 = _TailSet(suri(bucket2_uri), self._FlatListBucket(bucket2_uri)) | 785 listing2 = _TailSet(suri(bucket2_uri), self._FlatListBucket(bucket2_uri)) |
782 # First bucket should have un-altered content. | 786 # First bucket should have un-altered content. |
783 self.assertEquals(listing1, set(['/obj1', '/obj2', '/obj3'])) | 787 self.assertEquals(listing1, set(['/obj1', '/.obj2', '/obj3'])) |
784 # Second bucket should have content like first bucket but without the | 788 # Second bucket should have content like first bucket but without the |
785 # subdir objects synchronized. | 789 # subdir objects synchronized. |
786 self.assertEquals(listing2, set(['/obj1', '/obj2', '/obj3'])) | 790 self.assertEquals(listing2, set(['/obj1', '/.obj2', '/obj3'])) |
787 _Check1() | 791 _Check1() |
788 | 792 |
789 # Use @Retry as hedge against bucket listing eventual consistency. | 793 # Use @Retry as hedge against bucket listing eventual consistency. |
790 @Retry(AssertionError, tries=3, timeout_secs=1) | 794 @Retry(AssertionError, tries=3, timeout_secs=1) |
791 def _Check2(): | 795 def _Check2(): |
792 # Check that re-running the same rsync command causes no more changes. | 796 # Check that re-running the same rsync command causes no more changes. |
793 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 797 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
794 ['rsync', '-d', suri(bucket1_uri), suri(bucket2_uri)], | 798 ['rsync', '-d', suri(bucket1_uri), suri(bucket2_uri)], |
795 return_stderr=True)) | 799 return_stderr=True)) |
796 _Check2() | 800 _Check2() |
797 | 801 |
798 def test_bucket_to_bucket_minus_d_empty_dest(self): | 802 def test_bucket_to_bucket_minus_d_empty_dest(self): |
799 """Tests working with empty dest bucket (iter runs out before src iter).""" | 803 """Tests working with empty dest bucket (iter runs out before src iter).""" |
800 bucket1_uri = self.CreateBucket() | 804 bucket1_uri = self.CreateBucket() |
801 bucket2_uri = self.CreateBucket() | 805 bucket2_uri = self.CreateBucket() |
802 self.CreateObject(bucket_uri=bucket1_uri, object_name='obj1', | 806 self.CreateObject(bucket_uri=bucket1_uri, object_name='obj1', |
803 contents='obj1') | 807 contents='obj1') |
804 self.CreateObject(bucket_uri=bucket1_uri, object_name='obj2', | 808 self.CreateObject(bucket_uri=bucket1_uri, object_name='.obj2', |
805 contents='obj2') | 809 contents='.obj2') |
806 | 810 |
807 # Use @Retry as hedge against bucket listing eventual consistency. | 811 # Use @Retry as hedge against bucket listing eventual consistency. |
808 @Retry(AssertionError, tries=3, timeout_secs=1) | 812 @Retry(AssertionError, tries=3, timeout_secs=1) |
809 def _Check1(): | 813 def _Check1(): |
810 self.RunGsUtil(['rsync', '-d', suri(bucket1_uri), suri(bucket2_uri)]) | 814 self.RunGsUtil(['rsync', '-d', suri(bucket1_uri), suri(bucket2_uri)]) |
811 listing1 = _TailSet(suri(bucket1_uri), self._FlatListBucket(bucket1_uri)) | 815 listing1 = _TailSet(suri(bucket1_uri), self._FlatListBucket(bucket1_uri)) |
812 listing2 = _TailSet(suri(bucket2_uri), self._FlatListBucket(bucket2_uri)) | 816 listing2 = _TailSet(suri(bucket2_uri), self._FlatListBucket(bucket2_uri)) |
813 self.assertEquals(listing1, set(['/obj1', '/obj2'])) | 817 self.assertEquals(listing1, set(['/obj1', '/.obj2'])) |
814 self.assertEquals(listing2, set(['/obj1', '/obj2'])) | 818 self.assertEquals(listing2, set(['/obj1', '/.obj2'])) |
815 _Check1() | 819 _Check1() |
816 | 820 |
817 # Use @Retry as hedge against bucket listing eventual consistency. | 821 # Use @Retry as hedge against bucket listing eventual consistency. |
818 @Retry(AssertionError, tries=3, timeout_secs=1) | 822 @Retry(AssertionError, tries=3, timeout_secs=1) |
819 def _Check2(): | 823 def _Check2(): |
820 # Check that re-running the same rsync command causes no more changes. | 824 # Check that re-running the same rsync command causes no more changes. |
821 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 825 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
822 ['rsync', '-d', suri(bucket1_uri), suri(bucket2_uri)], | 826 ['rsync', '-d', suri(bucket1_uri), suri(bucket2_uri)], |
823 return_stderr=True)) | 827 return_stderr=True)) |
824 _Check2() | 828 _Check2() |
825 | 829 |
826 def test_bucket_to_bucket_minus_d_empty_src(self): | 830 def test_bucket_to_bucket_minus_d_empty_src(self): |
827 """Tests working with empty src bucket (iter runs out before dst iter).""" | 831 """Tests working with empty src bucket (iter runs out before dst iter).""" |
828 bucket1_uri = self.CreateBucket() | 832 bucket1_uri = self.CreateBucket() |
829 bucket2_uri = self.CreateBucket() | 833 bucket2_uri = self.CreateBucket() |
830 self.CreateObject(bucket_uri=bucket2_uri, object_name='obj1', | 834 self.CreateObject(bucket_uri=bucket2_uri, object_name='obj1', |
831 contents='obj1') | 835 contents='obj1') |
832 self.CreateObject(bucket_uri=bucket2_uri, object_name='obj2', | 836 self.CreateObject(bucket_uri=bucket2_uri, object_name='.obj2', |
833 contents='obj2') | 837 contents='.obj2') |
834 | 838 |
835 # Use @Retry as hedge against bucket listing eventual consistency. | 839 # Use @Retry as hedge against bucket listing eventual consistency. |
836 @Retry(AssertionError, tries=3, timeout_secs=1) | 840 @Retry(AssertionError, tries=3, timeout_secs=1) |
837 def _Check1(): | 841 def _Check1(): |
838 self.RunGsUtil(['rsync', '-d', suri(bucket1_uri), suri(bucket2_uri)]) | 842 self.RunGsUtil(['rsync', '-d', suri(bucket1_uri), suri(bucket2_uri)]) |
839 stderr = self.RunGsUtil(['ls', suri(bucket1_uri, '**')], | 843 stderr = self.RunGsUtil(['ls', suri(bucket1_uri, '**')], |
840 expected_status=1, return_stderr=True) | 844 expected_status=1, return_stderr=True) |
841 self.assertIn('One or more URLs matched no objects', stderr) | 845 self.assertIn('One or more URLs matched no objects', stderr) |
842 stderr = self.RunGsUtil(['ls', suri(bucket2_uri, '**')], | 846 stderr = self.RunGsUtil(['ls', suri(bucket2_uri, '**')], |
843 expected_status=1, return_stderr=True) | 847 expected_status=1, return_stderr=True) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
889 _Check2() | 893 _Check2() |
890 | 894 |
891 def test_rsync_to_nonexistent_bucket_subdir(self): | 895 def test_rsync_to_nonexistent_bucket_subdir(self): |
892 """Tests that rsync to non-existent bucket subdir works.""" | 896 """Tests that rsync to non-existent bucket subdir works.""" |
893 # Create dir with some objects and empty bucket. | 897 # Create dir with some objects and empty bucket. |
894 tmpdir = self.CreateTempDir() | 898 tmpdir = self.CreateTempDir() |
895 subdir = os.path.join(tmpdir, 'subdir') | 899 subdir = os.path.join(tmpdir, 'subdir') |
896 os.mkdir(subdir) | 900 os.mkdir(subdir) |
897 bucket_url = self.CreateBucket() | 901 bucket_url = self.CreateBucket() |
898 self.CreateTempFile(tmpdir=tmpdir, file_name='obj1', contents='obj1') | 902 self.CreateTempFile(tmpdir=tmpdir, file_name='obj1', contents='obj1') |
899 self.CreateTempFile(tmpdir=tmpdir, file_name='obj2', contents='obj2') | 903 self.CreateTempFile(tmpdir=tmpdir, file_name='.obj2', contents='.obj2') |
900 self.CreateTempFile(tmpdir=subdir, file_name='obj3', contents='subdir/obj3') | 904 self.CreateTempFile(tmpdir=subdir, file_name='obj3', contents='subdir/obj3') |
901 | 905 |
902 # Use @Retry as hedge against bucket listing eventual consistency. | 906 # Use @Retry as hedge against bucket listing eventual consistency. |
903 @Retry(AssertionError, tries=3, timeout_secs=1) | 907 @Retry(AssertionError, tries=3, timeout_secs=1) |
904 def _Check1(): | 908 def _Check1(): |
905 """Tests rsync works as expected.""" | 909 """Tests rsync works as expected.""" |
906 self.RunGsUtil(['rsync', '-r', tmpdir, suri(bucket_url, 'subdir')]) | 910 self.RunGsUtil(['rsync', '-r', tmpdir, suri(bucket_url, 'subdir')]) |
907 listing1 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) | 911 listing1 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) |
908 listing2 = _TailSet( | 912 listing2 = _TailSet( |
909 suri(bucket_url, 'subdir'), | 913 suri(bucket_url, 'subdir'), |
910 self._FlatListBucket(bucket_url.clone_replace_name('subdir'))) | 914 self._FlatListBucket(bucket_url.clone_replace_name('subdir'))) |
911 # Dir should have un-altered content. | 915 # Dir should have un-altered content. |
912 self.assertEquals(listing1, set(['/obj1', '/obj2', '/subdir/obj3'])) | 916 self.assertEquals(listing1, set(['/obj1', '/.obj2', '/subdir/obj3'])) |
913 # Bucket subdir should have content like dir. | 917 # Bucket subdir should have content like dir. |
914 self.assertEquals(listing2, set(['/obj1', '/obj2', '/subdir/obj3'])) | 918 self.assertEquals(listing2, set(['/obj1', '/.obj2', '/subdir/obj3'])) |
915 _Check1() | 919 _Check1() |
916 | 920 |
917 # Use @Retry as hedge against bucket listing eventual consistency. | 921 # Use @Retry as hedge against bucket listing eventual consistency. |
918 @Retry(AssertionError, tries=3, timeout_secs=1) | 922 @Retry(AssertionError, tries=3, timeout_secs=1) |
919 def _Check2(): | 923 def _Check2(): |
920 # Check that re-running the same rsync command causes no more changes. | 924 # Check that re-running the same rsync command causes no more changes. |
921 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 925 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
922 ['rsync', '-r', tmpdir, suri(bucket_url, 'subdir')], | 926 ['rsync', '-r', tmpdir, suri(bucket_url, 'subdir')], |
923 return_stderr=True)) | 927 return_stderr=True)) |
924 _Check2() | 928 _Check2() |
925 | 929 |
926 def test_rsync_from_nonexistent_bucket(self): | 930 def test_rsync_from_nonexistent_bucket(self): |
927 """Tests that rsync from a non-existent bucket subdir fails gracefully.""" | 931 """Tests that rsync from a non-existent bucket subdir fails gracefully.""" |
928 tmpdir = self.CreateTempDir() | 932 tmpdir = self.CreateTempDir() |
929 self.CreateTempFile(tmpdir=tmpdir, file_name='obj1', contents='obj1') | 933 self.CreateTempFile(tmpdir=tmpdir, file_name='obj1', contents='obj1') |
930 self.CreateTempFile(tmpdir=tmpdir, file_name='obj2', contents='obj2') | 934 self.CreateTempFile(tmpdir=tmpdir, file_name='.obj2', contents='.obj2') |
931 bucket_url_str = '%s://%s' % ( | 935 bucket_url_str = '%s://%s' % ( |
932 self.default_provider, self.nonexistent_bucket_name) | 936 self.default_provider, self.nonexistent_bucket_name) |
933 stderr = self.RunGsUtil(['rsync', '-d', bucket_url_str, tmpdir], | 937 stderr = self.RunGsUtil(['rsync', '-d', bucket_url_str, tmpdir], |
934 expected_status=1, return_stderr=True) | 938 expected_status=1, return_stderr=True) |
935 self.assertIn('Caught non-retryable exception', stderr) | 939 self.assertIn('Caught non-retryable exception', stderr) |
936 listing = _TailSet(tmpdir, self._FlatListDir(tmpdir)) | 940 listing = _TailSet(tmpdir, self._FlatListDir(tmpdir)) |
937 # Dir should have un-altered content. | 941 # Dir should have un-altered content. |
938 self.assertEquals(listing, set(['/obj1', '/obj2'])) | 942 self.assertEquals(listing, set(['/obj1', '/.obj2'])) |
939 | 943 |
940 def test_rsync_to_nonexistent_bucket(self): | 944 def test_rsync_to_nonexistent_bucket(self): |
941 """Tests that rsync from a non-existent bucket subdir fails gracefully.""" | 945 """Tests that rsync from a non-existent bucket subdir fails gracefully.""" |
942 tmpdir = self.CreateTempDir() | 946 tmpdir = self.CreateTempDir() |
943 self.CreateTempFile(tmpdir=tmpdir, file_name='obj1', contents='obj1') | 947 self.CreateTempFile(tmpdir=tmpdir, file_name='obj1', contents='obj1') |
944 self.CreateTempFile(tmpdir=tmpdir, file_name='obj2', contents='obj2') | 948 self.CreateTempFile(tmpdir=tmpdir, file_name='.obj2', contents='.obj2') |
945 bucket_url_str = '%s://%s' % ( | 949 bucket_url_str = '%s://%s' % ( |
946 self.default_provider, self.nonexistent_bucket_name) | 950 self.default_provider, self.nonexistent_bucket_name) |
947 stderr = self.RunGsUtil(['rsync', '-d', bucket_url_str, tmpdir], | 951 stderr = self.RunGsUtil(['rsync', '-d', bucket_url_str, tmpdir], |
948 expected_status=1, return_stderr=True) | 952 expected_status=1, return_stderr=True) |
949 self.assertIn('Caught non-retryable exception', stderr) | 953 self.assertIn('Caught non-retryable exception', stderr) |
950 listing = _TailSet(tmpdir, self._FlatListDir(tmpdir)) | 954 listing = _TailSet(tmpdir, self._FlatListDir(tmpdir)) |
951 # Dir should have un-altered content. | 955 # Dir should have un-altered content. |
952 self.assertEquals(listing, set(['/obj1', '/obj2'])) | 956 self.assertEquals(listing, set(['/obj1', '/.obj2'])) |
953 | 957 |
954 def test_bucket_to_bucket_minus_d_with_overwrite_and_punc_chars(self): | 958 def test_bucket_to_bucket_minus_d_with_overwrite_and_punc_chars(self): |
955 """Tests that punc chars in filenames don't confuse sort order.""" | 959 """Tests that punc chars in filenames don't confuse sort order.""" |
956 bucket1_uri = self.CreateBucket() | 960 bucket1_uri = self.CreateBucket() |
957 bucket2_uri = self.CreateBucket() | 961 bucket2_uri = self.CreateBucket() |
958 # Create 2 objects in each bucket, with one overwritten with a name that's | 962 # Create 2 objects in each bucket, with one overwritten with a name that's |
959 # less than the next name in destination bucket when encoded, but not when | 963 # less than the next name in destination bucket when encoded, but not when |
960 # compared without encoding. | 964 # compared without encoding. |
961 self.CreateObject(bucket_uri=bucket1_uri, object_name='e/obj1', | 965 self.CreateObject(bucket_uri=bucket1_uri, object_name='e/obj1', |
962 contents='obj1') | 966 contents='obj1') |
963 self.CreateObject(bucket_uri=bucket1_uri, object_name='e-1/obj2', | 967 self.CreateObject(bucket_uri=bucket1_uri, object_name='e-1/.obj2', |
964 contents='obj2') | 968 contents='.obj2') |
965 self.CreateObject(bucket_uri=bucket2_uri, object_name='e/obj1', | 969 self.CreateObject(bucket_uri=bucket2_uri, object_name='e/obj1', |
966 contents='OBJ1') | 970 contents='OBJ1') |
967 self.CreateObject(bucket_uri=bucket2_uri, object_name='e-1/obj2', | 971 self.CreateObject(bucket_uri=bucket2_uri, object_name='e-1/.obj2', |
968 contents='obj2') | 972 contents='.obj2') |
969 # Need to make sure the bucket listings are caught-up, otherwise the | 973 # Need to make sure the bucket listings are caught-up, otherwise the |
970 # rsync may not see all objects and fail to synchronize correctly. | 974 # rsync may not see all objects and fail to synchronize correctly. |
971 self.AssertNObjectsInBucket(bucket1_uri, 2) | 975 self.AssertNObjectsInBucket(bucket1_uri, 2) |
972 self.AssertNObjectsInBucket(bucket2_uri, 2) | 976 self.AssertNObjectsInBucket(bucket2_uri, 2) |
973 | 977 |
974 # Use @Retry as hedge against bucket listing eventual consistency. | 978 # Use @Retry as hedge against bucket listing eventual consistency. |
975 @Retry(AssertionError, tries=3, timeout_secs=1) | 979 @Retry(AssertionError, tries=3, timeout_secs=1) |
976 def _Check1(): | 980 def _Check1(): |
977 """Tests rsync works as expected.""" | 981 """Tests rsync works as expected.""" |
978 self.RunGsUtil(['rsync', '-rd', suri(bucket1_uri), suri(bucket2_uri)]) | 982 self.RunGsUtil(['rsync', '-rd', suri(bucket1_uri), suri(bucket2_uri)]) |
979 listing1 = _TailSet(suri(bucket1_uri), self._FlatListBucket(bucket1_uri)) | 983 listing1 = _TailSet(suri(bucket1_uri), self._FlatListBucket(bucket1_uri)) |
980 listing2 = _TailSet(suri(bucket2_uri), self._FlatListBucket(bucket2_uri)) | 984 listing2 = _TailSet(suri(bucket2_uri), self._FlatListBucket(bucket2_uri)) |
981 # First bucket should have un-altered content. | 985 # First bucket should have un-altered content. |
982 self.assertEquals(listing1, set(['/e/obj1', '/e-1/obj2'])) | 986 self.assertEquals(listing1, set(['/e/obj1', '/e-1/.obj2'])) |
983 self.assertEquals(listing2, set(['/e/obj1', '/e-1/obj2'])) | 987 self.assertEquals(listing2, set(['/e/obj1', '/e-1/.obj2'])) |
984 # Assert correct contents. | 988 # Assert correct contents. |
985 self.assertEquals('obj1', self.RunGsUtil( | 989 self.assertEquals('obj1', self.RunGsUtil( |
986 ['cat', suri(bucket2_uri, 'e/obj1')], return_stdout=True)) | 990 ['cat', suri(bucket2_uri, 'e/obj1')], return_stdout=True)) |
987 self.assertEquals('obj2', self.RunGsUtil( | 991 self.assertEquals('.obj2', self.RunGsUtil( |
988 ['cat', suri(bucket2_uri, 'e-1/obj2')], return_stdout=True)) | 992 ['cat', suri(bucket2_uri, 'e-1/.obj2')], return_stdout=True)) |
989 _Check1() | 993 _Check1() |
990 | 994 |
991 # Use @Retry as hedge against bucket listing eventual consistency. | 995 # Use @Retry as hedge against bucket listing eventual consistency. |
992 @Retry(AssertionError, tries=3, timeout_secs=1) | 996 @Retry(AssertionError, tries=3, timeout_secs=1) |
993 def _Check2(): | 997 def _Check2(): |
994 # Check that re-running the same rsync command causes no more changes. | 998 # Check that re-running the same rsync command causes no more changes. |
995 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 999 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
996 ['rsync', '-d', suri(bucket1_uri), suri(bucket2_uri)], | 1000 ['rsync', '-d', suri(bucket1_uri), suri(bucket2_uri)], |
997 return_stderr=True)) | 1001 return_stderr=True)) |
998 _Check2() | 1002 _Check2() |
999 | 1003 |
1000 def test_dir_to_bucket_minus_x(self): | 1004 def test_dir_to_bucket_minus_x(self): |
1001 """Tests that rsync -x option works correctly.""" | 1005 """Tests that rsync -x option works correctly.""" |
1002 # Create dir and bucket with 1 overlapping and 2 extra objects in each. | 1006 # Create dir and bucket with 1 overlapping and 2 extra objects in each. |
1003 tmpdir = self.CreateTempDir() | 1007 tmpdir = self.CreateTempDir() |
1004 bucket_uri = self.CreateBucket() | 1008 bucket_uri = self.CreateBucket() |
1005 self.CreateTempFile(tmpdir=tmpdir, file_name='obj1', contents='obj1') | 1009 self.CreateTempFile(tmpdir=tmpdir, file_name='obj1', contents='obj1') |
1006 self.CreateTempFile(tmpdir=tmpdir, file_name='obj2', contents='obj2') | 1010 self.CreateTempFile(tmpdir=tmpdir, file_name='.obj2', contents='.obj2') |
1007 self.CreateTempFile(tmpdir=tmpdir, file_name='obj3', contents='obj3') | 1011 self.CreateTempFile(tmpdir=tmpdir, file_name='obj3', contents='obj3') |
1008 self.CreateObject(bucket_uri=bucket_uri, object_name='obj2', | 1012 self.CreateObject(bucket_uri=bucket_uri, object_name='.obj2', |
1009 contents='obj2') | 1013 contents='.obj2') |
1010 self.CreateObject(bucket_uri=bucket_uri, object_name='obj4', | 1014 self.CreateObject(bucket_uri=bucket_uri, object_name='obj4', |
1011 contents='obj4') | 1015 contents='obj4') |
1012 self.CreateObject(bucket_uri=bucket_uri, object_name='obj5', | 1016 self.CreateObject(bucket_uri=bucket_uri, object_name='obj5', |
1013 contents='obj5') | 1017 contents='obj5') |
1014 | 1018 |
1015 # Need to make sure the bucket listing is caught-up, otherwise the | 1019 # Need to make sure the bucket listing is caught-up, otherwise the |
1016 # first rsync may not see obj2 and overwrite it. | 1020 # first rsync may not see .obj2 and overwrite it. |
1017 self.AssertNObjectsInBucket(bucket_uri, 3) | 1021 self.AssertNObjectsInBucket(bucket_uri, 3) |
1018 | 1022 |
1019 # Use @Retry as hedge against bucket listing eventual consistency. | 1023 # Use @Retry as hedge against bucket listing eventual consistency. |
1020 @Retry(AssertionError, tries=3, timeout_secs=1) | 1024 @Retry(AssertionError, tries=3, timeout_secs=1) |
1021 def _Check1(): | 1025 def _Check1(): |
1022 """Tests rsync works as expected.""" | 1026 """Tests rsync works as expected.""" |
1023 self.RunGsUtil(['rsync', '-d', '-x', 'obj[34]', tmpdir, suri(bucket_uri)]) | 1027 self.RunGsUtil(['rsync', '-d', '-x', 'obj[34]', tmpdir, suri(bucket_uri)]) |
1024 listing1 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) | 1028 listing1 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) |
1025 listing2 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) | 1029 listing2 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) |
1026 # Dir should have un-altered content. | 1030 # Dir should have un-altered content. |
1027 self.assertEquals(listing1, set(['/obj1', '/obj2', '/obj3'])) | 1031 self.assertEquals(listing1, set(['/obj1', '/.obj2', '/obj3'])) |
1028 # Bucket should have content like dir but ignoring obj3 from dir and not | 1032 # Bucket should have content like dir but ignoring obj3 from dir and not |
1029 # deleting obj4 from bucket (per exclude regex). | 1033 # deleting obj4 from bucket (per exclude regex). |
1030 self.assertEquals(listing2, set(['/obj1', '/obj2', '/obj4'])) | 1034 self.assertEquals(listing2, set(['/obj1', '/.obj2', '/obj4'])) |
1031 _Check1() | 1035 _Check1() |
1032 | 1036 |
1033 # Use @Retry as hedge against bucket listing eventual consistency. | 1037 # Use @Retry as hedge against bucket listing eventual consistency. |
1034 @Retry(AssertionError, tries=3, timeout_secs=1) | 1038 @Retry(AssertionError, tries=3, timeout_secs=1) |
1035 def _Check2(): | 1039 def _Check2(): |
1036 # Check that re-running the same rsync command causes no more changes. | 1040 # Check that re-running the same rsync command causes no more changes. |
1037 self.assertEquals(NO_CHANGES, self.RunGsUtil( | 1041 self.assertEquals(NO_CHANGES, self.RunGsUtil( |
1038 ['rsync', '-d', '-x', 'obj[34]', tmpdir, suri(bucket_uri)], | 1042 ['rsync', '-d', '-x', 'obj[34]', tmpdir, suri(bucket_uri)], |
1039 return_stderr=True)) | 1043 return_stderr=True)) |
1040 _Check2() | 1044 _Check2() |
| 1045 |
| 1046 @unittest.skipIf(IS_WINDOWS, |
| 1047 "os.chmod() won't make file unreadable on Windows.") |
| 1048 def test_dir_to_bucket_minus_C(self): |
| 1049 """Tests that rsync -C option works correctly.""" |
| 1050 # Create dir with 3 objects, the middle of which is unreadable. |
| 1051 tmpdir = self.CreateTempDir() |
| 1052 bucket_uri = self.CreateBucket() |
| 1053 self.CreateTempFile(tmpdir=tmpdir, file_name='obj1', contents='obj1') |
| 1054 path = self.CreateTempFile(tmpdir=tmpdir, file_name='obj2', contents='obj2') |
| 1055 os.chmod(path, 0) |
| 1056 self.CreateTempFile(tmpdir=tmpdir, file_name='obj3', contents='obj3') |
| 1057 |
| 1058 # Use @Retry as hedge against bucket listing eventual consistency. |
| 1059 @Retry(AssertionError, tries=3, timeout_secs=1) |
| 1060 def _Check(): |
| 1061 """Tests rsync works as expected.""" |
| 1062 stderr = self.RunGsUtil(['rsync', '-C', tmpdir, suri(bucket_uri)], |
| 1063 expected_status=1, return_stderr=True) |
| 1064 self.assertIn('1 files/objects could not be copied/removed.', stderr) |
| 1065 listing1 = _TailSet(tmpdir, self._FlatListDir(tmpdir)) |
| 1066 listing2 = _TailSet(suri(bucket_uri), self._FlatListBucket(bucket_uri)) |
| 1067 # Dir should have un-altered content. |
| 1068 self.assertEquals(listing1, set(['/obj1', '/obj2', '/obj3'])) |
| 1069 # Bucket should have obj1 and obj3 even though obj2 was unreadable. |
| 1070 self.assertEquals(listing2, set(['/obj1', '/obj3'])) |
| 1071 _Check() |
OLD | NEW |