source: main/waeup.cas/trunk/waeup/cas/tests/test_authenticators.py @ 10512

Last change on this file since 10512 was 10512, checked in by Henrik Bettermann, 11 years ago

Increase test coverage.

File size: 11.1 KB
Line 
1# Tests for waeup.cas.authentictors
2import os
3import threading
4import unittest
5from paste.deploy import loadapp
6try:
7    from SimpleXMLRPCServer import SimpleXMLRPCServer  # Python 2.x
8except ImportError:
9    from xmlrpc.server import SimpleXMLRPCServer       # Python 3.x
10try:
11    import xmlrpclib                     # Python 2.x
12except ImportError:
13    import xmlrpc.client as xmlrpclib    # Python 3.x
14from waeup.cas.authenticators import (
15    get_all_authenticators, get_authenticator, filter_auth_opts,
16    Authenticator, DummyAuthenticator, KofaAuthenticator,
17    KofaMoodleAuthenticator
18    )
19from waeup.cas.server import CASServer
20
21
22class TestHelpers(unittest.TestCase):
23
24    def test_get_all_authenticators(self):
25        # we can get authenticators via entry points
26        auths = get_all_authenticators()
27        assert 'dummy' in auths
28        assert auths['dummy'] is DummyAuthenticator
29
30    def test_filter_auth_opts(self):
31        # we can filter auth opts
32        result = filter_auth_opts(
33            dict(auth='foo', auth_bar='baz', auth_baz='blah')
34            )
35        assert result == (
36            {'auth': 'foo'},
37            {'auth_bar': 'baz', 'auth_baz': 'blah'}
38            )
39
40    def test_get_authenticator(self):
41        # we can parse a paste.deploy config dict for auth
42        result = get_authenticator({})
43        assert result == {}
44        result = get_authenticator({'auth': 'dummy'})
45        assert isinstance(result['auth'], DummyAuthenticator)
46
47
48class AuthenticatorTests(unittest.TestCase):
49
50    def test_create(self):
51        # we can create Authenticator instances
52        auth = Authenticator()
53        assert isinstance(auth, Authenticator)
54
55
56class DummyAuthenticatorTests(unittest.TestCase):
57
58    def test_create(self):
59        # we can create DummyAuthenticator instances
60        auth = DummyAuthenticator()
61        assert isinstance(auth, DummyAuthenticator)
62
63    def test_check_credentials(self):
64        # we can succeed with 'bird'/'bebop'. Others will fail.
65        auth = DummyAuthenticator()
66        result1 = auth.check_credentials('bird', 'bebop')
67        assert result1 == (True, '')
68        result2 = auth.check_credentials('foo', 'bar')
69        assert result2 == (False, 'Invalid username or password.')
70
71
72BACKENDS1 = dict(
73    inst1=dict(
74        url='http://localhost:6666/app',
75        marker='^MA-',
76        )
77    )
78
79BACKENDS2 = dict(
80    inst1=dict(
81        url='http://localhost:6666/',
82        marker='^SCHOOL1-',
83        )
84    )
85
86BACKENDS3 = dict(
87    inst1=dict(
88        url='http://localhost:6666/',
89        marker='^SCHOOL1-',
90        moodle_url = 'http://localhost:7777/',
91        )
92    )
93
94class KofaAuthenticatorTests(unittest.TestCase):
95
96    def test_create(self):
97        # we can create KofaAuthenticator instances
98        auth = KofaAuthenticator()
99        assert isinstance(auth, KofaAuthenticator)
100
101    def test_options_defaults(self):
102        # all options have sensible defaults
103        auth = KofaAuthenticator()
104        assert auth.backends == {}
105
106    def test_options(self):
107        # we can pass options
108        auth = KofaAuthenticator(auth_backends=str(BACKENDS1))
109        assert auth.backends == BACKENDS1
110        auth = KofaAuthenticator(auth_backends='{"foo": {"url": "bar"}}')
111        assert auth.backends['foo']['marker'] == '.+'
112        self.assertRaises(
113            ValueError, KofaAuthenticator, auth_backends='not-a-py-expr')
114        self.assertRaises(
115            ValueError, KofaAuthenticator, auth_backends='"Not a dict"')
116        self.assertRaises(
117            ValueError, KofaAuthenticator,
118            auth_backends='{"foo": "not-a-dict"}')
119        self.assertRaises(
120            ValueError, KofaAuthenticator,
121            auth_backends='{"foo": {"no-url-key": "bar"}}')
122        self.assertRaises(
123            ValueError, KofaAuthenticator,
124            auth_backends='{"foo": {"url": "bar", "marker": "inv_re)"}}')
125
126    def test_paste_deploy_options(self):
127        # we can set CAS server-related options via paste.deploy config
128        paste_conf = os.path.join(
129            os.path.dirname(__file__), 'sample3.ini')
130        app = loadapp('config:%s' % paste_conf)
131        assert isinstance(app, CASServer)
132        assert app.db_connection_string == 'sqlite:///:memory:'
133        assert isinstance(app.auth, KofaAuthenticator)
134
135class KofaMoodleAuthenticatorTests(unittest.TestCase):
136
137    def test_paste_deploy_options(self):
138        # we can set CAS server-related options via paste.deploy config
139        paste_conf = os.path.join(
140            os.path.dirname(__file__), 'sample4.ini')
141        app = loadapp('config:%s' % paste_conf)
142        assert isinstance(app, CASServer)
143        assert app.db_connection_string == 'sqlite:///:memory:'
144        assert isinstance(app.auth, KofaAuthenticator)
145        assert app.auth.name == 'kofa_moodle1'
146        auth_backends = {
147          'kofa_moodle1':
148            {'url': 'http://xmlrpcuser1:xmlrpcuser1@localhost:8080/app1/',
149             'marker': '^K',
150             'moodle_url': 'http://localhost/moodle/webservice/xmlrpc/server.php?wstoken=de1e1cbacf91ec6290bb6f6339122e7d',
151            },
152          }
153        assert app.auth.backends == auth_backends
154
155
156class FakeKofaServer(SimpleXMLRPCServer):
157    # A fake Kofa server that provides only XMLRPC methods
158
159    allow_reuse_address = True
160
161    def __init__(self, *args, **kw):
162        kw.update(allow_none=True)
163        SimpleXMLRPCServer.__init__(self, *args, **kw)
164        self.register_function(
165            self._check_credentials, 'check_applicant_credentials')
166        self.register_function(
167            self._check_credentials, 'check_student_credentials')
168        self.register_function(
169            self._get_moodle_data, 'get_moodle_data')
170
171    def _check_credentials(self, username, password):
172        # fake waeup.kofa check_credentials method.
173        #
174        # This method is supposed to mimic the behaviour of an
175        # original waeup.kofa check_credentials method. It returns a
176        # positive result for the credentials `bird`/`bebop`.
177        if username == 'bird' and password == 'bebop':
178            return {'id': 'bird', 'email': 'bird@gods.net',
179                    'description': 'Mr. Charles Parker',
180                    'type': 'student'}
181        if username == 'pig' and password == 'pog':
182            return {'id': 'pig', 'email': 'pig@gods.net',
183                    'description': 'Mr. Ray Charles',
184                    'type': 'applicant'}
185        return None
186
187    def _get_moodle_data(self, username):
188        # fake waeup.kofa get_moodle_data method.
189        if username == 'bird':
190            return dict(email='aa@aa.aa',
191                        firstname='Charles',
192                        lastname='Parker',
193                        )
194        if username == 'pig':
195            return dict(email='bb@bb.bb',
196                        firstname='Ray',
197                        lastname='Charles',
198                        )
199        return None
200
201class FakeMoodleServer(SimpleXMLRPCServer):
202    # A fake Moodle server that provides only XMLRPC methods
203
204    allow_reuse_address = True
205
206    def __init__(self, *args, **kw):
207        kw.update(allow_none=True)
208        SimpleXMLRPCServer.__init__(self, *args, **kw)
209        self.register_function(
210            self._core_user_create_users, 'core_user_create_users')
211        self.register_function(
212            self._core_user_get_users, 'core_user_get_users')
213        self.register_function(
214            self._core_user_update_users, 'core_user_update_users')
215
216    def _core_user_create_users(self, list_of_dicts):
217        # fake Moodle core_user_create_users method.
218        return None
219
220    def _core_user_get_users(self, list_of_dicts):
221        # fake Moodle core_user_get_users method.
222        return {'users':[{'id':'any id'}]}
223
224    def _core_user_update_users(self, list_of_dicts):
225        # fake Moodle core_user_update_users method.
226        return None
227
228class KofaAuthenticatorsIntegrationTests(unittest.TestCase):
229    # A test case where a fake Kofa server is started before tests (and
230    # shut down afterwards).
231
232    kofa_server = None
233    kofa_th = None
234    moodle_server = None
235    moodle_th = None
236
237    @classmethod
238    def setUpClass(cls):
239        # set up a fake kofa server
240        cls.kofa_server = FakeKofaServer(('localhost', 6666))
241        cls.kofa_th = threading.Thread(target=cls.kofa_server.serve_forever)
242        cls.kofa_th.daemon = True
243        cls.kofa_th.start()
244        # set up a fake moodle server
245        cls.moodle_server = FakeMoodleServer(('localhost', 7777))
246        cls.moodle_th = threading.Thread(target=cls.moodle_server.serve_forever)
247        cls.moodle_th.daemon = True
248        cls.moodle_th.start()
249
250    @classmethod
251    def tearDownClass(cls):
252        # tear down fake kofa server
253        cls.kofa_server.shutdown()
254        cls.kofa_server.server_close()
255        # tear down fake moodle server
256        cls.moodle_server.shutdown()
257        cls.moodle_server.server_close()
258
259    def test_fake_kofa_works(self):
260        # make sure the local fake kofa works
261        proxy = xmlrpclib.ServerProxy("http://localhost:6666", allow_none=True)
262        result = proxy.check_student_credentials('bird', 'bebop')
263        assert result == {
264            'description': 'Mr. Charles Parker',
265            'email': 'bird@gods.net',
266            'id': 'bird',
267            'type': 'student'}
268        result = proxy.check_applicant_credentials('pig', 'pog')
269        assert result == {
270            'description': 'Mr. Ray Charles',
271            'email': 'pig@gods.net',
272            'id': 'pig',
273            'type': 'applicant'}
274        result = proxy.get_moodle_data('pig')
275        assert result == {
276            'lastname': 'Charles',
277            'email': 'bb@bb.bb',
278            'firstname': 'Ray',
279            }
280        return
281
282    def test_moodle_works(self):
283        # make sure the local fake moodle works
284        proxy = xmlrpclib.ServerProxy("http://localhost:7777", allow_none=True)
285        result = proxy.core_user_create_users([])
286        assert result == None
287        result = proxy.core_user_get_users([])
288        assert result == {'users':[{'id':'any id'}]}
289        result = proxy.core_user_update_users([])
290        assert result == None
291        return
292
293    def test_check_credentials_1(self):
294        # we get real responses when querying Kofa instances
295        auth = KofaAuthenticator(auth_backends=str(BACKENDS2))
296        result1 = auth.check_credentials('SCHOOL1-bird', 'bebop')
297        assert result1 == (True, '')
298        result2 = auth.check_credentials('SCHOOL1-foo', 'bar')
299        assert result2 == (False, 'Invalid username or password.')
300        result3 = auth.check_credentials('SCHOOL2-bar', 'baz')
301        assert result3 == (False, 'Invalid username or password.')
302
303    def test_check_credentials_2(self):
304        # we get real responses when querying Kofa instances
305        auth = KofaMoodleAuthenticator(auth_backends=str(BACKENDS3))
306        result1 = auth.check_credentials('SCHOOL1-bird', 'bebop')
307        assert result1 == (True, '')
308        result2 = auth.check_credentials('SCHOOL1-foo', 'bar')
309        assert result2 == (False, 'Invalid username or password.')
310        result3 = auth.check_credentials('SCHOOL2-bar', 'baz')
311        assert result3 == (False, 'Invalid username or password.')
Note: See TracBrowser for help on using the repository browser.