Tres Seaver
2016-05-31 565160e0757c950b21db0104f42e778ca2a663a3
commit | author | age
0b4b05 1 import unittest
TS 2
9c1e6f 3
826ba0 4 class AuthTicketTests(unittest.TestCase):
0b4b05 5
TS 6     def _getTargetClass(self):
7         from .._auth_tkt import AuthTicket
8         return AuthTicket
9
10     def _makeOne(self, *args, **kw):
11         return self._getTargetClass()(*args, **kw)
12
13     def test_ctor_defaults(self):
b70ba3 14         import hashlib
0b4b05 15         from .. import _auth_tkt
TS 16         with _Monkey(_auth_tkt, time_mod=_Timemod):
17             tkt = self._makeOne('SEEKRIT', 'USERID', '1.2.3.4')
18         self.assertEqual(tkt.secret, 'SEEKRIT')
19         self.assertEqual(tkt.userid, 'USERID')
20         self.assertEqual(tkt.ip, '1.2.3.4')
21         self.assertEqual(tkt.tokens, '')
22         self.assertEqual(tkt.user_data, '')
23         self.assertEqual(tkt.time, _WHEN)
24         self.assertEqual(tkt.cookie_name, 'auth_tkt')
25         self.assertEqual(tkt.secure, False)
b70ba3 26         self.assertEqual(tkt.digest_algo, hashlib.md5)
0b4b05 27
TS 28     def test_ctor_explicit(self):
b70ba3 29         import hashlib
0b4b05 30         tkt = self._makeOne('SEEKRIT', 'USERID', '1.2.3.4', tokens=('a', 'b'),
TS 31                             user_data='DATA', time=_WHEN,
b70ba3 32                             cookie_name='oatmeal', secure=True,
DT 33                             digest_algo=hashlib.sha512)
0b4b05 34         self.assertEqual(tkt.secret, 'SEEKRIT')
TS 35         self.assertEqual(tkt.userid, 'USERID')
36         self.assertEqual(tkt.ip, '1.2.3.4')
37         self.assertEqual(tkt.tokens, 'a,b')
38         self.assertEqual(tkt.user_data, 'DATA')
39         self.assertEqual(tkt.time, _WHEN)
40         self.assertEqual(tkt.cookie_name, 'oatmeal')
41         self.assertEqual(tkt.secure, True)
b70ba3 42         self.assertEqual(tkt.digest_algo, hashlib.sha512)
DT 43
44     def test_ctor_string_algorithm(self):
45         import hashlib
46         tkt = self._makeOne('SEEKRIT', 'USERID', '1.2.3.4', tokens=('a', 'b'),
47                             user_data='DATA', time=_WHEN,
48                             cookie_name='oatmeal', secure=True,
49                             digest_algo='sha1')
50         self.assertEqual(tkt.secret, 'SEEKRIT')
51         self.assertEqual(tkt.userid, 'USERID')
52         self.assertEqual(tkt.ip, '1.2.3.4')
53         self.assertEqual(tkt.tokens, 'a,b')
54         self.assertEqual(tkt.user_data, 'DATA')
55         self.assertEqual(tkt.time, _WHEN)
56         self.assertEqual(tkt.cookie_name, 'oatmeal')
57         self.assertEqual(tkt.secure, True)
58         self.assertEqual(tkt.digest_algo, hashlib.sha1)
0b4b05 59
TS 60     def test_digest(self):
fcf53b 61         from .._auth_tkt import calculate_digest, hashlib
0b4b05 62         tkt = self._makeOne('SEEKRIT', 'USERID', '1.2.3.4', tokens=('a', 'b'),
TS 63                             user_data='DATA', time=_WHEN,
64                             cookie_name='oatmeal', secure=True)
65         digest = calculate_digest('1.2.3.4', _WHEN, 'SEEKRIT', 'USERID',
fcf53b 66                                   'a,b', 'DATA', hashlib.md5)
0b4b05 67         self.assertEqual(tkt.digest(), digest)
TS 68
69     def test_cookie_value_wo_tokens_or_userdata(self):
fcf53b 70         from .._auth_tkt import calculate_digest, hashlib
0b4b05 71         tkt = self._makeOne('SEEKRIT', 'USERID', '1.2.3.4', time=_WHEN)
565160 72         digest = calculate_digest('1.2.3.4', _WHEN, 'SEEKRIT', 'USERID',
TS 73                                   '', '', hashlib.md5)
0b4b05 74         self.assertEqual(tkt.cookie_value(),
TS 75                          '%s%08xUSERID!' % (digest, _WHEN))
76
77     def test_cookie_value_w_tokens_and_userdata(self):
fcf53b 78         from .._auth_tkt import calculate_digest, hashlib
0b4b05 79         tkt = self._makeOne('SEEKRIT', 'USERID', '1.2.3.4', tokens=('a', 'b'),
TS 80                             user_data='DATA', time=_WHEN)
81         digest = calculate_digest('1.2.3.4', _WHEN, 'SEEKRIT', 'USERID',
fcf53b 82                                   'a,b', 'DATA', hashlib.md5)
0b4b05 83         self.assertEqual(tkt.cookie_value(),
TS 84                          '%s%08xUSERID!a,b!DATA' % (digest, _WHEN))
85
86     def test_cookie_not_secure_wo_tokens_or_userdata(self):
fcf53b 87         from .._auth_tkt import calculate_digest, hashlib
0b4b05 88         from .._compat import encodestring
TS 89         tkt = self._makeOne('SEEKRIT', 'USERID', '1.2.3.4', time=_WHEN,
90                             cookie_name='oatmeal')
565160 91         digest = calculate_digest('1.2.3.4', _WHEN, 'SEEKRIT', 'USERID',
TS 92                                   '', '', hashlib.md5)
0b4b05 93         cookie = tkt.cookie()
TS 94         self.assertEqual(cookie['oatmeal'].value,
95                          encodestring('%s%08xUSERID!' % (digest, _WHEN)
96                                      ).strip())
97         self.assertEqual(cookie['oatmeal']['path'], '/')
98         self.assertEqual(cookie['oatmeal']['secure'], '')
99
100     def test_cookie_secure_w_tokens_and_userdata(self):
fcf53b 101         from .._auth_tkt import calculate_digest, hashlib
0b4b05 102         from .._compat import encodestring
TS 103         tkt = self._makeOne('SEEKRIT', 'USERID', '1.2.3.4', tokens=('a', 'b'),
104                             user_data='DATA', time=_WHEN,
105                             cookie_name='oatmeal', secure=True)
106         digest = calculate_digest('1.2.3.4', _WHEN, 'SEEKRIT', 'USERID',
fcf53b 107                                   'a,b', 'DATA', hashlib.md5)
0b4b05 108         cookie = tkt.cookie()
TS 109         self.assertEqual(cookie['oatmeal'].value,
110                          encodestring('%s%08xUSERID!a,b!DATA' % (digest, _WHEN)
111                                      ).strip())
112         self.assertEqual(cookie['oatmeal']['path'], '/')
113         self.assertEqual(cookie['oatmeal']['secure'], 'true')
114  
115
826ba0 116 class BadTicketTests(unittest.TestCase):
ff80e0 117
TS 118     def _getTargetClass(self):
119         from .._auth_tkt import BadTicket
120         return BadTicket
121
122     def _makeOne(self, *args, **kw):
123         return self._getTargetClass()(*args, **kw)
124
125     def test_wo_expected(self):
126         exc = self._makeOne('message')
127         self.assertEqual(exc.args, ('message',))
128         self.assertEqual(exc.expected, None)
129
130     def test_w_expected(self):
131         exc = self._makeOne('message', 'foo')
132         self.assertEqual(exc.args, ('message',))
133         self.assertEqual(exc.expected, 'foo')
134
135
826ba0 136 class Test_parse_ticket(unittest.TestCase):
ff80e0 137
565160 138     def _callFUT(self, secret='SEEKRIT', ticket=None,
TS 139                  ip='1.2.3.4', digest="md5"):
ff80e0 140         from .._auth_tkt import parse_ticket
b70ba3 141         return parse_ticket(secret, ticket, ip, digest)
ff80e0 142
TS 143     def test_bad_timestamp(self):
144         from .._auth_tkt import BadTicket
145         TICKET = '12345678901234567890123456789012XXXXXXXXuserid!'
146         try:
147             self._callFUT(ticket=TICKET)
148         except BadTicket as e:
826ba0 149             self.assertTrue(e.args[0].startswith(
ff80e0 150                             'Timestamp is not a hex integer:'))
d13829 151         else:  # pragma: no cover
ff80e0 152             self.fail('Did not raise')
TS 153
154     def test_no_bang_after_userid(self):
155         from .._auth_tkt import BadTicket
156         TICKET = '1234567890123456789012345678901201020304userid'
157         try:
158             self._callFUT(ticket=TICKET)
159         except BadTicket as e:
160             self.assertEqual(e.args[0], 'userid is not followed by !')
d13829 161         else:  # pragma: no cover
ff80e0 162             self.fail('Did not raise')
TS 163
164     def test_wo_tokens_or_data_bad_digest(self):
165         from .._auth_tkt import BadTicket
166         TICKET = '1234567890123456789012345678901201020304userid!'
167         try:
168             self._callFUT(ticket=TICKET)
169         except BadTicket as e:
170             self.assertEqual(e.args[0], 'Digest signature is not correct')
d13829 171         else:  # pragma: no cover
ff80e0 172             self.fail('Did not raise')
TS 173
174     def test_wo_tokens_or_data_ok_digest(self):
fcf53b 175         from .._auth_tkt import calculate_digest, hashlib
565160 176         digest = calculate_digest('1.2.3.4', _WHEN, 'SEEKRIT', 'USERID',
TS 177                                   '', '', hashlib.md5)
ff80e0 178         TICKET = '%s%08xUSERID!' % (digest, _WHEN)
TS 179         timestamp, userid, tokens, user_data = self._callFUT(ticket=TICKET)
180         self.assertEqual(timestamp, _WHEN)
181         self.assertEqual(userid, 'USERID')
182         self.assertEqual(tokens, [''])
183         self.assertEqual(user_data, '')
184
185     def test_w_tokens_and_data_ok_digest(self):
fcf53b 186         from .._auth_tkt import calculate_digest, hashlib
ff80e0 187         digest = calculate_digest('1.2.3.4', _WHEN, 'SEEKRIT', 'USERID',
fcf53b 188                                   'a,b', 'DATA', hashlib.md5)
ff80e0 189         TICKET = '%s%08xUSERID!a,b!DATA' % (digest, _WHEN)
TS 190         timestamp, userid, tokens, user_data = self._callFUT(ticket=TICKET)
191         self.assertEqual(timestamp, _WHEN)
192         self.assertEqual(userid, 'USERID')
193         self.assertEqual(tokens, ['a', 'b'])
194         self.assertEqual(user_data, 'DATA')
195
b70ba3 196     def test_w_tokens_and_data_ok_alternate_digest(self):
DT 197         from .._auth_tkt import calculate_digest, hashlib
198         digest = calculate_digest('1.2.3.4', _WHEN, 'SEEKRIT', 'USERID',
199                                   'a,b', 'DATA', hashlib.sha256)
200         TICKET = '%s%08xUSERID!a,b!DATA' % (digest, _WHEN)
565160 201         timestamp, userid, tokens, user_data = self._callFUT(
TS 202             ticket=TICKET, digest=hashlib.sha256)
b70ba3 203         self.assertEqual(timestamp, _WHEN)
DT 204         self.assertEqual(userid, 'USERID')
205         self.assertEqual(tokens, ['a', 'b'])
206         self.assertEqual(user_data, 'DATA')
207
ff80e0 208
826ba0 209 class Test_helpers(unittest.TestCase):
ff80e0 210
565160 211     # calculate_digest is not very testable, fully exercised through callers.
ff80e0 212
TS 213     def test_ints_to_bytes(self):
214         from struct import pack
215         from .._auth_tkt import ints2bytes
216         self.assertEqual(ints2bytes([1, 2, 3, 4]), pack('>BBBB', 1, 2, 3, 4))
217         
218     def test_encode_ip_timestamp(self):
219         from struct import pack
220         from .._auth_tkt import encode_ip_timestamp
221         self.assertEqual(encode_ip_timestamp('1.2.3.4', _WHEN),
222                          pack('>BBBBL', 1, 2, 3, 4, _WHEN))
223
224     def test_maybe_encode_bytes(self):
225         from .._auth_tkt import maybe_encode
226         foo = b'foo'
826ba0 227         self.assertTrue(maybe_encode(foo) is foo)
ff80e0 228
TS 229     def test_maybe_encode_native_string(self):
230         from .._auth_tkt import maybe_encode
231         foo = 'foo'
232         self.assertEqual(maybe_encode(foo), b'foo')
233
234     def test_maybe_encode_unicode(self):
235         from .._auth_tkt import maybe_encode
236         from .._compat import u
237         foo = u('foo')
238         self.assertEqual(maybe_encode(foo), b'foo')
239
0b4b05 240
TS 241 _WHEN = 1234567
242 class _Timemod(object):
243     @staticmethod
244     def time():
245         return _WHEN
246
247
248 class _Monkey(object):
249
250     def __init__(self, module, **replacements):
251         self.module = module
252         self.orig = {}
253         self.replacements = replacements
254         
255     def __enter__(self):
256         for k, v in self.replacements.items():
257             orig = getattr(self.module, k, self)
258             if orig is not self:
259                 self.orig[k] = orig
260             setattr(self.module, k, v)
261
262     def __exit__(self, *exc_info):
263         for k, v in self.replacements.items():
264             if k in self.orig:
265                 setattr(self.module, k, self.orig[k])
266             else: #pragma NO COVERSGE
267                 delattr(self.module, k)