174 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Python
		
	
	
	
""" master code and test dispatching for 
 | 
						|
    making 1-n master -> slave connection
 | 
						|
    and test it locally. 
 | 
						|
"""
 | 
						|
 | 
						|
import time, threading
 | 
						|
import py, sys
 | 
						|
 | 
						|
if sys.platform == 'win32':
 | 
						|
    py.test.skip("rsession is unsupported on Windows.")
 | 
						|
 | 
						|
from py.__.test.rsession.master import dispatch_loop, setup_slave, MasterNode, randomgen
 | 
						|
from py.__.test.rsession.outcome import ReprOutcome, Outcome 
 | 
						|
from py.__.test.rsession.testing.test_slave import funcpass_spec, funcfail_spec, funchang_spec
 | 
						|
from py.__.test.rsession import report
 | 
						|
from py.__.test.rsession.hostmanage import HostInfo
 | 
						|
 | 
						|
def setup_module(mod):
 | 
						|
    # bind an empty config
 | 
						|
    config = py.test.config._reparse([])
 | 
						|
    config._overwrite('dist_taskspernode', 10)
 | 
						|
    mod.pkgdir = py.path.local(py.__file__).dirpath().dirpath()
 | 
						|
    mod.rootcol = py.test.collect.Directory(mod.pkgdir)
 | 
						|
 | 
						|
class DummyGateway(object):
 | 
						|
    def __init__(self):
 | 
						|
        self.host = HostInfo("localhost")
 | 
						|
 | 
						|
class DummyChannel(object):
 | 
						|
    def __init__(self):
 | 
						|
        self.sent = []
 | 
						|
        self.gateway = DummyGateway()
 | 
						|
 | 
						|
    def setcallback(self, func):
 | 
						|
        self.callback = func 
 | 
						|
 | 
						|
    def send(self, item):
 | 
						|
        assert py.std.marshal.dumps(item)
 | 
						|
        self.sent.append(item)
 | 
						|
 | 
						|
class Item(py.test.Item):
 | 
						|
    def get_collector_trail(self):
 | 
						|
        return (self.name,)
 | 
						|
 | 
						|
def test_masternode():
 | 
						|
    try:
 | 
						|
        raise ValueError()
 | 
						|
    except ValueError:
 | 
						|
        excinfo = py.code.ExceptionInfo()
 | 
						|
    
 | 
						|
    ch = DummyChannel()
 | 
						|
    reportlist = []
 | 
						|
    mnode = MasterNode(ch, reportlist.append, {})
 | 
						|
    mnode.send(Item("ok"))
 | 
						|
    mnode.send(Item("notok"))
 | 
						|
    ch.callback(Outcome().make_repr())
 | 
						|
    ch.callback(Outcome(excinfo=excinfo).make_repr())
 | 
						|
    assert len(reportlist) == 4
 | 
						|
    received = [i for i in reportlist 
 | 
						|
        if isinstance(i, report.ReceivedItemOutcome)]
 | 
						|
    assert received[0].outcome.passed 
 | 
						|
    assert not received[1].outcome.passed 
 | 
						|
 | 
						|
def test_unique_nodes():
 | 
						|
    ch = DummyChannel()
 | 
						|
    reportlist = []
 | 
						|
    mnode = MasterNode(ch, reportlist.append, {})
 | 
						|
    mnode.send(Item("ok"))
 | 
						|
    mnode.send(Item("ok"))
 | 
						|
    ch.callback(Outcome().make_repr())
 | 
						|
    ch.callback(Outcome().make_repr())
 | 
						|
    assert len(reportlist) == 3
 | 
						|
 | 
						|
def test_outcome_repr():
 | 
						|
    out = ReprOutcome(Outcome(skipped=True).make_repr())
 | 
						|
    s = repr(out)
 | 
						|
    assert s.lower().find("skip") != -1
 | 
						|
 | 
						|
class DummyMasterNode(object):
 | 
						|
    def __init__(self):
 | 
						|
        self.pending = []
 | 
						|
    
 | 
						|
    def send(self, data):
 | 
						|
        self.pending.append(data)
 | 
						|
 | 
						|
def test_dispatch_loop():
 | 
						|
    masternodes = [DummyMasterNode(), DummyMasterNode()]
 | 
						|
    itemgenerator = iter(range(100))
 | 
						|
    shouldstop = lambda : False
 | 
						|
    def waiter():
 | 
						|
        for node in masternodes:
 | 
						|
            node.pending.pop()
 | 
						|
    dispatch_loop(masternodes, itemgenerator, shouldstop, waiter=waiter)
 | 
						|
 | 
						|
def test_slave_setup():
 | 
						|
    gw = py.execnet.PopenGateway()
 | 
						|
    config = py.test.config._reparse([])
 | 
						|
    channel = setup_slave(gw, pkgdir, config)
 | 
						|
    spec = rootcol.getitembynames(funcpass_spec).get_collector_trail()
 | 
						|
    channel.send(spec)
 | 
						|
    output = ReprOutcome(channel.receive())
 | 
						|
    assert output.passed
 | 
						|
    channel.send(42)
 | 
						|
    channel.waitclose(10)
 | 
						|
    gw.exit()
 | 
						|
 | 
						|
def test_slave_running():
 | 
						|
    def simple_report(event):
 | 
						|
        if not isinstance(event, report.ReceivedItemOutcome):
 | 
						|
            return
 | 
						|
        item = event.item
 | 
						|
        if item.code.name == 'funcpass':
 | 
						|
            assert event.outcome.passed
 | 
						|
        else:
 | 
						|
            assert not event.outcome.passed
 | 
						|
    
 | 
						|
    def open_gw():
 | 
						|
        gw = py.execnet.PopenGateway()
 | 
						|
        gw.host = HostInfo("localhost")
 | 
						|
        gw.host.gw = gw
 | 
						|
        config = py.test.config._reparse([])
 | 
						|
        channel = setup_slave(gw, pkgdir, config)
 | 
						|
        mn = MasterNode(channel, simple_report, {})
 | 
						|
        return mn
 | 
						|
    
 | 
						|
    master_nodes = [open_gw(), open_gw(), open_gw()]
 | 
						|
    funcpass_item = rootcol.getitembynames(funcpass_spec)
 | 
						|
    funcfail_item = rootcol.getitembynames(funcfail_spec)
 | 
						|
    itemgenerator = iter([funcfail_item] + 
 | 
						|
                         [funcpass_item] * 5 + [funcfail_item] * 5)
 | 
						|
    shouldstop = lambda : False
 | 
						|
    dispatch_loop(master_nodes, itemgenerator, shouldstop)
 | 
						|
 | 
						|
def test_slave_running_interrupted():
 | 
						|
    #def simple_report(event):
 | 
						|
    #    if not isinstance(event, report.ReceivedItemOutcome):
 | 
						|
    #        return
 | 
						|
    #    item = event.item
 | 
						|
    #    if item.code.name == 'funcpass':
 | 
						|
    #        assert event.outcome.passed
 | 
						|
    #    else:
 | 
						|
    #        assert not event.outcome.passed
 | 
						|
    reports = []
 | 
						|
    
 | 
						|
    def open_gw():
 | 
						|
        gw = py.execnet.PopenGateway()
 | 
						|
        gw.host = HostInfo("localhost")
 | 
						|
        gw.host.gw = gw
 | 
						|
        config = py.test.config._reparse([])
 | 
						|
        channel = setup_slave(gw, pkgdir, config)
 | 
						|
        mn = MasterNode(channel, reports.append, {})
 | 
						|
        return mn, gw, channel
 | 
						|
 | 
						|
    mn, gw, channel = open_gw()
 | 
						|
    rootcol = py.test.collect.Directory(pkgdir)
 | 
						|
    funchang_item = rootcol.getitembynames(funchang_spec)
 | 
						|
    mn.send(funchang_item)
 | 
						|
    mn.send(StopIteration)
 | 
						|
    # XXX: We have to wait here a bit to make sure that it really did happen
 | 
						|
    channel.waitclose(2)
 | 
						|
 | 
						|
def test_randomgen():
 | 
						|
    d = {}
 | 
						|
    gen = randomgen({1:True, 2:True, 3:True}, d)
 | 
						|
    for i in range(100):
 | 
						|
        assert gen.next() in [1,2,3]
 | 
						|
    d[3] = True
 | 
						|
    for i in range(100):
 | 
						|
        assert gen.next() in [1,2]
 | 
						|
    d[2] = True
 | 
						|
    d[1] = True
 | 
						|
    py.test.raises(StopIteration, "gen.next()")
 | 
						|
 |