Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / tools / telemetry / third_party / gsutilz / gslib / tests / testcase / unit_testcase.py
blobe36bd285c714aaf5bd29da7b19116a8a7db60733
1 # -*- coding: utf-8 -*-
2 # Copyright 2013 Google Inc. All Rights Reserved.
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
8 # http://www.apache.org/licenses/LICENSE-2.0
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 """Contains gsutil base unit test case class."""
17 from __future__ import absolute_import
19 import logging
20 import os
21 import sys
22 import tempfile
24 import boto
25 from gslib import wildcard_iterator
26 from gslib.boto_translation import BotoTranslation
27 from gslib.cloud_api_delegator import CloudApiDelegator
28 from gslib.command_runner import CommandRunner
29 from gslib.cs_api_map import ApiMapConstants
30 from gslib.cs_api_map import ApiSelector
31 from gslib.tests.mock_logging_handler import MockLoggingHandler
32 from gslib.tests.testcase import base
33 import gslib.tests.util as util
34 from gslib.tests.util import unittest
35 from gslib.tests.util import WorkingDirectory
36 from gslib.util import GsutilStreamHandler
39 class GsutilApiUnitTestClassMapFactory(object):
40 """Class map factory for use in unit tests.
42 BotoTranslation is used for all cases so that GSMockBucketStorageUri can
43 be used to communicate with the mock XML service.
44 """
46 @classmethod
47 def GetClassMap(cls):
48 """Returns a class map for use in unit tests."""
49 gs_class_map = {
50 ApiSelector.XML: BotoTranslation,
51 ApiSelector.JSON: BotoTranslation
53 s3_class_map = {
54 ApiSelector.XML: BotoTranslation
56 class_map = {
57 'gs': gs_class_map,
58 's3': s3_class_map
60 return class_map
63 @unittest.skipUnless(util.RUN_UNIT_TESTS,
64 'Not running integration tests.')
65 class GsUtilUnitTestCase(base.GsUtilTestCase):
66 """Base class for gsutil unit tests."""
68 @classmethod
69 def setUpClass(cls):
70 base.GsUtilTestCase.setUpClass()
71 cls.mock_bucket_storage_uri = util.GSMockBucketStorageUri
72 cls.mock_gsutil_api_class_map_factory = GsutilApiUnitTestClassMapFactory
73 cls.logger = logging.getLogger()
74 cls.command_runner = CommandRunner(
75 bucket_storage_uri_class=cls.mock_bucket_storage_uri,
76 gsutil_api_class_map_factory=cls.mock_gsutil_api_class_map_factory)
78 def setUp(self):
79 super(GsUtilUnitTestCase, self).setUp()
80 self.bucket_uris = []
81 self.stdout_save = sys.stdout
82 self.stderr_save = sys.stderr
83 fd, self.stdout_file = tempfile.mkstemp()
84 sys.stdout = os.fdopen(fd, 'w+')
85 fd, self.stderr_file = tempfile.mkstemp()
86 sys.stderr = os.fdopen(fd, 'w+')
87 self.accumulated_stdout = []
88 self.accumulated_stderr = []
90 self.root_logger = logging.getLogger()
91 self.is_debugging = self.root_logger.isEnabledFor(logging.DEBUG)
92 self.log_handlers_save = self.root_logger.handlers
93 fd, self.log_handler_file = tempfile.mkstemp()
94 self.log_handler_stream = os.fdopen(fd, 'w+')
95 self.temp_log_handler = GsutilStreamHandler(self.log_handler_stream)
96 self.root_logger.handlers = [self.temp_log_handler]
98 def tearDown(self):
99 super(GsUtilUnitTestCase, self).tearDown()
101 self.root_logger.handlers = self.log_handlers_save
102 self.temp_log_handler.flush()
103 self.temp_log_handler.close()
104 self.log_handler_stream.seek(0)
105 log_output = self.log_handler_stream.read()
106 self.log_handler_stream.close()
107 os.unlink(self.log_handler_file)
109 sys.stdout.seek(0)
110 sys.stderr.seek(0)
111 stdout = sys.stdout.read()
112 stderr = sys.stderr.read()
113 stdout += ''.join(self.accumulated_stdout)
114 stderr += ''.join(self.accumulated_stderr)
115 sys.stdout.close()
116 sys.stderr.close()
117 sys.stdout = self.stdout_save
118 sys.stderr = self.stderr_save
119 os.unlink(self.stdout_file)
120 os.unlink(self.stderr_file)
122 if self.is_debugging and stdout:
123 sys.stderr.write('==== stdout %s ====\n' % self.id())
124 sys.stderr.write(stdout)
125 sys.stderr.write('==== end stdout ====\n')
126 if self.is_debugging and stderr:
127 sys.stderr.write('==== stderr %s ====\n' % self.id())
128 sys.stderr.write(stderr)
129 sys.stderr.write('==== end stderr ====\n')
130 if self.is_debugging and log_output:
131 sys.stderr.write('==== log output %s ====\n' % self.id())
132 sys.stderr.write(log_output)
133 sys.stderr.write('==== end log output ====\n')
135 def RunCommand(self, command_name, args=None, headers=None, debug=0,
136 test_method=None, return_stdout=False, return_stderr=False,
137 return_log_handler=False, cwd=None):
138 """Method for calling gslib.command_runner.CommandRunner.
140 Passes parallel_operations=False for all tests, optionally saving/returning
141 stdout output. We run all tests multi-threaded, to exercise those more
142 complicated code paths.
143 TODO: Change to run with parallel_operations=True for all tests. At
144 present when you do this it causes many test failures.
146 Args:
147 command_name: The name of the command being run.
148 args: Command-line args (arg0 = actual arg, not command name ala bash).
149 headers: Dictionary containing optional HTTP headers to pass to boto.
150 debug: Debug level to pass in to boto connection (range 0..3).
151 test_method: Optional general purpose method for testing purposes.
152 Application and semantics of this method will vary by
153 command and test type.
154 return_stdout: If True, will save and return stdout produced by command.
155 return_stderr: If True, will save and return stderr produced by command.
156 return_log_handler: If True, will return a MockLoggingHandler instance
157 that was attached to the command's logger while running.
158 cwd: The working directory that should be switched to before running the
159 command. The working directory will be reset back to its original
160 value after running the command. If not specified, the working
161 directory is left unchanged.
163 Returns:
164 One or a tuple of requested return values, depending on whether
165 return_stdout, return_stderr, and/or return_log_handler were specified.
167 args = args or []
169 command_line = ' '.join([command_name] + args)
170 if self.is_debugging:
171 self.stderr_save.write('\nRunCommand of %s\n' % command_line)
173 # Save and truncate stdout and stderr for the lifetime of RunCommand. This
174 # way, we can return just the stdout and stderr that was output during the
175 # RunNamedCommand call below.
176 sys.stdout.seek(0)
177 sys.stderr.seek(0)
178 stdout = sys.stdout.read()
179 stderr = sys.stderr.read()
180 if stdout:
181 self.accumulated_stdout.append(stdout)
182 if stderr:
183 self.accumulated_stderr.append(stderr)
184 sys.stdout.seek(0)
185 sys.stderr.seek(0)
186 sys.stdout.truncate()
187 sys.stderr.truncate()
189 mock_log_handler = MockLoggingHandler()
190 logging.getLogger(command_name).addHandler(mock_log_handler)
192 try:
193 with WorkingDirectory(cwd):
194 self.command_runner.RunNamedCommand(
195 command_name, args=args, headers=headers, debug=debug,
196 parallel_operations=False, test_method=test_method,
197 do_shutdown=False)
198 finally:
199 sys.stdout.seek(0)
200 stdout = sys.stdout.read()
201 sys.stderr.seek(0)
202 stderr = sys.stderr.read()
203 logging.getLogger(command_name).removeHandler(mock_log_handler)
204 mock_log_handler.close()
206 log_output = '\n'.join(
207 '%s:\n ' % level + '\n '.join(records)
208 for level, records in mock_log_handler.messages.iteritems()
209 if records)
210 if self.is_debugging and log_output:
211 self.stderr_save.write(
212 '==== logging RunCommand %s %s ====\n' % (self.id(), command_line))
213 self.stderr_save.write(log_output)
214 self.stderr_save.write('\n==== end logging ====\n')
215 if self.is_debugging and stdout:
216 self.stderr_save.write(
217 '==== stdout RunCommand %s %s ====\n' % (self.id(), command_line))
218 self.stderr_save.write(stdout)
219 self.stderr_save.write('==== end stdout ====\n')
220 if self.is_debugging and stderr:
221 self.stderr_save.write(
222 '==== stderr RunCommand %s %s ====\n' % (self.id(), command_line))
223 self.stderr_save.write(stderr)
224 self.stderr_save.write('==== end stderr ====\n')
226 # Reset stdout and stderr files, so that we won't print them out again
227 # in tearDown if debugging is enabled.
228 sys.stdout.seek(0)
229 sys.stderr.seek(0)
230 sys.stdout.truncate()
231 sys.stderr.truncate()
233 to_return = []
234 if return_stdout:
235 to_return.append(stdout)
236 if return_stderr:
237 to_return.append(stderr)
238 if return_log_handler:
239 to_return.append(mock_log_handler)
240 if len(to_return) == 1:
241 return to_return[0]
242 return tuple(to_return)
244 @classmethod
245 def MakeGsUtilApi(cls, debug=0):
246 gsutil_api_map = {
247 ApiMapConstants.API_MAP: (
248 cls.mock_gsutil_api_class_map_factory.GetClassMap()),
249 ApiMapConstants.SUPPORT_MAP: {
250 'gs': [ApiSelector.XML, ApiSelector.JSON],
251 's3': [ApiSelector.XML]
253 ApiMapConstants.DEFAULT_MAP: {
254 'gs': ApiSelector.JSON,
255 's3': ApiSelector.XML
259 return CloudApiDelegator(
260 cls.mock_bucket_storage_uri, gsutil_api_map, cls.logger, debug=debug)
262 @classmethod
263 def _test_wildcard_iterator(cls, uri_or_str, debug=0):
264 """Convenience method for instantiating a test instance of WildcardIterator.
266 This makes it unnecessary to specify all the params of that class
267 (like bucket_storage_uri_class=mock_storage_service.MockBucketStorageUri).
268 Also, naming the factory method this way makes it clearer in the test code
269 that WildcardIterator needs to be set up for testing.
271 Args are same as for wildcard_iterator.wildcard_iterator(), except
272 there are no class args for bucket_storage_uri_class or gsutil_api_class.
274 Args:
275 uri_or_str: StorageUri or string representing the wildcard string.
276 debug: debug level to pass to the underlying connection (0..3)
278 Returns:
279 WildcardIterator, over which caller can iterate.
281 # TODO: Remove when tests no longer pass StorageUri arguments.
282 uri_string = uri_or_str
283 if hasattr(uri_or_str, 'uri'):
284 uri_string = uri_or_str.uri
286 return wildcard_iterator.CreateWildcardIterator(
287 uri_string, cls.MakeGsUtilApi())
289 @staticmethod
290 def _test_storage_uri(uri_str, default_scheme='file', debug=0,
291 validate=True):
292 """Convenience method for instantiating a testing instance of StorageUri.
294 This makes it unnecessary to specify
295 bucket_storage_uri_class=mock_storage_service.MockBucketStorageUri.
296 Also naming the factory method this way makes it clearer in the test
297 code that StorageUri needs to be set up for testing.
299 Args, Returns, and Raises are same as for boto.storage_uri(), except there's
300 no bucket_storage_uri_class arg.
302 Args:
303 uri_str: Uri string to create StorageUri for.
304 default_scheme: Default scheme for the StorageUri
305 debug: debug level to pass to the underlying connection (0..3)
306 validate: If True, validate the resource that the StorageUri refers to.
308 Returns:
309 StorageUri based on the arguments.
311 return boto.storage_uri(uri_str, default_scheme, debug, validate,
312 util.GSMockBucketStorageUri)
314 def CreateBucket(self, bucket_name=None, test_objects=0, storage_class=None,
315 provider='gs'):
316 """Creates a test bucket.
318 The bucket and all of its contents will be deleted after the test.
320 Args:
321 bucket_name: Create the bucket with this name. If not provided, a
322 temporary test bucket name is constructed.
323 test_objects: The number of objects that should be placed in the bucket or
324 a list of object names to place in the bucket. Defaults to
326 storage_class: storage class to use. If not provided we us standard.
327 provider: string provider to use, default gs.
329 Returns:
330 StorageUri for the created bucket.
332 bucket_name = bucket_name or self.MakeTempName('bucket')
333 bucket_uri = boto.storage_uri(
334 '%s://%s' % (provider, bucket_name.lower()),
335 suppress_consec_slashes=False,
336 bucket_storage_uri_class=util.GSMockBucketStorageUri)
337 bucket_uri.create_bucket(storage_class=storage_class)
338 self.bucket_uris.append(bucket_uri)
339 try:
340 iter(test_objects)
341 except TypeError:
342 test_objects = [self.MakeTempName('obj') for _ in range(test_objects)]
343 for i, name in enumerate(test_objects):
344 self.CreateObject(bucket_uri=bucket_uri, object_name=name,
345 contents='test %d' % i)
346 return bucket_uri
348 def CreateObject(self, bucket_uri=None, object_name=None, contents=None):
349 """Creates a test object.
351 Args:
352 bucket_uri: The URI of the bucket to place the object in. If not
353 specified, a new temporary bucket is created.
354 object_name: The name to use for the object. If not specified, a temporary
355 test object name is constructed.
356 contents: The contents to write to the object. If not specified, the key
357 is not written to, which means that it isn't actually created
358 yet on the server.
360 Returns:
361 A StorageUri for the created object.
363 bucket_uri = bucket_uri or self.CreateBucket()
364 object_name = object_name or self.MakeTempName('obj')
365 key_uri = bucket_uri.clone_replace_name(object_name)
366 if contents is not None:
367 key_uri.set_contents_from_string(contents)
368 return key_uri