doctweaks and some skeleton tests for event-aliveness
authorTero Marttila <terom@fixme.fi>
Sat, 26 Sep 2009 23:38:02 +0300
changeset 56 07ed878c847b
parent 55 99c4344a35ce
child 57 8c4032265c8c
doctweaks and some skeleton tests for event-aliveness
qmsk/net/lib/event2/base.pxd
qmsk/net/lib/event2/base.pyx
test/lib_event.py
--- a/qmsk/net/lib/event2/base.pxd	Sat Sep 26 22:09:24 2009 +0300
+++ b/qmsk/net/lib/event2/base.pxd	Sat Sep 26 23:38:02 2009 +0300
@@ -9,11 +9,9 @@
         An event_base stores the "global" state associated with events - it holds a set of events (pending/active/scheduled),
         and uses some specific multiplexing method (select/poll/epoll/kqueue/etc) to drive these events.
         
-        Constructs a new event_base with default parameters.
+        
+        *** POSIX Signal Handling ***
 
-        XXX: you must keep a reference to the event_base around yourself!
-        XXX: what happens to events once we are destructed?
-        
         Libevent has its own asynchronous signal-handling mechanism that is incompatible with Python's signal-handling
         mechanism.
         
@@ -31,14 +29,15 @@
         This means that python's default signals and any other signals added using the signal module continue to work
         at the cost of some additional complexity, but any libevent signal-events also work as well :)
         
-        XXX: currently, you can only have one event_base at a time - there should be separate types used for the main
+        *** TODO ***
+
+        Currently, you can only have one event_base at a time - there should be separate types used for the main
         thread and sub-threads, since the python signal handling mechanism only works in the main thread.
 
-        XXX: the propagate-exceptions doesn't actually work either, it just aborts the event loop :)
+        The propagate-exceptions doesn't actually work either, it just aborts the event loop :)
 
-        XXX: add support for event_config!
-        XXX: add support for event_base_priority_init!
-
+        Support for event_config!
+        Support for event_base_priority_init!
     """
     
     # the underlying ev_base object
--- a/qmsk/net/lib/event2/base.pyx	Sat Sep 26 22:09:24 2009 +0300
+++ b/qmsk/net/lib/event2/base.pyx	Sat Sep 26 23:38:02 2009 +0300
@@ -81,6 +81,9 @@
 cdef class event_base :
 
     def __init__ (self) :
+        """
+            Constructs a new event_base with default parameters.
+        """
 
         # construct
         self.ev_base = lib.event_base_new()
@@ -124,7 +127,7 @@
                 once        - only run the event loop once, at most
                 nonblock    - do not block waiting for events
 
-            Returns True if succesfull, False if no events were registered
+            Returns True if the event loop exited, False if there were no more events to process
         """
 
         cdef int flags = 0
--- a/test/lib_event.py	Sat Sep 26 22:09:24 2009 +0300
+++ b/test/lib_event.py	Sat Sep 26 23:38:02 2009 +0300
@@ -1,7 +1,7 @@
 import unittest
 
 from qmsk.net.lib.event2.base import event_base
-from qmsk.net.lib.event2.event import event
+from qmsk.net.lib.event2.event import event, CallbackEvent
 from qmsk.net.lib.event2.constants import *
 
 import os
@@ -20,6 +20,7 @@
 
         self.res = (mask == self.ev_in)
 
+
 class TestEventBase (unittest.TestCase) :
     """
         Simple event_base bits
@@ -42,6 +43,7 @@
 
         self.assertFalse(self.ev_base.loop(nonblock=True))
 
+
 class TestEvent (unittest.TestCase) :
     """
         Simple event bits.
@@ -126,6 +128,93 @@
         
         ev = event(self.ev_base, 0, 0)
         ev.add()
+    
+    def test_init_nonalive (self) :
+        """
+            An event is not alive after init
+        """
+
+        ev = event(self.ev_base, 0, 0)
+
+        self.assertFalse(ev.alive)
+
+    def test_add_alive (self) :
+        """
+            An event is considered alive and pending after add
+        """
+
+        ev = event(self.ev_base, 0, EV_READ)
+        ev.add()
+
+        self.assertTrue(ev.alive)
+
+    def test_del_nonalive (self) :
+        """
+            An event is not considered alive anymore after del
+        """
+    
+        ev = event(self.ev_base, 0, EV_READ)
+        ev.add()
+
+        ev.delete()
+
+        self.assertFalse(ev.alive)
+
+    def test_fire_nonalive (self) :
+        """
+            An event is not considered alive anymore during callback execution the callback fires, nor afterwards
+        """
+
+        fired = []
+
+        def cb (ev, what) :
+            fired.append(1)
+
+            self.assertFalse(ev.alive)
+        
+        ev = CallbackEvent(self.ev_base, 0, EV_READ, cb)
+        ev.add(-1)
+        
+        self.ev_base.loop()
+
+        # fired
+        self.assertTrue(fired)
+        
+        # not alive anymore
+        self.assertFalse(ev.alive)
+
+    def test_fire_add_alive (self) :
+        """
+            An event is considered alive if it is re-added during callback exec
+        """
+
+        ev = CallbackEvent(self.ev_base, 0, EV_READ,
+            lambda ev, what: ev.add()
+        )
+
+        ev.add(0)
+
+        self.ev_base.loop(once=True, nonblock=True)
+
+        # still alive
+        self.assertTrue(ev.alive)
+    
+    def test_persistent_fire_alive (self) :
+        """
+            A persistent event is still considered alive during and after callback exec
+        """
+
+        ev = CallbackEvent(self.ev_base, 0, EV_READ,
+            lambda ev, what: self.assertTrue(ev.alive)
+        )
+
+        ev.add()
+
+        self.ev_base.loop(once=True, nonblock=True)
+        
+        # persists -> stays alive
+        self.assertTrue(ev.alive)
+
 
 class TestEventPipe (unittest.TestCase) :
     """