diff --git a/doc/source/development_saio.rst b/doc/source/development_saio.rst index 10d05a83f7..ed9472b70c 100644 --- a/doc/source/development_saio.rst +++ b/doc/source/development_saio.rst @@ -268,7 +268,7 @@ Do these commands as you on guest. `cd ~/swift; sudo python setup.py develop` #. Edit `~/.bashrc` and add to the end:: - export SWIFT_TEST_CONFIG_FILE=/etc/swift/func_test.conf + export SWIFT_TEST_CONFIG_FILE=/etc/swift/test.conf export PATH=${PATH}:~/bin #. `. ~/.bashrc` @@ -658,7 +658,7 @@ Setting up scripts for running Swift #. Get an `X-Storage-Url` and `X-Auth-Token`: ``curl -v -H 'X-Storage-User: test:tester' -H 'X-Storage-Pass: testing' http://127.0.0.1:8080/auth/v1.0`` #. Check that you can GET account: ``curl -v -H 'X-Auth-Token: ' `` #. Check that `swift` works: `swift -A http://127.0.0.1:8080/auth/v1.0 -U test:tester -K testing stat` - #. `cp ~/swift/test/functional/sample.conf /etc/swift/func_test.conf` + #. `cp ~/swift/test/sample.conf /etc/swift/test.conf` #. `cd ~/swift; ./.functests` (Note: functional tests will first delete everything in the configured accounts.) #. `cd ~/swift; ./.probetests` (Note: probe tests will reset your @@ -691,3 +691,8 @@ If all doesn't go as planned, and tests fail, or you can't auth, or something do `swift-object-server /etc/swift/object-server/1.conf` will start the object server. If there are problems not showing up in syslog, then you will likely see the traceback on startup. +#. If you need to, you can turn off syslog for unit tests. This can be + useful for environments where /dev/log is unavailable, or which + cannot rate limit (unit tests generate a lot of logs very quickly). + Open the file SWIFT_TEST_CONFIG_FILE points to, and change the + value of fake_syslog to True. diff --git a/test/__init__.py b/test/__init__.py index ef2ce31744..50b24ed1a9 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -18,19 +18,32 @@ import logging logging.raiseExceptions = False -def get_config(): +def get_config(section_name=None, defaults=None): """ - Attempt to get a functional config dictionary. + Attempt to get a test config dictionary. + + :param section_name: the section to read (all sections if not defined) + :param defaults: an optional dictionary namespace of defaults """ config_file = os.environ.get('SWIFT_TEST_CONFIG_FILE', - '/etc/swift/func_test.conf') + '/etc/swift/test.conf') config = {} + if defaults is not None: + config.update(defaults) + try: - try: - config = readconf(config_file, 'func_test') - except MissingSectionHeaderError: - config_fp = StringIO('[func_test]\n' + open(config_file).read()) - config = readconf(config_fp, 'func_test') + config = readconf(config_file, section_name) except SystemExit: - print >>sys.stderr, 'UNABLE TO READ FUNCTIONAL TESTS CONFIG FILE' + if not os.path.exists(config_file): + print >>sys.stderr, \ + 'Unable to read test config %s - file not found' \ + % config_file + elif not os.access(config_file, os.R_OK): + print >>sys.stderr, \ + 'Unable to read test config %s - permission denied' \ + % config_file + else: + print >>sys.stderr, \ + 'Unable to read test config %s - section %s not found' \ + % (config_file, section_name) return config diff --git a/test/functional/tests.py b/test/functional/tests.py index 91173f376d..27aaf7c1aa 100644 --- a/test/functional/tests.py +++ b/test/functional/tests.py @@ -26,7 +26,7 @@ import unittest from test import get_config from test.functional.swift import Account, Connection, File, ResponseError -config = get_config() +config = get_config('func_test') locale.setlocale(locale.LC_COLLATE, config.get('collate', 'C')) diff --git a/test/functionalnosetests/swift_testing.py b/test/functionalnosetests/swift_testing.py index 31df205efd..be80e1f0e7 100644 --- a/test/functionalnosetests/swift_testing.py +++ b/test/functionalnosetests/swift_testing.py @@ -11,7 +11,7 @@ from test import get_config from swift.common.client import get_auth, http_connection -conf = get_config() +conf = get_config('func_test') # If no conf was read, we will fall back to old school env vars swift_test_auth = os.environ.get('SWIFT_TEST_AUTH') diff --git a/test/functional/sample.conf b/test/sample.conf similarity index 93% rename from test/functional/sample.conf rename to test/sample.conf index 00009c6db0..7594c02213 100644 --- a/test/functional/sample.conf +++ b/test/sample.conf @@ -20,3 +20,6 @@ username3 = tester3 password3 = testing3 collate = C + +[unit_test] +fake_syslog = False diff --git a/test/unit/__init__.py b/test/unit/__init__.py index 345931285f..a75b37ba15 100644 --- a/test/unit/__init__.py +++ b/test/unit/__init__.py @@ -1,11 +1,19 @@ """ Swift tests """ +import sys import os +import copy from contextlib import contextmanager from tempfile import NamedTemporaryFile from eventlet.green import socket from tempfile import mkdtemp from shutil import rmtree +from test import get_config +from ConfigParser import MissingSectionHeaderError +from StringIO import StringIO +from swift.common.utils import readconf, TRUE_VALUES +from logging import Handler +import logging.handlers def readuntil2crlfs(fd): @@ -91,11 +99,14 @@ def temptree(files, contents=''): rmtree(tempdir) -class FakeLogger(object): +class FakeLogger(Handler): # a thread safe logger def __init__(self, *args, **kwargs): self.log_dict = dict(error=[], info=[], warning=[], debug=[]) + self.level = logging.NOTSET + if 'facility' in kwargs: + self.facility = kwargs['facility'] def error(self, *args, **kwargs): self.log_dict['error'].append((args, kwargs)) @@ -109,12 +120,61 @@ class FakeLogger(object): def debug(self, *args, **kwargs): self.log_dict['debug'].append((args, kwargs)) + def setFormatter(self, obj): + self.formatter = obj + + def close(self): + self.log_dict = dict(error=[], info=[], warning=[], debug=[]) + + def set_name(self, name): + # don't touch _handlers + self._name = name + + def acquire(self): + pass + + def release(self): + pass + + def createLock(self): + pass + + def emit(self, record): + pass + + def handle(self, record): + pass + + def flush(self): + pass + + def handleError(self, record): + pass + +original_syslog_handler = logging.handlers.SysLogHandler + + +def fake_syslog_handler(): + for attr in dir(original_syslog_handler): + if attr.startswith('LOG'): + setattr(FakeLogger, attr, + copy.copy(getattr(logging.handlers.SysLogHandler, attr))) + FakeLogger.priority_map = \ + copy.deepcopy(logging.handlers.SysLogHandler.priority_map) + + logging.handlers.SysLogHandler = FakeLogger + + +if get_config('unit_test').get('fake_syslog', 'False').lower() in TRUE_VALUES: + fake_syslog_handler() + class MockTrue(object): """ Instances of MockTrue evaluate like True - Any attr accessed on an instance of MockTrue will return a MockTrue instance - Any method called on an instance of MockTrue will return a MockTrue instance + Any attr accessed on an instance of MockTrue will return a MockTrue + instance. Any method called on an instance of MockTrue will return + a MockTrue instance. >>> thing = MockTrue() >>> thing @@ -140,11 +200,15 @@ class MockTrue(object): def __getattribute__(self, *args, **kwargs): return self + def __call__(self, *args, **kwargs): return self + def __repr__(*args, **kwargs): return repr(True) + def __eq__(self, other): return other is True + def __ne__(self, other): return other is not True