[py-svn] r35122 - in py/branch/test-web-multiclient/py/test/rsession: . testing webdata

guido at codespeak.net guido at codespeak.net
Wed Nov 29 16:10:25 CET 2006


Author: guido
Date: Wed Nov 29 16:10:23 2006
New Revision: 35122

Modified:
   py/branch/test-web-multiclient/py/test/rsession/testing/test_web.py
   py/branch/test-web-multiclient/py/test/rsession/web.py
   py/branch/test-web-multiclient/py/test/rsession/webdata/source.js
   py/branch/test-web-multiclient/py/test/rsession/webjs.py
Log:
First steps to multi-client access to the web server. There is now a MultiQueue
object that is used instead of a normal queue, to queue events. This holds a
queue per connected client, determining the id of the client using a session id.
The session id is already passed along, and the MultiQueue in place, but somehow
accessing the server from multiple clients at the same time freezes the app...
For Fijal to test.


Modified: py/branch/test-web-multiclient/py/test/rsession/testing/test_web.py
==============================================================================
--- py/branch/test-web-multiclient/py/test/rsession/testing/test_web.py	(original)
+++ py/branch/test-web-multiclient/py/test/rsession/testing/test_web.py	Wed Nov 29 16:10:23 2006
@@ -14,6 +14,9 @@
 except ImportError:
     py.test.skip("No PyPy detected")
 
+from py.__.test.rsession.web import TestHandler as _TestHandler
+from py.__.test.rsession.web import MultiQueue
+
 def test_js_generate():
     from py.__.test.rsession import webjs
     from py.__.test.rsession.web import FUNCTION_LIST
@@ -22,8 +25,7 @@
     assert source
 
 def test_parse_args():
-    from py.__.test.rsession.web import TestHandler
-    class TestTestHandler(TestHandler):
+    class TestTestHandler(_TestHandler):
         def __init__(self):
             pass
     h = TestTestHandler()
@@ -33,3 +35,53 @@
     assert h.parse_args('foo=bar%baz') == {'foo': 'bar\xbaz'}
     py.test.raises(ValueError, 'h.parse_args("foo")')
 
+class TestMultiQueue(object):
+    def test_get_one_sessid(self):
+        mq = MultiQueue()
+        mq.put(1)
+        result = mq.get(1234)
+        assert result == 1
+
+    def test_get_two_sessid(self):
+        mq = MultiQueue()
+        mq.put(1)
+        result = mq.get(1234)
+        assert result == 1
+        mq.put(2)
+        result = mq.get(1234)
+        assert result == 2
+        result = mq.get(5678)
+        assert result == 1
+        result = mq.get(5678)
+        assert result == 2
+
+    def test_get_blocking(self):
+        import thread
+        result = []
+        def getitem(mq, sessid):
+            result.append(mq.get(sessid))
+        mq = MultiQueue()
+        thread.start_new_thread(getitem, (mq, 1234))
+        assert not result
+        mq.put(1)
+        py.std.time.sleep(0.1)
+        assert result == [1]
+
+    def test_empty(self):
+        mq = MultiQueue()
+        assert mq.empty()
+        mq.put(1)
+        assert not mq.empty()
+        result = mq.get(1234)
+        result == 1
+        assert mq.empty()
+        mq.put(2)
+        result = mq.get(4567)
+        assert result == 1
+        result = mq.get(1234)
+        assert result == 2
+        assert not mq.empty()
+        result = mq.get(4567)
+        assert result == 2
+        assert mq.empty()
+

Modified: py/branch/test-web-multiclient/py/test/rsession/web.py
==============================================================================
--- py/branch/test-web-multiclient/py/test/rsession/web.py	(original)
+++ py/branch/test-web-multiclient/py/test/rsession/web.py	Wed Nov 29 16:10:23 2006
@@ -63,10 +63,59 @@
             d['length'] = "?"
     return d
 
+class MultiQueue(object):
+    """ a tailor-made queue (internally using Queue) for py.test.rsession.web
+
+        API-wise the main difference is that the get() method gets a sessid
+        argument, which is used to determine what data to feed to the client
+
+        when a data queue for a sessid doesn't yet exist, it is created, and
+        filled with data that has already been fed to the other clients
+    """
+    def __init__(self):
+        self._cache = []
+        self._session_queues = {}
+        self._lock = py.std.thread.allocate_lock()
+
+    def put(self, item):
+        self._lock.acquire()
+        try:
+            self._cache.append(item)
+            for q in self._session_queues.values():
+                q.put(item)
+        finally:
+            self._lock.release()
+
+    def get(self, sessid=-1):
+        self._lock.acquire()
+        try:
+            if not sessid in self._session_queues:
+                self._create_session_queue(sessid)
+        finally:
+            self._lock.release()
+        return self._session_queues[sessid].get(sessid)
+
+    def empty(self):
+        self._lock.acquire()
+        try:
+            if not self._session_queues:
+                return not len(self._cache)
+            for q in self._session_queues.values():
+                if not q.empty():
+                    return False
+        finally:
+            self._lock.release()
+        return True
+
+    def _create_session_queue(self, sessid):
+        self._session_queues[sessid] = q = Queue.Queue()
+        for item in self._cache:
+            q.put(item)
+
 class ExportedMethods(BasicExternal):
     _render_xmlhttp = True
     def __init__(self):
-        self.pending_events = Queue.Queue()
+        self.pending_events = MultiQueue()
         self.start_event = threading.Event()
         self.end_event = threading.Event()
         self.skip_reasons = {}
@@ -104,16 +153,35 @@
                            'stderr':self.stderr[item_name]})
     show_fail = described(retval={"aa": "aa"})(show_fail)
     
-    def show_all_statuses(self):
-        retlist = [self.show_status_change()]
+    _sessids = None
+    _sesslock = py.std.thread.allocate_lock()
+    def show_sessid(self):
+        if not self._sessids:
+            self._sessids = []
+        self._sesslock.acquire()
+        try:
+            while 1:
+                chars = list(py.std.string.lowercase)
+                py.std.random.shuffle(chars)
+                sessid = ''.join(chars[:8])
+                if sessid not in self._sessids:
+                    self._sessids.append(sessid)
+                    break
+        finally:
+            self._sesslock.release()
+        return json.write(sessid)
+    show_sessid = described(retval="aa")(show_sessid)
+    
+    def show_all_statuses(self, sessid=-1):
+        retlist = [self.show_status_change(sessid)]
         while not self.pending_events.empty():
-            retlist.append(self.show_status_change())
+            retlist.append(self.show_status_change(sessid))
         retval = json.write(retlist)
         return retval
     show_all_statuses = described(retval=[{"aa": "aa"}])(show_all_statuses)
         
-    def show_status_change(self):
-        event = self.pending_events.get()
+    def show_status_change(self, sessid):
+        event = self.pending_events.get(sessid)
         if event is None:
             self.end_event.set()
             return {}

Modified: py/branch/test-web-multiclient/py/test/rsession/webdata/source.js
==============================================================================
Binary files. No diff available.

Modified: py/branch/test-web-multiclient/py/test/rsession/webjs.py
==============================================================================
--- py/branch/test-web-multiclient/py/test/rsession/webjs.py	(original)
+++ py/branch/test-web-multiclient/py/test/rsession/webjs.py	Wed Nov 29 16:10:23 2006
@@ -28,11 +28,11 @@
 
 MAX_COUNTER = 50 # Maximal size of one-line table
 
-class Pending(object):
+class Globals(object):
     def __init__(self):
         self.pending = []
 
-glob = Pending()
+glob = Globals()
 
 def comeback(msglist=[{"aa": "aa"}]):
     if len(msglist) == 0:
@@ -44,7 +44,7 @@
     for msg in msglist:
         if not process(msg):
             return
-    exported_methods.show_all_statuses(comeback)
+    exported_methods.show_all_statuses(glob.sessid, comeback)
 
 def show_info(data="aa"):
     info = dom.get_document().getElementById("info")
@@ -199,7 +199,11 @@
         td.id = host
         elem.appendChild(td)
 
+def sessid_comeback(id):
+    glob.sessid = id
+    exported_methods.show_all_statuses(id, comeback)
+
 def main():
     exported_methods.show_hosts(host_init)
-    exported_methods.show_all_statuses(comeback)
+    exported_methods.show_sessid(sessid_comeback)
 



More information about the pytest-commit mailing list