Bladeren bron

Radicale: tests: fix for multiples tests + test auth

Bastien Sevajol (Algoo) 8 jaren geleden
bovenliggende
commit
0f361f6552

+ 1 - 0
install/requirements.txt Bestand weergeven

@@ -52,3 +52,4 @@ who-ldap==3.1.0
52 52
 unicode-slugify==0.1.3
53 53
 Radicale==1.1.1
54 54
 icalendar==3.10
55
+caldav==0.4.0

+ 53 - 4
tracim/tracim/lib/daemons.py Bestand weergeven

@@ -1,6 +1,8 @@
1 1
 import threading
2 2
 from wsgiref.simple_server import make_server
3 3
 import signal
4
+
5
+import collections
4 6
 import transaction
5 7
 
6 8
 from radicale import Application as RadicaleApplication
@@ -59,7 +61,7 @@ class DaemonsManager(object):
59 61
 
60 62
     def stop_all(self, *args, **kwargs) -> None:
61 63
         """
62
-        Stop all started daemons and w<ait for them.
64
+        Stop all started daemons and wait for them.
63 65
         """
64 66
         logger.info(self, 'Stopping all daemons')
65 67
         for name, daemon in self._running_daemons.items():
@@ -72,12 +74,27 @@ class DaemonsManager(object):
72 74
 
73 75
         self._running_daemons = {}
74 76
 
77
+    def execute_in_thread(self, thread_name, callback):
78
+        self._running_daemons[thread_name].append_thread_callback(callback)
79
+
75 80
 
76 81
 class TracimSocketServerMixin(object):
77 82
     """
78 83
     Mixin to use with socketserver.BaseServer who add _after_serve_actions
79 84
     method executed after end of server execution.
80 85
     """
86
+    def __init__(self, *args, **kwargs):
87
+        super().__init__(*args, **kwargs)
88
+        self._daemon_execute_callbacks = []
89
+
90
+    def append_thread_callback(self, callback: collections.Callable) -> None:
91
+        """
92
+        Add callback to self._daemon_execute_callbacks. See service_actions
93
+        function to their usages.
94
+        :param callback: callback to execute in daemon
95
+        """
96
+        self._daemon_execute_callbacks.append(callback)
97
+
81 98
     def serve_forever(self, *args, **kwargs):
82 99
         super().serve_forever(*args, **kwargs)
83 100
         # After serving (in case of stop) do following:
@@ -88,7 +105,15 @@ class TracimSocketServerMixin(object):
88 105
         Override (and call super if needed) to execute actions when server
89 106
         finish it's job.
90 107
         """
91
-        transaction.commit()
108
+        pass
109
+
110
+    def service_actions(self):
111
+        if len(self._daemon_execute_callbacks):
112
+            try:
113
+                while True:
114
+                    self._daemon_execute_callbacks.pop()()
115
+            except IndexError:
116
+                pass  # Finished to iter
92 117
 
93 118
 
94 119
 class Daemon(threading.Thread):
@@ -96,10 +121,26 @@ class Daemon(threading.Thread):
96 121
     Thread who contains daemon. You must implement start and stop methods to
97 122
     manage daemon life correctly.
98 123
     """
99
-    def run(self):
124
+    def run(self) -> None:
125
+        """
126
+        Place here code who have to be executed in Daemon.
127
+        """
100 128
         raise NotImplementedError()
101 129
 
102
-    def stop(self):
130
+    def stop(self) -> None:
131
+        """
132
+        Place here code who stop your daemon
133
+        """
134
+        raise NotImplementedError()
135
+
136
+    def append_thread_callback(self, callback: collections.Callable) -> None:
137
+        """
138
+        Place here the logic who permit to execute a callback in your daemon.
139
+        To get an exemple of that, take a look at
140
+        socketserver.BaseServer#service_actions  and how we use it in
141
+        tracim.lib.daemons.TracimSocketServerMixin#service_actions .
142
+        :param callback: callback to execute in your thread.
143
+        """
103 144
         raise NotImplementedError()
104 145
 
105 146
 
@@ -157,3 +198,11 @@ class RadicaleDaemon(Daemon):
157 198
             RadicaleHTTPSServer if cfg.RADICALE_SERVER_SSL else RadicaleHTTPServer,
158 199
             RadicaleRequestHandler
159 200
         )
201
+
202
+    def append_thread_callback(self, callback: collections.Callable) -> None:
203
+        """
204
+        Give the callback to running server through
205
+        tracim.lib.daemons.TracimSocketServerMixin#append_thread_callback
206
+        :param callback: callback to execute in daemon
207
+        """
208
+        self._server.append_thread_callback(callback)

+ 15 - 2
tracim/tracim/tests/__init__.py Bestand weergeven

@@ -28,12 +28,14 @@ from who_ldap import make_connection
28 28
 
29 29
 from tracim.fixtures import FixturesLoader
30 30
 from tracim.fixtures.users_and_groups import Base as BaseFixture
31
-from tracim.config.app_cfg import daemons
31
+from tracim.fixtures.users_and_groups import Test as TestFixture
32
+from tracim.config.app_cfg import daemons, start_daemons
32 33
 from tracim.lib.base import logger
33 34
 from tracim.lib.content import ContentApi
34 35
 from tracim.lib.workspace import WorkspaceApi
35 36
 from tracim.model import DBSession, Content
36 37
 from tracim.model.data import Workspace, ContentType, ContentRevisionRO
38
+from tracim.lib.calendar import CALENDAR_BASE_URL
37 39
 
38 40
 __all__ = ['setup_app', 'setup_db', 'teardown_db', 'TestController']
39 41
 
@@ -240,7 +242,7 @@ class TestController(object):
240 242
     def tearDown(self):
241 243
         """Tear down test fixture for each functional test method."""
242 244
         DBSession.close()
243
-        daemons.stop_all()
245
+        daemons.execute_in_thread('radicale', lambda: transaction.commit())
244 246
         teardown_db()
245 247
 
246 248
 
@@ -349,6 +351,7 @@ class BaseTestThread(BaseTest):
349 351
 
350 352
 
351 353
 class TestCalendar(TestController):
354
+    fixtures = [BaseFixture, TestFixture]
352 355
     application_under_test = 'radicale'
353 356
 
354 357
     def setUp(self):
@@ -364,3 +367,13 @@ class TestCalendar(TestController):
364 367
                 os.remove('{0}/{1}'.format(radicale_fs_path, file))
365 368
         except FileNotFoundError:
366 369
             pass  # Dir not exists yet, no need to clear it
370
+
371
+    def _get_base_url(self):
372
+        from tracim.config.app_cfg import CFG
373
+        cfg = CFG.get_instance()
374
+
375
+        return CALENDAR_BASE_URL.format(
376
+            proto='https' if cfg.RADICALE_CLIENT_SSL else 'http',
377
+            domain=cfg.RADICALE_CLIENT_HOST or '127.0.0.1',
378
+            port=str(cfg.RADICALE_CLIENT_PORT)
379
+        )

+ 14 - 9
tracim/tracim/tests/functional/test_calendar.py Bestand weergeven

@@ -1,23 +1,18 @@
1 1
 import time
2 2
 
3
+import caldav
4
+from caldav.lib.error import AuthorizationError
3 5
 from nose.tools import eq_, ok_
4 6
 import requests
5 7
 from requests.exceptions import ConnectionError
6 8
 
7
-from tracim.lib.calendar import CALENDAR_BASE_URL
8 9
 from tracim.tests import TestCalendar as BaseTestCalendar
9 10
 
10 11
 
11 12
 class TestCalendar(BaseTestCalendar):
12
-    def test_unit__radicale_connectivity__ok__nominal_case(self):
13
-        from tracim.config.app_cfg import CFG
14
-        cfg = CFG.get_instance()
13
+    def test_func__radicale_connectivity__ok__nominal_case(self):
14
+        radicale_base_url = self._get_base_url()
15 15
 
16
-        radicale_base_url = CALENDAR_BASE_URL.format(
17
-            proto='https' if cfg.RADICALE_CLIENT_SSL else 'http',
18
-            domain=cfg.RADICALE_CLIENT_HOST or '127.0.0.1',
19
-            port=str(cfg.RADICALE_CLIENT_PORT)
20
-        )
21 16
         try:
22 17
             time.sleep(2)  # TODO - 20160606 - Bastien: sleep to wait ...
23 18
             # ... radicale daemon started. We should lock something somewhere !
@@ -25,3 +20,13 @@ class TestCalendar(BaseTestCalendar):
25 20
             eq_(response.status_code, 401, 'Radicale http response is 401')
26 21
         except ConnectionError:
27 22
             ok_(False, 'Unable to contact radicale on HTTP')
23
+
24
+    def test_func__radicale_auth__ok__as_lawrence(self):
25
+        client = caldav.DAVClient('http://127.0.0.1:15232',
26
+                                  username='lawrence-not-real-email@fsf.local',
27
+                                  password='foobarbaz')
28
+        try:
29
+            client.propfind()
30
+            ok_(True, 'No auth error when communicate with radicale server')
31
+        except AuthorizationError:
32
+            ok_(False, 'AuthorizationError when communicate with radicale')