Загрузить файлы в «venv/Lib/site-packages/passlib/tests»

This commit is contained in:
2026-07-02 18:52:00 +00:00
parent 56b5e37802
commit 717a5d6b7c
5 changed files with 3305 additions and 0 deletions

View File

@@ -0,0 +1,97 @@
"""test passlib.hosts"""
#=============================================================================
# imports
#=============================================================================
from __future__ import with_statement
# core
import logging; log = logging.getLogger(__name__)
# site
# pkg
from passlib import hosts, hash as hashmod
from passlib.utils import unix_crypt_schemes
from passlib.tests.utils import TestCase
# module
#=============================================================================
# test predefined app contexts
#=============================================================================
class HostsTest(TestCase):
"""perform general tests to make sure contexts work"""
# NOTE: these tests are not really comprehensive,
# since they would do little but duplicate
# the presets in apps.py
#
# they mainly try to ensure no typos
# or dynamic behavior foul-ups.
def check_unix_disabled(self, ctx):
for hash in [
"",
"!",
"*",
"!$1$TXl/FX/U$BZge.lr.ux6ekjEjxmzwz0",
]:
self.assertEqual(ctx.identify(hash), 'unix_disabled')
self.assertFalse(ctx.verify('test', hash))
def test_linux_context(self):
ctx = hosts.linux_context
for hash in [
('$6$rounds=41128$VoQLvDjkaZ6L6BIE$4pt.1Ll1XdDYduEwEYPCMOBiR6W6'
'znsyUEoNlcVXpv2gKKIbQolgmTGe6uEEVJ7azUxuc8Tf7zV9SD2z7Ij751'),
('$5$rounds=31817$iZGmlyBQ99JSB5n6$p4E.pdPBWx19OajgjLRiOW0itGny'
'xDGgMlDcOsfaI17'),
'$1$TXl/FX/U$BZge.lr.ux6ekjEjxmzwz0',
'kAJJz.Rwp0A/I',
]:
self.assertTrue(ctx.verify("test", hash))
self.check_unix_disabled(ctx)
def test_bsd_contexts(self):
for ctx in [
hosts.freebsd_context,
hosts.openbsd_context,
hosts.netbsd_context,
]:
for hash in [
'$1$TXl/FX/U$BZge.lr.ux6ekjEjxmzwz0',
'kAJJz.Rwp0A/I',
]:
self.assertTrue(ctx.verify("test", hash))
h1 = "$2a$04$yjDgE74RJkeqC0/1NheSSOrvKeu9IbKDpcQf/Ox3qsrRS/Kw42qIS"
if hashmod.bcrypt.has_backend():
self.assertTrue(ctx.verify("test", h1))
else:
self.assertEqual(ctx.identify(h1), "bcrypt")
self.check_unix_disabled(ctx)
def test_host_context(self):
ctx = getattr(hosts, "host_context", None)
if not ctx:
return self.skipTest("host_context not available on this platform")
# validate schemes is non-empty,
# and contains unix_disabled + at least one real scheme
schemes = list(ctx.schemes())
self.assertTrue(schemes, "appears to be unix system, but no known schemes supported by crypt")
self.assertTrue('unix_disabled' in schemes)
schemes.remove("unix_disabled")
self.assertTrue(schemes, "should have schemes beside fallback scheme")
self.assertTrue(set(unix_crypt_schemes).issuperset(schemes))
# check for hash support
self.check_unix_disabled(ctx)
for scheme, hash in [
("sha512_crypt", ('$6$rounds=41128$VoQLvDjkaZ6L6BIE$4pt.1Ll1XdDYduEwEYPCMOBiR6W6'
'znsyUEoNlcVXpv2gKKIbQolgmTGe6uEEVJ7azUxuc8Tf7zV9SD2z7Ij751')),
("sha256_crypt", ('$5$rounds=31817$iZGmlyBQ99JSB5n6$p4E.pdPBWx19OajgjLRiOW0itGny'
'xDGgMlDcOsfaI17')),
("md5_crypt", '$1$TXl/FX/U$BZge.lr.ux6ekjEjxmzwz0'),
("des_crypt", 'kAJJz.Rwp0A/I'),
]:
if scheme in schemes:
self.assertTrue(ctx.verify("test", hash))
#=============================================================================
# eof
#=============================================================================

View File

@@ -0,0 +1,205 @@
"""passlib.tests -- tests for passlib.pwd"""
#=============================================================================
# imports
#=============================================================================
# core
import itertools
import logging; log = logging.getLogger(__name__)
# site
# pkg
from passlib.tests.utils import TestCase
# local
__all__ = [
"UtilsTest",
"GenerateTest",
"StrengthTest",
]
#=============================================================================
#
#=============================================================================
class UtilsTest(TestCase):
"""test internal utilities"""
descriptionPrefix = "passlib.pwd"
def test_self_info_rate(self):
"""_self_info_rate()"""
from passlib.pwd import _self_info_rate
self.assertEqual(_self_info_rate(""), 0)
self.assertEqual(_self_info_rate("a" * 8), 0)
self.assertEqual(_self_info_rate("ab"), 1)
self.assertEqual(_self_info_rate("ab" * 8), 1)
self.assertEqual(_self_info_rate("abcd"), 2)
self.assertEqual(_self_info_rate("abcd" * 8), 2)
self.assertAlmostEqual(_self_info_rate("abcdaaaa"), 1.5488, places=4)
# def test_total_self_info(self):
# """_total_self_info()"""
# from passlib.pwd import _total_self_info
#
# self.assertEqual(_total_self_info(""), 0)
#
# self.assertEqual(_total_self_info("a" * 8), 0)
#
# self.assertEqual(_total_self_info("ab"), 2)
# self.assertEqual(_total_self_info("ab" * 8), 16)
#
# self.assertEqual(_total_self_info("abcd"), 8)
# self.assertEqual(_total_self_info("abcd" * 8), 64)
# self.assertAlmostEqual(_total_self_info("abcdaaaa"), 12.3904, places=4)
#=============================================================================
# word generation
#=============================================================================
# import subject
from passlib.pwd import genword, default_charsets
ascii_62 = default_charsets['ascii_62']
hex = default_charsets['hex']
class WordGeneratorTest(TestCase):
"""test generation routines"""
descriptionPrefix = "passlib.pwd.genword()"
def setUp(self):
super(WordGeneratorTest, self).setUp()
# patch some RNG references so they're reproducible.
from passlib.pwd import SequenceGenerator
self.patchAttr(SequenceGenerator, "rng",
self.getRandom("pwd generator"))
def assertResultContents(self, results, count, chars, unique=True):
"""check result list matches expected count & charset"""
self.assertEqual(len(results), count)
if unique:
if unique is True:
unique = count
self.assertEqual(len(set(results)), unique)
self.assertEqual(set("".join(results)), set(chars))
def test_general(self):
"""general behavior"""
# basic usage
result = genword()
self.assertEqual(len(result), 9)
# malformed keyword should have useful error.
self.assertRaisesRegex(TypeError, "(?i)unexpected keyword.*badkwd", genword, badkwd=True)
def test_returns(self):
"""'returns' keyword"""
# returns=int option
results = genword(returns=5000)
self.assertResultContents(results, 5000, ascii_62)
# returns=iter option
gen = genword(returns=iter)
results = [next(gen) for _ in range(5000)]
self.assertResultContents(results, 5000, ascii_62)
# invalid returns option
self.assertRaises(TypeError, genword, returns='invalid-type')
def test_charset(self):
"""'charset' & 'chars' options"""
# charset option
results = genword(charset="hex", returns=5000)
self.assertResultContents(results, 5000, hex)
# chars option
# there are 3**3=27 possible combinations
results = genword(length=3, chars="abc", returns=5000)
self.assertResultContents(results, 5000, "abc", unique=27)
# chars + charset
self.assertRaises(TypeError, genword, chars='abc', charset='hex')
# TODO: test rng option
#=============================================================================
# phrase generation
#=============================================================================
# import subject
from passlib.pwd import genphrase
simple_words = ["alpha", "beta", "gamma"]
class PhraseGeneratorTest(TestCase):
"""test generation routines"""
descriptionPrefix = "passlib.pwd.genphrase()"
def assertResultContents(self, results, count, words, unique=True, sep=" "):
"""check result list matches expected count & charset"""
self.assertEqual(len(results), count)
if unique:
if unique is True:
unique = count
self.assertEqual(len(set(results)), unique)
out = set(itertools.chain.from_iterable(elem.split(sep) for elem in results))
self.assertEqual(out, set(words))
def test_general(self):
"""general behavior"""
# basic usage
result = genphrase()
self.assertEqual(len(result.split(" ")), 4) # 48 / log(7776, 2) ~= 3.7 -> 4
# malformed keyword should have useful error.
self.assertRaisesRegex(TypeError, "(?i)unexpected keyword.*badkwd", genphrase, badkwd=True)
def test_entropy(self):
"""'length' & 'entropy' keywords"""
# custom entropy
result = genphrase(entropy=70)
self.assertEqual(len(result.split(" ")), 6) # 70 / log(7776, 2) ~= 5.4 -> 6
# custom length
result = genphrase(length=3)
self.assertEqual(len(result.split(" ")), 3)
# custom length < entropy
result = genphrase(length=3, entropy=48)
self.assertEqual(len(result.split(" ")), 4)
# custom length > entropy
result = genphrase(length=4, entropy=12)
self.assertEqual(len(result.split(" ")), 4)
def test_returns(self):
"""'returns' keyword"""
# returns=int option
results = genphrase(returns=1000, words=simple_words)
self.assertResultContents(results, 1000, simple_words)
# returns=iter option
gen = genphrase(returns=iter, words=simple_words)
results = [next(gen) for _ in range(1000)]
self.assertResultContents(results, 1000, simple_words)
# invalid returns option
self.assertRaises(TypeError, genphrase, returns='invalid-type')
def test_wordset(self):
"""'wordset' & 'words' options"""
# wordset option
results = genphrase(words=simple_words, returns=5000)
self.assertResultContents(results, 5000, simple_words)
# words option
results = genphrase(length=3, words=simple_words, returns=5000)
self.assertResultContents(results, 5000, simple_words, unique=3**3)
# words + wordset
self.assertRaises(TypeError, genphrase, words=simple_words, wordset='bip39')
#=============================================================================
# eof
#=============================================================================

View File

@@ -0,0 +1,228 @@
"""tests for passlib.hash -- (c) Assurance Technologies 2003-2009"""
#=============================================================================
# imports
#=============================================================================
from __future__ import with_statement
# core
from logging import getLogger
import warnings
import sys
# site
# pkg
from passlib import hash, registry, exc
from passlib.registry import register_crypt_handler, register_crypt_handler_path, \
get_crypt_handler, list_crypt_handlers, _unload_handler_name as unload_handler_name
import passlib.utils.handlers as uh
from passlib.tests.utils import TestCase
# module
log = getLogger(__name__)
#=============================================================================
# dummy handlers
#
# NOTE: these are defined outside of test case
# since they're used by test_register_crypt_handler_path(),
# which needs them to be available as module globals.
#=============================================================================
class dummy_0(uh.StaticHandler):
name = "dummy_0"
class alt_dummy_0(uh.StaticHandler):
name = "dummy_0"
dummy_x = 1
#=============================================================================
# test registry
#=============================================================================
class RegistryTest(TestCase):
descriptionPrefix = "passlib.registry"
def setUp(self):
super(RegistryTest, self).setUp()
# backup registry state & restore it after test.
locations = dict(registry._locations)
handlers = dict(registry._handlers)
def restore():
registry._locations.clear()
registry._locations.update(locations)
registry._handlers.clear()
registry._handlers.update(handlers)
self.addCleanup(restore)
def test_hash_proxy(self):
"""test passlib.hash proxy object"""
# check dir works
dir(hash)
# check repr works
repr(hash)
# check non-existent attrs raise error
self.assertRaises(AttributeError, getattr, hash, 'fooey')
# GAE tries to set __loader__,
# make sure that doesn't call register_crypt_handler.
old = getattr(hash, "__loader__", None)
test = object()
hash.__loader__ = test
self.assertIs(hash.__loader__, test)
if old is None:
del hash.__loader__
self.assertFalse(hasattr(hash, "__loader__"))
else:
hash.__loader__ = old
self.assertIs(hash.__loader__, old)
# check storing attr calls register_crypt_handler
class dummy_1(uh.StaticHandler):
name = "dummy_1"
hash.dummy_1 = dummy_1
self.assertIs(get_crypt_handler("dummy_1"), dummy_1)
# check storing under wrong name results in error
self.assertRaises(ValueError, setattr, hash, "dummy_1x", dummy_1)
def test_register_crypt_handler_path(self):
"""test register_crypt_handler_path()"""
# NOTE: this messes w/ internals of registry, shouldn't be used publically.
paths = registry._locations
# check namespace is clear
self.assertTrue('dummy_0' not in paths)
self.assertFalse(hasattr(hash, 'dummy_0'))
# check invalid names are rejected
self.assertRaises(ValueError, register_crypt_handler_path,
"dummy_0", ".test_registry")
self.assertRaises(ValueError, register_crypt_handler_path,
"dummy_0", __name__ + ":dummy_0:xxx")
self.assertRaises(ValueError, register_crypt_handler_path,
"dummy_0", __name__ + ":dummy_0.xxx")
# try lazy load
register_crypt_handler_path('dummy_0', __name__)
self.assertTrue('dummy_0' in list_crypt_handlers())
self.assertTrue('dummy_0' not in list_crypt_handlers(loaded_only=True))
self.assertIs(hash.dummy_0, dummy_0)
self.assertTrue('dummy_0' in list_crypt_handlers(loaded_only=True))
unload_handler_name('dummy_0')
# try lazy load w/ alt
register_crypt_handler_path('dummy_0', __name__ + ':alt_dummy_0')
self.assertIs(hash.dummy_0, alt_dummy_0)
unload_handler_name('dummy_0')
# check lazy load w/ wrong type fails
register_crypt_handler_path('dummy_x', __name__)
self.assertRaises(TypeError, get_crypt_handler, 'dummy_x')
# check lazy load w/ wrong name fails
register_crypt_handler_path('alt_dummy_0', __name__)
self.assertRaises(ValueError, get_crypt_handler, "alt_dummy_0")
unload_handler_name("alt_dummy_0")
# TODO: check lazy load which calls register_crypt_handler (warning should be issued)
sys.modules.pop("passlib.tests._test_bad_register", None)
register_crypt_handler_path("dummy_bad", "passlib.tests._test_bad_register")
with warnings.catch_warnings():
warnings.filterwarnings("ignore", "xxxxxxxxxx", DeprecationWarning)
h = get_crypt_handler("dummy_bad")
from passlib.tests import _test_bad_register as tbr
self.assertIs(h, tbr.alt_dummy_bad)
def test_register_crypt_handler(self):
"""test register_crypt_handler()"""
self.assertRaises(TypeError, register_crypt_handler, {})
self.assertRaises(ValueError, register_crypt_handler, type('x', (uh.StaticHandler,), dict(name=None)))
self.assertRaises(ValueError, register_crypt_handler, type('x', (uh.StaticHandler,), dict(name="AB_CD")))
self.assertRaises(ValueError, register_crypt_handler, type('x', (uh.StaticHandler,), dict(name="ab-cd")))
self.assertRaises(ValueError, register_crypt_handler, type('x', (uh.StaticHandler,), dict(name="ab__cd")))
self.assertRaises(ValueError, register_crypt_handler, type('x', (uh.StaticHandler,), dict(name="default")))
class dummy_1(uh.StaticHandler):
name = "dummy_1"
class dummy_1b(uh.StaticHandler):
name = "dummy_1"
self.assertTrue('dummy_1' not in list_crypt_handlers())
register_crypt_handler(dummy_1)
register_crypt_handler(dummy_1)
self.assertIs(get_crypt_handler("dummy_1"), dummy_1)
self.assertRaises(KeyError, register_crypt_handler, dummy_1b)
self.assertIs(get_crypt_handler("dummy_1"), dummy_1)
register_crypt_handler(dummy_1b, force=True)
self.assertIs(get_crypt_handler("dummy_1"), dummy_1b)
self.assertTrue('dummy_1' in list_crypt_handlers())
def test_get_crypt_handler(self):
"""test get_crypt_handler()"""
class dummy_1(uh.StaticHandler):
name = "dummy_1"
# without available handler
self.assertRaises(KeyError, get_crypt_handler, "dummy_1")
self.assertIs(get_crypt_handler("dummy_1", None), None)
# already loaded handler
register_crypt_handler(dummy_1)
self.assertIs(get_crypt_handler("dummy_1"), dummy_1)
with warnings.catch_warnings():
warnings.filterwarnings("ignore", "handler names should be lower-case, and use underscores instead of hyphens:.*", UserWarning)
# already loaded handler, using incorrect name
self.assertIs(get_crypt_handler("DUMMY-1"), dummy_1)
# lazy load of unloaded handler, using incorrect name
register_crypt_handler_path('dummy_0', __name__)
self.assertIs(get_crypt_handler("DUMMY-0"), dummy_0)
# check system & private names aren't returned
from passlib import hash
hash.__dict__["_fake"] = "dummy"
for name in ["_fake", "__package__"]:
self.assertRaises(KeyError, get_crypt_handler, name)
self.assertIs(get_crypt_handler(name, None), None)
def test_list_crypt_handlers(self):
"""test list_crypt_handlers()"""
from passlib.registry import list_crypt_handlers
# check system & private names aren't returned
hash.__dict__["_fake"] = "dummy"
for name in list_crypt_handlers():
self.assertFalse(name.startswith("_"), "%r: " % name)
unload_handler_name("_fake")
def test_handlers(self):
"""verify we have tests for all builtin handlers"""
from passlib.registry import list_crypt_handlers
from passlib.tests.test_handlers import get_handler_case, conditionally_available_hashes
for name in list_crypt_handlers():
# skip some wrappers that don't need independant testing
if name.startswith("ldap_") and name[5:] in list_crypt_handlers():
continue
if name in ["roundup_plaintext"]:
continue
# check the remaining ones all have a handler
try:
self.assertTrue(get_handler_case(name))
except exc.MissingBackendError:
if name in conditionally_available_hashes: # expected to fail on some setups
continue
raise
#=============================================================================
# eof
#=============================================================================

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff