[py-svn] r57152 - in py/branch/event/py/test2: dist dist/testing testing

hpk at codespeak.net hpk at codespeak.net
Sat Aug 9 21:18:33 CEST 2008


Author: hpk
Date: Sat Aug  9 21:18:31 2008
New Revision: 57152

Modified:
   py/branch/event/py/test2/dist/async.py
   py/branch/event/py/test2/dist/testing/test_async.py
   py/branch/event/py/test2/testing/acceptance_test.py
Log:
fix hostdown/reschedule issues 
factor out a "loop_once" method also to ease testing


Modified: py/branch/event/py/test2/dist/async.py
==============================================================================
--- py/branch/event/py/test2/dist/async.py	(original)
+++ py/branch/event/py/test2/dist/async.py	Sat Aug  9 21:18:31 2008
@@ -17,6 +17,15 @@
 from py.__.test2.runner import basic_run_report, basic_collect_report, skip_report 
 import Queue 
 
+class LoopState(object):
+    def __init__(self, colitems, dowork=True):
+        self.colitems = colitems
+        self.exitstatus = None 
+        # loopstate.dowork is False after reschedule events 
+        # because otherwise we might very busily loop 
+        # waiting for a host to become ready.  
+        self.dowork = dowork 
+
 class AsyncSession(object): 
     """ 
         Session drives the collection and running of tests
@@ -61,33 +70,41 @@
         exitstatus = self.loop(colitems)
         self.sessionfinishes(exitstatus=exitstatus)
 
+    def loop_once(self, loopstate):
+        colitems = loopstate.colitems 
+        if loopstate.dowork and loopstate.colitems:
+            self.triggertesting(colitems) 
+            colitems[:] = []
+        ev = self.queue.get()
+        loopstate.dowork = True 
+        self.bus.notify(ev)
+        if isinstance(ev, repevent.HostDown):
+            pending = self.removehost(ev.host)
+            colitems.extend(pending)
+        elif isinstance(ev, repevent.RescheduleItems):
+            if not self.hosts:
+                loopstate.exitstatus = self.EXIT_NOHOSTS
+                return 
+            colitems.extend(ev.items)
+            loopstate.dowork = False 
+        elif isinstance(ev, repevent.ItemTestReport):
+            all_completed = self.processresult(ev)
+            if all_completed:
+                self.act_on_completed_tests()
+                loopstate.exitstatus = self.EXIT_OK
+                return 
+        elif isinstance(ev, repevent.CollectionReport):
+            if ev.passed:
+                colitems.extend(ev.result)
+
     def loop(self, colitems):
-        exitstatus = self.EXIT_OK
         try:
-            wait_for_event = False
+            loopstate = LoopState(colitems)
             while 1:
-                if not wait_for_event and colitems:
-                    self.triggertesting(colitems) 
-                    colitems = []
-                ev = self.queue.get()
-                wait_for_event = False
-                self.bus.notify(ev)
-                if isinstance(ev, repevent.HostDown):
-                    self.handle_hostdown(ev)
-                elif isinstance(ev, repevent.RescheduleItems):
-                    if not self.hosts:
-                        exitstatus = self.EXIT_NOHOSTS
-                        break
-                    colitems.extend(ev.items)
-                    wait_for_event = True
-                elif isinstance(ev, repevent.ItemTestReport):
-                    all_completed = self.processresult(ev)
-                    if all_completed:
-                        self.act_on_completed_tests()
-                        break
-                elif isinstance(ev, repevent.CollectionReport):
-                    if ev.passed:
-                        colitems.extend(ev.result)
+                self.loop_once(loopstate)
+                if loopstate.exitstatus is not None:
+                    exitstatus = loopstate.exitstatus
+                    break 
         except KeyboardInterrupt:
             #print py.code.ExceptionInfo().getrepr(funcargs=True)
             #raise
@@ -162,10 +179,6 @@
             self.queue.put(repevent.Deselected(deselected))
         return remaining 
 
-    def handle_hostdown(self, ev):
-        pending = self.removehost(ev.host)
-        self.queue.put(repevent.RescheduleItems(pending))
-
     def sendtestitems(self, tosend):
         for host, pending in self.host2pending.items():
             if not tosend:

Modified: py/branch/event/py/test2/dist/testing/test_async.py
==============================================================================
--- py/branch/event/py/test2/dist/testing/test_async.py	(original)
+++ py/branch/event/py/test2/dist/testing/test_async.py	Sat Aug  9 21:18:31 2008
@@ -1,5 +1,5 @@
 from py.__.test2.testing.suptest import InlineCollection
-from py.__.test2.dist.async import AsyncSession
+from py.__.test2.dist.async import AsyncSession, LoopState
 from py.__.test2.dist.hostmanage import Host
 from py.__.test2.runner import basic_collect_report 
 from py.__.test2 import repevent
@@ -121,10 +121,35 @@
         # setup a HostDown event
         ev = repevent.HostDown(host1, None)
         session.queue.put(ev)
+
+        # call the loop which should come back 
+        # because it doesn't have any hosts left
         exitstatus = session.loop([item])
         dumpqueue(session.queue)
         assert exitstatus == session.EXIT_NOHOSTS
 
+    def test_hostdown_causes_reschedule_pending(self):
+        item = self.getitem("def test_func(): pass")
+
+        # setup a session with two hosts 
+        session = AsyncSession(item._config)
+        host1 = Host("localhost")
+        host1.node = MockNode()
+        session.addhost(host1)
+        host2 = Host("localhost")
+        host2.node = MockNode()
+        session.addhost(host2)
+      
+        # have one test pending for a host that goes down 
+        session.host2pending[host1].append(item)
+        ev = repevent.HostDown(host1, None)
+        session.queue.put(ev)
+
+        loopstate = LoopState([])
+        session.loop_once(loopstate)
+        
+        assert loopstate.colitems == [item]
+
     def test_event_propagation(self):
         item = self.getitem("def test_func(): pass")
         session = AsyncSession(item._config)

Modified: py/branch/event/py/test2/testing/acceptance_test.py
==============================================================================
--- py/branch/event/py/test2/testing/acceptance_test.py	(original)
+++ py/branch/event/py/test2/testing/acceptance_test.py	Sat Aug  9 21:18:31 2008
@@ -283,8 +283,7 @@
             "HostReady*localhost*",
             "HostReady*localhost*",
             "HostReady*localhost*",
-            "HostDown*localhost*",
-            "Error: TERMINATED", 
+            "HostDown*localhost*TERMINATED*",
             "*1/3 passed + 1 skip*",
             "*failures: 2*",
         ])



More information about the pytest-commit mailing list