Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 

230 řádky
9.2 KiB

  1. """tests for passlib.hash -- (c) Assurance Technologies 2003-2009"""
  2. #=============================================================================
  3. # imports
  4. #=============================================================================
  5. from __future__ import with_statement
  6. # core
  7. from logging import getLogger
  8. import warnings
  9. import sys
  10. # site
  11. # pkg
  12. from passlib import hash, registry, exc
  13. from passlib.registry import register_crypt_handler, register_crypt_handler_path, \
  14. get_crypt_handler, list_crypt_handlers, _unload_handler_name as unload_handler_name
  15. import passlib.utils.handlers as uh
  16. from passlib.tests.utils import TestCase
  17. # module
  18. log = getLogger(__name__)
  19. #=============================================================================
  20. # dummy handlers
  21. #
  22. # NOTE: these are defined outside of test case
  23. # since they're used by test_register_crypt_handler_path(),
  24. # which needs them to be available as module globals.
  25. #=============================================================================
  26. class dummy_0(uh.StaticHandler):
  27. name = "dummy_0"
  28. class alt_dummy_0(uh.StaticHandler):
  29. name = "dummy_0"
  30. dummy_x = 1
  31. #=============================================================================
  32. # test registry
  33. #=============================================================================
  34. class RegistryTest(TestCase):
  35. descriptionPrefix = "passlib.registry"
  36. def setUp(self):
  37. super(RegistryTest, self).setUp()
  38. # backup registry state & restore it after test.
  39. locations = dict(registry._locations)
  40. handlers = dict(registry._handlers)
  41. def restore():
  42. registry._locations.clear()
  43. registry._locations.update(locations)
  44. registry._handlers.clear()
  45. registry._handlers.update(handlers)
  46. self.addCleanup(restore)
  47. def test_hash_proxy(self):
  48. """test passlib.hash proxy object"""
  49. # check dir works
  50. dir(hash)
  51. # check repr works
  52. repr(hash)
  53. # check non-existent attrs raise error
  54. self.assertRaises(AttributeError, getattr, hash, 'fooey')
  55. # GAE tries to set __loader__,
  56. # make sure that doesn't call register_crypt_handler.
  57. old = getattr(hash, "__loader__", None)
  58. test = object()
  59. hash.__loader__ = test
  60. self.assertIs(hash.__loader__, test)
  61. if old is None:
  62. del hash.__loader__
  63. self.assertFalse(hasattr(hash, "__loader__"))
  64. else:
  65. hash.__loader__ = old
  66. self.assertIs(hash.__loader__, old)
  67. # check storing attr calls register_crypt_handler
  68. class dummy_1(uh.StaticHandler):
  69. name = "dummy_1"
  70. hash.dummy_1 = dummy_1
  71. self.assertIs(get_crypt_handler("dummy_1"), dummy_1)
  72. # check storing under wrong name results in error
  73. self.assertRaises(ValueError, setattr, hash, "dummy_1x", dummy_1)
  74. def test_register_crypt_handler_path(self):
  75. """test register_crypt_handler_path()"""
  76. # NOTE: this messes w/ internals of registry, shouldn't be used publically.
  77. paths = registry._locations
  78. # check namespace is clear
  79. self.assertTrue('dummy_0' not in paths)
  80. self.assertFalse(hasattr(hash, 'dummy_0'))
  81. # check invalid names are rejected
  82. self.assertRaises(ValueError, register_crypt_handler_path,
  83. "dummy_0", ".test_registry")
  84. self.assertRaises(ValueError, register_crypt_handler_path,
  85. "dummy_0", __name__ + ":dummy_0:xxx")
  86. self.assertRaises(ValueError, register_crypt_handler_path,
  87. "dummy_0", __name__ + ":dummy_0.xxx")
  88. # try lazy load
  89. register_crypt_handler_path('dummy_0', __name__)
  90. self.assertTrue('dummy_0' in list_crypt_handlers())
  91. self.assertTrue('dummy_0' not in list_crypt_handlers(loaded_only=True))
  92. self.assertIs(hash.dummy_0, dummy_0)
  93. self.assertTrue('dummy_0' in list_crypt_handlers(loaded_only=True))
  94. unload_handler_name('dummy_0')
  95. # try lazy load w/ alt
  96. register_crypt_handler_path('dummy_0', __name__ + ':alt_dummy_0')
  97. self.assertIs(hash.dummy_0, alt_dummy_0)
  98. unload_handler_name('dummy_0')
  99. # check lazy load w/ wrong type fails
  100. register_crypt_handler_path('dummy_x', __name__)
  101. self.assertRaises(TypeError, get_crypt_handler, 'dummy_x')
  102. # check lazy load w/ wrong name fails
  103. register_crypt_handler_path('alt_dummy_0', __name__)
  104. self.assertRaises(ValueError, get_crypt_handler, "alt_dummy_0")
  105. unload_handler_name("alt_dummy_0")
  106. # TODO: check lazy load which calls register_crypt_handler (warning should be issued)
  107. sys.modules.pop("passlib.tests._test_bad_register", None)
  108. register_crypt_handler_path("dummy_bad", "passlib.tests._test_bad_register")
  109. with warnings.catch_warnings():
  110. warnings.filterwarnings("ignore", "xxxxxxxxxx", DeprecationWarning)
  111. h = get_crypt_handler("dummy_bad")
  112. from passlib.tests import _test_bad_register as tbr
  113. self.assertIs(h, tbr.alt_dummy_bad)
  114. def test_register_crypt_handler(self):
  115. """test register_crypt_handler()"""
  116. self.assertRaises(TypeError, register_crypt_handler, {})
  117. self.assertRaises(ValueError, register_crypt_handler, type('x', (uh.StaticHandler,), dict(name=None)))
  118. self.assertRaises(ValueError, register_crypt_handler, type('x', (uh.StaticHandler,), dict(name="AB_CD")))
  119. self.assertRaises(ValueError, register_crypt_handler, type('x', (uh.StaticHandler,), dict(name="ab-cd")))
  120. self.assertRaises(ValueError, register_crypt_handler, type('x', (uh.StaticHandler,), dict(name="ab__cd")))
  121. self.assertRaises(ValueError, register_crypt_handler, type('x', (uh.StaticHandler,), dict(name="default")))
  122. class dummy_1(uh.StaticHandler):
  123. name = "dummy_1"
  124. class dummy_1b(uh.StaticHandler):
  125. name = "dummy_1"
  126. self.assertTrue('dummy_1' not in list_crypt_handlers())
  127. register_crypt_handler(dummy_1)
  128. register_crypt_handler(dummy_1)
  129. self.assertIs(get_crypt_handler("dummy_1"), dummy_1)
  130. self.assertRaises(KeyError, register_crypt_handler, dummy_1b)
  131. self.assertIs(get_crypt_handler("dummy_1"), dummy_1)
  132. register_crypt_handler(dummy_1b, force=True)
  133. self.assertIs(get_crypt_handler("dummy_1"), dummy_1b)
  134. self.assertTrue('dummy_1' in list_crypt_handlers())
  135. def test_get_crypt_handler(self):
  136. """test get_crypt_handler()"""
  137. class dummy_1(uh.StaticHandler):
  138. name = "dummy_1"
  139. # without available handler
  140. self.assertRaises(KeyError, get_crypt_handler, "dummy_1")
  141. self.assertIs(get_crypt_handler("dummy_1", None), None)
  142. # already loaded handler
  143. register_crypt_handler(dummy_1)
  144. self.assertIs(get_crypt_handler("dummy_1"), dummy_1)
  145. with warnings.catch_warnings():
  146. warnings.filterwarnings("ignore", "handler names should be lower-case, and use underscores instead of hyphens:.*", UserWarning)
  147. # already loaded handler, using incorrect name
  148. self.assertIs(get_crypt_handler("DUMMY-1"), dummy_1)
  149. # lazy load of unloaded handler, using incorrect name
  150. register_crypt_handler_path('dummy_0', __name__)
  151. self.assertIs(get_crypt_handler("DUMMY-0"), dummy_0)
  152. # check system & private names aren't returned
  153. import passlib.hash # ensure module imported, so py3.3 sets __package__
  154. passlib.hash.__dict__["_fake"] = "dummy" # so behavior seen under py2x also
  155. for name in ["_fake", "__package__"]:
  156. self.assertRaises(KeyError, get_crypt_handler, name)
  157. self.assertIs(get_crypt_handler(name, None), None)
  158. def test_list_crypt_handlers(self):
  159. """test list_crypt_handlers()"""
  160. from passlib.registry import list_crypt_handlers
  161. # check system & private names aren't returned
  162. import passlib.hash # ensure module imported, so py3.3 sets __package__
  163. passlib.hash.__dict__["_fake"] = "dummy" # so behavior seen under py2x also
  164. for name in list_crypt_handlers():
  165. self.assertFalse(name.startswith("_"), "%r: " % name)
  166. unload_handler_name("_fake")
  167. def test_handlers(self):
  168. """verify we have tests for all builtin handlers"""
  169. from passlib.registry import list_crypt_handlers
  170. from passlib.tests.test_handlers import get_handler_case, conditionally_available_hashes
  171. for name in list_crypt_handlers():
  172. # skip some wrappers that don't need independant testing
  173. if name.startswith("ldap_") and name[5:] in list_crypt_handlers():
  174. continue
  175. if name in ["roundup_plaintext"]:
  176. continue
  177. # check the remaining ones all have a handler
  178. try:
  179. self.assertTrue(get_handler_case(name))
  180. except exc.MissingBackendError:
  181. if name in conditionally_available_hashes: # expected to fail on some setups
  182. continue
  183. raise
  184. #=============================================================================
  185. # eof
  186. #=============================================================================