summaryrefslogtreecommitdiff
path: root/passlib/tests/utils.py
diff options
context:
space:
mode:
authorEli Collins <elic@assurancetechnologies.com>2012-02-09 15:19:20 -0500
committerEli Collins <elic@assurancetechnologies.com>2012-02-09 15:19:20 -0500
commit9bcfe9d440c56774a7e138aafcbaccb6b0ce6626 (patch)
tree720249f82734323f1f3f566256dd8768269442b9 /passlib/tests/utils.py
parent4b3590ab0d73e9defb70c97763a1b69a07a7f9be (diff)
downloadpasslib-9bcfe9d440c56774a7e138aafcbaccb6b0ce6626.tar.gz
consolidated some unit tests
Diffstat (limited to 'passlib/tests/utils.py')
-rw-r--r--passlib/tests/utils.py115
1 files changed, 107 insertions, 8 deletions
diff --git a/passlib/tests/utils.py b/passlib/tests/utils.py
index c4019ab..f853874 100644
--- a/passlib/tests/utils.py
+++ b/passlib/tests/utils.py
@@ -170,12 +170,22 @@ class TestCase(unittest.TestCase):
@classproperty
def __unittest_skip__(cls):
+ # make this mirror nose's '__test__' attr
return not getattr(cls, "__test__", True)
@classproperty
def __test__(cls):
- #so nose won't auto run *this* cls, but it will for subclasses
- return cls is not TestCase and not cls.__name__.startswith("_")
+ # nose uses to this to skip tests. overridding this to
+ # skip classes with '__<cls>_unittest_skip' set - that way
+ # we can omit specific classes without affecting subclasses.
+ name = cls.__name__
+ if name.startswith("_"):
+ return False
+ if getattr(cls, "_%s__unittest_skip" % name, False):
+ return False
+ return True
+
+ __unittest_skip = True
#============================================================
# tweak msg formatting for some assert methods
@@ -663,23 +673,23 @@ class HandlerCase(TestCase):
if not isinstance(cls, type) or not issubclass(cls, uh.HasManyIdents):
raise self.skipTest("handler doesn't derive from HasManyIdents")
- #check settings
+ # check settings
self.assertTrue('ident' in cls.setting_kwds)
- #check ident_values list
+ # check ident_values list
for value in cls.ident_values:
self.assertIsInstance(value, unicode,
"cls.ident_values must be unicode:")
self.assertTrue(len(cls.ident_values)>1,
"cls.ident_values must have 2+ elements:")
- #check default_ident value
+ # check default_ident value
self.assertIsInstance(cls.default_ident, unicode,
"cls.default_ident must be unicode:")
self.assertTrue(cls.default_ident in cls.ident_values,
"cls.default_ident must specify member of cls.ident_values")
- #check optional aliases list
+ # check optional aliases list
if cls.ident_aliases:
for alias, ident in iteritems(cls.ident_aliases):
self.assertIsInstance(alias, unicode,
@@ -689,6 +699,27 @@ class HandlerCase(TestCase):
self.assertTrue(ident in cls.ident_values,
"cls.ident_aliases must map to cls.ident_values members: %r" % (ident,))
+ # check constructor validates ident correctly.
+ handler = cls
+ if self.known_correct_hashes:
+ hash = self.known_correct_hashes[0][1]
+ else:
+ hash = self.do_encrypt("stub")
+ kwds = _hobj_to_dict(handler.from_string(hash))
+ del kwds['ident']
+
+ # ... accepts good ident
+ handler(ident=cls.default_ident, **kwds)
+
+ # ... requires ident w/o defaults
+ self.assertRaises(TypeError, handler, **kwds)
+
+ # ... supplies default ident
+ handler(use_defaults=True, **kwds)
+
+ # ... rejects bad ident
+ self.assertRaises(ValueError, handler, ident='xXx', **kwds)
+
RESERVED_BACKEND_NAMES = [ "any", "default", None ]
def test_04_backend_handler(self):
@@ -954,7 +985,7 @@ class HandlerCase(TestCase):
self.assertRaises(ValueError, handler.genhash, 'secret', None)
#=========================================================
- #encrypt()
+ # encrypt()
#=========================================================
def test_50_encrypt_plain(self):
"test encrypt() basic behavior"
@@ -1029,7 +1060,7 @@ class HandlerCase(TestCase):
helper(secret, hash)
#=========================================================
- #test max password size
+ # misc tests
#=========================================================
def test_60_secret_chars(self):
"test secret_chars limit"
@@ -1073,6 +1104,63 @@ class HandlerCase(TestCase):
#eoc
#=========================================================
+class UserHandlerMixin(HandlerCase):
+ """helper for handlers w/ 'user' context kwd; mixin for HandlerCase
+
+ this overrides the HandlerCase test harness methods
+ so that a username is automatically inserted to encrypt/verify
+ calls. as well, passing in a pair of strings as the password
+ will be interpreted as (secret,user)
+ """
+ __unittest_skip = True
+
+ def test_70_user(self):
+ "test user context keyword is required"
+ handler = self.handler
+ password = 'stub'
+ hash = self.known_correct_hashes[0][1]
+
+ handler.encrypt(password, u('user'))
+
+ self.assertRaises(TypeError, handler.encrypt, password)
+ self.assertRaises(TypeError, handler.encrypt, password, None)
+
+ self.assertRaises(TypeError, handler.genhash, password, hash)
+ self.assertRaises(TypeError, handler.genhash, password, hash, None)
+
+ self.assertRaises(TypeError, handler.verify, password, hash)
+ self.assertRaises(TypeError, handler.verify, password, hash, None)
+
+ def create_mismatch(self, secret):
+ if isinstance(secret, tuple):
+ secret, user = secret
+ return 'x' + secret, user
+ else:
+ return 'x' + secret
+
+ def do_encrypt(self, secret, **kwds):
+ if isinstance(secret, tuple):
+ secret, user = secret
+ else:
+ user = 'default'
+ assert 'user' not in kwds
+ kwds['user'] = user
+ return self.handler.encrypt(secret, **kwds)
+
+ def do_verify(self, secret, hash):
+ if isinstance(secret, tuple):
+ secret, user = secret
+ else:
+ user = 'default'
+ return self.handler.verify(secret, hash, user=user)
+
+ def do_genhash(self, secret, config):
+ if isinstance(secret, tuple):
+ secret, user = secret
+ else:
+ user = 'default'
+ return self.handler.genhash(secret, config, user=user)
+
#=========================================================
#backend test helpers
#=========================================================
@@ -1125,6 +1213,17 @@ def _has_relaxed_setting(handler):
return 'relaxed' in handler.setting_kwds or issubclass(handler,
uh.GenericHandler)
+def _hobj_to_dict(hobj):
+ "hack to convert handler instance to dict"
+ # FIXME: would be good to distinguish config-string keywords
+ # from generation options (e.g. salt size) in programmatic manner.
+ exclude_keys = ["salt_size", "relaxed"]
+ return dict(
+ (key, getattr(hobj, key))
+ for key in hobj.setting_kwds
+ if key not in exclude_keys
+ )
+
def create_backend_case(base, name, module="passlib.tests.test_handlers"):
"create a test case for specific backend of a multi-backend handler"
#get handler, figure out if backend should be tested