summaryrefslogtreecommitdiff
path: root/passlib/tests/test_registry.py
blob: 87c994f09365822f103da39eab28006710ebfe1a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
"""tests for passlib.pwhash -- (c) Assurance Technologies 2003-2009"""
#=========================================================
#imports
#=========================================================
from __future__ import with_statement
#core
import hashlib
from logging import getLogger
import os
import time
import warnings
import sys
#site
#pkg
from passlib import hash, registry
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, catch_warnings
#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 tearDown(self):
        for name in ("dummy_0", "dummy_1", "dummy_x", "dummy_bad"):
            unload_handler_name(name)

    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")

        #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 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 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)

#=========================================================
#EOF
#=========================================================