mmgen-wallet/test/modtest_d/lockable.py

191 lines
4.9 KiB
Python
Executable file

#!/usr/bin/env python3
"""
test.modtest_d.lockable: unit test for the MMGen suite's Lockable class
"""
from decimal import Decimal
from mmgen.base_obj import AttrCtrl, Lockable
class unit_tests:
def attrctl(self, name, ut, desc='AttrCtrl class'):
class MyAttrCtrl(AttrCtrl):
_autolock = False
foo = 'fooval'
ac = MyAttrCtrl()
ac._lock()
ac.foo = 'new fooval'
ac.foo = 'new fooval2'
class MyAttrCtrlAutolock(AttrCtrl):
pass
aca = MyAttrCtrlAutolock()
class MyAttrCtrlClsCheck(AttrCtrl):
_autolock = False
_use_class_attr = True
foo = 'fooval'
bar = None
acc = MyAttrCtrlClsCheck()
acc._lock()
acc.foo = 'new_fooval'
acc.foo = 'new_fooval2'
acc.bar = 'bar val'
acc.bar = 1 # class attribute bar is None, so can be set to any type
class MyAttrCtrlDflNone(AttrCtrl):
_default_to_none = True
foo = 'fooval'
bar = None
acdn = MyAttrCtrlDflNone()
assert acdn.foo == 'fooval', f'{acdn.foo}'
assert acdn.bar is None, f'{acdn.bar}'
assert acdn.baz is None, f'{acdn.baz}'
def bad1(): ac.x = 1
def bad2(): acc.foo = 1
def bad3(): aca._lock()
def bad4(): acdn.baz = None
ut.process_bad_data((
('attr', 'AttributeError', 'has no attr', bad1),
('attr type', 'AttributeError', 'type', bad2),
('call to _lock()', 'AssertionError', 'only once', bad3),
('attr', 'AttributeError', 'has no attr', bad4),
))
return True
def base(self, name, ut, desc='Lockable class'):
class MyLockable(Lockable): # class without attrs
_autolock = False
_set_ok = ('foo', 'baz', 'alpha', 'beta', 'gamma', 'delta', 'epsilon')
_reset_ok = ('bar', 'baz')
lc = MyLockable()
lc.foo = None
lc.bar = 'barval'
lc.baz = 1
lc.qux = 1
# are these considered set?
lc.alpha = 0 # yes
lc.beta = False # yes
lc.gamma = Decimal('0') # yes
lc.delta = 0.0 # yes
lc.epsilon = [] # no
lc._lock()
lc.foo = 'fooval2'
lc.bar = 'barval2'
lc.bar = 'barval3'
lc.baz = 2
lc.baz = 3
lc.epsilon = [0]
def bad1(): lc.foo = 'fooval3'
def bad2(): lc.baz = 'str'
def bad3(): lc.qux = 2
def bad4(): lc.x = 1
def bad5(): lc.alpha = 0
def bad6(): lc.beta = False
def bad7(): lc.gamma = Decimal('0')
def bad8(): lc.delta = float(0)
def bad9(): lc.epsilon = [0]
ut.process_bad_data((
('attr (can’t reset)', 'AttributeError', 'reset', bad1),
('attr type (2)', 'AttributeError', 'type', bad2),
('attr (can’t set)', 'AttributeError', 'read-only', bad3),
('attr (2)', 'AttributeError', 'has no attr', bad4),
('attr (can’t reset)', 'AttributeError', 'reset', bad5),
('attr (can’t reset)', 'AttributeError', 'reset', bad6),
('attr (can’t reset)', 'AttributeError', 'reset', bad7),
('attr (can’t reset)', 'AttributeError', 'reset', bad8),
('attr (can’t reset)', 'AttributeError', 'reset', bad9),
))
return True
def classattr(self, name, ut, desc='Lockable class with class attrs'):
class MyLockableClsCheck(Lockable): # class with attrs
_autolock = False
_use_class_attr = True
_set_ok = ('foo', 'baz')
_reset_ok = ('bar', 'baz')
foo = None
bar = 1
baz = 3.5
qux = 'quxval'
lcc = MyLockableClsCheck()
lcc._lock()
lcc.foo = 'fooval2' # class attribute foo is None, so can be set to any type
lcc.bar = 2
lcc.bar = 3 # bar is in reset list
lcc.baz = 3.2
lcc.baz = 3.1 # baz is in both lists
def bad1(): lcc.bar = 'str'
def bad2(): lcc.qux = 'quxval2'
def bad3(): lcc.foo = 'fooval3'
def bad4(): lcc.x = 1
ut.process_bad_data((
('attr type (3)', 'AttributeError', 'type', bad1),
('attr (can’t set)', 'AttributeError', 'read-only', bad2),
('attr (can’t reset)', 'AttributeError', 'reset', bad3),
('attr (3)', 'AttributeError', 'has no attr', bad4),
))
return True
def autolock(self, name, ut, desc='Lockable class with autolock'):
class MyLockableAutolock(Lockable):
def __init__(self):
self.foo = True
lca = MyLockableAutolock()
assert lca._autolock is True
assert lca._locked is True
assert lca.foo is True
class MyLockableAutolockDflNone(Lockable):
_default_to_none = True
foo = 0
lcdn = MyLockableAutolockDflNone()
assert lcdn.foo == 0
assert lcdn.bar is None
class MyLockableBad(Lockable):
_set_ok = ('foo', 'bar')
foo = 1
def bad1(): lca.foo = None
def bad2(): MyLockableBad()
def bad3(): lcdn.foo = 1
def bad4(): lcdn.bar = None
def bad5(): del lcdn.foo
ut.process_bad_data((
('attr (can’t set)', 'AttributeError', 'read-only', bad1),
('attr (bad _set_ok)', 'AssertionError', 'not found in', bad2),
('attr (can’t set)', 'AttributeError', 'read-only', bad3),
('attr (5)', 'AttributeError', 'has no attr', bad4),
('attr (can’t delete)', 'AttributeError', 'not be delet', bad5),
))
return True