an early version of chakana, an automated test framework used with COOJA
This commit is contained in:
parent
9be473e4b9
commit
65533c0c00
29 changed files with 4983 additions and 0 deletions
279
tools/chakana/debug.py
Normal file
279
tools/chakana/debug.py
Normal file
|
@ -0,0 +1,279 @@
|
|||
#
|
||||
# Copyright (C) 2003-2007 Swedish Institute of Computer Science.
|
||||
#
|
||||
# Please refer to the file named LICENSE in the same directory as this
|
||||
# file for licensing information.
|
||||
#
|
||||
|
||||
# $Id: debug.py,v 1.1 2007/08/21 14:41:01 fros4943 Exp $
|
||||
|
||||
import inspect
|
||||
import os
|
||||
import sys
|
||||
import threading
|
||||
import StringIO
|
||||
|
||||
DebugMin = 0
|
||||
Always = 0
|
||||
Fatal = 1
|
||||
Critical = 2
|
||||
Error = 3
|
||||
Warning = 4
|
||||
Check = 5
|
||||
Information = 6
|
||||
MajorEvent = 7
|
||||
Event = 8
|
||||
MinorEvent = 9
|
||||
Debug = 10
|
||||
Debug2 = 11
|
||||
Debug3 = 12
|
||||
Debug4 = 13
|
||||
Disabled = 14
|
||||
DebugMax = 15
|
||||
|
||||
DefaultDebugLevel = Information
|
||||
|
||||
def levelName(level):
|
||||
for (varName, value) in globals().items():
|
||||
if not varName in ("DebugMin", "DebugMax"):
|
||||
if value == level:
|
||||
return varName
|
||||
return "Unknown"
|
||||
|
||||
class DebugSingleton:
|
||||
def __init__(self, output = sys.stderr, defaultLevel = DefaultDebugLevel,
|
||||
logLevel = Debug4):
|
||||
self.maxBufferLen = 1024 * 1024
|
||||
self.__level = defaultLevel
|
||||
self.__output = output
|
||||
self.__logBuffer = []
|
||||
self.__logBufferSize = 0
|
||||
self.__logLevel = Debug4
|
||||
self.__logFile = None
|
||||
self.__logFileName = None
|
||||
self.__lock = threading.RLock()
|
||||
self._transformers = []
|
||||
|
||||
def level(self):
|
||||
return self.__level
|
||||
|
||||
def setLog(self, fileName):
|
||||
assert(not self.__logBuffer is None)
|
||||
if not fileName is None:
|
||||
self.__logFileName = fileName
|
||||
self.__logFile = open(fileName, "w")
|
||||
self.__logFile.write("".join(self.__logBuffer))
|
||||
self.write(MajorEvent, "Saving debug log in " + fileName + "\n")
|
||||
self.__logBuffer = None
|
||||
|
||||
def logFileName(self):
|
||||
return self.__logFileName
|
||||
|
||||
def logLevel(self):
|
||||
return self.__logLevel
|
||||
|
||||
def cleanLog(self):
|
||||
self.setLog(None)
|
||||
|
||||
def setLogLevel(self, level):
|
||||
self.__logLevel = level
|
||||
self.write(MinorEvent, "Changed debug log verbosity to " +
|
||||
levelName(self.__logLevel) + " (" +
|
||||
str(self.__logLevel) + ")\n")
|
||||
|
||||
def setLevel(self, level):
|
||||
self.__level = level
|
||||
if self.__level < Always:
|
||||
self.__level = Always
|
||||
if self.__level >= Disabled:
|
||||
self.__level = Disabled - 1
|
||||
self.write(MinorEvent, "Changed debug verbosity to " +
|
||||
levelName(self.__level) + " (" + str(self.__level) + ")\n")
|
||||
|
||||
def increaseLevel(self, amount = 1):
|
||||
self.setLevel(self.level() + amount)
|
||||
|
||||
def decreaseLevel(self, amount = 1):
|
||||
self.increaseLevel(- amount)
|
||||
|
||||
def write(self, level, * messages):
|
||||
"""Write messages if current verbosity level >= level. Messages should
|
||||
either be callable functors taking a writer function parameter, or they
|
||||
should be strings or convertible to strings."""
|
||||
|
||||
writers = []
|
||||
if self.level() >= level:
|
||||
writers.append(self.__output.write)
|
||||
if self.logLevel() >= level:
|
||||
writers.append(self.logWrite)
|
||||
if writers != []:
|
||||
self.__lock.acquire()
|
||||
try:
|
||||
for writer in writers:
|
||||
writer(self.transform(level = level,
|
||||
message = self.format(messages)))
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
def format(self, messages):
|
||||
buf = StringIO.StringIO()
|
||||
for msg in messages:
|
||||
if callable(msg):
|
||||
msg(buf.write)
|
||||
else:
|
||||
buf.write(msg)
|
||||
return buf.getvalue()
|
||||
|
||||
def transform(self, level, message):
|
||||
for transform in self._transformers:
|
||||
message = transform(level = level, message = message)
|
||||
return message
|
||||
|
||||
def writer(self, level):
|
||||
return lambda what: self.write(level, what)
|
||||
|
||||
def logWrite(self, what):
|
||||
if self.__logFile is None:
|
||||
if not self.__logBuffer is None:
|
||||
self.__logBuffer.append(what)
|
||||
self.__logBufferSize += len(what)
|
||||
if self.__logBufferSize > self.maxBufferLen:
|
||||
self.__logBuffer = None
|
||||
self.write(Warning, "Cleaned log buffer since it overflowed " +
|
||||
str(self.maxBufferLen) + " bytes\n")
|
||||
else:
|
||||
self.__logFile.write(what)
|
||||
self.__logFile.flush()
|
||||
|
||||
def pushTransformer(self, transformer):
|
||||
assert(callable(transformer))
|
||||
if not transformer in self._transformers:
|
||||
self._transformers.append(transformer)
|
||||
|
||||
debugStream = DebugSingleton()
|
||||
|
||||
def debug(level, message):
|
||||
debugStream.write(level, message, "\n")
|
||||
|
||||
|
||||
class DebugDumper:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def __call__(self, writer):
|
||||
raise NotImplementedError()
|
||||
|
||||
def __add__(self, other):
|
||||
return DebugCombiner(self, other)
|
||||
|
||||
def __radd__(self, other):
|
||||
return DebugCombiner(other, self)
|
||||
|
||||
|
||||
class DebugCombiner:
|
||||
def __init__(self, first, second):
|
||||
self.__first = first
|
||||
self.__second = second
|
||||
|
||||
def __call__(self, writer):
|
||||
for elem in [self.__first, self.__second]:
|
||||
if callable(elem):
|
||||
elem(writer)
|
||||
else:
|
||||
writer(str(elem))
|
||||
|
||||
class DebugFile:
|
||||
def __init__(self):
|
||||
self.__str = ""
|
||||
|
||||
def write(self, msg):
|
||||
self.__str += msg
|
||||
|
||||
def __str__(self):
|
||||
return self.__str
|
||||
|
||||
DebugStderr = DebugFile
|
||||
|
||||
def exceptionDump((type, value, traceback)):
|
||||
"""Print an exception stack trace to DebugStderr(). Pass
|
||||
sys.exc_info() as parameter."""
|
||||
if type is None:
|
||||
return ""
|
||||
oldStderr = sys.stderr
|
||||
debugStderr = DebugStderr()
|
||||
sys.stderr = debugStderr
|
||||
sys.__excepthook__(type, value, traceback)
|
||||
sys.stderr = oldStderr
|
||||
return str(debugStderr)
|
||||
|
||||
def exceptionMessage((type, value, traceback)):
|
||||
import urllib2
|
||||
if isinstance(value, urllib2.HTTPError):
|
||||
return str(value) + ": " + value.filename
|
||||
else:
|
||||
return str(value)
|
||||
|
||||
class CallTracer:
|
||||
def __init__(self, level, prefix = lambda f, e, a: "", traceSystem = 0,
|
||||
traceDebug = 0):
|
||||
self._level = level
|
||||
self._prefix = prefix
|
||||
self._traceSystem = traceSystem
|
||||
self._traceDebug = traceDebug
|
||||
|
||||
def indent(self, frame):
|
||||
stack = inspect.stack()
|
||||
depth = len(stack) - 4
|
||||
assert(depth >= 0)
|
||||
while len(stack) > 0:
|
||||
del stack[0]
|
||||
del stack
|
||||
return " " * depth
|
||||
|
||||
def prefix(self, frame, event, arg):
|
||||
return self._prefix(frame, event, arg) + self.indent(frame)
|
||||
|
||||
def inDebugCode(self, frame):
|
||||
if frame is None:
|
||||
return 0
|
||||
if os.path.basename(frame.f_code.co_filename) == "debug.py":
|
||||
ret = 1
|
||||
else:
|
||||
ret = self.inDebugCode(frame.f_back)
|
||||
del frame
|
||||
return ret
|
||||
|
||||
def __call__(self, frame, event, arg):
|
||||
if frame.f_back is None:
|
||||
callerDir = ""
|
||||
else:
|
||||
callerDir = os.path.dirname(frame.f_back.f_code.co_filename)
|
||||
sourceFile = os.path.basename(frame.f_code.co_filename)
|
||||
funcName = sourceFile + ":" + frame.f_code.co_name + "()"
|
||||
if (not self._traceDebug) and self.inDebugCode(frame):
|
||||
return None
|
||||
if self._traceSystem or \
|
||||
not (callerDir.startswith(sys.prefix + "/lib/python")):
|
||||
if event == "call":
|
||||
debug(self._level, self.prefix(
|
||||
frame = frame, event = event, arg = arg) + "-> " + funcName)
|
||||
elif event == "return":
|
||||
debug(self._level, self.prefix(
|
||||
frame = frame, event = event, arg = arg) + "<- " + funcName)
|
||||
elif event == "exception":
|
||||
debug(self._level, self.prefix(
|
||||
frame = frame, event = event, arg = arg) + "X " + funcName)
|
||||
return self
|
||||
|
||||
def pidPrefix(message = "", ** kwArgs):
|
||||
return str(os.getpid()) + ": " + message
|
||||
|
||||
def threadPrefix(message = "", ** kwArgs):
|
||||
return threading.currentThread().getName() + ": " + message
|
||||
|
||||
def objectAsString(obj):
|
||||
names = [(name, value) for name,value in vars(obj).iteritems()]
|
||||
names.insert(0,("Instace of", obj.__class__.__name__))
|
||||
max_length = len(max([name for (name, value) in names]))
|
||||
return "\n".join([name.rjust(max_length) + ": " + str(value) for (name,value) in names])
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue