OLD | NEW |
(Empty) | |
| 1 # Copyright 2011 Google Inc. All Rights Reserved. |
| 2 # |
| 3 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 # you may not use this file except in compliance with the License. |
| 5 # You may obtain a copy of the License at |
| 6 # |
| 7 # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 # |
| 9 # Unless required by applicable law or agreed to in writing, software |
| 10 # distributed under the License is distributed on an "AS IS" BASIS, |
| 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 # See the License for the specific language governing permissions and |
| 13 # limitations under the License. |
| 14 |
| 15 import logging |
| 16 import os.path |
| 17 import re |
| 18 |
| 19 from gslib.command import Command |
| 20 from gslib.command import COMMAND_NAME |
| 21 from gslib.command import COMMAND_NAME_ALIASES |
| 22 from gslib.command import CONFIG_REQUIRED |
| 23 from gslib.command import FILE_URIS_OK |
| 24 from gslib.command import MAX_ARGS |
| 25 from gslib.command import MIN_ARGS |
| 26 from gslib.command import PROVIDER_URIS_OK |
| 27 from gslib.command import SUPPORTED_SUB_ARGS |
| 28 from gslib.command import URIS_START_ARG |
| 29 from gslib.exception import CommandException |
| 30 from gslib.help_provider import HELP_NAME |
| 31 from gslib.help_provider import HELP_NAME_ALIASES |
| 32 from gslib.help_provider import HELP_ONE_LINE_SUMMARY |
| 33 from gslib.help_provider import HELP_TEXT |
| 34 from gslib.help_provider import HELP_TYPE |
| 35 from gslib.help_provider import HelpType |
| 36 import gslib.tests as tests |
| 37 from gslib.util import NO_MAX |
| 38 |
| 39 |
| 40 # For Python 2.6, unittest2 is required to run the tests. If it's not available, |
| 41 # display an error if the test command is run instead of breaking the whole |
| 42 # program. |
| 43 try: |
| 44 from gslib.tests.util import unittest |
| 45 except ImportError as e: |
| 46 if 'unittest2' in str(e): |
| 47 unittest = None |
| 48 else: |
| 49 raise |
| 50 |
| 51 |
| 52 COMMANDS_DIR = os.path.abspath(os.path.dirname(__file__)) |
| 53 GSLIB_DIR = os.path.split(COMMANDS_DIR)[0] |
| 54 TESTS_DIR = os.path.join(GSLIB_DIR, 'tests') |
| 55 |
| 56 |
| 57 _detailed_help_text = (""" |
| 58 <B>SYNOPSIS</B> |
| 59 gsutil test [command command...] |
| 60 |
| 61 |
| 62 <B>DESCRIPTION</B> |
| 63 The gsutil test command runs the gsutil unit tests and integration tests. |
| 64 The unit tests use an in-memory mock storage service implementation, while |
| 65 the integration tests send requests to the production service. |
| 66 |
| 67 To run both the unit tests and integration tests, run the command with no |
| 68 arguments: |
| 69 |
| 70 gsutil test |
| 71 |
| 72 To run the unit tests only (which run quickly): |
| 73 |
| 74 gsutil test -u |
| 75 |
| 76 To see additional details for test failures: |
| 77 |
| 78 gsutil -d test |
| 79 |
| 80 To have the tests stop running immediately when an error occurs: |
| 81 |
| 82 gsutil test -f |
| 83 |
| 84 To run tests for one or more individual commands add those commands as |
| 85 arguments. For example, the following command will run the cp and mv command |
| 86 tests: |
| 87 |
| 88 gsutil test cp mv |
| 89 |
| 90 To list available tests, run the test command with the -l argument: |
| 91 |
| 92 gsutil test -l |
| 93 |
| 94 Note: the tests are defined in the code under the gslib/tests module. Each |
| 95 test file is of the format test_[name].py where [name] is the test name you |
| 96 can pass to this command. For example, running "gsutil test ls" would run the |
| 97 tests in "gslib/tests/test_ls.py". |
| 98 """) |
| 99 |
| 100 |
| 101 def MakeCustomTestResultClass(total_tests): |
| 102 """Creates a closure of CustomTestResult. |
| 103 |
| 104 Args: |
| 105 total_tests: The total number of tests being run. |
| 106 |
| 107 Returns: |
| 108 An instance of CustomTestResult. |
| 109 """ |
| 110 |
| 111 class CustomTestResult(unittest.TextTestResult): |
| 112 """A subclass of unittest.TextTestResult that prints a progress report.""" |
| 113 |
| 114 def startTest(self, test): |
| 115 super(CustomTestResult, self).startTest(test) |
| 116 if self.dots: |
| 117 id = '.'.join(test.id().split('.')[-2:]) |
| 118 message = ('\r%d/%d finished - E[%d] F[%d] s[%d] - %s' % ( |
| 119 self.testsRun, total_tests, len(self.errors), |
| 120 len(self.failures), len(self.skipped), id)) |
| 121 message = message[:73] |
| 122 message = message.ljust(73) |
| 123 self.stream.write('%s - ' % message) |
| 124 |
| 125 return CustomTestResult |
| 126 |
| 127 |
| 128 class TestCommand(Command): |
| 129 """Implementation of gsutil test command.""" |
| 130 |
| 131 # Command specification (processed by parent class). |
| 132 command_spec = { |
| 133 # Name of command. |
| 134 COMMAND_NAME: 'test', |
| 135 # List of command name aliases. |
| 136 COMMAND_NAME_ALIASES: [], |
| 137 # Min number of args required by this command. |
| 138 MIN_ARGS: 0, |
| 139 # Max number of args required by this command, or NO_MAX. |
| 140 MAX_ARGS: NO_MAX, |
| 141 # Getopt-style string specifying acceptable sub args. |
| 142 SUPPORTED_SUB_ARGS: 'ufl', |
| 143 # True if file URIs acceptable for this command. |
| 144 FILE_URIS_OK: True, |
| 145 # True if provider-only URIs acceptable for this command. |
| 146 PROVIDER_URIS_OK: False, |
| 147 # Index in args of first URI arg. |
| 148 URIS_START_ARG: 0, |
| 149 # True if must configure gsutil before running command. |
| 150 CONFIG_REQUIRED: True, |
| 151 } |
| 152 help_spec = { |
| 153 # Name of command or auxiliary help info for which this help applies. |
| 154 HELP_NAME: 'test', |
| 155 # List of help name aliases. |
| 156 HELP_NAME_ALIASES: [], |
| 157 # Type of help: |
| 158 HELP_TYPE: HelpType.COMMAND_HELP, |
| 159 # One line summary of this help. |
| 160 HELP_ONE_LINE_SUMMARY: 'Run gsutil tests', |
| 161 # The full help text. |
| 162 HELP_TEXT: _detailed_help_text, |
| 163 } |
| 164 |
| 165 # Command entry point. |
| 166 def RunCommand(self): |
| 167 if not unittest: |
| 168 raise CommandException('On Python 2.6, the unittest2 module is required ' |
| 169 'to run the gsutil tests.') |
| 170 |
| 171 failfast = False |
| 172 list_tests = False |
| 173 if self.sub_opts: |
| 174 for o, _ in self.sub_opts: |
| 175 if o == '-u': |
| 176 tests.util.RUN_INTEGRATION_TESTS = False |
| 177 elif o == '-f': |
| 178 failfast = True |
| 179 elif o == '-l': |
| 180 list_tests = True |
| 181 |
| 182 if list_tests: |
| 183 test_files = os.listdir(TESTS_DIR) |
| 184 matcher = re.compile(r'^test_(?P<name>.*).py$') |
| 185 test_names = [] |
| 186 for fname in test_files: |
| 187 m = matcher.match(fname) |
| 188 if m: |
| 189 test_names.append(m.group('name')) |
| 190 print 'Found %d test names:' % len(test_names) |
| 191 print ' ', '\n '.join(sorted(test_names)) |
| 192 return 0 |
| 193 |
| 194 # Set list of commands to test if supplied. |
| 195 commands_to_test = [] |
| 196 if self.args: |
| 197 for name in self.args: |
| 198 test_file = os.path.join(TESTS_DIR, 'test_%s.py' % name) |
| 199 if not os.path.exists(test_file): |
| 200 raise CommandException('The requested test, "%s", was not found at ' |
| 201 '"%s".' % (name, test_file)) |
| 202 commands_to_test.append('gslib.tests.test_%s' % name) |
| 203 |
| 204 # Installs a ctrl-c handler that tries to cleanly tear down tests. |
| 205 unittest.installHandler() |
| 206 |
| 207 loader = unittest.TestLoader() |
| 208 |
| 209 if commands_to_test: |
| 210 suite = loader.loadTestsFromNames(commands_to_test) |
| 211 else: |
| 212 suite = loader.discover(TESTS_DIR) |
| 213 |
| 214 if logging.getLogger().getEffectiveLevel() <= logging.INFO: |
| 215 verbosity = 2 |
| 216 else: |
| 217 verbosity = 1 |
| 218 logging.disable(logging.ERROR) |
| 219 |
| 220 total_tests = suite.countTestCases() |
| 221 resultclass = MakeCustomTestResultClass(total_tests) |
| 222 |
| 223 runner = unittest.TextTestRunner(verbosity=verbosity, |
| 224 resultclass=resultclass, failfast=failfast) |
| 225 ret = runner.run(suite) |
| 226 if ret.wasSuccessful(): |
| 227 return 0 |
| 228 return 1 |
OLD | NEW |