[py-svn] r38397 - in py/trunk/py/test/rsession: . testing

fijal at codespeak.net fijal at codespeak.net
Sat Feb 10 17:50:50 CET 2007


Author: fijal
Date: Sat Feb 10 17:50:47 2007
New Revision: 38397

Modified:
   py/trunk/py/test/rsession/executor.py
   py/trunk/py/test/rsession/local.py
   py/trunk/py/test/rsession/outcome.py
   py/trunk/py/test/rsession/slave.py
   py/trunk/py/test/rsession/testing/test_executor.py
   py/trunk/py/test/rsession/testing/test_master.py
   py/trunk/py/test/rsession/testing/test_slave.py
Log:
Kill PidInfo and make boxing optional for distributed testing.
This should make dist testing on windows possible.


Modified: py/trunk/py/test/rsession/executor.py
==============================================================================
--- py/trunk/py/test/rsession/executor.py	(original)
+++ py/trunk/py/test/rsession/executor.py	Sat Feb 10 17:50:47 2007
@@ -20,12 +20,19 @@
         self.config = config
         assert self.config
 
-    def run(self):
-        self.item.run()
+    def run(self, capture=True):
+        if capture:
+            try:
+                self.item.startcapture()
+                self.item.run()
+            finally:
+                self.item.finishcapture()
+        else:
+            self.item.run()
 
-    def execute(self):
+    def execute(self, capture=True):
         try:
-            self.run()
+            self.run(capture)
             outcome = Outcome()
         except Skipped, e: 
             outcome = Outcome(skipped=str(e))
@@ -49,8 +56,7 @@
                 # XXX hmm, we probably will not like to continue from that
                 #     point
                 raise SystemExit()
-        outcome.stdout = ""
-        outcome.stderr = ""
+        outcome.stdout, outcome.stderr = self.item._getouterr()
         return outcome
 
 class ApigenExecutor(RunExecutor):
@@ -68,7 +74,7 @@
         finally:
             self.tracer.end_tracing()
 
-    def run(self):
+    def run(self, capture):
         """ We want to trace *only* function objects here. Unsure
         what to do with custom collectors at all
         """
@@ -83,7 +89,7 @@
 
     def execute(self):
         def fun():
-            outcome = RunExecutor.execute(self)
+            outcome = RunExecutor.execute(self, False)
             return outcome.make_repr(self.config.option.tbstyle)
         b = Box(fun, config=self.config)
         pid = b.run()
@@ -105,7 +111,7 @@
 
     def execute(self):
         def fun():
-            outcome = RunExecutor.execute(self)
+            outcome = RunExecutor.execute(self, False)
             return outcome.make_repr(self.config.option.tbstyle)
         
         b = Box(fun, config=self.config)

Modified: py/trunk/py/test/rsession/local.py
==============================================================================
--- py/trunk/py/test/rsession/local.py	(original)
+++ py/trunk/py/test/rsession/local.py	Sat Feb 10 17:50:47 2007
@@ -8,29 +8,14 @@
 from py.__.test.rsession import repevent
 from py.__.test.rsession.outcome import ReprOutcome
 
-# XXX copied from session.py
-def startcapture(session):
-    if not session.config.option.nocapture:
-        session._capture = py.io.StdCapture()
-
-def finishcapture(session): 
-    if hasattr(session, '_capture'): 
-        capture = session._capture 
-        del session._capture
-        return capture.reset()
-    return "", ""
-
 def box_runner(item, session, reporter):
     r = BoxExecutor(item, config=session.config)
     return ReprOutcome(r.execute())
 
 def plain_runner(item, session, reporter):
-    # box executor is doing stdout/err catching for us, let's do it here
-    startcapture(session)
     r = RunExecutor(item, usepdb=session.config.option.usepdb, reporter=reporter, config=session.config)
     outcome = r.execute()
     outcome = ReprOutcome(outcome.make_repr(session.config.option.tbstyle))
-    outcome.stdout, outcome.stderr = finishcapture(session)
     return outcome
 
 def benchmark_runner(item, session, reporter):

Modified: py/trunk/py/test/rsession/outcome.py
==============================================================================
--- py/trunk/py/test/rsession/outcome.py	(original)
+++ py/trunk/py/test/rsession/outcome.py	Sat Feb 10 17:50:47 2007
@@ -18,6 +18,8 @@
         self.excinfo = excinfo
         self.is_critical = is_critical
         self.signal = 0
+        self.stdout = "" # XXX temporary
+        self.stderr = ""
         assert bool(self.passed) + bool(excinfo) + bool(skipped) == 1
     
     def make_excinfo_repr(self, tbstyle):
@@ -54,7 +56,7 @@
     def make_repr(self, tbstyle="long"):
         return (self.passed, self.setupfailure, 
                 self.make_excinfo_repr(tbstyle), 
-                self.skipped, self.is_critical, 0, "", "")
+                self.skipped, self.is_critical, 0, self.stdout, self.stderr)
 
 class TracebackEntryRepr(object):
     def __init__(self, tbentry):

Modified: py/trunk/py/test/rsession/slave.py
==============================================================================
--- py/trunk/py/test/rsession/slave.py	(original)
+++ py/trunk/py/test/rsession/slave.py	Sat Feb 10 17:50:47 2007
@@ -9,59 +9,16 @@
 import thread
 import os
 
-class PidInfo(object):
-    """ Pure container class to store information of actually running
-    pid
-    """
-    def __init__(self):
-        self.pid = 0
-        self.lock = thread.allocate_lock()
-
-    def set_pid(self, pid):
-        self.lock.acquire()
-        try:
-            self.pid = pid
-        finally:
-            self.lock.release()
-
-    def kill(self):
-        self.lock.acquire()
-        try:
-            if self.pid:
-                os.kill(self.pid, 15)
-                self.pid = 0
-        finally:
-            self.lock.release()
-
-    def waitandclear(self, pid, num):
-        """ This is an obscure hack to keep locking properly, adhere to posix semantics
-        and try to clean it as much as possible, not clean at all
-        """
-        self.lock.acquire()
-        try:
-            retval = os.waitpid(self.pid, 0)
-            self.pid = 0
-            return retval
-        finally:
-            self.lock.release()
-
 class SlaveNode(object):
-    def __init__(self, config, pidinfo, executor=AsyncExecutor):
+    def __init__(self, config, executor):
         #self.rootcollector = rootcollector
         self.config = config
         self.executor = executor
-        self.pidinfo = pidinfo
 
     def execute(self, itemspec):
         item = self.config._getcollector(itemspec)
         ex = self.executor(item, config=self.config)
-        if self.executor is AsyncExecutor:
-            cont, pid = ex.execute()
-            self.pidinfo.set_pid(pid)
-        else:
-            # for tests only
-            return ex.execute()
-        return cont(self.pidinfo.waitandclear)
+        return ex.execute()
 
     def run(self, itemspec):
         #outcome = self.execute(itemspec)
@@ -72,7 +29,7 @@
         else:
             return outcome.make_repr(self.config.option.tbstyle)
 
-def slave_main(receive, send, path, config, pidinfo):
+def slave_main(receive, send, path, config):
     import os
     assert os.path.exists(path) 
     path = os.path.abspath(path) 
@@ -82,7 +39,11 @@
         if node is not None:
             return node
         col = py.test.collect.Directory(str(py.path.local(path).join(item[0])))
-        node = nodes[item[0]] = SlaveNode(config, pidinfo)
+        if config.option.boxed:
+            executor = BoxExecutor
+        else:
+            executor = RunExecutor
+        node = nodes[item[0]] = SlaveNode(config, executor)
         return node
     while 1:
         nextitem = receive()
@@ -120,15 +81,6 @@
     return channel
 
 def setup():
-    def callback_gen(channel, queue, info):
-        def callback(item):
-            if item == 42: # magic call-cleanup
-                # XXX should kill a pid here
-                info.kill()
-                channel.close()
-                sys.exit(0)
-            queue.put(item)
-        return callback
     # our current dir is the topdir
     import os, sys
     basedir = channel.receive()
@@ -139,13 +91,13 @@
     config = py.test.config
     assert not config._initialized 
     config.initdirect(basedir, config_repr)
+    if hasattr(os, 'nice'):
+        nice_level = config.getvalue('dist_nicelevel')
+        os.nice(nice_level) 
     if not config.option.nomagic:
         py.magic.invoke(assertion=1)
-    from py.__.test.rsession.slave import slave_main, PidInfo
-    queue = py.std.Queue.Queue()
-    pidinfo = PidInfo()
-    channel.setcallback(callback_gen(channel, queue, pidinfo))
-    slave_main(queue.get, channel.send, basedir, config, pidinfo)
+    from py.__.test.rsession.slave import slave_main
+    slave_main(channel.receive, channel.send, basedir, config)
     if not config.option.nomagic:
         py.magic.revoke(assertion=1)
     channel.close()

Modified: py/trunk/py/test/rsession/testing/test_executor.py
==============================================================================
--- py/trunk/py/test/rsession/testing/test_executor.py	(original)
+++ py/trunk/py/test/rsession/testing/test_executor.py	Sat Feb 10 17:50:47 2007
@@ -11,46 +11,60 @@
     if py.std.sys.platform == "win32":
         py.test.skip("skipping executor tests (some require os.fork)")
 
-class ItemTestPassing(py.test.Item):    
+class Item(py.test.Item):
+    def __init__(self, name, config):
+        super(Item, self).__init__(name)
+        self._config = config
+
+class ItemTestPassing(Item):    
     def run(self):
         return None
 
-class ItemTestFailing(py.test.Item):
+class ItemTestFailing(Item):
     def run(self):
         assert 0 == 1
 
-class ItemTestSkipping(py.test.Item):
+class ItemTestSkipping(Item):
     def run(self):
         py.test.skip("hello")
 
+class ItemTestPrinting(Item):
+    def run(self):
+        print "hello"
+
 class TestExecutor(BasicRsessionTest):
     def test_run_executor(self):
-        ex = RunExecutor(ItemTestPassing("pass"), config=self.config)
+        ex = RunExecutor(ItemTestPassing("pass", self.config), config=self.config)
         outcome = ex.execute()
         assert outcome.passed
     
-        ex = RunExecutor(ItemTestFailing("fail"), config=self.config)
+        ex = RunExecutor(ItemTestFailing("fail", self.config), config=self.config)
         outcome = ex.execute()
         assert not outcome.passed
 
-        ex = RunExecutor(ItemTestSkipping("skip"), config=self.config)
+        ex = RunExecutor(ItemTestSkipping("skip", self.config), config=self.config)
         outcome = ex.execute()
         assert outcome.skipped 
         assert not outcome.passed
-        assert not outcome.excinfo 
+        assert not outcome.excinfo
+
+    def test_run_executor_capture(self):
+        ex = RunExecutor(ItemTestPrinting("print", self.config), config=self.config)
+        outcome = ex.execute()
+        assert outcome.stdout == "hello\n"
 
     def test_box_executor(self):
-        ex = BoxExecutor(ItemTestPassing("pass"), config=self.config)
+        ex = BoxExecutor(ItemTestPassing("pass", self.config), config=self.config)
         outcome_repr = ex.execute()
         outcome = ReprOutcome(outcome_repr)
         assert outcome.passed
     
-        ex = BoxExecutor(ItemTestFailing("fail"), config=self.config)
+        ex = BoxExecutor(ItemTestFailing("fail", self.config), config=self.config)
         outcome_repr = ex.execute()
         outcome = ReprOutcome(outcome_repr)
         assert not outcome.passed
 
-        ex = BoxExecutor(ItemTestSkipping("skip"), config=self.config)
+        ex = BoxExecutor(ItemTestSkipping("skip", self.config), config=self.config)
         outcome_repr = ex.execute()
         outcome = ReprOutcome(outcome_repr)
         assert outcome.skipped 

Modified: py/trunk/py/test/rsession/testing/test_master.py
==============================================================================
--- py/trunk/py/test/rsession/testing/test_master.py	(original)
+++ py/trunk/py/test/rsession/testing/test_master.py	Sat Feb 10 17:50:47 2007
@@ -137,6 +137,7 @@
         return self.config.get_collector_trail(item) 
         
     def test_slave_setup(self):
+        py.test.skip("Doesn't work anymore")
         pkgname = self.pkgpath.basename
         host = HostInfo("localhost:%s" %(self.tmpdir,))
         host.initgateway()

Modified: py/trunk/py/test/rsession/testing/test_slave.py
==============================================================================
--- py/trunk/py/test/rsession/testing/test_slave.py	(original)
+++ py/trunk/py/test/rsession/testing/test_slave.py	Sat Feb 10 17:50:47 2007
@@ -1,6 +1,6 @@
 
 """ Testing the slave side node code (in a local way). """
-from py.__.test.rsession.slave import SlaveNode, slave_main, setup, PidInfo
+from py.__.test.rsession.slave import SlaveNode, slave_main, setup
 from py.__.test.rsession.outcome import ReprOutcome
 import py, sys
 from py.__.test.rsession.testing.basetest import BasicRsessionTest
@@ -17,8 +17,7 @@
 
 class TestSlave(BasicRsessionTest):
     def gettestnode(self):
-        pidinfo = PidInfo()
-        node = SlaveNode(self.config, pidinfo, executor=RunExecutor) 
+        node = SlaveNode(self.config, executor=RunExecutor) 
         return node
 
     def test_slave_run_passing(self):
@@ -74,18 +73,3 @@
         node = self.gettestnode()
         node.run(self.rootcol._getitembynames("py doc log.txt".split()).
                  _get_collector_trail())
-
-def test_pidinfo():
-    if not hasattr(os, 'fork') or not hasattr(os, 'waitpid'):
-        py.test.skip("Platform does not support fork")
-    pidinfo = PidInfo()
-    pid = os.fork()
-    if pid:
-        pidinfo.set_pid(pid)
-        pidinfo.waitandclear(pid, 0)
-    else:
-        import time, sys
-        time.sleep(.3)
-        os._exit(0)
-    # check if this really exits
-    py.test.raises(OSError, "os.waitpid(pid, 0)")



More information about the pytest-commit mailing list