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

Side by Side Diff: gslib/tests/test_copy_helper_funcs.py

Issue 698893003: Update checked in version of gsutil to version 4.6 (Closed) Base URL: http://dart.googlecode.com/svn/third_party/gsutil/
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « gslib/tests/test_compose.py ('k') | gslib/tests/test_cors.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 # -*- coding: utf-8 -*-
2 # Copyright 2013 Google Inc. All Rights Reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (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
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 """Unit tests for parallel upload functions in copy_helper."""
16
17 from gslib.copy_helper import _AppendComponentTrackerToParallelUploadTrackerFile
18 from gslib.copy_helper import _CreateParallelUploadTrackerFile
19 from gslib.copy_helper import _GetPartitionInfo
20 from gslib.copy_helper import _HashFilename
21 from gslib.copy_helper import _ParseParallelUploadTrackerFile
22 from gslib.copy_helper import FilterExistingComponents
23 from gslib.copy_helper import ObjectFromTracker
24 from gslib.copy_helper import PerformParallelUploadFileToObjectArgs
25 from gslib.hashing_helper import CalculateB64EncodedMd5FromContents
26 from gslib.storage_url import StorageUrlFromString
27 from gslib.tests.mock_cloud_api import MockCloudApi
28 from gslib.tests.testcase.unit_testcase import GsUtilUnitTestCase
29 from gslib.third_party.storage_apitools import storage_v1_messages as apitools_m essages
30 from gslib.util import CreateLock
31
32
33 class TestCpFuncs(GsUtilUnitTestCase):
34 """Unit tests for parallel upload functions in cp command."""
35
36 def test_HashFilename(self):
37 # Tests that _HashFilename function works for both string and unicode
38 # filenames (without raising any Unicode encode/decode errors).
39 _HashFilename('file1')
40 _HashFilename(u'file1')
41
42 def test_GetPartitionInfo(self):
43 """Tests the _GetPartitionInfo function."""
44 # Simplest case - threshold divides file_size.
45 (num_components, component_size) = _GetPartitionInfo(300, 200, 10)
46 self.assertEqual(30, num_components)
47 self.assertEqual(10, component_size)
48
49 # Threshold = 1 (mod file_size).
50 (num_components, component_size) = _GetPartitionInfo(301, 200, 10)
51 self.assertEqual(31, num_components)
52 self.assertEqual(10, component_size)
53
54 # Threshold = -1 (mod file_size).
55 (num_components, component_size) = _GetPartitionInfo(299, 200, 10)
56 self.assertEqual(30, num_components)
57 self.assertEqual(10, component_size)
58
59 # Too many components needed.
60 (num_components, component_size) = _GetPartitionInfo(301, 2, 10)
61 self.assertEqual(2, num_components)
62 self.assertEqual(151, component_size)
63
64 # Test num_components with huge numbers.
65 (num_components, component_size) = _GetPartitionInfo((10 ** 150) + 1,
66 10 ** 200,
67 10)
68 self.assertEqual((10 ** 149) + 1, num_components)
69 self.assertEqual(10, component_size)
70
71 # Test component_size with huge numbers.
72 (num_components, component_size) = _GetPartitionInfo((10 ** 150) + 1,
73 10,
74 10)
75 self.assertEqual(10, num_components)
76 self.assertEqual((10 ** 149) + 1, component_size)
77
78 # Test component_size > file_size (make sure we get at least two components.
79 (num_components, component_size) = _GetPartitionInfo(100, 500, 51)
80 self.assertEquals(2, num_components)
81 self.assertEqual(50, component_size)
82
83 def test_ParseParallelUploadTrackerFile(self):
84 """Tests the _ParseParallelUploadTrackerFile function."""
85 tracker_file_lock = CreateLock()
86 random_prefix = '123'
87 objects = ['obj1', '42', 'obj2', '314159']
88 contents = '\n'.join([random_prefix] + objects)
89 fpath = self.CreateTempFile(file_name='foo',
90 contents=contents)
91 expected_objects = [ObjectFromTracker(objects[2 * i], objects[2 * i + 1])
92 for i in range(0, len(objects) / 2)]
93 (actual_prefix, actual_objects) = _ParseParallelUploadTrackerFile(
94 fpath, tracker_file_lock)
95 self.assertEqual(random_prefix, actual_prefix)
96 self.assertEqual(expected_objects, actual_objects)
97
98 def test_CreateParallelUploadTrackerFile(self):
99 """Tests the _CreateParallelUploadTrackerFile function."""
100 tracker_file = self.CreateTempFile(file_name='foo', contents='asdf')
101 tracker_file_lock = CreateLock()
102 random_prefix = '123'
103 objects = ['obj1', '42', 'obj2', '314159']
104 expected_contents = [random_prefix] + objects
105 objects = [ObjectFromTracker(objects[2 * i], objects[2 * i + 1])
106 for i in range(0, len(objects) / 2)]
107 _CreateParallelUploadTrackerFile(tracker_file, random_prefix, objects,
108 tracker_file_lock)
109 with open(tracker_file, 'rb') as f:
110 lines = f.read().splitlines()
111 self.assertEqual(expected_contents, lines)
112
113 def test_AppendComponentTrackerToParallelUploadTrackerFile(self):
114 """Tests the _CreateParallelUploadTrackerFile function with append."""
115 tracker_file = self.CreateTempFile(file_name='foo', contents='asdf')
116 tracker_file_lock = CreateLock()
117 random_prefix = '123'
118 objects = ['obj1', '42', 'obj2', '314159']
119 expected_contents = [random_prefix] + objects
120 objects = [ObjectFromTracker(objects[2 * i], objects[2 * i + 1])
121 for i in range(0, len(objects) / 2)]
122 _CreateParallelUploadTrackerFile(tracker_file, random_prefix, objects,
123 tracker_file_lock)
124
125 new_object = ['obj2', '1234']
126 expected_contents += new_object
127 new_object = ObjectFromTracker(new_object[0], new_object[1])
128 _AppendComponentTrackerToParallelUploadTrackerFile(tracker_file, new_object,
129 tracker_file_lock)
130 with open(tracker_file, 'rb') as f:
131 lines = f.read().splitlines()
132 self.assertEqual(expected_contents, lines)
133
134 def test_FilterExistingComponentsNonVersioned(self):
135 """Tests upload with a variety of component states."""
136 mock_api = MockCloudApi()
137 bucket_name = self.MakeTempName('bucket')
138 tracker_file = self.CreateTempFile(file_name='foo', contents='asdf')
139 tracker_file_lock = CreateLock()
140
141 # dst_obj_metadata used for passing content-type.
142 empty_object = apitools_messages.Object()
143
144 # Already uploaded, contents still match, component still used.
145 fpath_uploaded_correctly = self.CreateTempFile(file_name='foo1',
146 contents='1')
147 fpath_uploaded_correctly_url = StorageUrlFromString(
148 str(fpath_uploaded_correctly))
149 object_uploaded_correctly_url = StorageUrlFromString('%s://%s/%s' % (
150 self.default_provider, bucket_name,
151 fpath_uploaded_correctly))
152 with open(fpath_uploaded_correctly) as f_in:
153 fpath_uploaded_correctly_md5 = CalculateB64EncodedMd5FromContents(f_in)
154 mock_api.MockCreateObjectWithMetadata(
155 apitools_messages.Object(bucket=bucket_name,
156 name=fpath_uploaded_correctly,
157 md5Hash=fpath_uploaded_correctly_md5),
158 contents='1')
159
160 args_uploaded_correctly = PerformParallelUploadFileToObjectArgs(
161 fpath_uploaded_correctly, 0, 1, fpath_uploaded_correctly_url,
162 object_uploaded_correctly_url, '', empty_object, tracker_file,
163 tracker_file_lock)
164
165 # Not yet uploaded, but needed.
166 fpath_not_uploaded = self.CreateTempFile(file_name='foo2', contents='2')
167 fpath_not_uploaded_url = StorageUrlFromString(str(fpath_not_uploaded))
168 object_not_uploaded_url = StorageUrlFromString('%s://%s/%s' % (
169 self.default_provider, bucket_name, fpath_not_uploaded))
170 args_not_uploaded = PerformParallelUploadFileToObjectArgs(
171 fpath_not_uploaded, 0, 1, fpath_not_uploaded_url,
172 object_not_uploaded_url, '', empty_object, tracker_file,
173 tracker_file_lock)
174
175 # Already uploaded, but contents no longer match. Even though the contents
176 # differ, we don't delete this since the bucket is not versioned and it
177 # will be overwritten anyway.
178 fpath_wrong_contents = self.CreateTempFile(file_name='foo4', contents='4')
179 fpath_wrong_contents_url = StorageUrlFromString(str(fpath_wrong_contents))
180 object_wrong_contents_url = StorageUrlFromString('%s://%s/%s' % (
181 self.default_provider, bucket_name, fpath_wrong_contents))
182 with open(self.CreateTempFile(contents='_')) as f_in:
183 fpath_wrong_contents_md5 = CalculateB64EncodedMd5FromContents(f_in)
184 mock_api.MockCreateObjectWithMetadata(
185 apitools_messages.Object(bucket=bucket_name,
186 name=fpath_wrong_contents,
187 md5Hash=fpath_wrong_contents_md5),
188 contents='1')
189
190 args_wrong_contents = PerformParallelUploadFileToObjectArgs(
191 fpath_wrong_contents, 0, 1, fpath_wrong_contents_url,
192 object_wrong_contents_url, '', empty_object, tracker_file,
193 tracker_file_lock)
194
195 # Exists in tracker file, but component object no longer exists.
196 fpath_remote_deleted = self.CreateTempFile(file_name='foo5', contents='5')
197 fpath_remote_deleted_url = StorageUrlFromString(
198 str(fpath_remote_deleted))
199 args_remote_deleted = PerformParallelUploadFileToObjectArgs(
200 fpath_remote_deleted, 0, 1, fpath_remote_deleted_url, '', '',
201 empty_object, tracker_file, tracker_file_lock)
202
203 # Exists in tracker file and already uploaded, but no longer needed.
204 fpath_no_longer_used = self.CreateTempFile(file_name='foo6', contents='6')
205 with open(fpath_no_longer_used) as f_in:
206 file_md5 = CalculateB64EncodedMd5FromContents(f_in)
207 mock_api.MockCreateObjectWithMetadata(
208 apitools_messages.Object(bucket=bucket_name,
209 name='foo6', md5Hash=file_md5), contents='6')
210
211 dst_args = {fpath_uploaded_correctly: args_uploaded_correctly,
212 fpath_not_uploaded: args_not_uploaded,
213 fpath_wrong_contents: args_wrong_contents,
214 fpath_remote_deleted: args_remote_deleted}
215
216 existing_components = [ObjectFromTracker(fpath_uploaded_correctly, ''),
217 ObjectFromTracker(fpath_wrong_contents, ''),
218 ObjectFromTracker(fpath_remote_deleted, ''),
219 ObjectFromTracker(fpath_no_longer_used, '')]
220
221 bucket_url = StorageUrlFromString('%s://%s' % (self.default_provider,
222 bucket_name))
223
224 (components_to_upload, uploaded_components, existing_objects_to_delete) = (
225 FilterExistingComponents(dst_args, existing_components,
226 bucket_url, mock_api))
227
228 for arg in [args_not_uploaded, args_wrong_contents, args_remote_deleted]:
229 self.assertTrue(arg in components_to_upload)
230 self.assertEqual(1, len(uploaded_components))
231 self.assertEqual(args_uploaded_correctly.dst_url.url_string,
232 uploaded_components[0].url_string)
233 self.assertEqual(1, len(existing_objects_to_delete))
234 no_longer_used_url = StorageUrlFromString('%s://%s/%s' % (
235 self.default_provider, bucket_name, fpath_no_longer_used))
236 self.assertEqual(no_longer_used_url.url_string,
237 existing_objects_to_delete[0].url_string)
238
239 def test_FilterExistingComponentsVersioned(self):
240 """Tests upload with versionined parallel components."""
241
242 mock_api = MockCloudApi()
243 bucket_name = self.MakeTempName('bucket')
244 mock_api.MockCreateVersionedBucket(bucket_name)
245
246 # dst_obj_metadata used for passing content-type.
247 empty_object = apitools_messages.Object()
248
249 tracker_file = self.CreateTempFile(file_name='foo', contents='asdf')
250 tracker_file_lock = CreateLock()
251
252 # Already uploaded, contents still match, component still used.
253 fpath_uploaded_correctly = self.CreateTempFile(file_name='foo1',
254 contents='1')
255 fpath_uploaded_correctly_url = StorageUrlFromString(
256 str(fpath_uploaded_correctly))
257 with open(fpath_uploaded_correctly) as f_in:
258 fpath_uploaded_correctly_md5 = CalculateB64EncodedMd5FromContents(f_in)
259 object_uploaded_correctly = mock_api.MockCreateObjectWithMetadata(
260 apitools_messages.Object(bucket=bucket_name,
261 name=fpath_uploaded_correctly,
262 md5Hash=fpath_uploaded_correctly_md5),
263 contents='1')
264 object_uploaded_correctly_url = StorageUrlFromString('%s://%s/%s#%s' % (
265 self.default_provider, bucket_name,
266 fpath_uploaded_correctly, object_uploaded_correctly.generation))
267 args_uploaded_correctly = PerformParallelUploadFileToObjectArgs(
268 fpath_uploaded_correctly, 0, 1, fpath_uploaded_correctly_url,
269 object_uploaded_correctly_url, object_uploaded_correctly.generation,
270 empty_object, tracker_file, tracker_file_lock)
271
272 # Duplicate object name in tracker file, but uploaded correctly.
273 fpath_duplicate = fpath_uploaded_correctly
274 fpath_duplicate_url = StorageUrlFromString(str(fpath_duplicate))
275 duplicate_uploaded_correctly = mock_api.MockCreateObjectWithMetadata(
276 apitools_messages.Object(bucket=bucket_name,
277 name=fpath_duplicate,
278 md5Hash=fpath_uploaded_correctly_md5),
279 contents='1')
280 duplicate_uploaded_correctly_url = StorageUrlFromString('%s://%s/%s#%s' % (
281 self.default_provider, bucket_name,
282 fpath_uploaded_correctly, duplicate_uploaded_correctly.generation))
283 args_duplicate = PerformParallelUploadFileToObjectArgs(
284 fpath_duplicate, 0, 1, fpath_duplicate_url,
285 duplicate_uploaded_correctly_url,
286 duplicate_uploaded_correctly.generation, empty_object, tracker_file,
287 tracker_file_lock)
288
289 # Already uploaded, but contents no longer match.
290 fpath_wrong_contents = self.CreateTempFile(file_name='foo4', contents='4')
291 fpath_wrong_contents_url = StorageUrlFromString(str(fpath_wrong_contents))
292 with open(self.CreateTempFile(contents='_')) as f_in:
293 fpath_wrong_contents_md5 = CalculateB64EncodedMd5FromContents(f_in)
294 object_wrong_contents = mock_api.MockCreateObjectWithMetadata(
295 apitools_messages.Object(bucket=bucket_name,
296 name=fpath_wrong_contents,
297 md5Hash=fpath_wrong_contents_md5),
298 contents='_')
299 wrong_contents_url = StorageUrlFromString('%s://%s/%s#%s' % (
300 self.default_provider, bucket_name,
301 fpath_wrong_contents, object_wrong_contents.generation))
302 args_wrong_contents = PerformParallelUploadFileToObjectArgs(
303 fpath_wrong_contents, 0, 1, fpath_wrong_contents_url,
304 wrong_contents_url, '', empty_object, tracker_file,
305 tracker_file_lock)
306
307 dst_args = {fpath_uploaded_correctly: args_uploaded_correctly,
308 fpath_wrong_contents: args_wrong_contents}
309
310 existing_components = [
311 ObjectFromTracker(fpath_uploaded_correctly,
312 object_uploaded_correctly_url.generation),
313 ObjectFromTracker(fpath_duplicate,
314 duplicate_uploaded_correctly_url.generation),
315 ObjectFromTracker(fpath_wrong_contents,
316 wrong_contents_url.generation)]
317
318 bucket_url = StorageUrlFromString('%s://%s' % (self.default_provider,
319 bucket_name))
320
321 (components_to_upload, uploaded_components, existing_objects_to_delete) = (
322 FilterExistingComponents(dst_args, existing_components,
323 bucket_url, mock_api))
324
325 self.assertEqual([args_wrong_contents], components_to_upload)
326 self.assertEqual(args_uploaded_correctly.dst_url.url_string,
327 uploaded_components[0].url_string)
328 expected_to_delete = [(args_wrong_contents.dst_url.object_name,
329 args_wrong_contents.dst_url.generation),
330 (args_duplicate.dst_url.object_name,
331 args_duplicate.dst_url.generation)]
332 for uri in existing_objects_to_delete:
333 self.assertTrue((uri.object_name, uri.generation) in expected_to_delete)
334 self.assertEqual(len(expected_to_delete), len(existing_objects_to_delete))
335
OLDNEW
« no previous file with comments | « gslib/tests/test_compose.py ('k') | gslib/tests/test_cors.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698