diff options
Diffstat (limited to 'passlib/tests/utils.py')
-rw-r--r-- | passlib/tests/utils.py | 252 |
1 files changed, 126 insertions, 126 deletions
diff --git a/passlib/tests/utils.py b/passlib/tests/utils.py index ffce80a..6257acb 100644 --- a/passlib/tests/utils.py +++ b/passlib/tests/utils.py @@ -1,9 +1,9 @@ """helpers for passlib unittests""" -#========================================================= -#imports -#========================================================= +#============================================================================= +# imports +#============================================================================= from __future__ import with_statement -#core +# core import logging; log = logging.getLogger(__name__) import re import os @@ -14,8 +14,8 @@ from passlib.exc import PasslibHashWarning from passlib.utils.compat import PY27, PY_MIN_32, PY3, JYTHON import warnings from warnings import warn -#site -#pkg +# site +# pkg from passlib.exc import MissingBackendError import passlib.registry as registry from passlib.tests.backports import TestCase as _TestCase, catch_warnings, skip, skipIf, skipUnless @@ -25,20 +25,20 @@ from passlib.utils import has_rounds_info, has_salt_info, rounds_cost_values, \ from passlib.utils.compat import b, bytes, iteritems, irange, callable, \ base_string_types, exc_err, u, unicode, PY2 import passlib.utils.handlers as uh -#local +# local __all__ = [ - #util funcs + # util funcs 'TEST_MODE', 'set_file', 'get_file', - #unit testing + # unit testing 'TestCase', 'HandlerCase', ] -#========================================================= +#============================================================================= # environment detection -#========================================================= +#============================================================================= # figure out if we're running under GAE; # some tests (e.g. FS writing) should be skipped. # XXX: is there better way to do this? @@ -67,9 +67,9 @@ def _get_timer_resolution(timer): return min(sample() for _ in range(3)) TICK_RESOLUTION = _get_timer_resolution(tick) -#========================================================= +#============================================================================= # test mode -#========================================================= +#============================================================================= _TEST_MODES = ["quick", "default", "full"] _test_mode = _TEST_MODES.index(os.environ.get("PASSLIB_TEST_MODE", "default").strip().lower()) @@ -99,9 +99,9 @@ def TEST_MODE(min=None, max=None): return False return True -#========================================================= +#============================================================================= # hash object inspection -#========================================================= +#============================================================================= def has_crypt_support(handler): "check if host's crypt() supports this natively" if hasattr(handler, "orig_prefix"): @@ -156,9 +156,9 @@ class temporary_backend(object): def __exit__(self, *exc_info): self.handler.set_backend(self._orig) -#========================================================= +#============================================================================= # misc helpers -#========================================================= +#============================================================================= def set_file(path, content): "set file to specified bytes" if isinstance(content, unicode): @@ -200,9 +200,9 @@ def quicksleep(delay): while tick()-start < delay: pass -#========================================================= +#============================================================================= # custom test harness -#========================================================= +#============================================================================= class TestCase(_TestCase): """passlib-specific test case class @@ -213,13 +213,13 @@ class TestCase(_TestCase): * __msg__ kwd added to assertRaises() * suite of methods for matching against warnings """ - #==================================================================== + #=================================================================== # add various custom features - #==================================================================== + #=================================================================== - #---------------------------------------------------------------- + #--------------------------------------------------------------- # make it easy for test cases to add common prefix to shortDescription - #---------------------------------------------------------------- + #--------------------------------------------------------------- # string prepended to all tests in TestCase descriptionPrefix = None @@ -232,10 +232,10 @@ class TestCase(_TestCase): desc = "%s: %s" % (prefix, desc or str(self)) return desc - #---------------------------------------------------------------- + #--------------------------------------------------------------- # hack things so nose and ut2 both skip subclasses who have # "__unittest_skip=True" set, or whose names start with "_" - #---------------------------------------------------------------- + #--------------------------------------------------------------- @classproperty def __unittest_skip__(cls): # NOTE: this attr is technically a unittest2 internal detail. @@ -254,9 +254,9 @@ class TestCase(_TestCase): # flag to skip *this* class __unittest_skip = True - #---------------------------------------------------------------- + #--------------------------------------------------------------- # reset warning filters & registry before each test - #---------------------------------------------------------------- + #--------------------------------------------------------------- # flag to reset all warning filters & ignore state resetWarningState = True @@ -272,10 +272,10 @@ class TestCase(_TestCase): ctx.__enter__() self.addCleanup(ctx.__exit__) - #---------------------------------------------------------------- + #--------------------------------------------------------------- # tweak message formatting so longMessage mode is only enabled # if msg ends with ":", and turn on longMessage by default. - #---------------------------------------------------------------- + #--------------------------------------------------------------- longMessage = True def _formatMessage(self, msg, std): @@ -284,9 +284,9 @@ class TestCase(_TestCase): else: return msg or std - #---------------------------------------------------------------- + #--------------------------------------------------------------- # override assertRaises() to support '__msg__' keyword - #---------------------------------------------------------------- + #--------------------------------------------------------------- def assertRaises(self, _exc_type, _callable=None, *args, **kwds): msg = kwds.pop("__msg__", None) if _callable is None: @@ -301,16 +301,16 @@ class TestCase(_TestCase): _exc_type) raise self.failureException(self._formatMessage(msg, std)) - #---------------------------------------------------------------- + #--------------------------------------------------------------- # forbid a bunch of deprecated aliases so I stop using them - #---------------------------------------------------------------- + #--------------------------------------------------------------- def assertEquals(self, *a, **k): raise AssertionError("this alias is deprecated by unittest2") assertNotEquals = assertRegexMatches = assertEquals - #============================================================ + #=================================================================== # custom methods for matching warnings - #============================================================ + #=================================================================== def assertWarning(self, warning, message_re=None, message=None, category=None, @@ -425,9 +425,9 @@ class TestCase(_TestCase): def _formatWarningList(self, wlist): return "[%s]" % ", ".join(self._formatWarning(entry) for entry in wlist) - #============================================================ + #=================================================================== # capability tests - #============================================================ + #=================================================================== def require_stringprep(self): "helper to skip test if stringprep is missing" from passlib.utils import stringprep @@ -446,9 +446,9 @@ class TestCase(_TestCase): if GAE: return self.skipTest("GAE doesn't offer read/write filesystem access") - #============================================================ + #=================================================================== # other - #============================================================ + #=================================================================== _mktemp_queue = None def mktemp(self, *args, **kwds): @@ -468,13 +468,13 @@ class TestCase(_TestCase): queue.append(path) return path - #============================================================ - #eoc - #============================================================ + #=================================================================== + # eoc + #=================================================================== -#========================================================= -#other unittest helpers -#========================================================= +#============================================================================= +# other unittest helpers +#============================================================================= RESERVED_BACKEND_NAMES = ["any", "default"] class HandlerCase(TestCase): @@ -494,13 +494,13 @@ class HandlerCase(TestCase): This is subclass of :class:`unittest.TestCase` (or :class:`unittest2.TestCase` if available). """ - #========================================================= + #=================================================================== # class attrs - should be filled in by subclass - #========================================================= + #=================================================================== - #-------------------------------------------------- + #--------------------------------------------------------------- # handler setup - #-------------------------------------------------- + #--------------------------------------------------------------- # handler class to test [required] handler = None @@ -508,9 +508,9 @@ class HandlerCase(TestCase): # if set, run tests against specified backend backend = None - #-------------------------------------------------- + #--------------------------------------------------------------- # test vectors - #-------------------------------------------------- + #--------------------------------------------------------------- # list of (secret, hash) tuples which are known to be correct known_correct_hashes = [] @@ -549,9 +549,9 @@ class HandlerCase(TestCase): b('\xe2\x82\xac\xc2\xa5$') ] - #-------------------------------------------------- + #--------------------------------------------------------------- # option flags - #-------------------------------------------------- + #--------------------------------------------------------------- # maximum number of chars which hash will include in digest. # ``None`` (the default) indicates the hash uses ALL of the password. @@ -580,9 +580,9 @@ class HandlerCase(TestCase): return b("\x00") return None - #========================================================= + #=================================================================== # internal class attrs - #========================================================= + #=================================================================== __unittest_skip = True @property @@ -593,19 +593,19 @@ class HandlerCase(TestCase): name += " (%s backend)" % (handler.get_backend(),) return name - #========================================================= + #=================================================================== # internal instance attrs - #========================================================= + #=================================================================== # indicates safe_crypt() has been patched to use another backend of handler. using_patched_crypt = False - #========================================================= + #=================================================================== # support methods - #========================================================= + #=================================================================== - #------------------------------------------------------ + #--------------------------------------------------------------- # configuration helpers - #------------------------------------------------------ + #--------------------------------------------------------------- @property def supports_config_string(self): return self.do_genconfig() is not None @@ -625,9 +625,9 @@ class HandlerCase(TestCase): known = list(self.iter_known_hashes()) return rng.choice(known) - #------------------------------------------------------ + #--------------------------------------------------------------- # test helpers - #------------------------------------------------------ + #--------------------------------------------------------------- def check_verify(self, secret, hash, msg=None, negate=False): "helper to check verify() outcome, honoring is_disabled_handler" result = self.do_verify(secret, hash) @@ -651,10 +651,10 @@ class HandlerCase(TestCase): self.assertIsInstance(result, str, "%s() failed to return native string: %r" % (func_name, result,)) - #------------------------------------------------------ + #--------------------------------------------------------------- # PasswordHash helpers - wraps all calls to PasswordHash api, # so that subclasses can fill in defaults and account for other specialized behavior - #------------------------------------------------------ + #--------------------------------------------------------------- def populate_settings(self, kwds): "subclassable method to populate default settings" # use lower rounds settings for certain test modes @@ -703,10 +703,10 @@ class HandlerCase(TestCase): secret = self.populate_context(secret, kwds) return self.handler.genhash(secret, config, **kwds) - #------------------------------------------------------ + #--------------------------------------------------------------- # automatically generate subclasses for testing specific backends, # and other backend helpers - #------------------------------------------------------ + #--------------------------------------------------------------- @classmethod def _enable_backend_case(cls, backend): "helper for create_backend_cases(); returns reason to skip backend, or None" @@ -721,8 +721,8 @@ class HandlerCase(TestCase): from passlib.utils import has_crypt if backend == "os_crypt" and has_crypt: if TEST_MODE("full") and cls.find_crypt_replacement(): - #in this case, HandlerCase will monkeypatch os_crypt - #to use another backend, just so we can test os_crypt fully. + # in this case, HandlerCase will monkeypatch os_crypt + # to use another backend, just so we can test os_crypt fully. return None else: return "hash not supported by os crypt()" @@ -761,9 +761,9 @@ class HandlerCase(TestCase): return name return None - #========================================================= + #=================================================================== # setup - #========================================================= + #=================================================================== def setUp(self): super(HandlerCase, self).setUp() @@ -776,9 +776,9 @@ class HandlerCase(TestCase): self.addCleanup(handler.set_backend, handler.get_backend()) handler.set_backend(backend) - #========================================================= + #=================================================================== # basic tests - #========================================================= + #=================================================================== def test_01_required_attributes(self): "validate required attributes" handler = self.handler @@ -969,9 +969,9 @@ class HandlerCase(TestCase): raise TypeError("has_backend(%r) returned invalid " "value: %r" % (backend, ret)) - #============================================================== + #=================================================================== # salts - #============================================================== + #=================================================================== def require_salt(self): if 'salt' not in self.handler.setting_kwds: raise self.skipTest("handler doesn't have salt") @@ -988,24 +988,24 @@ class HandlerCase(TestCase): AssertionError = self.failureException cls = self.handler - #check max_salt_size + # check max_salt_size mx_set = (cls.max_salt_size is not None) if mx_set and cls.max_salt_size < 1: raise AssertionError("max_salt_chars must be >= 1") - #check min_salt_size + # check min_salt_size if cls.min_salt_size < 0: raise AssertionError("min_salt_chars must be >= 0") if mx_set and cls.min_salt_size > cls.max_salt_size: raise AssertionError("min_salt_chars must be <= max_salt_chars") - #check default_salt_size + # check default_salt_size if cls.default_salt_size < cls.min_salt_size: raise AssertionError("default_salt_size must be >= min_salt_size") if mx_set and cls.default_salt_size > cls.max_salt_size: raise AssertionError("default_salt_size must be <= max_salt_size") - #check for 'salt_size' keyword + # check for 'salt_size' keyword if 'salt_size' not in cls.setting_kwds and \ (not mx_set or cls.min_salt_size < cls.max_salt_size): # NOTE: only bothering to issue warning if default_salt_size @@ -1014,7 +1014,7 @@ class HandlerCase(TestCase): warn("%s: hash handler supports range of salt sizes, " "but doesn't offer 'salt_size' setting" % (cls.name,)) - #check salt_chars & default_salt_chars + # check salt_chars & default_salt_chars if cls.salt_chars: if not cls.default_salt_chars: raise AssertionError("default_salt_chars must not be empty") @@ -1200,9 +1200,9 @@ class HandlerCase(TestCase): if not (salt_type is bytes or (PY2 and salt_type is unicode)): self.assertRaises(TypeError, self.do_encrypt, 'stub', salt=b('x')) - #============================================================== + #=================================================================== # rounds - #============================================================== + #=================================================================== def require_rounds_info(self): if not has_rounds_info(self.handler): raise self.skipTest("handler lacks rounds attributes") @@ -1214,26 +1214,26 @@ class HandlerCase(TestCase): cls = self.handler AssertionError = self.failureException - #check max_rounds + # check max_rounds if cls.max_rounds is None: raise AssertionError("max_rounds not specified") if cls.max_rounds < 1: raise AssertionError("max_rounds must be >= 1") - #check min_rounds + # check min_rounds if cls.min_rounds < 0: raise AssertionError("min_rounds must be >= 0") if cls.min_rounds > cls.max_rounds: raise AssertionError("min_rounds must be <= max_rounds") - #check default_rounds + # check default_rounds if cls.default_rounds is not None: if cls.default_rounds < cls.min_rounds: raise AssertionError("default_rounds must be >= min_rounds") if cls.default_rounds > cls.max_rounds: raise AssertionError("default_rounds must be <= max_rounds") - #check rounds_cost + # check rounds_cost if cls.rounds_cost not in rounds_cost_values: raise AssertionError("unknown rounds cost constant: %r" % (cls.rounds_cost,)) @@ -1271,9 +1271,9 @@ class HandlerCase(TestCase): # TODO: check relaxed mode clips max+1 - #============================================================== + #=================================================================== # idents - #============================================================== + #=================================================================== def test_30_HasManyIdents(self): "validate HasManyIdents configuration" cls = self.handler @@ -1300,7 +1300,7 @@ class HandlerCase(TestCase): if cls.ident_aliases: for alias, ident in iteritems(cls.ident_aliases): self.assertIsInstance(alias, unicode, - "cls.ident_aliases keys must be unicode:") #XXX: allow ints? + "cls.ident_aliases keys must be unicode:") # XXX: allow ints? self.assertIsInstance(ident, unicode, "cls.ident_aliases values must be unicode:") self.assertTrue(ident in cls.ident_values, @@ -1326,9 +1326,9 @@ class HandlerCase(TestCase): # TODO: check various supported idents - #============================================================== + #=================================================================== # passwords - #============================================================== + #=================================================================== def test_60_secret_size(self): "test password size limits" sc = self.secret_size @@ -1428,9 +1428,9 @@ class HandlerCase(TestCase): for c in chars: self.assertRaises(ValueError, self.do_encrypt, base + c + base) - #============================================================== + #=================================================================== # check identify(), verify(), genhash() against test vectors - #============================================================== + #=================================================================== def is_secret_8bit(self, secret): secret = self.populate_context(secret, {}) return not is_ascii_safe(secret) @@ -1652,9 +1652,9 @@ class HandlerCase(TestCase): self.do_identify('\xe2\x82\xac\xc2\xa5$') # utf-8 self.do_identify('abc\x91\x00') # non-utf8 - #========================================================= + #=================================================================== # fuzz testing - #========================================================= + #=================================================================== """the following attempts to perform some basic fuzz testing of the handler, based on whatever information can be found about it. it does as much as it can within a fixed amount of time @@ -1879,13 +1879,13 @@ class HandlerCase(TestCase): return None return ident - #========================================================= + #=================================================================== # eoc - #========================================================= + #=================================================================== -#================================================================= +#============================================================================= # HandlerCase mixins providing additional tests for certain hashes -#================================================================= +#============================================================================= class OsCryptMixin(HandlerCase): """helper used by create_backend_case() which adds additional features to test the os_crypt backend. @@ -1898,16 +1898,16 @@ class OsCryptMixin(HandlerCase): * check that native crypt support is detected correctly for known platforms. """ - #========================================================= + #=================================================================== # option flags - #========================================================= + #=================================================================== # platforms that are known to support / not support this hash natively. # list of (platform_regex, True|False|None) entries. platform_crypt_support = [] - #========================================================= + #=================================================================== # instance attrs - #========================================================= + #=================================================================== __unittest_skip = True # force this backend @@ -1916,9 +1916,9 @@ class OsCryptMixin(HandlerCase): # flag read by HandlerCase to detect if fake os crypt is enabled. using_patched_crypt = False - #========================================================= + #=================================================================== # setup - #========================================================= + #=================================================================== def setUp(self): assert self.backend == "os_crypt" if not self.handler.has_backend("os_crypt"): @@ -1949,9 +1949,9 @@ class OsCryptMixin(HandlerCase): mod._crypt = crypt_stub self.using_patched_crypt = True - #========================================================= + #=================================================================== # custom tests - #========================================================= + #=================================================================== def _use_mock_crypt(self): "patch safe_crypt() so it returns mock value" import passlib.utils as mod @@ -2017,7 +2017,7 @@ class OsCryptMixin(HandlerCase): # e.g. platform='freebsd8' ... sha256_crypt not added until 8.3 raise self.skipTest("varied support on %r platform" % platform) elif state != self.using_patched_crypt: - return + return elif state: self.fail("expected %r platform would have native support " "for %r" % (platform, self.handler.name)) @@ -2025,9 +2025,9 @@ class OsCryptMixin(HandlerCase): self.fail("did not expect %r platform would have native support " "for %r" % (platform, self.handler.name)) - #========================================================= + #=================================================================== # eoc - #========================================================= + #=================================================================== class UserHandlerMixin(HandlerCase): """helper for handlers w/ 'user' context kwd; mixin for HandlerCase @@ -2037,21 +2037,21 @@ class UserHandlerMixin(HandlerCase): calls. as well, passing in a pair of strings as the password will be interpreted as (secret,user) """ - #========================================================= + #=================================================================== # option flags - #========================================================= + #=================================================================== default_user = "user" requires_user = True user_case_insensitive = False - #========================================================= + #=================================================================== # instance attrs - #========================================================= + #=================================================================== __unittest_skip = True - #========================================================= + #=================================================================== # custom tests - #========================================================= + #=================================================================== def test_80_user(self): "test user context keyword" handler = self.handler @@ -2091,9 +2091,9 @@ class UserHandlerMixin(HandlerCase): # TODO: user size? kinda dicey, depends on algorithm. - #========================================================= + #=================================================================== # override test helpers - #========================================================= + #=================================================================== def populate_context(self, secret, kwds): "insert username into kwds" if isinstance(secret, tuple): @@ -2106,9 +2106,9 @@ class UserHandlerMixin(HandlerCase): kwds['user'] = user return secret - #========================================================= + #=================================================================== # modify fuzz testing - #========================================================= + #=================================================================== fuzz_user_alphabet = u("asdQWE123") fuzz_settings = HandlerCase.fuzz_settings + ["user"] @@ -2118,9 +2118,9 @@ class UserHandlerMixin(HandlerCase): return None return getrandstr(rng, self.fuzz_user_alphabet, rng.randint(2,10)) - #========================================================= + #=================================================================== # eoc - #========================================================= + #=================================================================== class EncodingHandlerMixin(HandlerCase): """helper for handlers w/ 'encoding' context kwd; mixin for HandlerCase @@ -2130,9 +2130,9 @@ class EncodingHandlerMixin(HandlerCase): calls by passing in a pair of strings as the password will be interpreted as (secret,encoding) """ - #========================================================= + #=================================================================== # instance attrs - #========================================================= + #=================================================================== __unittest_skip = True # restrict stock passwords & fuzz alphabet to latin-1, @@ -2151,9 +2151,9 @@ class EncodingHandlerMixin(HandlerCase): secret, encoding = secret kwds.setdefault('encoding', encoding) return secret - #========================================================= + #=================================================================== # eoc - #========================================================= + #=================================================================== #============================================================================= # warnings helpers |