Commit a376b8e2 authored by U. Artie Eoff's avatar U. Artie Eoff Committed by Ian Romanick
Browse files

Added a simple logging class. Updated Test::doRun to use the new log.



Added log.py which includes a simple Logger class that wraps some
basic functions from the Python logging module. The log wrapper
simplifies setup and will accommodate thread synchronization in the
future.  Test::doRun now uses the new log facility.
NOTE: this changes the format of the 'test progress' previously
printed via stdout.

Added patterns.py which includes a Singleton class design pattern
to support the Logger class.  Future design patterns can be added
to this file.

Tested with Python 2.7 on Linux.  All should be compatible with
Windows and Mac and most earlier widely-used versions of Python.
Signed-off-by: default avatarIan Romanick <ian.d.romanick@intel.com>
Reviewed-by: default avatarChad Versace <chad.versace@intel.com>
parent 203e3f89
......@@ -31,6 +31,7 @@ import subprocess
import sys
import time
import traceback
from log import log
from cStringIO import StringIO
__all__ = [
......@@ -304,10 +305,14 @@ class Test:
if len(env.exclude_filter) > 0:
if True in map(lambda f: f.search(path) != None, env.exclude_filter):
return None
def status(msg):
log(msg = msg, channel = path)
# Run the test
if env.execute:
try:
print "Test: %(path)s" % locals()
status("running")
time_start = time.time()
result = self.run()
time_end = time.time()
......@@ -325,8 +330,7 @@ class Test:
result['exception'] = str(sys.exc_info()[0]) + str(sys.exc_info()[1])
result['traceback'] = '@@@' + "".join(traceback.format_tb(sys.exc_info()[2]))
if result['result'] != 'pass':
print " result: %(result)s" % { 'result': result['result'] }
status(result['result'])
result.write(env.file, path)
if Test.sleep:
......
#
# Copyright (c) 2010 Intel Corporation
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
from patterns import Singleton
import logging
class Logger(Singleton):
def __logMessage(self, logfunc, message, **kwargs):
[logfunc(line, **kwargs) for line in message.split('\n')]
def getLogger(self, channel = None):
if 0 == len(logging.root.handlers):
logging.basicConfig(
format = "[%(asctime)s] :: %(message)+8s :: %(name)s",
datefmt = "%c",
level = logging.INFO,
)
if channel is None:
channel = "base"
logger = logging.getLogger(channel)
return logger
def log(self, type = logging.INFO, msg = "", channel = None):
self.__logMessage(lambda m, **kwargs: self.getLogger(channel).log(type, m, **kwargs), msg)
log = Logger().log
#
# Copyright (c) 2010 Intel Corporation
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
import threading
class Singleton(object):
'''
Modeled after http://www.python.org/download/releases/2.2.3/descrintro/*__new__
A thread-safe (mostly -- see NOTE) Singleton class pattern.
NOTE: deleting a singleton instance (i.e. Singleton::delInstance) does not guarantee that something
else is currently using it. To reduce this risk, a program should not hold a reference to the
instance. Rather, use the create/construct syntax (see example below) to access the instance. Yet,
this still does not guarantee that this type of usage will result in a desired effect in a
multithreaded program.
You've been warned so use the singleton pattern wisely!
Example:
class MySingletonClass(Singleton):
def init(self):
print "in MySingletonClass::init()", self
def foo(self):
print "in MySingletonClass::foo()", self
MySingletonClass().foo()
MySingletonClass().foo()
MySingletonClass().foo()
---> output will look something like this:
in MySingletonClass::init() <__main__.MySingletonClass object at 0x7ff5b322f3d0>
in MySingletonClass::foo() <__main__.MySingletonClass object at 0x7ff5b322f3d0>
in MySingletonClass::foo() <__main__.MySingletonClass object at 0x7ff5b322f3d0>
in MySingletonClass::foo() <__main__.MySingletonClass object at 0x7ff5b322f3d0>
'''
lock = threading.RLock()
def __new__(cls, *args, **kwargs):
try:
cls.lock.acquire()
it = cls.__dict__.get('__it__')
if it is not None:
return it
cls.__it__ = it = object.__new__(cls)
it.init(*args, **kwargs)
return it
finally: # this always gets called, even when returning from within the try block
cls.lock.release()
def init(self, *args, **kwargs):
'''
Derived classes should override this method to do its initializations
The derived class should not implement a '__init__' method.
'''
pass
@classmethod
def delInstance(cls):
cls.lock.acquire()
try:
if cls.__dict__.get('__it__') is not None:
del cls.__it__
finally:
cls.lock.release()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment