source: OpenRLabs-Git/deploy/rlabs-docker/web2py-rlabs/gluon/tests/test_tools.py @ 42095c5

mainqndtest v1.1.1
Last change on this file since 42095c5 was 42bd667, checked in by David Fuertes <dfuertes@…>, 4 years ago

Historial Limpio

  • Property mode set to 100755
File size: 66.7 KB
Line 
1#!/bin/python
2# -*- coding: utf-8 -*-
3
4"""
5    Unit tests for gluon.tools
6"""
7import os
8import sys
9import shutil
10import tempfile
11import smtplib
12import datetime
13import unittest
14
15DEFAULT_URI = os.getenv('DB', 'sqlite:memory')
16
17from gluon.dal import DAL, Field
18from pydal.objects import Table
19from gluon import tools
20from gluon.tools import Auth, Mail, Recaptcha2, prettydate, Expose
21from gluon._compat import PY2, to_bytes
22from gluon.globals import Request, Response, Session
23from gluon.storage import Storage
24from gluon.languages import TranslatorFactory
25from gluon.http import HTTP
26from gluon import SPAN, H3, TABLE, TR, TD, A, URL, current
27
28IS_IMAP = "imap" in DEFAULT_URI
29
30
31class TestMail(unittest.TestCase):
32    """
33    Test the Mail class.
34    """
35
36    class Message(object):
37
38        def __init__(self, sender, to, payload):
39            self.sender = sender
40            self.to = to
41            self.payload = payload
42            self._parsed_payload = None
43
44        @property
45        def parsed_payload(self):
46            if self._parsed_payload is None:
47                import email
48                self._parsed_payload = email.message_from_string(self.payload)
49            return self._parsed_payload
50
51    class DummySMTP(object):
52        """
53        Dummy smtp server
54
55        NOTE: Test methods should take care of always leaving inbox and users empty when they finish.
56        """
57        inbox = []
58        users = {}
59
60        def __init__(self, address, port, **kwargs):
61            self.address = address
62            self.port = port
63            self.has_quit = False
64            self.tls = False
65
66        def login(self, username, password):
67            if username not in self.users or self.users[username] != password:
68                raise smtplib.SMTPAuthenticationError
69            self.username = username
70            self.password = password
71
72        def sendmail(self, sender, to, payload):
73            self.inbox.append(TestMail.Message(sender, to, payload))
74
75        def quit(self):
76            self.has_quit = True
77
78        def ehlo(self, hostname=None):
79            pass
80
81        def starttls(self):
82            self.tls = True
83
84    def setUp(self):
85        self.original_SMTP = smtplib.SMTP
86        self.original_SMTP_SSL = smtplib.SMTP_SSL
87        smtplib.SMTP = TestMail.DummySMTP
88        smtplib.SMTP_SSL = TestMail.DummySMTP
89
90    def tearDown(self):
91        smtplib.SMTP = self.original_SMTP
92        smtplib.SMTP_SSL = self.original_SMTP_SSL
93
94    def test_hello_world(self):
95        mail = Mail()
96        mail.settings.server = 'smtp.example.com:25'
97        mail.settings.sender = 'you@example.com'
98        self.assertTrue(mail.send(to=['somebody@example.com'],
99                                  subject='hello',
100                                  # If reply_to is omitted, then mail.settings.sender is used
101                                  reply_to='us@example.com',
102                                  message='world'))
103        message = TestMail.DummySMTP.inbox.pop()
104        self.assertEqual(message.sender, mail.settings.sender)
105        self.assertEqual(message.to, ['somebody@example.com'])
106        header = "To: somebody@example.com\nReply-To: us@example.com\nSubject: hello\n"
107        self.assertTrue(header in message.payload)
108        self.assertTrue(message.payload.endswith('world'))
109
110    def test_failed_login(self):
111        mail = Mail()
112        mail.settings.server = 'smtp.example.com:25'
113        mail.settings.sender = 'you@example.com'
114        mail.settings.login = 'username:password'
115        self.assertFalse(mail.send(to=['somebody@example.com'],
116                                   subject='hello',
117                                   # If reply_to is omitted, then mail.settings.sender is used
118                                   reply_to='us@example.com',
119                                   message='world'))
120
121    def test_login(self):
122        TestMail.DummySMTP.users['username'] = 'password'
123        mail = Mail()
124        mail.settings.server = 'smtp.example.com:25'
125        mail.settings.sender = 'you@example.com'
126        mail.settings.login = 'username:password'
127        self.assertTrue(mail.send(to=['somebody@example.com'],
128                                  subject='hello',
129                                  # If reply_to is omitted, then mail.settings.sender is used
130                                  reply_to='us@example.com',
131                                  message='world'))
132        del TestMail.DummySMTP.users['username']
133        TestMail.DummySMTP.inbox.pop()
134
135    def test_html(self):
136        mail = Mail()
137        mail.settings.server = 'smtp.example.com:25'
138        mail.settings.sender = 'you@example.com'
139        self.assertTrue(mail.send(to=['somebody@example.com'],
140                                  subject='hello',
141                                  # If reply_to is omitted, then mail.settings.sender is used
142                                  reply_to='us@example.com',
143                                  message='<html><head></head><body></body></html>'))
144        message = TestMail.DummySMTP.inbox.pop()
145        self.assertTrue('Content-Type: text/html' in message.payload)
146
147    def test_alternative(self):
148        mail = Mail()
149        mail.settings.server = 'smtp.example.com:25'
150        mail.settings.sender = 'you@example.com'
151        self.assertTrue(mail.send(to=['somebody@example.com'],
152                                  message=('Text only', '<html><pre>HTML Only</pre></html>')))
153        message = TestMail.DummySMTP.inbox.pop()
154        self.assertTrue(message.parsed_payload.is_multipart())
155        self.assertTrue(message.parsed_payload.get_content_type() == 'multipart/alternative')
156        parts = message.parsed_payload.get_payload()
157        self.assertTrue('Text only' in parts[0].as_string())
158        self.assertTrue('<html><pre>HTML Only</pre></html>' in parts[1].as_string())
159
160    def test_ssl(self):
161        mail = Mail()
162        mail.settings.server = 'smtp.example.com:25'
163        mail.settings.sender = 'you@example.com'
164        mail.settings.ssl = True
165        self.assertTrue(mail.send(to=['somebody@example.com'],
166                                  subject='hello',
167                                  # If reply_to is omitted, then mail.settings.sender is used
168                                  reply_to='us@example.com',
169                                  message='world'))
170        TestMail.DummySMTP.inbox.pop()
171
172    def test_tls(self):
173        mail = Mail()
174        mail.settings.server = 'smtp.example.com:25'
175        mail.settings.sender = 'you@example.com'
176        mail.settings.tls = True
177        self.assertTrue(mail.send(to=['somebody@example.com'],
178                                  subject='hello',
179                                  # If reply_to is omitted, then mail.settings.sender is used
180                                  reply_to='us@example.com',
181                                  message='world'))
182        TestMail.DummySMTP.inbox.pop()
183
184    def test_attachment(self):
185        module_file = os.path.abspath(__file__)
186        mail = Mail()
187        mail.settings.server = 'smtp.example.com:25'
188        mail.settings.sender = 'you@example.com'
189        self.assertTrue(mail.send(to=['somebody@example.com'],
190                                  subject='hello',
191                                  message='world',
192                                  attachments=Mail.Attachment(module_file)))
193        message = TestMail.DummySMTP.inbox.pop()
194        attachment = message.parsed_payload.get_payload(1).get_payload(decode=True)
195        with open(module_file, 'rb') as mf:
196            self.assertEqual(to_bytes(attachment), to_bytes(mf.read()))
197        # Test missing attachment name error
198        stream = open(module_file)
199        self.assertRaises(Exception, lambda *args, **kwargs: Mail.Attachment(*args, **kwargs), stream)
200        stream.close()
201        # Test you can define content-id and content type
202        self.assertTrue(mail.send(to=['somebody@example.com'],
203                                  subject='hello',
204                                  message='world',
205                                  attachments=Mail.Attachment(module_file, content_id='trololo', content_type='tra/lala')))
206        message = TestMail.DummySMTP.inbox.pop()
207        self.assertTrue('Content-Type: tra/lala' in message.payload)
208        self.assertTrue('Content-Id: <trololo>' in message.payload)
209
210
211# TODO: class TestAuthJWT(unittest.TestCase):
212class TestAuthJWT(unittest.TestCase):
213    def setUp(self):
214        from gluon.tools import AuthJWT
215
216        from gluon import current
217
218        self.request = Request(env={})
219        self.request.application = 'a'
220        self.request.controller = 'c'
221        self.request.function = 'f'
222        self.request.folder = 'applications/admin'
223        self.current = current
224        self.current.request = self.request
225
226        self.db = DAL(DEFAULT_URI, check_reserved=['all'])
227        self.auth = Auth(self.db)
228        self.auth.define_tables(username=True, signature=False)
229        self.user_data = dict(username='jwtuser', password='jwtuser123')
230        self.db.auth_user.insert(username=self.user_data['username'],
231                                 password=str(
232                                     self.db.auth_user.password.requires[0](
233                                         self.user_data['password'])[0]))
234        self.jwtauth = AuthJWT(self.auth, secret_key='secret', verify_expiration=True)
235
236    def test_jwt_token_manager(self):
237        import gluon.serializers
238        self.request.vars.update(self.user_data)
239        self.token = self.jwtauth.jwt_token_manager()
240        self.assertIsNotNone(self.token)
241        del self.request.vars['username']
242        del self.request.vars['password']
243        self.request.vars._token = gluon.serializers.json_parser.loads(self.token)['token']
244        self.token = self.jwtauth.jwt_token_manager()
245        self.assertIsNotNone(self.token)
246
247    def test_allows_jwt(self):
248        import gluon.serializers
249        self.request.vars.update(self.user_data)
250        self.token = self.jwtauth.jwt_token_manager()
251        self.assertIsNotNone(self.token)
252        del self.request.vars['username']
253        del self.request.vars['password']
254        self.token = self.jwtauth.jwt_token_manager()
255        self.request.vars._token = gluon.serializers.json_parser.loads(self.token)['token']
256
257        @self.jwtauth.allows_jwt()
258        def optional_auth():
259            self.assertEqual(self.user_data['username'], self.auth.user.username)
260        optional_auth()
261
262
263@unittest.skipIf(IS_IMAP, "TODO: Imap raises 'Connection refused'")
264# class TestAuth(unittest.TestCase):
265#
266#     def setUp(self):
267#         request = Request(env={})
268#         request.application = 'a'
269#         request.controller = 'c'
270#         request.function = 'f'
271#         request.folder = 'applications/admin'
272#         response = Response()
273#         session = Session()
274#         T = TranslatorFactory('', 'en')
275#         session.connect(request, response)
276#         from gluon.globals import current
277#         current.request = request
278#         current.response = response
279#         current.session = session
280#         current.T = T
281#         self.db = DAL(DEFAULT_URI, check_reserved=['all'])
282#         self.auth = Auth(self.db)
283#         self.auth.define_tables(username=True, signature=False)
284#         self.db.define_table('t0', Field('tt'), self.auth.signature)
285#         self.auth.enable_record_versioning(self.db)
286#         # Create a user
287#         self.auth.get_or_create_user(dict(first_name='Bart',
288#                                           last_name='Simpson',
289#                                           username='bart',
290#                                           email='bart@simpson.com',
291#                                           password='bart_password',
292#                                           registration_key='bart',
293#                                           registration_id=''
294#                                           ))
295#         # self.auth.settings.registration_requires_verification = False
296#         # self.auth.settings.registration_requires_approval = False
297#
298#     def test_assert_setup(self):
299#         self.assertEqual(self.db(self.db.auth_user.username == 'bart').select().first()['username'], 'bart')
300#         self.assertTrue('auth_user' in self.db)
301#         self.assertTrue('auth_group' in self.db)
302#         self.assertTrue('auth_membership' in self.db)
303#         self.assertTrue('auth_permission' in self.db)
304#         self.assertTrue('auth_event' in self.db)
305#
306#     def test_enable_record_versioning(self):
307#         self.assertTrue('t0_archive' in self.db)
308#
309#     def test_basic_blank_forms(self):
310#         for f in ['login', 'retrieve_password',
311#                   'retrieve_username',
312#                   # 'register'  # register complain about : client_side=self.settings.client_side
313#                   ]:
314#             html_form = getattr(self.auth, f)().xml()
315#             self.assertTrue('name="_formkey"' in html_form)
316#
317#         # NOTE: Not sure it is the proper way to logout_bare() as there is not methods for that and auth.logout() failed
318#         self.auth.logout_bare()
319#         # self.assertTrue(self.auth.is_logged_in())
320#
321#         for f in ['logout', 'verify_email', 'reset_password',
322#                   'change_password', 'profile', 'groups']:
323#             self.assertRaisesRegexp(HTTP, "303*", getattr(self.auth, f))
324#
325#         self.assertRaisesRegexp(HTTP, "401*", self.auth.impersonate)
326#
327#         try:
328#             for t in ['t0_archive', 't0', 'auth_cas', 'auth_event',
329#                       'auth_membership', 'auth_permission', 'auth_group',
330#                       'auth_user']:
331#                 self.db[t].drop()
332#         except SyntaxError as e:
333#             # GAE doesn't support drop
334#             pass
335#         return
336#
337#     def test_get_or_create_user(self):
338#         self.db.auth_user.insert(email='user1@test.com', username='user1', password='password_123')
339#         self.db.commit()
340#         # True case
341#         self.assertEqual(self.auth.get_or_create_user({'email': 'user1@test.com',
342#                                                        'username': 'user1',
343#                                                        'password': 'password_123'
344#                                                        })['username'], 'user1')
345#         # user2 doesn't exist yet and get created
346#         self.assertEqual(self.auth.get_or_create_user({'email': 'user2@test.com',
347#                                                        'username': 'user2'})['username'], 'user2')
348#         # user3 for corner case
349#         self.assertEqual(self.auth.get_or_create_user({'first_name': 'Omer',
350#                                                        'last_name': 'Simpson',
351#                                                        'email': 'user3@test.com',
352#                                                        'registration_id': 'user3',
353#                                                        'username': 'user3'})['username'], 'user3')
354#         # False case
355#         self.assertEqual(self.auth.get_or_create_user({'email': ''}), None)
356#         self.db.auth_user.truncate()
357#         self.db.commit()
358#
359#     def test_login_bare(self):
360#         # The following test case should succeed but failed as I never received the user record but False
361#         self.auth.login_bare(username='bart@simpson.com', password='bart_password')
362#         self.assertTrue(self.auth.is_logged_in())
363#         # Failing login because bad_password
364#         self.assertEqual(self.auth.login_bare(username='bart', password='wrong_password'), False)
365#         self.db.auth_user.truncate()
366#
367#     def test_register_bare(self):
368#         # corner case empty register call register_bare without args
369#         self.assertRaises(ValueError, self.auth.register_bare)
370#         # failing register_bare user already exist
371#         self.assertEqual(self.auth.register_bare(username='bart', password='wrong_password'), False)
372#         # successful register_bare
373#         self.assertEqual(self.auth.register_bare(username='user2',
374#                                                  email='user2@test.com',
375#                                                  password='password_123')['username'], 'user2')
376#         # raise ValueError
377#         self.assertRaises(ValueError, self.auth.register_bare,
378#                           **dict(wrong_field_name='user3', password='password_123'))
379#         # raise ValueError wrong email
380#         self.assertRaises(ValueError, self.auth.register_bare,
381#                           **dict(email='user4@', password='password_123'))
382#         self.db.auth_user.truncate()
383#         self.db.commit()
384#
385#     def test_bulk_register(self):
386#         self.auth.login_bare(username='bart', password='bart_password')
387#         self.auth.settings.bulk_register_enabled = True
388#         bulk_register_form = self.auth.bulk_register(max_emails=10).xml()
389#         self.assertTrue('name="_formkey"' in bulk_register_form)
390#
391#     def test_change_password(self):
392#         self.auth.login_bare(username='bart', password='bart_password')
393#         change_password_form = getattr(self.auth, 'change_password')().xml()
394#         self.assertTrue('name="_formkey"' in change_password_form)
395#
396#     def test_profile(self):
397#         self.auth.login_bare(username='bart', password='bart_password')
398#         profile_form = getattr(self.auth, 'profile')().xml()
399#         self.assertTrue('name="_formkey"' in profile_form)
400#
401#     # def test_impersonate(self):
402#     #     # Create a user to be impersonated
403#     #     self.auth.get_or_create_user(dict(first_name='Omer',
404#     #                                       last_name='Simpson',
405#     #                                       username='omer',
406#     #                                       email='omer@test.com',
407#     #                                       password='password_omer',
408#     #                                       registration_key='',
409#     #                                       registration_id=''))
410#     #     # Create impersonate group, assign bart to impersonate group and add impersonate permission over auth_user
411#     #     self.auth.add_group('impersonate')
412#     #     self.auth.add_membership(user_id=1,
413#     #                              group_id=self.db(self.db.auth_user.username == 'bart'
414#     #                                               ).select(self.db.auth_user.id).first().id)
415#     #     self.auth.add_permission(group_id=self.db(self.db.auth_group.role == 'impersonate'
416#     #                                               ).select(self.db.auth_group.id).first().id,
417#     #                              name='impersonate',
418#     #                              table_name='auth_user',
419#     #                              record_id=0)
420#     #     # Bart login
421#     #     self.auth.login_bare(username='bart', password='bart_password')
422#     #     self.assertTrue(self.auth.is_logged_in())
423#     #     # Bart impersonate Omer
424#     #     omer_id = self.db(self.db.auth_user.username == 'omer').select(self.db.auth_user.id).first().id
425#     #     impersonate_form = self.auth.impersonate(user_id=omer_id)
426#     #     self.assertTrue(self.auth.is_impersonating())
427#     #     self.assertEqual(impersonate_form, 'test')
428#
429#     # def test_impersonate(self):
430#     #     request = Request(env={})
431#     #     request.application = 'a'
432#     #     request.controller = 'c'
433#     #     request.function = 'f'
434#     #     request.folder = 'applications/admin'
435#     #     response = Response()
436#     #     session = Session()
437#     #     T = TranslatorFactory('', 'en')
438#     #     session.connect(request, response)
439#     #     from gluon.globals import current
440#     #     current.request = request
441#     #     current.response = response
442#     #     current.session = session
443#     #     current.T = T
444#     #     db = DAL(DEFAULT_URI, check_reserved=['all'])
445#     #     auth = Auth(db)
446#     #     auth.define_tables(username=True, signature=False)
447#     #     db.define_table('t0', Field('tt'), auth.signature)
448#     #     auth.enable_record_versioning(db)
449#     #     # Create a user
450#     #     auth.get_or_create_user(dict(first_name='Bart',
451#     #                                       last_name='Simpson',
452#     #                                       username='bart',
453#     #                                       email='bart@simpson.com',
454#     #                                       password='bart_password',
455#     #                                       registration_key='bart',
456#     #                                       registration_id=''
457#     #                                       ))
458#     #     # Create a user to be impersonated
459#     #     auth.get_or_create_user(dict(first_name='Omer',
460#     #                                       last_name='Simpson',
461#     #                                       username='omer',
462#     #                                       email='omer@test.com',
463#     #                                       password='password_omer',
464#     #                                       registration_key='',
465#     #                                       registration_id=''))
466#     #     # Create impersonate group, assign bart to impersonate group and add impersonate permission over auth_user
467#     #     auth.add_group('impersonate')
468#     #     auth.add_membership(user_id=1,
469#     #                              group_id=db(db.auth_user.username == 'bart'
470#     #                                               ).select(db.auth_user.id).first().id)
471#     #     auth.add_permission(group_id=db(db.auth_group.role == 'impersonate'
472#     #                                               ).select(db.auth_group.id).first().id,
473#     #                              name='impersonate',
474#     #                              table_name='auth_user',
475#     #                              record_id=0)
476#     #     # Bart login
477#     #     auth.login_bare(username='bart', password='bart_password')
478#     #     # Bart impersonate Omer
479#     #     omer_id = db(db.auth_user.username == 'omer').select(db.auth_user.id).first().id
480#     #     impersonate_form = auth.impersonate(user_id=omer_id)
481#     #     self.assertTrue(auth.is_impersonating())
482#     #     self.assertEqual(impersonate_form, 'test')
483class TestAuth(unittest.TestCase):
484
485    def myassertRaisesRegex(self, *args, **kwargs):
486        if PY2:
487            return getattr(self, 'assertRaisesRegexp')(*args, **kwargs)
488        return getattr(self, 'assertRaisesRegex')(*args, **kwargs)
489
490    def setUp(self):
491        self.request = Request(env={})
492        self.request.application = 'a'
493        self.request.controller = 'c'
494        self.request.function = 'f'
495        self.request.folder = 'applications/admin'
496        self.response = Response()
497        self.session = Session()
498        T = TranslatorFactory('', 'en')
499        self.session.connect(self.request, self.response)
500        from gluon.globals import current
501        self.current = current
502        self.current.request = self.request
503        self.current.response = self.response
504        self.current.session = self.session
505        self.current.T = T
506        self.db = DAL(DEFAULT_URI, check_reserved=['all'])
507        self.auth = Auth(self.db)
508        self.auth.define_tables(username=True, signature=False)
509        self.db.define_table('t0', Field('tt'), self.auth.signature)
510        self.auth.enable_record_versioning(self.db)
511        self.auth.settings.registration_requires_verification = False
512        self.auth.settings.registration_requires_approval = False
513        # Create a user
514        # Note: get_or_create_user() doesn't seems to create user properly it better to use register_bare() and
515        #       prevent login_bare() test from succeed. db insert the user manually not properly work either.
516        # Not working
517        # self.auth.get_or_create_user(dict(first_name='Bart',
518        #                                   last_name='Simpson',
519        #                                   username='bart',
520        #                                   email='bart@simpson.com',
521        #                                   password='bart_password',
522        #                                   # registration_key=None,
523        #                                   #registration_id='bart@simpson.com'
524        #                                  ),
525        #                              login=False)
526        # Not working
527        # self.db.auth_user.insert(first_name='Bart',
528        #                         last_name='Simpson',
529        #                         username='bart',
530        #                         email='bart@simpson.com',
531        #                         password='bart_password')
532        # self.db.commit()
533        self.auth.register_bare(first_name='Bart',
534                                last_name='Simpson',
535                                username='bart',
536                                email='bart@simpson.com',
537                                password='bart_password')
538
539    def test_assert_setup(self):
540        self.assertTrue('auth_user' in self.db)
541        self.assertTrue('auth_group' in self.db)
542        self.assertTrue('auth_membership' in self.db)
543        self.assertTrue('auth_permission' in self.db)
544        self.assertTrue('auth_event' in self.db)
545        bart_record = self.db(self.db.auth_user.username == 'bart').select().first()
546        self.assertEqual(bart_record['username'], 'bart')
547        self.assertEqual(bart_record['registration_key'], '')
548        bart_id = self.db(self.db.auth_user.username == 'bart').select().first().id
549        bart_group_id = self.db(self.db.auth_group.role == 'user_{0}'.format(bart_id)).select().first().id
550        self.assertTrue(self.db((self.db.auth_membership.group_id == bart_group_id) &
551                                (self.db.auth_membership.user_id == bart_id)).select().first())
552
553    # Just calling many form functions
554    def test_basic_blank_forms(self):
555        for f in ['login', 'retrieve_password', 'retrieve_username', 'register']:
556            html_form = getattr(self.auth, f)().xml()
557            self.assertTrue(b'name="_formkey"' in html_form)
558
559        for f in ['logout', 'verify_email', 'reset_password', 'change_password', 'profile', 'groups']:
560            self.myassertRaisesRegex(HTTP, "303*", getattr(self.auth, f))
561
562        self.myassertRaisesRegex(HTTP, "401*", self.auth.impersonate)
563
564        try:
565            for t in ['t0_archive', 't0', 'auth_cas', 'auth_event',
566                      'auth_membership', 'auth_permission', 'auth_group',
567                      'auth_user']:
568                self.db[t].drop()
569        except SyntaxError as e:
570            # GAE doesn't support drop
571            pass
572        return
573
574    def test_get_vars_next(self):
575        self.current.request.vars._next = 'next_test'
576        self.assertEqual(self.auth.get_vars_next(), 'next_test')
577
578    # TODO: def test_navbar(self):
579    # TODO: def test___get_migrate(self):
580
581    def test_enable_record_versioning(self):
582        self.assertTrue('t0_archive' in self.db)
583
584    # TODO: def test_define_signature(self):
585    # TODO: def test_define_signature(self):
586    # TODO: def test_define_table(self):
587
588    def test_log_event(self):
589        self.auth.login_user(self.db(self.db.auth_user.username == 'bart').select().first())  # bypass login_bare()
590        bart_id = self.db(self.db.auth_user.username == 'bart').select(self.db.auth_user.id).first().id
591        # user logged in
592        self.auth.log_event(description='some_log_event_description_%(var1)s',
593                            vars={"var1": "var1"},
594                            origin='log_event_test_1')
595        rtn = self.db(self.db.auth_event.origin == 'log_event_test_1'
596                      ).select(*[self.db.auth_event[f]
597                                 for f in self.db.auth_event.fields if f not in ('id', 'time_stamp')]).first().as_dict()
598        self.assertEqual(set(rtn.items()), set({'origin': 'log_event_test_1',
599                                                'client_ip': None,
600                                                'user_id': bart_id,
601                                                'description': 'some_log_event_description_var1'}.items()))
602        # user not logged
603        self.auth.logout_bare()
604        self.auth.log_event(description='some_log_event_description_%(var2)s',
605                            vars={"var2": "var2"},
606                            origin='log_event_test_2')
607        rtn = self.db(self.db.auth_event.origin == 'log_event_test_2'
608                      ).select(*[self.db.auth_event[f]
609                                 for f in self.db.auth_event.fields if f not in ('id', 'time_stamp')]).first().as_dict()
610        self.assertEqual(set(rtn.items()), set({'origin': 'log_event_test_2',
611                                                'client_ip': None,
612                                                'user_id': None,
613                                                'description': 'some_log_event_description_var2'}.items()))
614        # no logging tests
615        self.auth.settings.logging_enabled = False
616        count_log_event_test_before = self.db(self.db.auth_event.id > 0).count()
617        self.auth.log_event(description='some_log_event_description_%(var3)s',
618                            vars={"var3": "var3"},
619                            origin='log_event_test_3')
620        count_log_event_test_after = self.db(self.db.auth_event.id > 0).count()
621        self.assertEqual(count_log_event_test_after, count_log_event_test_before)
622        self.auth.settings.logging_enabled = True
623        count_log_event_test_before = self.db(self.db.auth_event.id > 0).count()
624        self.auth.log_event(description=None,
625                            vars={"var4": "var4"},
626                            origin='log_event_test_4')
627        count_log_event_test_after = self.db(self.db.auth_event.id > 0).count()
628        self.assertEqual(count_log_event_test_after, count_log_event_test_before)
629        # TODO: Corner case translated description...
630
631    def test_get_or_create_user(self):
632        self.db.auth_user.insert(email='user1@test.com', username='user1', password='password_123')
633        self.db.commit()
634        # True case
635        self.assertEqual(self.auth.get_or_create_user({'email': 'user1@test.com',
636                                                       'username': 'user1',
637                                                       'password': 'password_123'
638                                                       })['username'], 'user1')
639        # user2 doesn't exist yet and get created
640        self.assertEqual(self.auth.get_or_create_user({'email': 'user2@test.com',
641                                                       'username': 'user2'})['username'], 'user2')
642        # user3 for corner case
643        self.assertEqual(self.auth.get_or_create_user({'first_name': 'Omer',
644                                                       'last_name': 'Simpson',
645                                                       'email': 'user3@test.com',
646                                                       'registration_id': 'user3',
647                                                       'username': 'user3'})['username'], 'user3')
648        # False case
649        self.assertEqual(self.auth.get_or_create_user({'email': ''}), None)
650        self.db.auth_user.truncate()
651        self.db.commit()
652
653    # TODO: def test_basic(self):
654    # TODO: def test_login_user(self):
655    # TODO: def test__get_login_settings(self):
656
657    def test_login_bare(self):
658        self.auth.login_bare(username='bart', password='bart_password')
659        self.assertTrue(self.auth.is_logged_in())
660        self.auth.logout_bare()
661        # Failing login because wrong_password
662        self.assertFalse(self.auth.login_bare(username='bart', password='wrong_password'))
663        # NOTE : The following failed for some reason, but I can't find out why
664        # self.auth = Auth(self.db)
665        # self.auth.define_tables(username=False, signature=False)
666        # self.auth.settings.registration_requires_verification = False
667        # self.auth.settings.registration_requires_approval = False
668        # self.auth.register_bare(first_name='Omer',
669        #                         last_name='Simpson',
670        #                         # no username field passed, failed with :
671        #                         # ValueError('register_bare: userfield not provided or invalid')
672        #                         # Or
673        #                         # username='omer',
674        #                         # Or
675        #                         # username='omer@simpson.com',
676        #                         # In either previous cases, it failed with :
677        #                         # self.assertTrue(self.auth.is_logged_in()) AssertionError: False is not true
678        #                         email='omer@simpson.com',
679        #                         password='omer_password')
680        # self.auth.login_bare(username='omer@sympson.com', password='omer_password')
681        # self.assertTrue(self.auth.is_logged_in())
682
683    def test_register_bare(self):
684        # corner case empty register call register_bare without args
685        self.assertRaises(ValueError, self.auth.register_bare)
686        # failing register_bare user already exist
687        self.assertEqual(self.auth.register_bare(username='bart', password='wrong_password'), False)
688        # successful register_bare
689        self.assertEqual(self.auth.register_bare(username='user2',
690                                                 email='user2@test.com',
691                                                 password='password_123')['username'], 'user2')
692        # raise ValueError
693        self.assertRaises(ValueError, self.auth.register_bare,
694                          **dict(wrong_field_name='user3', password='password_123'))
695        # raise ValueError wrong email
696        self.assertRaises(ValueError, self.auth.register_bare,
697                          **dict(email='user4@', password='password_123'))
698        self.db.auth_user.truncate()
699        self.db.commit()
700
701    # TODO: def test_cas_login(self):
702    # TODO: def test_cas_validate(self):
703    # TODO: def test__reset_two_factor_auth(self):
704    # TODO: def test_when_is_logged_in_bypass_next_in_url(self):
705    # TODO: def test_login(self):
706    # TODO: def test_logout(self):
707
708    def test_logout_bare(self):
709        self.auth.login_user(self.db(self.db.auth_user.username == 'bart').select().first())  # bypass login_bare()
710        self.assertTrue(self.auth.is_logged_in())
711        self.auth.logout_bare()
712        self.assertFalse(self.auth.is_logged_in())
713
714    # TODO: def test_register(self):
715
716    def test_is_logged_in(self):
717        self.auth.user = 'logged_in'
718        self.assertTrue(self.auth.is_logged_in())
719        self.auth.user = None
720        self.assertFalse(self.auth.is_logged_in())
721
722    # TODO: def test_verify_email(self):
723    # TODO: def test_retrieve_username(self):
724
725    def test_random_password(self):
726        # let just check that the function is callable
727        self.assertTrue(self.auth.random_password())
728
729    # TODO: def test_reset_password_deprecated(self):
730    # TODO: def test_confirm_registration(self):
731    # TODO: def test_email_registration(self):
732
733    def test_bulk_register(self):
734        self.auth.login_user(self.db(self.db.auth_user.username == 'bart').select().first())  # bypass login_bare()
735        self.auth.settings.bulk_register_enabled = True
736        bulk_register_form = self.auth.bulk_register(max_emails=10).xml()
737        self.assertTrue(b'name="_formkey"' in bulk_register_form)
738
739    # TODO: def test_manage_tokens(self):
740    # TODO: def test_reset_password(self):
741    # TODO: def test_request_reset_password(self):
742    # TODO: def test_email_reset_password(self):
743    # TODO: def test_retrieve_password(self):
744
745    def test_change_password(self):
746        self.auth.login_user(self.db(self.db.auth_user.username == 'bart').select().first())  # bypass login_bare()
747        change_password_form = getattr(self.auth, 'change_password')().xml()
748        self.assertTrue(b'name="_formkey"' in change_password_form)
749
750    def test_profile(self):
751        self.auth.login_user(self.db(self.db.auth_user.username == 'bart').select().first())  # bypass login_bare()
752        profile_form = getattr(self.auth, 'profile')().xml()
753        self.assertTrue(b'name="_formkey"' in profile_form)
754
755    # TODO: def test_run_login_onaccept(self):
756    # TODO: def test_jwt(self):
757    # TODO: def test_is_impersonating(self):
758
759    def test_impersonate(self):
760        # Create a user to be impersonated
761        self.auth.get_or_create_user(dict(first_name='Omer',
762                                          last_name='Simpson',
763                                          username='omer',
764                                          email='omer@test.com',
765                                          password='password_omer',
766                                          registration_key='',
767                                          registration_id=''),
768                                     login=False)
769        self.db.commit()
770        self.assertFalse(self.auth.is_logged_in())
771        # Create impersonate group, assign bart to impersonate group and add impersonate permission over auth_user
772        group_id = self.auth.add_group('impersonate')
773        self.auth.add_membership(user_id=self.db(self.db.auth_user.username == 'bart'
774                                                 ).select(self.db.auth_user.id).first().id,
775                                 group_id=group_id)
776        self.auth.add_permission(group_id=group_id,
777                                 name='impersonate',
778                                 table_name='auth_user',
779                                 record_id=0)
780        # Bart login
781        # self.auth.login_bare(username='bart', password='bart_password')
782        self.auth.login_user(self.db(self.db.auth_user.username == 'bart').select().first())  # bypass login_bare()
783        self.assertTrue(self.auth.is_logged_in())
784        bart_id = self.db(self.db.auth_user.username == 'bart').select(self.db.auth_user.id).first().id
785        self.assertEqual(self.auth.user_id, bart_id)
786        # self.session.auth = self.auth
787        # self.assertTrue(self.session.auth)
788
789        # basic impersonate() test that return a read form
790        self.assertEqual(self.auth.impersonate().xml(),
791                         b'<form action="#" enctype="multipart/form-data" method="post"><table><tr id="no_table_user_id__row"><td class="w2p_fl"><label class="" for="no_table_user_id" id="no_table_user_id__label">User Id: </label></td><td class="w2p_fw"><input class="integer" id="no_table_user_id" name="user_id" type="text" value="" /></td><td class="w2p_fc"></td></tr><tr id="submit_record__row"><td class="w2p_fl"></td><td class="w2p_fw"><input type="submit" value="Submit" /></td><td class="w2p_fc"></td></tr></table></form>')
792        # bart impersonate itself
793        self.assertEqual(self.auth.impersonate(bart_id), None)
794        self.assertFalse(self.auth.is_impersonating())  # User shouldn't impersonate itself?
795        # Bart impersonate Omer
796        omer_id = self.db(self.db.auth_user.username == 'omer').select(self.db.auth_user.id).first().id
797        impersonate_form = self.auth.impersonate(user_id=omer_id)
798        self.assertTrue(self.auth.is_impersonating())
799        self.assertEqual(self.auth.user_id, omer_id)  # we make it really sure
800        self.assertEqual(impersonate_form.xml(),
801                         b'<form action="#" enctype="multipart/form-data" method="post"><table><tr id="auth_user_id__row"><td class="w2p_fl"><label class="readonly" for="auth_user_id" id="auth_user_id__label">Id: </label></td><td class="w2p_fw"><span id="auth_user_id">2</span></td><td class="w2p_fc"></td></tr><tr id="auth_user_first_name__row"><td class="w2p_fl"><label class="readonly" for="auth_user_first_name" id="auth_user_first_name__label">First name: </label></td><td class="w2p_fw">Omer</td><td class="w2p_fc"></td></tr><tr id="auth_user_last_name__row"><td class="w2p_fl"><label class="readonly" for="auth_user_last_name" id="auth_user_last_name__label">Last name: </label></td><td class="w2p_fw">Simpson</td><td class="w2p_fc"></td></tr><tr id="auth_user_email__row"><td class="w2p_fl"><label class="readonly" for="auth_user_email" id="auth_user_email__label">E-mail: </label></td><td class="w2p_fw">omer@test.com</td><td class="w2p_fc"></td></tr><tr id="auth_user_username__row"><td class="w2p_fl"><label class="readonly" for="auth_user_username" id="auth_user_username__label">Username: </label></td><td class="w2p_fw">omer</td><td class="w2p_fc"></td></tr></table><div style="display:none;"><input name="id" type="hidden" value="2" /></div></form>')
802        self.auth.logout_bare()
803        # Failing impersonation
804        # User lacking impersonate membership
805        self.auth.login_user(self.db(self.db.auth_user.username == 'omer').select().first())  # bypass login_bare()
806        # self.assertTrue(self.auth.is_logged_in())  # For developing test
807        # self.assertFalse(self.auth.is_impersonating())  # For developing test
808        self.myassertRaisesRegex(HTTP, "403*", self.auth.impersonate, bart_id)
809        self.auth.logout_bare()
810        # Try impersonate a non existing user
811        self.auth.login_user(self.db(self.db.auth_user.username == 'bart').select().first())  # bypass login_bare()
812        # self.assertTrue(self.auth.is_logged_in())  # For developing test
813        # self.assertFalse(self.auth.is_impersonating())  # For developing test
814        self.myassertRaisesRegex(HTTP, "401*", self.auth.impersonate, 1000)  # user with id 1000 shouldn't exist
815        # Try impersonate user with id = 0 or '0' when bart impersonating omer
816        self.auth.impersonate(user_id=omer_id)
817        self.assertTrue(self.auth.is_impersonating())
818        self.assertEqual(self.auth.impersonate(user_id=0), None)
819
820    # TODO: def test_update_groups(self):
821
822    def test_groups(self):
823        self.auth.login_user(self.db(self.db.auth_user.username == 'bart').select().first())  # bypass login_bare()
824        self.assertEqual(self.auth.groups().xml(),
825                         b'<table><tr><td><h3>user_1(1)</h3></td></tr><tr><td><p></p></td></tr></table>')
826
827    def test_not_authorized(self):
828        self.current.request.ajax = 'facke_ajax_request'
829        self.myassertRaisesRegex(HTTP, "403*", self.auth.not_authorized)
830        self.current.request.ajax = None
831        self.assertEqual(self.auth.not_authorized(), self.auth.messages.access_denied)
832
833    def test_allows_jwt(self):
834        self.myassertRaisesRegex(HTTP, "400*", self.auth.allows_jwt)
835
836    # TODO: def test_requires(self):
837
838    # def test_login(self):
839    # Basic testing above in "test_basic_blank_forms()" could be refined here
840
841    # TODO: def test_requires_login_or_token(self):
842    # TODO: def test_requires_membership(self):
843    # TODO: def test_requires_permission(self):
844    # TODO: def test_requires_signature(self):
845
846    def test_add_group(self):
847        self.assertEqual(self.auth.add_group(role='a_group', description='a_group_role_description'),
848                         self.db(self.db.auth_group.role == 'a_group').select(self.db.auth_group.id).first().id)
849
850    def test_del_group(self):
851        bart_group_id = 1  # Should be group 1, 'user_1'
852        self.assertEqual(self.auth.del_group(group_id=bart_group_id), None)
853
854    def test_id_group(self):
855        self.assertEqual(self.auth.id_group(role='user_1'), 1)
856        # If role don't exist it return None
857        self.assertEqual(self.auth.id_group(role='non_existing_role_name'), None)
858
859    def test_user_group(self):
860        self.assertEqual(self.auth.user_group(user_id=1), 1)
861        # Bart should be user 1 and it unique group should be 1, 'user_1'
862
863    def test_user_group_role(self):
864        self.auth.login_user(self.db(self.db.auth_user.username == 'bart').select().first())  # bypass login_bare()
865        user_group_role = 'user_%s' % self.db(self.db.auth_user.username == 'bart'
866                                              ).select(self.db.auth_user.id).first().id
867        self.assertEqual(self.auth.user_group_role(), user_group_role)
868        self.auth.logout_bare()
869        # with user_id args
870        self.assertEqual(self.auth.user_group_role(user_id=1), 'user_1')
871        # test None
872        self.auth.settings.create_user_groups = None
873        self.assertEqual(self.auth.user_group_role(user_id=1), None)
874
875    def test_has_membership(self):
876        self.auth.login_user(self.db(self.db.auth_user.username == 'bart').select().first())  # bypass login_bare()
877        self.assertTrue(self.auth.has_membership('user_1'))
878        self.assertFalse(self.auth.has_membership('user_555'))
879        self.assertTrue(self.auth.has_membership(group_id=1))
880        self.auth.logout_bare()
881        self.assertTrue(self.auth.has_membership(role='user_1', user_id=1))
882        self.assertTrue(self.auth.has_membership(group_id=1, user_id=1))
883        # check that event is logged
884        count_log_event_test_before = self.db(self.db.auth_event.id > 0).count()
885        self.assertTrue(self.auth.has_membership(group_id=1, user_id=1))
886        count_log_event_test_after = self.db(self.db.auth_event.id > 0).count()
887        self.assertEqual(count_log_event_test_after, count_log_event_test_before)
888
889    def test_add_membership(self):
890        user = self.db(self.db.auth_user.username == 'bart').select().first()  # bypass login_bare()
891        user_id = user.id
892        role_name = 'test_add_membership_group'
893        group_id = self.auth.add_group(role_name)
894        self.assertFalse(self.auth.has_membership(role_name))
895
896        self.auth.add_membership(group_id=group_id, user_id=user_id)
897        self.assertTrue(self.auth.has_membership(group_id, user_id=user_id))
898        self.auth.del_membership(group_id=group_id, user_id=user_id)
899        self.assertFalse(self.auth.has_membership(group_id, user_id=user_id))
900
901        self.auth.add_membership(role=role_name, user_id=user_id)
902        self.assertTrue(self.auth.has_membership(group_id, user_id=user_id))
903        self.auth.del_membership(group_id=group_id, user_id=user_id)
904        self.assertFalse(self.auth.has_membership(group_id, user_id=user_id))
905
906        with self.myassertRaisesRegex(ValueError, '^group_id not provided or invalid$'):
907            self.auth.add_membership(group_id='not_existing_group_name', user_id=user_id)
908        with self.myassertRaisesRegex(ValueError, '^group_id not provided or invalid$'):
909            self.auth.add_membership(role='not_existing_role_name', user_id=user_id)
910        with self.myassertRaisesRegex(ValueError, '^user_id not provided or invalid$'):
911            self.auth.add_membership(group_id=group_id, user_id=None)
912        with self.myassertRaisesRegex(ValueError, '^user_id not provided or invalid$'):
913            self.auth.add_membership(role=role_name, user_id=None)
914
915        self.auth.login_user(user)
916
917        self.auth.add_membership(group_id=group_id)
918        self.assertTrue(self.auth.has_membership(group_id))
919        self.auth.del_membership(group_id=group_id)
920        self.assertFalse(self.auth.has_membership(group_id))
921
922        self.auth.add_membership(role=role_name)
923        self.assertTrue(self.auth.has_membership(group_id))
924        self.auth.del_membership(group_id=group_id)
925        self.assertFalse(self.auth.has_membership(group_id))
926
927        # default usage (group_id=role_name)
928        self.auth.add_membership(role_name)
929        self.assertTrue(self.auth.has_membership(group_id))
930        self.auth.del_membership(group_id=group_id)
931        self.assertFalse(self.auth.has_membership(group_id))
932
933        # re-adding a membership should return the existing membership
934        record0_id = self.auth.add_membership(group_id)
935        self.assertTrue(self.auth.has_membership(group_id))
936        record1_id = self.auth.add_membership(group_id)
937        self.assertEqual(record0_id, record1_id)
938        self.auth.del_membership(group_id=group_id)
939        self.assertFalse(self.auth.has_membership(group_id))
940
941        with self.myassertRaisesRegex(ValueError, '^group_id not provided or invalid$'):
942            self.auth.add_membership(group_id='not_existing_group_name')
943        with self.myassertRaisesRegex(ValueError, '^group_id not provided or invalid$'):
944            self.auth.add_membership(role='not_existing_role_name')
945
946    def test_del_membership(self):
947        self.auth.login_user(self.db(self.db.auth_user.username == 'bart').select().first())  # bypass login_bare()
948        count_log_event_test_before = self.db(self.db.auth_event.id > 0).count()
949        user_1_role_id = self.db(self.db.auth_membership.group_id == self.auth.id_group('user_1')
950                                 ).select(self.db.auth_membership.id).first().id
951        self.assertEqual(self.auth.del_membership('user_1'), user_1_role_id)
952        count_log_event_test_after = self.db(self.db.auth_event.id > 0).count()
953        # check that event is logged
954        self.assertEqual(count_log_event_test_after, count_log_event_test_before)
955        # not logged in test case
956        group_id = self.auth.add_group('some_test_group')
957        membership_id = self.auth.add_membership('some_test_group')
958        self.assertEqual(self.auth.user_groups[group_id], 'some_test_group')
959        self.auth.logout_bare()
960        # not deleted
961        self.assertFalse(self.auth.del_membership('some_test_group'))
962        self.assertEqual(set(self.db.auth_membership(membership_id).as_dict().items()),
963                         set({'group_id': 2, 'user_id': 1, 'id': 2}.items()))  # is not deleted
964        # deleted
965        bart_id = self.db(self.db.auth_user.username == 'bart').select(self.db.auth_user.id).first().id
966        self.assertTrue(self.auth.del_membership('some_test_group', user_id=bart_id))
967        self.assertEqual(self.db.auth_membership(membership_id), None)  # is really deleted
968
969    def test_has_permission(self):
970        self.auth.login_user(self.db(self.db.auth_user.username == 'bart').select().first())  # bypass login_bare()
971        bart_id = self.db(self.db.auth_user.username == 'bart').select(self.db.auth_user.id).first().id
972        self.auth.add_permission(group_id=self.auth.id_group('user_1'),
973                                 name='some_permission',
974                                 table_name='auth_user',
975                                 record_id=0,
976                                 )
977        # True case
978        self.assertTrue(self.auth.has_permission(name='some_permission',
979                                                 table_name='auth_user',
980                                                 record_id=0,
981                                                 user_id=bart_id,
982                                                 group_id=self.auth.id_group('user_1')))
983        # False case
984        self.assertFalse(self.auth.has_permission(name='some_other_permission',
985                                                  table_name='auth_user',
986                                                  record_id=0,
987                                                  user_id=bart_id,
988                                                  group_id=self.auth.id_group('user_1')))
989
990    def test_add_permission(self):
991        count_log_event_test_before = self.db(self.db.auth_event.id > 0).count()
992        permission_id = \
993            self.auth.add_permission(group_id=self.auth.id_group('user_1'),
994                                     name='some_permission',
995                                     table_name='auth_user',
996                                     record_id=0,
997                                     )
998        count_log_event_test_after = self.db(self.db.auth_event.id > 0).count()
999        # check that event is logged
1000        self.assertEqual(count_log_event_test_after, count_log_event_test_before)
1001        # True case
1002        permission_count = \
1003            self.db(self.db.auth_permission.id == permission_id).count()
1004        self.assertTrue(permission_count)
1005        # False case
1006        permission_count = \
1007            self.db((self.db.auth_permission.group_id == self.auth.id_group('user_1')) &
1008                    (self.db.auth_permission.name == 'no_permission') &
1009                    (self.db.auth_permission.table_name == 'no_table') &
1010                    (self.db.auth_permission.record_id == 0)).count()
1011        self.assertFalse(permission_count)
1012        # corner case
1013        self.auth.login_user(self.db(self.db.auth_user.username == 'bart').select().first())  # bypass login_bare()
1014        permission_id = \
1015            self.auth.add_permission(group_id=0,
1016                                     name='user_1_permission',
1017                                     table_name='auth_user',
1018                                     record_id=0,
1019                                     )
1020        permission_name = \
1021            self.db(self.db.auth_permission.id == permission_id).select(self.db.auth_permission.name).first().name
1022        self.assertEqual(permission_name, 'user_1_permission')
1023        # add an existing permission
1024        permission_id =\
1025            self.auth.add_permission(group_id=0,
1026                                     name='user_1_permission',
1027                                     table_name='auth_user',
1028                                     record_id=0,
1029                                     )
1030        self.assertTrue(permission_id)
1031
1032    def test_del_permission(self):
1033        permission_id = \
1034            self.auth.add_permission(group_id=self.auth.id_group('user_1'),
1035                                     name='del_permission_test',
1036                                     table_name='auth_user',
1037                                     record_id=0,
1038                                     )
1039        count_log_event_test_before = self.db(self.db.auth_event.id > 0).count()
1040        self.assertTrue(self.auth.del_permission(group_id=self.auth.id_group('user_1'),
1041                                                 name='del_permission_test',
1042                                                 table_name='auth_user',
1043                                                 record_id=0,))
1044        count_log_event_test_after = self.db(self.db.auth_event.id > 0).count()
1045        # check that event is logged
1046        self.assertEqual(count_log_event_test_after, count_log_event_test_before)
1047        # really deleted
1048        permission_count = \
1049            self.db(self.db.auth_permission.id == permission_id).count()
1050        self.assertFalse(permission_count)
1051
1052    # TODO: def test_accessible_query(self):
1053    # TODO: def test_archive(self):
1054    # TODO: def test_wiki(self):
1055    # TODO: def test_wikimenu(self):
1056    # End Auth test
1057
1058
1059# TODO: class TestCrud(unittest.TestCase):
1060# It deprecated so far from a priority
1061
1062
1063# TODO: class TestService(unittest.TestCase):
1064
1065
1066# TODO: class TestPluginManager(unittest.TestCase):
1067
1068
1069# TODO: class TestWiki(unittest.TestCase):
1070
1071
1072# TODO: class TestConfig(unittest.TestCase):
1073
1074
1075class TestToolsFunctions(unittest.TestCase):
1076    """
1077    Test suite for all the tools.py functions
1078    """
1079    def test_prettydate(self):
1080        # plain
1081        now = datetime.datetime.now()
1082        self.assertEqual(prettydate(d=now), 'now')
1083        one_second = now - datetime.timedelta(seconds=1)
1084        self.assertEqual(prettydate(d=one_second), '1 second ago')
1085        more_than_one_second = now - datetime.timedelta(seconds=2)
1086        self.assertEqual(prettydate(d=more_than_one_second), '2 seconds ago')
1087        one_minute = now - datetime.timedelta(seconds=60)
1088        self.assertEqual(prettydate(d=one_minute), '1 minute ago')
1089        more_than_one_minute = now - datetime.timedelta(seconds=61)
1090        self.assertEqual(prettydate(d=more_than_one_minute), '1 minute ago')
1091        two_minutes = now - datetime.timedelta(seconds=120)
1092        self.assertEqual(prettydate(d=two_minutes), '2 minutes ago')
1093        more_than_two_minutes = now - datetime.timedelta(seconds=121)
1094        self.assertEqual(prettydate(d=more_than_two_minutes), '2 minutes ago')
1095        one_hour = now - datetime.timedelta(seconds=60 * 60)
1096        self.assertEqual(prettydate(d=one_hour), '1 hour ago')
1097        more_than_one_hour = now - datetime.timedelta(seconds=3601)
1098        self.assertEqual(prettydate(d=more_than_one_hour), '1 hour ago')
1099        two_hours = now - datetime.timedelta(seconds=2 * 60 * 60)
1100        self.assertEqual(prettydate(d=two_hours), '2 hours ago')
1101        more_than_two_hours = now - datetime.timedelta(seconds=2 * 60 * 60 + 1)
1102        self.assertEqual(prettydate(d=more_than_two_hours), '2 hours ago')
1103        one_day = now - datetime.timedelta(days=1)
1104        self.assertEqual(prettydate(d=one_day), '1 day ago')
1105        more_than_one_day = now - datetime.timedelta(days=2)
1106        self.assertEqual(prettydate(d=more_than_one_day), '2 days ago')
1107        one_week = now - datetime.timedelta(days=7)
1108        self.assertEqual(prettydate(d=one_week), '1 week ago')
1109        more_than_one_week = now - datetime.timedelta(days=8)
1110        self.assertEqual(prettydate(d=more_than_one_week), '1 week ago')
1111        two_weeks = now - datetime.timedelta(days=14)
1112        self.assertEqual(prettydate(d=two_weeks), '2 weeks ago')
1113        more_than_two_weeks = now - datetime.timedelta(days=15)
1114        self.assertEqual(prettydate(d=more_than_two_weeks), '2 weeks ago')
1115        three_weeks = now - datetime.timedelta(days=21)
1116        self.assertEqual(prettydate(d=three_weeks), '3 weeks ago')
1117        one_month = now - datetime.timedelta(days=27)
1118        self.assertEqual(prettydate(d=one_month), '1 month ago')
1119        more_than_one_month = now - datetime.timedelta(days=28)
1120        self.assertEqual(prettydate(d=more_than_one_month), '1 month ago')
1121        two_months = now - datetime.timedelta(days=60)
1122        self.assertEqual(prettydate(d=two_months), '2 months ago')
1123        three_months = now - datetime.timedelta(days=90)
1124        self.assertEqual(prettydate(d=three_months), '3 months ago')
1125        one_year = now - datetime.timedelta(days=365)
1126        self.assertEqual(prettydate(d=one_year), '1 year ago')
1127        more_than_one_year = now - datetime.timedelta(days=366)
1128        self.assertEqual(prettydate(d=more_than_one_year), '1 year ago')
1129        two_years = now - datetime.timedelta(days=2 * 365)
1130        self.assertEqual(prettydate(d=two_years), '2 years ago')
1131        more_than_two_years = now - datetime.timedelta(days=2 * 365 + 1)
1132        self.assertEqual(prettydate(d=more_than_two_years), '2 years ago')
1133        # date()
1134        d = now.date()
1135        self.assertEqual(prettydate(d=d), 'now')
1136        one_day = now.date() - datetime.timedelta(days=1)
1137        self.assertEqual(prettydate(d=one_day), '1 day ago')
1138        tow_days = now.date() - datetime.timedelta(days=2)
1139        self.assertEqual(prettydate(d=tow_days), '2 days ago')
1140        # from now
1141        # from now is picky depending of the execution time, so we can't use sharp value like 1 second or 1 day
1142        in_one_minute = now - datetime.timedelta(seconds=-65)
1143        self.assertEqual(prettydate(d=in_one_minute), '1 minute from now')
1144        in_twenty_three_hours = now - datetime.timedelta(hours=-23.5)
1145        self.assertEqual(prettydate(d=in_twenty_three_hours), '23 hours from now')
1146        in_one_year = now - datetime.timedelta(days=-366)
1147        self.assertEqual(prettydate(d=in_one_year), '1 year from now')
1148        # utc=True
1149        now = datetime.datetime.utcnow()
1150        self.assertEqual(prettydate(d=now, utc=True), 'now')
1151        one_second = now - datetime.timedelta(seconds=1)
1152        self.assertEqual(prettydate(d=one_second, utc=True), '1 second ago')
1153        # not d or invalid date
1154        self.assertEqual(prettydate(d=None), '')
1155        self.assertEqual(prettydate(d='invalid_date'), '[invalid date]')
1156
1157
1158pjoin = os.path.join
1159
1160
1161def have_symlinks():
1162    return os.name == 'posix'
1163
1164
1165class Test_Expose__in_base(unittest.TestCase):
1166
1167    def test_in_base(self):
1168        are_under = [
1169            # (sub, base)
1170            ('/foo/bar', '/foo'),
1171            ('/foo', '/foo'),
1172            ('/foo', '/'),
1173            ('/', '/'),
1174        ]
1175        for sub, base in are_under:
1176            self.assertTrue(Expose._Expose__in_base(subdir=sub, basedir=base, sep='/'),
1177                            '%s is not under %s' % (sub, base))
1178
1179    def test_not_in_base(self):
1180        are_not_under = [
1181            # (sub, base)
1182            ('/foobar', '/foo'),
1183            ('/foo', '/foo/bar'),
1184            ('/bar', '/foo'),
1185            ('/foo/bar', '/bar'),
1186            ('/', '/x'),
1187        ]
1188        for sub, base in are_not_under:
1189            self.assertFalse(Expose._Expose__in_base(subdir=sub, basedir=base, sep='/'),
1190                             '%s should not be under %s' % (sub, base))
1191
1192
1193class TestExpose(unittest.TestCase):
1194
1195    def setUp(self):
1196        self.base_dir = tempfile.mkdtemp()
1197
1198        self.make_dirs()
1199        self.touch_files()
1200        self.make_readme()
1201        if have_symlinks():
1202            self.make_symlinks()
1203
1204        # $BASE/
1205        # |-- inside/
1206        # |   |-- dir1/
1207        # |   |   |-- file1
1208        # |   |   `-- file2
1209        # |   |-- dir2/
1210        # |   |   |-- link_to_dir1/@ -> $BASE/inside/dir1/
1211        # |   |   `-- link_to_file1@ -> $BASE/inside/dir1/file1
1212        # |   |-- link_to_outside/@ -> $BASE/outside/
1213        # |   |-- link_to_file3@ -> $BASE/outside/file3
1214        # |   `-- README
1215        # `-- outside/
1216        #     `-- file3
1217
1218        self.set_expectations()
1219        tools.URL = lambda args: URL(a='a', c='c', f='f', args=args)
1220
1221    def tearDown(self):
1222        tools.URL = URL
1223        shutil.rmtree(self.base_dir)
1224
1225    def make_dirs(self):
1226        """setup directory structure"""
1227        for d in (['inside'],
1228                  ['inside', 'dir1'],
1229                  ['inside', 'dir2'],
1230                  ['outside']):
1231            os.mkdir(pjoin(self.base_dir, *d))
1232
1233    def touch_files(self):
1234        """create some files"""
1235        for f in (['inside', 'dir1', 'file1'],
1236                  ['inside', 'dir1', 'file2'],
1237                  ['outside', 'file3']):
1238            with open(pjoin(self.base_dir, *f), 'a'):
1239                pass
1240
1241    def make_readme(self):
1242        with open(pjoin(self.base_dir, 'inside', 'README'), 'w') as f:
1243            f.write('README content')
1244
1245    def make_symlinks(self):
1246        """setup extension for posix systems"""
1247        # inside links
1248        os.symlink(
1249            pjoin(self.base_dir, 'inside', 'dir1'),
1250            pjoin(self.base_dir, 'inside', 'dir2', 'link_to_dir1'))
1251        os.symlink(
1252            pjoin(self.base_dir, 'inside', 'dir1', 'file1'),
1253            pjoin(self.base_dir, 'inside', 'dir2', 'link_to_file1'))
1254        # outside links
1255        os.symlink(
1256            pjoin(self.base_dir, 'outside'),
1257            pjoin(self.base_dir, 'inside', 'link_to_outside'))
1258        os.symlink(
1259            pjoin(self.base_dir, 'outside', 'file3'),
1260            pjoin(self.base_dir, 'inside', 'link_to_file3'))
1261
1262    def set_expectations(self):
1263        url = lambda args: URL('a', 'c', 'f', args=args)
1264
1265        self.expected_folders = {}
1266        self.expected_folders['inside'] = SPAN(H3('Folders'), TABLE(
1267            TR(TD(A('dir1', _href=url(args=['dir1'])))),
1268            TR(TD(A('dir2', _href=url(args=['dir2'])))),
1269            _class='table',
1270        ))
1271        self.expected_folders[pjoin('inside', 'dir1')] = ''
1272        if have_symlinks():
1273            self.expected_folders[pjoin('inside', 'dir2')] = SPAN(H3('Folders'), TABLE(
1274                TR(TD(A('link_to_dir1', _href=url(args=['dir2', 'link_to_dir1'])))),
1275                _class='table',
1276            ))
1277        else:
1278            self.expected_folders[pjoin('inside', 'dir2')] = ''
1279
1280        self.expected_files = {}
1281        self.expected_files['inside'] = SPAN(H3('Files'), TABLE(
1282            TR(TD(A('README', _href=url(args=['README']))), TD('')),
1283            _class='table',
1284        ))
1285        self.expected_files[pjoin('inside', 'dir1')] = SPAN(H3('Files'), TABLE(
1286            TR(TD(A('file1', _href=url(args=['dir1', 'file1']))), TD('')),
1287            TR(TD(A('file2', _href=url(args=['dir1', 'file2']))), TD('')),
1288            _class='table',
1289        ))
1290        if have_symlinks():
1291            self.expected_files[pjoin('inside', 'dir2')] = SPAN(H3('Files'), TABLE(
1292                TR(TD(A('link_to_file1', _href=url(args=['dir2', 'link_to_file1']))), TD('')),
1293                _class='table',
1294            ))
1295        else:
1296            self.expected_files[pjoin('inside', 'dir2')] = ''
1297
1298    def make_expose(self, base, show='', follow_symlink_out=False):
1299        current.request = Request(env={})
1300        current.request.raw_args = show
1301        current.request.args = show.split('/')
1302        return Expose(base=pjoin(self.base_dir, base),
1303                      basename=base,
1304                      follow_symlink_out=follow_symlink_out)
1305
1306    def test_expose_inside_state(self):
1307        expose = self.make_expose(base='inside', show='')
1308        self.assertEqual(expose.args, [])
1309        self.assertEqual(expose.folders, ['dir1', 'dir2'])
1310        self.assertEqual(expose.filenames, ['README'])
1311
1312    @unittest.skipUnless(have_symlinks(), 'requires symlinks')
1313    def test_expose_inside_state_floow_symlink_out(self):
1314        expose = self.make_expose(base='inside', show='',
1315                                  follow_symlink_out=True)
1316        self.assertEqual(expose.args, [])
1317        self.assertEqual(expose.folders, ['dir1', 'dir2', 'link_to_outside'])
1318        self.assertEqual(expose.filenames, ['README', 'link_to_file3'])
1319
1320    def test_expose_inside_dir1_state(self):
1321        expose = self.make_expose(base='inside', show='dir1')
1322        self.assertEqual(expose.args, ['dir1'])
1323        self.assertEqual(expose.folders, [])
1324        self.assertEqual(expose.filenames, ['file1', 'file2'])
1325
1326    def test_expose_inside_dir2_state(self):
1327        expose = self.make_expose(base='inside', show='dir2')
1328        self.assertEqual(expose.args, ['dir2'])
1329        if have_symlinks():
1330            self.assertEqual(expose.folders, ['link_to_dir1'])
1331            self.assertEqual(expose.filenames, ['link_to_file1'])
1332        else:
1333            self.assertEqual(expose.folders, [])
1334            self.assertEqual(expose.filenames, [])
1335
1336    def test_expose_base_inside_state(self):
1337        expose = self.make_expose(base='', show='inside')
1338        self.assertEqual(expose.args, ['inside'])
1339        if have_symlinks():
1340            self.assertEqual(expose.folders, ['dir1', 'dir2', 'link_to_outside'])
1341            self.assertEqual(expose.filenames, ['README', 'link_to_file3'])
1342        else:
1343            self.assertEqual(expose.folders, ['dir1', 'dir2'])
1344            self.assertEqual(expose.filenames, ['README'])
1345
1346    def test_expose_base_inside_dir2_state(self):
1347        expose = self.make_expose(base='', show='inside/dir2')
1348        self.assertEqual(expose.args, ['inside', 'dir2'])
1349        if have_symlinks():
1350            self.assertEqual(expose.folders, ['link_to_dir1'])
1351            self.assertEqual(expose.filenames, ['link_to_file1'])
1352        else:
1353            self.assertEqual(expose.folders, [])
1354            self.assertEqual(expose.filenames, [])
1355
1356    def assertSameXML(self, a, b):
1357        self.assertEqual(a if isinstance(a, str) else a.xml(),
1358                         b if isinstance(b, str) else b.xml())
1359
1360    def run_test_xml_for(self, base, show):
1361        expose = self.make_expose(base, show)
1362        path = pjoin(base, show).rstrip(os.path.sep)
1363        request = Request(env={})
1364        self.assertSameXML(expose.table_files(), self.expected_files[path])
1365        self.assertSameXML(expose.table_folders(), self.expected_folders[path])
1366
1367    def test_xml_inside(self):
1368        self.run_test_xml_for(base='inside', show='')
1369
1370    def test_xml_dir1(self):
1371        self.run_test_xml_for(base='inside', show='dir1')
1372
1373    def test_xml_dir2(self):
1374        self.run_test_xml_for(base='inside', show='dir2')
1375
1376    def test_file_not_found(self):
1377        with self.assertRaises(HTTP):
1378            self.make_expose(base='inside', show='dir1/file_not_found')
1379
1380    def test_not_authorized(self):
1381        with self.assertRaises(HTTP):
1382            self.make_expose(base='inside', show='link_to_file3')
Note: See TracBrowser for help on using the repository browser.