import sys
import unittest
import types
from UserDict import UserDict
import FixPath
from MiscUtils.NamedValueAccess import \
NamedValueAccessError, valueForKey, valueForName, NamedValueAccess
from MiscUtils import AbstractError,NoDefault
class T:
pass
class T1(T):
def foo(self):
return 1
class T2(T):
def _foo(self):
return 1
class T3(T):
def foo(self):
return 1
def _foo(self):
return 0
class T4(T):
def foo(self):
return 1
def __init__(self):
self._foo = 0
class T5(T):
def __init__(self):
self.foo = 0
def _foo(self):
return 1
class T6(T):
def __init__(self):
self.foo = 1
self._foo = 0
class T7(T):
def valueForKey(self, key, default):
if key == 'foo':
return 1
elif key == 'nextObject':
return getattr(self, 'nextObject')
else:
if default is NoDefault:
raise NamedValueAccessError, key
else:
return default
class T8(T):
def valueForUnknownKey(self, key, default):
if key == 'foo':
return 1
else:
if default is NoDefault:
raise NamedValueAccessError, key
else:
return default
# Make a list of all the 't' classes which are used in testing
tClasses = []
for name in dir():
if len(name) == 2 and name[0] == 'T':
tClasses.append(globals()[name])
class NamedValueAccessTest(unittest.TestCase):
"""
This is the abstract root ancestor for all test case classes in this file.
"""
pass
class LookupTest(NamedValueAccessTest):
"""
This is an abstract super class for the test cases that cover the
functions. Subclasses must implement self.lookup() and can make use
of self.classes and self.objs.
"""
def setUp(self):
self.setUpClasses()
self.setUpObjects()
def setUpClasses(self):
self.classes = tClasses
def setUpObjects(self):
self.objs = map(lambda klass: klass(), self.classes)
def lookup(self, obj, key, default=NoDefault):
raise AbstractError, self.__class__
def checkBasicAccess(self):
"""
Invoke the look up function with key 'foo', expecting 1 in return.
Invoke the look up with 'bar', expected an exception.
Invoke the look up with 'bar' and default 2, expecting 2.
"""
func = self.lookup
for obj in self.objs:
value = func(obj, 'foo')
assert value == 1, 'value = %r, obj = %r' % (value, obj)
self.assertRaises(NamedValueAccessError, func, obj, 'bar')
value = func(obj, 'bar', 2)
assert value == 2, 'value = %r, obj = %r' % (value, obj)
def checkBasicAccessRepeated(self):
"""
Just repeat checkBasicAccess multiple times to check stability.
"""
for count in xrange(50):
# Yes, it's safe to invoke this other particular test
# multiple times without the usual setUp()/tearDown()
# cycle
self.checkBasicAccess()
class ValueForKeyTest(LookupTest):
def lookup(self, obj, key, default=NoDefault):
return valueForKey(obj, key, default)
class ValueForNameTest(LookupTest):
def lookup(self, obj, key, default=NoDefault):
return valueForName(obj, key, default)
def checkNamedValueAccess(self):
objs = self.objs
# link the objects
for i in range(len(objs)-1):
objs[i].nextObject = objs[i+1]
# test the links
for i in range(len(objs)):
name = 'nextObject.' * i + 'foo'
assert self.lookup(objs[0], name) == 1
def checkDicts(self):
# Basic dicts
dict = {'origin': {'x':1, 'y':2}, 'size': {'width':3, 'height':4}}
obj = self.objs[0]
obj.rect = dict
self._checkDicts(dict, obj)
# User dicts
dict = UserDict(dict)
obj.rect = dict
self._checkDicts(dict, obj)
def _checkDicts(self, dict, obj):
""" Used exclusively by checkDicts(). """
assert self.lookup(dict, 'origin.x') == 1
assert self.lookup(obj, 'rect.origin.x')
self.assertRaises(NamedValueAccessError, self.lookup, dict, 'bar')
self.assertRaises(NamedValueAccessError, self.lookup, obj, 'bar')
assert self.lookup(dict, 'bar', 2) == 2
assert self.lookup(obj, 'rect.bar', 2) == 2
class MixInTest(NamedValueAccessTest):
"""
This test case is really just a utility to mix-in the
NamedValueAccess so that the test classes (T1, T2, ...) inherit it.
Run this test suite after the basic tests, but before the
NamedValueAccess mix-in tests.
"""
def setUp(self):
if NamedValueAccess not in T.__bases__:
T.__bases__ += (NamedValueAccess,)
def checkNothing(self):
pass
class MixInKeyTest(ValueForKeyTest):
def lookup(self, obj, key, default=NoDefault):
if type(obj) is not types.InstanceType:
# just so non-obj cases pass
return valueForKey(obj, key, default)
else:
# What we're really testing, the mix-in method:
return obj.valueForKey(key, default)
class MixInNameTest(ValueForNameTest):
def lookup(self, obj, key, default=NoDefault):
if type(obj) is not types.InstanceType:
# just so non-obj cases pass
return valueForName(obj, key, default)
else:
# What we're really testing, the mix-in method:
return obj.valueForName(key, default)
class MixInExtrasTest(MixInTest, NamedValueAccessTest):
def checkValuesForNames(self):
# def valuesForNames(self, keys, default=None, defaults=None, forgive=0)
# set up structure: rect(attrs(origin(x, y), size(width, height)))
rect = T1()
origin = T1()
origin.x = 5
origin.y = 6
size = T1()
size.width = 43
size.height = 87
attrs = {'origin': origin, 'size': size}
rect.attrs = attrs
# test integrity of structure and validity of valueForName()
assert rect.valueForName('attrs') is attrs
assert rect.valueForName('attrs.origin') is origin
assert rect.valueForName('attrs.size') is size
# test valuesForNames()
notFound = 'notFound'
assert rect.valuesForNames(['attrs', 'attrs.origin',
'attrs.size']) == [attrs, origin, size]
assert rect.valuesForNames(['attrs.dontFind', 'attrs',
'attrs.origin.dontFind'],
default=notFound) == [notFound, attrs, notFound]
assert rect.valuesForNames(['attrs.dontFind', 'attrs',
'attrs.origin.dontFind'], defaults=[1, 2, 3]) == [1, attrs, 3]
assert rect.valuesForNames(['attrs.dontFind', 'attrs',
'attrs.origin.dontFind'], forgive=1) == [attrs]
class WrapperTest(NamedValueAccessTest):
"""
This is a utility class that modifies LookupTest. After running this,
run all the LookupTests (e.g., all subclasses) as usual in order to
test wrappers.
"""
def setUp(self):
def setUpObjects(self):
wrapper = NamedValueAccessWrapper
self.objs = map(lambda klass, wrapper=wrapper: wrapper(klass()), self.classes)
LookupTest.setUpObjects = setUpObjects
def makeTestSuite():
testClasses = [
ValueForKeyTest,
ValueForNameTest,
MixInTest, # utility
MixInKeyTest,
MixInNameTest,
MixInExtrasTest,
WrapperTest, # utility
MixInKeyTest,
MixInNameTest,
MixInExtrasTest,
]
make = unittest.makeSuite
suites = [make(klass, 'check') for klass in testClasses]
return unittest.TestSuite(suites)
def testUse():
runner = unittest.TextTestRunner(stream=sys.stdout)
unittest.main(defaultTest='makeTestSuite', testRunner=runner)
def usage():
sys.stdout = sys.stderr
print 'usage:'
print ' TestNamedValueAccess.py use'
print ' TestNamedValueAccess.py leaks <iterations>'
print
sys.exit(1)
if __name__ == '__main__':
if len(sys.argv) < 2:
testUse()
elif sys.argv[1] in ('-h', '--help', 'help'):
usage()
elif sys.argv[1] == 'use':
testUse()
elif sys.argv[1] == 'leaks':
testLeaks()
else:
usage()
|