Skip to content

Commit

Permalink
Implement unit_test config to disable syslog.
Browse files Browse the repository at this point in the history
bug 701248
bug 819303

This change makes syslog optional, by providing a unit test
config with the ability to cause test/unit/__init__.py to
replace SysLogHandler with a fake logging class. The
default behavior is unchanged.

FakeLogger now inherits directly from Handler and mocks out
its API - this was a backward-compatibility issue.

Change-Id: I653dec148c4f6cf81759de03964c6a3290c1a290
  • Loading branch information
Dan Dillinger committed May 3, 2012
1 parent e22ee45 commit f7fdb9c
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 16 deletions.
9 changes: 7 additions & 2 deletions doc/source/development_saio.rst
Expand Up @@ -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`
Expand Down Expand Up @@ -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: <token-from-x-auth-token-above>' <url-from-x-storage-url-above>``
#. 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
Expand Down Expand Up @@ -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.
31 changes: 22 additions & 9 deletions test/__init__.py
Expand Up @@ -18,19 +18,32 @@
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
2 changes: 1 addition & 1 deletion test/functional/tests.py
Expand Up @@ -26,7 +26,7 @@
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'))

Expand Down
2 changes: 1 addition & 1 deletion test/functionalnosetests/swift_testing.py
Expand Up @@ -11,7 +11,7 @@

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')
Expand Down
3 changes: 3 additions & 0 deletions test/functional/sample.conf → test/sample.conf
Expand Up @@ -20,3 +20,6 @@ username3 = tester3
password3 = testing3

collate = C

[unit_test]
fake_syslog = False
70 changes: 67 additions & 3 deletions 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):
Expand Down Expand Up @@ -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))
Expand All @@ -109,12 +120,61 @@ def warning(self, *args, **kwargs):
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
Expand All @@ -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

0 comments on commit f7fdb9c

Please sign in to comment.