ut_lockable.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #!/usr/bin/env python3
  2. """
  3. test.modtest_d.ut_lockable: unit test for the MMGen suite's Lockable class
  4. """
  5. from decimal import Decimal
  6. from mmgen.base_obj import AttrCtrl, Lockable
  7. class unit_tests:
  8. def attrctl(self, name, ut, desc='AttrCtrl class'):
  9. class MyAttrCtrl(AttrCtrl):
  10. _autolock = False
  11. foo = 'fooval'
  12. ac = MyAttrCtrl()
  13. ac._lock()
  14. ac.foo = 'new fooval'
  15. ac.foo = 'new fooval2'
  16. class MyAttrCtrlAutolock(AttrCtrl):
  17. pass
  18. aca = MyAttrCtrlAutolock()
  19. class MyAttrCtrlClsCheck(AttrCtrl):
  20. _autolock = False
  21. _use_class_attr = True
  22. foo = 'fooval'
  23. bar = None
  24. acc = MyAttrCtrlClsCheck()
  25. acc._lock()
  26. acc.foo = 'new_fooval'
  27. acc.foo = 'new_fooval2'
  28. acc.bar = 'bar val'
  29. acc.bar = 1 # class attribute bar is None, so can be set to any type
  30. class MyAttrCtrlDflNone(AttrCtrl):
  31. _default_to_none = True
  32. foo = 'fooval'
  33. bar = None
  34. acdn = MyAttrCtrlDflNone()
  35. assert acdn.foo == 'fooval', f'{acdn.foo}'
  36. assert acdn.bar is None, f'{acdn.bar}'
  37. assert acdn.baz is None, f'{acdn.baz}'
  38. def bad1(): ac.x = 1
  39. def bad2(): acc.foo = 1
  40. def bad3(): aca._lock()
  41. def bad4(): acdn.baz = None
  42. ut.process_bad_data((
  43. ('attr', 'AttributeError', 'has no attr', bad1),
  44. ('attr type', 'AttributeError', 'type', bad2),
  45. ('call to _lock()', 'AssertionError', 'only once', bad3),
  46. ('attr', 'AttributeError', 'has no attr', bad4),
  47. ))
  48. return True
  49. def base(self, name, ut, desc='Lockable class'):
  50. class MyLockable(Lockable): # class without attrs
  51. _autolock = False
  52. _set_ok = ('foo', 'baz', 'alpha', 'beta', 'gamma', 'delta', 'epsilon')
  53. _reset_ok = ('bar', 'baz')
  54. lc = MyLockable()
  55. lc.foo = None
  56. lc.bar = 'barval'
  57. lc.baz = 1
  58. lc.qux = 1
  59. # are these considered set?
  60. lc.alpha = 0 # yes
  61. lc.beta = False # yes
  62. lc.gamma = Decimal('0') # yes
  63. lc.delta = 0.0 # yes
  64. lc.epsilon = [] # no
  65. lc._lock()
  66. lc.foo = 'fooval2'
  67. lc.bar = 'barval2'
  68. lc.bar = 'barval3'
  69. lc.baz = 2
  70. lc.baz = 3
  71. lc.epsilon = [0]
  72. def bad1(): lc.foo = 'fooval3'
  73. def bad2(): lc.baz = 'str'
  74. def bad3(): lc.qux = 2
  75. def bad4(): lc.x = 1
  76. def bad5(): lc.alpha = 0
  77. def bad6(): lc.beta = False
  78. def bad7(): lc.gamma = Decimal('0')
  79. def bad8(): lc.delta = float(0)
  80. def bad9(): lc.epsilon = [0]
  81. ut.process_bad_data((
  82. ('attr (can’t reset)', 'AttributeError', 'reset', bad1),
  83. ('attr type (2)', 'AttributeError', 'type', bad2),
  84. ('attr (can’t set)', 'AttributeError', 'read-only', bad3),
  85. ('attr (2)', 'AttributeError', 'has no attr', bad4),
  86. ('attr (can’t reset)', 'AttributeError', 'reset', bad5),
  87. ('attr (can’t reset)', 'AttributeError', 'reset', bad6),
  88. ('attr (can’t reset)', 'AttributeError', 'reset', bad7),
  89. ('attr (can’t reset)', 'AttributeError', 'reset', bad8),
  90. ('attr (can’t reset)', 'AttributeError', 'reset', bad9),
  91. ))
  92. return True
  93. def classattr(self, name, ut, desc='Lockable class with class attrs'):
  94. class MyLockableClsCheck(Lockable): # class with attrs
  95. _autolock = False
  96. _use_class_attr = True
  97. _set_ok = ('foo', 'baz')
  98. _reset_ok = ('bar', 'baz')
  99. foo = None
  100. bar = 1
  101. baz = 3.5
  102. qux = 'quxval'
  103. lcc = MyLockableClsCheck()
  104. lcc._lock()
  105. lcc.foo = 'fooval2' # class attribute foo is None, so can be set to any type
  106. lcc.bar = 2
  107. lcc.bar = 3 # bar is in reset list
  108. lcc.baz = 3.2
  109. lcc.baz = 3.1 # baz is in both lists
  110. def bad1(): lcc.bar = 'str'
  111. def bad2(): lcc.qux = 'quxval2'
  112. def bad3(): lcc.foo = 'fooval3'
  113. def bad4(): lcc.x = 1
  114. ut.process_bad_data((
  115. ('attr type (3)', 'AttributeError', 'type', bad1),
  116. ('attr (can’t set)', 'AttributeError', 'read-only', bad2),
  117. ('attr (can’t reset)', 'AttributeError', 'reset', bad3),
  118. ('attr (3)', 'AttributeError', 'has no attr', bad4),
  119. ))
  120. return True
  121. def autolock(self, name, ut, desc='Lockable class with autolock'):
  122. class MyLockableAutolock(Lockable):
  123. def __init__(self):
  124. self.foo = True
  125. lca = MyLockableAutolock()
  126. assert lca._autolock is True
  127. assert lca._locked is True
  128. assert lca.foo is True
  129. class MyLockableAutolockDflNone(Lockable):
  130. _default_to_none = True
  131. foo = 0
  132. lcdn = MyLockableAutolockDflNone()
  133. assert lcdn.foo == 0
  134. assert lcdn.bar is None
  135. class MyLockableBad(Lockable):
  136. _set_ok = ('foo', 'bar')
  137. foo = 1
  138. def bad1(): lca.foo = None
  139. def bad2(): MyLockableBad()
  140. def bad3(): lcdn.foo = 1
  141. def bad4(): lcdn.bar = None
  142. def bad5(): del lcdn.foo
  143. ut.process_bad_data((
  144. ('attr (can’t set)', 'AttributeError', 'read-only', bad1),
  145. ('attr (bad _set_ok)', 'AssertionError', 'not found in', bad2),
  146. ('attr (can’t set)', 'AttributeError', 'read-only', bad3),
  147. ('attr (5)', 'AttributeError', 'has no attr', bad4),
  148. ('attr (can’t delete)', 'AttributeError', 'not be delet', bad5),
  149. ))
  150. return True