[tor-commits] [stem/master] Testing for the controller's asynchronous event handling

atagar at torproject.org atagar at torproject.org
Sun May 6 02:20:50 UTC 2012


commit 80809adcf7023d91c08f97ee9e7affcb3a3bc748
Author: Damian Johnson <atagar at torproject.org>
Date:   Sat May 5 19:17:55 2012 -0700

    Testing for the controller's asynchronous event handling
    
    Adding a test that hammers the control socket with queries while also listening
    for BW events. This also tests for and fixes a bug where listeners wouldn't get
    all of the enqueued events if the controller was closed.
---
 stem/control.py                       |    4 ++-
 test/integ/control/base_controller.py |   56 +++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+), 1 deletions(-)

diff --git a/stem/control.py b/stem/control.py
index b3bd29c..9b912e5 100644
--- a/stem/control.py
+++ b/stem/control.py
@@ -414,11 +414,13 @@ class BaseController:
     socket.
     """
     
-    while self.is_alive():
+    while True:
       try:
         event_message = self._event_queue.get_nowait()
         self._handle_event(event_message)
       except Queue.Empty:
+        if not self.is_alive(): break
+        
         self._event_notice.wait()
         self._event_notice.clear()
 
diff --git a/test/integ/control/base_controller.py b/test/integ/control/base_controller.py
index 940ef99..cb5eaf2 100644
--- a/test/integ/control/base_controller.py
+++ b/test/integ/control/base_controller.py
@@ -2,6 +2,7 @@
 Integration tests for the stem.control.BaseController class.
 """
 
+import re
 import time
 import unittest
 import threading
@@ -135,6 +136,61 @@ class TestBaseController(unittest.TestCase):
       for msg_thread in message_threads:
         msg_thread.join()
   
+  def test_asynchronous_event_handling(self):
+    """
+    Check that we can both receive asynchronous events while hammering our
+    socket with queries, and checks that when a controller is closed the
+    listeners will still receive all of the enqueued events.
+    """
+    
+    class ControlledListener(stem.control.BaseController):
+      """
+      Controller that blocks event handling until told to do so.
+      """
+      
+      def __init__(self, control_socket):
+        stem.control.BaseController.__init__(self, control_socket)
+        self.received_events = []
+        self.receive_notice = threading.Event()
+      
+      def _handle_event(self, event_message):
+        self.receive_notice.wait()
+        self.received_events.append(event_message)
+    
+    with test.runner.get_runner().get_tor_socket() as control_socket:
+      controller = ControlledListener(control_socket)
+      controller.msg("SETEVENTS BW")
+      
+      # Wait for a couple events for events to be enqueued. Doing a bunch of
+      # GETINFO queries while waiting to better exercise the asynchronous event
+      # handling.
+      
+      start_time = time.time()
+      
+      while (time.time() - start_time) < 2:
+        test.runner.exercise_controller(self, controller)
+      
+      # Concurrently shut down the controller. We need to do this in another
+      # thread because it'll block on the event handling, which in turn is
+      # currently blocking on the reveive_notice.
+      
+      close_thread = threading.Thread(target = controller.close, name = "Closing controller")
+      close_thread.setDaemon(True)
+      close_thread.start()
+      
+      # Finally start handling the BW events that we've received. We should
+      # have at least a couple of them.
+      
+      controller.receive_notice.set()
+      close_thread.join()
+      
+      self.assertTrue(len(controller.received_events) >= 2)
+      
+      for bw_event in controller.received_events:
+        self.assertTrue(re.match("BW [0-9]+ [0-9]+", str(bw_event)))
+        self.assertTrue(re.match("650 BW [0-9]+ [0-9]+\r\n", bw_event.raw_content()))
+        self.assertEquals(("650", " "), bw_event.content()[0][:2])
+  
   def test_status_notifications(self):
     """
     Checks basic functionality of the add_status_listener() and



More information about the tor-commits mailing list