diff --git a/src/wormhole/_boss.py b/src/wormhole/_boss.py index 2a1d2db..3b8950b 100644 --- a/src/wormhole/_boss.py +++ b/src/wormhole/_boss.py @@ -86,32 +86,38 @@ class Boss(object): def start(self): self._RC.start() + def _print_trace(self, old_state, input, new_state, + client_name, machine, file): + if new_state: + print("%s.%s[%s].%s -> [%s]" % + (client_name, machine, old_state, input, + new_state), file=file) + else: + # the RendezvousConnector emits message events as if + # they were state transitions, except that old_state + # and new_state are empty strings. "input" is one of + # R.connected, R.rx(type phase+side), R.tx(type + # phase), R.lost . + print("%s.%s.%s" % (client_name, machine, input), + file=file) + file.flush() + def output_tracer(output): + print(" %s.%s.%s()" % (client_name, machine, output), + file=file) + file.flush() + return output_tracer + def _set_trace(self, client_name, which, file): names = {"B": self, "N": self._N, "M": self._M, "S": self._S, "O": self._O, "K": self._K, "SK": self._K._SK, "R": self._R, "RC": self._RC, "L": self._L, "C": self._C, "T": self._T} for machine in which.split(): - def tracer(old_state, input, new_state, machine=machine): - if new_state: - print("%s.%s[%s].%s -> [%s]" % - (client_name, machine, old_state, input, - new_state), file=file) - else: - # the RendezvousConnector emits message events as if - # they were state transitions, except that old_state - # and new_state are empty strings. "input" is one of - # R.connected, R.rx(type phase+side), R.tx(type - # phase), R.lost . - print("%s.%s.%s" % (client_name, machine, input), - file=file) - file.flush() - def output_tracer(output): - print(" %s.%s.%s()" % (client_name, machine, output), - file=file) - file.flush() - return output_tracer - names[machine].set_trace(tracer) + t = (lambda old_state, input, new_state: + self._print_trace(old_state, input, new_state, + client_name=client_name, + machine=machine, file=file)) + names[machine].set_trace(t) ## def serialize(self): ## raise NotImplemented diff --git a/src/wormhole/test/test_wormhole.py b/src/wormhole/test/test_wormhole.py index 5b307d1..b42f6d3 100644 --- a/src/wormhole/test/test_wormhole.py +++ b/src/wormhole/test/test_wormhole.py @@ -527,3 +527,35 @@ class Reconnection(ServerBase, unittest.TestCase): self.assertEqual(c1, "happy") c2 = yield w2.close() self.assertEqual(c2, "happy") + +class Trace(unittest.TestCase): + def test_basic(self): + w1 = wormhole.create(APPID, "ws://localhost:1", reactor) + stderr = io.StringIO() + w1.debug_set_trace("W1", file=stderr) + # if Automat doesn't have the tracing API, then we won't actually + # exercise the tracing function, so exercise the RendezvousConnector + # function manually (it isn't a state machine, so it will always wire + # up the tracer) + w1._boss._RC._debug("what") + + stderr = io.StringIO() + out = w1._boss._print_trace("OLD", "IN", "NEW", "C1", "M1", stderr) + self.assertEqual(stderr.getvalue().splitlines(), + ["C1.M1[OLD].IN -> [NEW]"]) + out("OUT1") + self.assertEqual(stderr.getvalue().splitlines(), + ["C1.M1[OLD].IN -> [NEW]", + " C1.M1.OUT1()"]) + w1._boss._print_trace("", "R.connected", "", "C1", "RC1", stderr) + self.assertEqual(stderr.getvalue().splitlines(), + ["C1.M1[OLD].IN -> [NEW]", + " C1.M1.OUT1()", + "C1.RC1.R.connected"]) + + def test_delegated(self): + dg = Delegate() + w1 = wormhole.create(APPID, "ws://localhost:1", reactor, delegate=dg) + stderr = io.StringIO() + w1.debug_set_trace("W1", file=stderr) + w1._boss._RC._debug("what")