diff --git a/py/execnet/gwmanage.py b/py/execnet/gwmanage.py index 6f67b9b34..6049a8735 100644 --- a/py/execnet/gwmanage.py +++ b/py/execnet/gwmanage.py @@ -147,20 +147,22 @@ class GatewayManager: """ perform rsync to all remote hosts. """ rsync = HostRSync(source, verbose=verbose, ignores=ignores) - added = False + seen = {} for gateway in self.gateways: spec = gateway.spec if not spec.inplacelocal(): - self.trace("add_target_host %r" %(gateway,)) + key = spec.type, spec.address, spec.joinpath + if key in seen: + continue def finished(): if notify: notify("rsyncrootready", spec, source) rsync.add_target_host(gateway, finished=finished) - added = True - if added: - self.trace("rsyncing %r" % source) + seen[key] = gateway + if seen: + self.notify("gwmanage_rsyncstart", source=source, gateways=seen.values()) rsync.send() - self.trace("rsyncing %r finished" % source) + self.notify("gwmanage_rsyncfinish", source=source, gateways=seen.values()) else: self.trace("rsync: nothing to do.") diff --git a/py/execnet/testing/test_gwmanage.py b/py/execnet/testing/test_gwmanage.py index ca357ced7..d115732f2 100644 --- a/py/execnet/testing/test_gwmanage.py +++ b/py/execnet/testing/test_gwmanage.py @@ -50,18 +50,18 @@ class TestGatewayManagerPopen: assert dest.join("dir1", "dir2").check() assert dest.join("dir1", "dir2", 'hello').check() - def XXXtest_ssh_rsync_samehost_twice(self): - #XXX we have no easy way to have a temp directory remotely! - option = py.test.config.option - if option.sshhost is None: - py.test.skip("no known ssh target, use -S to set one") - host1 = Host("%s" % (option.sshhost, )) - host2 = Host("%s" % (option.sshhost, )) - hm = HostManager(config, hosts=[host1, host2]) - events = [] - hm.init_rsync(events.append) - print events - assert 0 + def test_hostmanage_rsync_same_popen_twice(self, source, dest, eventrecorder): + hm = GatewayManager(["popen::%s" %dest] * 2) + hm.makegateways() + source.ensure("dir1", "dir2", "hello") + hm.rsync(source) + event = eventrecorder.popevent("gwmanage_rsyncstart") + source2 = event.kwargs['source'] + gws = event.kwargs['gateways'] + assert source2 == source + assert len(gws) == 1 + assert hm.gateways[0] == gws[0] + event = eventrecorder.popevent("gwmanage_rsyncfinish") def test_multi_chdir_popen_with_path(self, testdir): import os @@ -132,4 +132,3 @@ class TestHRSync: gw.exit() assert dest.join(source.basename, "hello.py").check() assert len(finished) == 1 - diff --git a/py/test/dsession/testing/test_hostmanage.py b/py/test/dsession/testing/test_hostmanage.py index 96283bf4f..bb617fa10 100644 --- a/py/test/dsession/testing/test_hostmanage.py +++ b/py/test/dsession/testing/test_hostmanage.py @@ -147,9 +147,7 @@ class TestHostManager: ev = sorter.getfirstnamed("itemtestreport") assert ev.passed - @py.test.mark.xfail("implement double-rsync test") - def test_ssh_rsync_samehost_twice(self): - sshhost = getsshhost(withpython=True) + def test_rsync_samehost_twice(self): host1 = Host("%s" % (sshhost, )) host2 = Host("%s" % (sshhost, )) hm = HostManager(config, hosts=[host1, host2]) diff --git a/py/test/plugin/pytest_plugintester.py b/py/test/plugin/pytest_plugintester.py index 46b45fade..947c19e10 100644 --- a/py/test/plugin/pytest_plugintester.py +++ b/py/test/plugin/pytest_plugintester.py @@ -161,6 +161,12 @@ class PytestPluginHooks: def pyevent_gateway_exit(self, gateway): """ called when gateway is being exited. """ + def pyevent_gwmanage_rsyncstart(self, source, gateways): + """ called before rsyncing a directory to remote gateways takes place. """ + + def pyevent_gwmanage_rsyncfinish(self, source, gateways): + """ called after rsyncing a directory to remote gateways takes place. """ + def pyevent_trace(self, category, msg): """ called for tracing events. """ diff --git a/py/test/plugin/pytest_terminal.py b/py/test/plugin/pytest_terminal.py index 97dae73fe..b334d3b05 100644 --- a/py/test/plugin/pytest_terminal.py +++ b/py/test/plugin/pytest_terminal.py @@ -87,9 +87,13 @@ class TerminalReporter: def pyevent_gwmanage_newgateway(self, gateway): self.write_line("%s instantiated gateway from spec %r" %(gateway.id, gateway.spec._spec)) - def pyevent_hostgatewayready(self, event): - if self.config.option.verbose: - self.write_line("HostGatewayReady: %s" %(event.host,)) + def pyevent_gwmanage_rsyncstart(self, source, gateways): + targets = ", ".join([gw.id for gw in gateways]) + self.write_line("rsyncstart: %s -> %s" %(source, targets)) + + def pyevent_gwmanage_rsyncfinish(self, source, gateways): + targets = ", ".join([gw.id for gw in gateways]) + self.write_line("rsyncfinish: %s -> %s" %(source, targets)) def pyevent_plugin_registered(self, plugin): if self.config.option.traceconfig: @@ -323,7 +327,6 @@ from py.__.test.dsession.masterslave import makehostup class TestTerminal: def test_hostup(self, testdir, linecomp): - from py.__.execnet.gwmanage import GatewaySpec item = testdir.getitem("def test_func(): pass") rep = TerminalReporter(item.config, linecomp.stringio) rep.pyevent_hostup(makehostup()) @@ -416,21 +419,31 @@ class TestTerminal: "InternalException: >*raise ValueError*" ]) - def test_hostready_crash(self, testdir, linecomp): - from py.__.execnet.gwmanage import GatewaySpec + def test_gwmanage_events(self, testdir, linecomp): modcol = testdir.getmodulecol(""" def test_one(): pass """, configargs=("-v",)) - host1 = GatewaySpec("localhost") + rep = TerminalReporter(modcol.config, file=linecomp.stringio) - rep.pyevent_hostgatewayready(event.HostGatewayReady(host1, None)) + class gw1: + id = "X1" + spec = py.execnet.GatewaySpec("popen") + class gw2: + id = "X2" + spec = py.execnet.GatewaySpec("popen") + rep.pyevent_gwmanage_newgateway(gateway=gw1) linecomp.assert_contains_lines([ - "*HostGatewayReady*" + "X1 instantiated gateway from spec*", ]) - rep.pyevent_hostdown(event.HostDown(host1, "myerror")) + + rep.pyevent_gwmanage_rsyncstart(source="hello", gateways=[gw1, gw2]) linecomp.assert_contains_lines([ - "*HostDown*myerror*", + "rsyncstart: hello -> X1, X2" + ]) + rep.pyevent_gwmanage_rsyncfinish(source="hello", gateways=[gw1, gw2]) + linecomp.assert_contains_lines([ + "rsyncfinish: hello -> X1, X2" ]) def test_writeline(self, testdir, linecomp): diff --git a/py/test/testing/test_pickling.py b/py/test/testing/test_pickling.py index 7a2058306..285b382f1 100644 --- a/py/test/testing/test_pickling.py +++ b/py/test/testing/test_pickling.py @@ -44,7 +44,7 @@ class TestImmutablePickling: assert config1.topdir == testdir.tmpdir testdir.chdir() p2config = pickletransport.p1_to_p2(config1) - assert p2config.topdir == config1.topdir + assert p2config.topdir.realpath() == config1.topdir.realpath() config_back = pickletransport.p2_to_p1(p2config) assert config_back is config1 @@ -160,10 +160,10 @@ class TestConfigPickling: newcol3 = unpickler.load() assert newcol2.config is newcol.config assert newcol2.parent == newcol - assert newcol2.config.topdir == topdir - assert newcol.fspath == topdir + assert newcol2.config.topdir.realpath() == topdir.realpath() + assert newcol.fspath.realpath() == topdir.realpath() assert newcol2.fspath.basename == dir1.basename - assert newcol2.fspath.relto(topdir) + assert newcol2.fspath.relto(newcol2.config.topdir) finally: old.chdir()