[py-svn] r35637 - in py/dist/py/test/rsession: . testing
fijal at codespeak.net
fijal at codespeak.net
Tue Dec 12 18:58:22 CET 2006
Author: fijal
Date: Tue Dec 12 18:58:19 2006
New Revision: 35637
Modified:
py/dist/py/test/rsession/box.py
py/dist/py/test/rsession/executor.py
py/dist/py/test/rsession/master.py
py/dist/py/test/rsession/reporter.py
py/dist/py/test/rsession/slave.py
py/dist/py/test/rsession/testing/test_boxing.py
py/dist/py/test/rsession/testing/test_executor.py
py/dist/py/test/rsession/testing/test_reporter.py
py/dist/py/test/rsession/testing/test_rsession.py
py/dist/py/test/rsession/testing/test_slave.py
Log:
svn merge -r 35555:HEAD http://codespeak.net/svn/py/branch/rsession-cleanup
Modified: py/dist/py/test/rsession/box.py
==============================================================================
--- py/dist/py/test/rsession/box.py (original)
+++ py/dist/py/test/rsession/box.py Tue Dec 12 18:58:19 2006
@@ -21,6 +21,7 @@
def __init__(self, fun, args = [], kwargs = {}):
self.fun = fun
self.args = args
+ self.info = info
self.kwargs = kwargs
def run(self):
@@ -48,7 +49,7 @@
self.args = args
self.kwargs = kwargs
- def run(self):
+ def run(self, continuation=False):
tempdir = py.test.ensuretemp("box%d" % self.count)
self.count += 1
self.tempdir = tempdir
@@ -59,7 +60,10 @@
nice_level = py.test.remote.nice_level
pid = os.fork()
if pid:
- self.parent(pid)
+ if not continuation:
+ self.parent(pid)
+ else:
+ return self.parent, pid
else:
try:
outcome = self.children(nice_level)
Modified: py/dist/py/test/rsession/executor.py
==============================================================================
--- py/dist/py/test/rsession/executor.py (original)
+++ py/dist/py/test/rsession/executor.py Tue Dec 12 18:58:19 2006
@@ -65,27 +65,27 @@
else:
return (False, False, None, False, False, b.signal, b.stdoutrepr, b.stderrrepr)
-# XXX old code
-class XXXExecutor(object):
- def __init__(self, fun, setup=lambda: None):
- self.fun = fun
- self.setup = setup
+class AsyncExecutor(RunExecutor):
+ """ same as box executor, but instead it returns function to continue
+ computations (more async mode)
+ """
+ wraps = True
- def _execute(self, fun):
- try:
- fun()
- except:
- excinfo = py.code.ExceptionInfo()
- code = py.code.Code(fun)
- excinfo.traceback = excinfo.traceback.cut(
- path=code.path, firstlineno=code.firstlineno)
- return excinfo
-
def execute(self):
- excinfo = self._execute(self.setup)
- if excinfo is not None:
- return Outcome(excinfo=excinfo, setupfailure=True)
- excinfo = self._execute(self.fun)
- if excinfo is not None:
- return Outcome(excinfo=excinfo, setupfailure=False)
- return Outcome()
+ def fun():
+ outcome = RunExecutor.execute(self)
+ return outcome.make_repr()
+
+ b = Box(fun)
+ parent, pid = b.run(continuation=True)
+
+ def cont():
+ parent(pid)
+ if b.retval is not None:
+ passed, setupfailure, excinfo, skipped, critical, _, _, _ = b.retval
+ return (passed, setupfailure, excinfo, skipped, critical, 0,
+ b.stdoutrepr, b.stderrrepr)
+ else:
+ return (False, False, None, False, False, b.signal, b.stdoutrepr, b.stderrrepr)
+
+ return cont, pid
Modified: py/dist/py/test/rsession/master.py
==============================================================================
--- py/dist/py/test/rsession/master.py (original)
+++ py/dist/py/test/rsession/master.py Tue Dec 12 18:58:19 2006
@@ -20,11 +20,14 @@
self.channel, item, repr_outcome))
def send(self, item):
- self.pending.insert(0, item)
- itemspec = item.listnames()[1:]
- self.channel.send(itemspec)
- # send start report
- self.reporter(report.SendItem(self.channel, item))
+ if item is StopIteration:
+ self.channel.send(42)
+ else:
+ self.pending.insert(0, item)
+ itemspec = item.listnames()[1:]
+ self.channel.send(itemspec)
+ # send start report
+ self.reporter(report.SendItem(self.channel, item))
def dispatch_loop(masternodes, itemgenerator, shouldstop,
waiter = lambda: py.std.time.sleep(0.1)):
@@ -37,6 +40,8 @@
if len(node.pending) < max_tasks_per_node:
item = itemgenerator.next()
if shouldstop():
+ for _node in masternodes:
+ _node.send(StopIteration) # magic connector
return
node.send(item)
except StopIteration:
Modified: py/dist/py/test/rsession/reporter.py
==============================================================================
--- py/dist/py/test/rsession/reporter.py (original)
+++ py/dist/py/test/rsession/reporter.py Tue Dec 12 18:58:19 2006
@@ -91,6 +91,10 @@
def hangs(self):
h = []
+ if self.config.option.exitfirst:
+ # reporting hanging nodes in that case makes no sense at all
+ # but we should share some code in all reporters than
+ return
for node in self.nodes:
h += [(i, node.channel.gateway.sshaddress) for i in node.pending]
if h:
Modified: py/dist/py/test/rsession/slave.py
==============================================================================
--- py/dist/py/test/rsession/slave.py (original)
+++ py/dist/py/test/rsession/slave.py Tue Dec 12 18:58:19 2006
@@ -3,11 +3,14 @@
"""
import py
-from py.__.test.rsession.executor import RunExecutor, BoxExecutor
+from py.__.test.rsession.executor import RunExecutor, BoxExecutor, AsyncExecutor
from py.__.test.rsession.outcome import Outcome
+class Info:
+ pid = None
+
class SlaveNode(object):
- def __init__(self, rootcollector, executor=BoxExecutor):
+ def __init__(self, rootcollector, executor=AsyncExecutor):
self.rootcollector = rootcollector
self.executor = executor
@@ -17,7 +20,13 @@
# ex = Executor(item.obj, setup=item.setup)
#else:
ex = self.executor(item)
- return ex.execute()
+ if self.executor is AsyncExecutor:
+ cont, pid = ex.execute()
+ else:
+ # for tests only
+ return ex.execute()
+ Info.pid = pid
+ return cont()
def run(self, itemspec):
#outcome = self.execute(itemspec)
@@ -28,7 +37,7 @@
else:
return outcome.make_repr()
-def slave_main(receive, send, path):
+def slave_main(receive, send, path, info = None):
import os
assert os.path.exists(path)
path = os.path.abspath(path)
@@ -61,9 +70,21 @@
while nextitem is not None:
nextitem = receive()
-
+
def setup():
+ def callback_gen(queue):
+ from py.__.test.rsession.slave import Info
+ def callback(item):
+ if item == 42: # magic call-cleanup
+ # XXX should kill a pid here
+ if Info.pid:
+ os.kill(Info.pid, 15)
+ sys.exit(0)
+ queue.put(item)
+ return callback
+
import os, sys
+ from Queue import Queue
pkgdir = channel.receive() # path is ready
options = channel.receive() # options stuff, should be dictionary
basedir = os.path.dirname(pkgdir)
@@ -73,6 +94,8 @@
import py
options['we_are_remote'] = True
from py.__.test.rsession.rsession import RemoteOptions
+ from py.__.test.rsession.slave import Info
+ Info.pid = 0
py.test.remote = RemoteOptions(options)
# XXX the following assumes that py lib is there, a bit
# much of an assumtion
@@ -81,6 +104,8 @@
mod = __import__(pkgname)
assert py.path.local(mod.__file__).dirpath() == py.path.local(pkgdir)
from py.__.test.rsession.slave import slave_main
- slave_main(channel.receive, channel.send, basedir)
+ queue = Queue()
+ channel.setcallback(callback_gen(queue))
+ slave_main(queue.get, channel.send, basedir)
if not py.test.remote.nomagic:
py.magic.revoke(assertion=1)
Modified: py/dist/py/test/rsession/testing/test_boxing.py
==============================================================================
--- py/dist/py/test/rsession/testing/test_boxing.py (original)
+++ py/dist/py/test/rsession/testing/test_boxing.py Tue Dec 12 18:58:19 2006
@@ -2,7 +2,7 @@
""" test boxing functionality
"""
-import py, sys
+import py, sys, os
if sys.platform == 'win32':
py.test.skip("rsession is unsupported on Windows.")
@@ -74,3 +74,18 @@
assert b.exitstat == 0
assert b.signal == 0
assert b.retval == 2
+
+def test_box_killer():
+ class A:
+ pass
+ info = A()
+ import time
+
+ def box_fun():
+ time.sleep(300) # we don't want to last forever here
+
+ b = RealBox(box_fun)
+ par, pid = b.run(continuation=True)
+ os.kill(pid, 15)
+ par(pid)
+ assert b.signal == 15
Modified: py/dist/py/test/rsession/testing/test_executor.py
==============================================================================
--- py/dist/py/test/rsession/testing/test_executor.py (original)
+++ py/dist/py/test/rsession/testing/test_executor.py Tue Dec 12 18:58:19 2006
@@ -2,13 +2,16 @@
import py
import example1
-from py.__.test.rsession.executor import RunExecutor, BoxExecutor
+from py.__.test.rsession.executor import RunExecutor, BoxExecutor,\
+ AsyncExecutor
from py.__.test.rsession.outcome import ReprOutcome
from py.__.test.rsession.testing.test_slave import funcprint_spec, \
funcprintfail_spec
def setup_module(mod):
mod.rootdir = py.path.local(py.__file__).dirpath().dirpath()
+ from py.__.test.rsession.rsession import remote_options
+ remote_options['nice_level'] = 0
def XXXtest_executor_passing_function():
ex = Executor(example1.f1)
@@ -107,3 +110,14 @@
outcome = ReprOutcome(outcome_repr)
assert not outcome.passed
assert outcome.stdout == "samfing elz\n"
+
+def test_cont_executor():
+ rootcol = py.test.collect.Directory(rootdir)
+ item = rootcol.getitembynames(funcprintfail_spec)
+ ex = AsyncExecutor(item)
+ cont, pid = ex.execute()
+ assert pid
+ outcome_repr = cont()
+ outcome = ReprOutcome(outcome_repr)
+ assert not outcome.passed
+ assert outcome.stdout == "samfing elz\n"
Modified: py/dist/py/test/rsession/testing/test_reporter.py
==============================================================================
--- py/dist/py/test/rsession/testing/test_reporter.py (original)
+++ py/dist/py/test/rsession/testing/test_reporter.py Tue Dec 12 18:58:19 2006
@@ -140,7 +140,7 @@
assert self.report_received_item_outcome() == 'FsF.'
def test_module(self):
- assert self._test_module().endswith("test_slave.py[8] FsF."),\
+ assert self._test_module().endswith("test_slave.py[9] FsF."),\
self._test_module()
def test_full_module(self):
Modified: py/dist/py/test/rsession/testing/test_rsession.py
==============================================================================
--- py/dist/py/test/rsession/testing/test_rsession.py (original)
+++ py/dist/py/test/rsession/testing/test_rsession.py Tue Dec 12 18:58:19 2006
@@ -302,7 +302,7 @@
if isinstance(x, report.ReceivedItemOutcome)]
passevents = [x for x in testevents if x.outcome.passed]
assert len(passevents) == 1
-
+
class TestDirectories(object):
def test_simple_parse(self):
sshhosts = ['h1', 'h2', 'h3']
Modified: py/dist/py/test/rsession/testing/test_slave.py
==============================================================================
--- py/dist/py/test/rsession/testing/test_slave.py (original)
+++ py/dist/py/test/rsession/testing/test_slave.py Tue Dec 12 18:58:19 2006
@@ -40,6 +40,10 @@
def funcoptioncustom():
assert py.test.remote.custom == "custom"
+def funchang():
+ import time
+ time.sleep(1000)
+
BASE = "py/test/rsession/testing/test_slave.py/"
funcpass_spec = (BASE + "funcpass").split("/")
funcfail_spec = (BASE + "funcfail").split("/")
@@ -48,6 +52,7 @@
funcprintfail_spec = (BASE + "funcprintfail").split("/")
funcoption_spec = (BASE + "funcoption").split("/")
funcoptioncustom_spec = (BASE + "funcoptioncustom").split("/")
+funchang_spec = (BASE + "funchang").split("/")
mod_spec = BASE[:-1].split("/")
# ----------------------------------------------------------------------
@@ -132,7 +137,7 @@
from py.__.test.rsession.rsession import remote_options
retval = remote_options.d
else:
- raise NotImplementedError("mora data")
+ raise NotImplementedError("more data")
self.count += 1
return retval
try:
@@ -143,6 +148,43 @@
else:
py.test.fail("missing exception")
+def test_slave_setup_exit():
+ tmp = py.test.ensuretemp("slaveexit")
+ tmp.ensure("__init__.py")
+ from py.__.test.rsession.slave import setup
+ from Queue import Queue
+ q = Queue()
+
+ class C:
+ res = []
+ def __init__(self):
+ from py.__.test.rsession.rsession import remote_options
+ self.q = [str(tmp),
+ remote_options.d,
+ funchang_spec,
+ 42,
+ funcpass_spec]
+ self.q.reverse()
+
+ def receive(self):
+ return self.q.pop()
+
+ def setcallback(self, callback):
+ import thread
+ def f():
+ while 1:
+ callback(self.q.pop())
+ f()
+ #thread.start_new_thread(f, ())
+
+ send = res.append
+ try:
+ exec py.code.Source(setup, "setup()").compile() in {'channel':C()}
+ except SystemExit:
+ pass
+ else:
+ py.test.fail("Did not exit")
+
def test_slave_setup_fails_on_missing_pkg():
from py.__.test.rsession.slave import setup
tmp = py.test.ensuretemp("slavesetup2")
@@ -158,7 +200,7 @@
from py.__.test.rsession.rsession import remote_options
retval = remote_options.d
else:
- raise NotImplementedError("mora data")
+ raise NotImplementedError("more data")
self.count += 1
return retval
try:
More information about the py-svn
mailing list