changeset 62:50297a64414c

Added locking.py for super non-grannular thread safety, and more tests.
author Atul Varma <avarma@mozilla.com>
date Tue, 29 Jun 2010 11:17:34 -0700
parents 2d981c2a7f9a
children 5cf375ec179e
files summitidp/easy.py summitidp/locking.py tests/test_easy.py tests/test_locking.py
diffstat 4 files changed, 74 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/summitidp/easy.py	Mon Jun 28 22:32:03 2010 -0700
+++ b/summitidp/easy.py	Tue Jun 29 11:17:34 2010 -0700
@@ -4,6 +4,7 @@
 
 from summitidp.app import Server, TokenStore, ProfileStore
 from summitidp.file_storage import FileStorage
+from summitidp.locking import synced_app
 
 CHALLENGE_TOKEN_LIFETIME = datetime.timedelta(days=1)
 AUTH_TOKEN_LIFETIME = None
@@ -31,4 +32,4 @@
         profiles=ProfileStore(FileStorage(profile_dir))
         )
 
-    return server.wsgi_app
+    return synced_app(server.wsgi_app)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/summitidp/locking.py	Tue Jun 29 11:17:34 2010 -0700
@@ -0,0 +1,13 @@
+import threading
+
+def synced_app(app):
+    lock = threading.Lock()
+
+    def synced_wsgi_app(environ, start_response):
+        lock.acquire()
+        try:
+            return app(environ, start_response)
+        finally:
+            lock.release()
+
+    return synced_wsgi_app
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test_easy.py	Tue Jun 29 11:17:34 2010 -0700
@@ -0,0 +1,21 @@
+import tempfile
+import shutil
+import os
+import json
+
+from summitidp.easy import make_wsgi_app
+
+def fake_send_email(*args, **kwargs):
+    pass
+
+def test_ensure_easy_does_not_smoke():
+    dirname = tempfile.mkdtemp(prefix="testing")
+
+    f = open(os.path.join(dirname, 'attendees.json'), 'w')
+    f.write(json.dumps(['bob@foo.com']))
+    f.close()
+
+    app = make_wsgi_app(dirname, fake_send_email)
+    assert callable(app)
+
+    shutil.rmtree(dirname)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test_locking.py	Tue Jun 29 11:17:34 2010 -0700
@@ -0,0 +1,38 @@
+from summitidp import locking
+
+def fake_start_response(*args, **kwargs):
+    pass
+
+class FakeException(Exception):
+    pass
+
+def test_synced_app_works_consecutively():
+    @locking.synced_app
+    def myapp(environ, start_response):
+        assert start_response == fake_start_response
+        assert isinstance(environ, dict)
+        return []
+
+    assert myapp({}, fake_start_response) == []
+    assert myapp({}, fake_start_response) == []
+
+def test_synced_app_throws_exception():
+    @locking.synced_app
+    def myapp(environ, start_response):
+        assert start_response == fake_start_response
+        assert isinstance(environ, dict)
+        raise FakeException()
+
+    try:
+        myapp({}, fake_start_response)
+        raise Exception("exception should have been raised!")
+    except FakeException:
+        pass
+
+    # Ensure the lock was released when the exception was thrown.
+
+    try:
+        myapp({}, fake_start_response)
+        raise Exception("exception should have been raised!")
+    except FakeException:
+        pass