get null test working (open and immediate close)
This commit is contained in:
parent
c95b6d402c
commit
ef1904bc52
|
@ -17,6 +17,8 @@ digraph {
|
||||||
S0 [label="S0: empty"]
|
S0 [label="S0: empty"]
|
||||||
S0 -> P0_build [label="set_code"]
|
S0 -> P0_build [label="set_code"]
|
||||||
|
|
||||||
|
S0 -> P_close_lonely [label="close"]
|
||||||
|
|
||||||
P0_build [shape="box" label="W.got_code\nM.set_nameplate\nK.got_code"]
|
P0_build [shape="box" label="W.got_code\nM.set_nameplate\nK.got_code"]
|
||||||
P0_build -> S1
|
P0_build -> S1
|
||||||
S1 [label="S1: lonely" color="orange"]
|
S1 [label="S1: lonely" color="orange"]
|
||||||
|
|
|
@ -1,17 +1,8 @@
|
||||||
digraph {
|
digraph {
|
||||||
/* new idea */
|
/* new idea */
|
||||||
|
|
||||||
{rank=same; title entry_whole_code entry_allocation entry_interactive}
|
|
||||||
entry_whole_code [label="whole\ncode"]
|
|
||||||
entry_whole_code -> S0A
|
|
||||||
title [label="Message\nMachine" style="dotted"]
|
title [label="Message\nMachine" style="dotted"]
|
||||||
|
|
||||||
entry_allocation [label="allocation" color="orange"]
|
|
||||||
entry_allocation -> S0B [label="(already\nconnected)"
|
|
||||||
color="orange" fontcolor="orange"]
|
|
||||||
entry_interactive [label="interactive" color="orange"]
|
|
||||||
entry_interactive -> S0B [color="orange"]
|
|
||||||
|
|
||||||
{rank=same; S0A P0_connected S0B}
|
{rank=same; S0A P0_connected S0B}
|
||||||
S0A [label="S0A:\nknow nothing"]
|
S0A [label="S0A:\nknow nothing"]
|
||||||
S0B [label="S0B:\nknow nothing\n(bound)" color="orange"]
|
S0B [label="S0B:\nknow nothing\n(bound)" color="orange"]
|
||||||
|
|
|
@ -16,6 +16,7 @@ from .util import bytes_to_dict
|
||||||
@attrs
|
@attrs
|
||||||
@implementer(_interfaces.IBoss)
|
@implementer(_interfaces.IBoss)
|
||||||
class Boss(object):
|
class Boss(object):
|
||||||
|
_W = attrib()
|
||||||
_side = attrib(validator=instance_of(type(u"")))
|
_side = attrib(validator=instance_of(type(u"")))
|
||||||
_url = attrib(validator=instance_of(type(u"")))
|
_url = attrib(validator=instance_of(type(u"")))
|
||||||
_appid = attrib(validator=instance_of(type(u"")))
|
_appid = attrib(validator=instance_of(type(u"")))
|
||||||
|
@ -24,14 +25,15 @@ class Boss(object):
|
||||||
_timing = attrib(validator=provides(_interfaces.ITiming))
|
_timing = attrib(validator=provides(_interfaces.ITiming))
|
||||||
m = MethodicalMachine()
|
m = MethodicalMachine()
|
||||||
|
|
||||||
def __init__(self, wormhole):
|
def __attrs_post_init__(self):
|
||||||
self._W = wormhole
|
|
||||||
self._M = Mailbox(self._side)
|
self._M = Mailbox(self._side)
|
||||||
self._S = Send(self._side, self._timing)
|
self._S = Send(self._side, self._timing)
|
||||||
self._O = Order(self._side, self._timing)
|
self._O = Order(self._side, self._timing)
|
||||||
self._K = Key(self._timing)
|
self._K = Key(self._timing)
|
||||||
self._R = Receive(self._side, self._timing)
|
self._R = Receive(self._side, self._timing)
|
||||||
self._RC = RendezvousConnector(self._side, self._timing, self._reactor)
|
self._RC = RendezvousConnector(self._url, self._appid, self._side,
|
||||||
|
self._reactor, self._journal,
|
||||||
|
self._timing)
|
||||||
self._NL = NameplateListing()
|
self._NL = NameplateListing()
|
||||||
self._C = Code(self._timing)
|
self._C = Code(self._timing)
|
||||||
|
|
||||||
|
@ -44,6 +46,10 @@ class Boss(object):
|
||||||
self._NL.wire(self._RC, self._C)
|
self._NL.wire(self._RC, self._C)
|
||||||
self._C.wire(self, self._RC, self._NL)
|
self._C.wire(self, self._RC, self._NL)
|
||||||
|
|
||||||
|
self._next_tx_phase = 0
|
||||||
|
self._next_rx_phase = 0
|
||||||
|
self._rx_phases = {} # phase -> plaintext
|
||||||
|
|
||||||
# these methods are called from outside
|
# these methods are called from outside
|
||||||
def start(self):
|
def start(self):
|
||||||
self._RC.start()
|
self._RC.start()
|
||||||
|
@ -82,7 +88,7 @@ class Boss(object):
|
||||||
self._C.set_code(code)
|
self._C.set_code(code)
|
||||||
|
|
||||||
@m.input()
|
@m.input()
|
||||||
def send(self, phase, plaintext): pass
|
def send(self, plaintext): pass
|
||||||
@m.input()
|
@m.input()
|
||||||
def close(self): pass
|
def close(self): pass
|
||||||
|
|
||||||
|
@ -127,7 +133,9 @@ class Boss(object):
|
||||||
# ignored for now
|
# ignored for now
|
||||||
|
|
||||||
@m.output()
|
@m.output()
|
||||||
def S_send(self, phase, plaintext):
|
def S_send(self, plaintext):
|
||||||
|
phase = self._next_tx_phase
|
||||||
|
self._next_tx_phase += 1
|
||||||
self._S.send(phase, plaintext)
|
self._S.send(phase, plaintext)
|
||||||
|
|
||||||
@m.output()
|
@m.output()
|
||||||
|
@ -145,13 +153,19 @@ class Boss(object):
|
||||||
self._W.got_verifier(verifier)
|
self._W.got_verifier(verifier)
|
||||||
@m.output()
|
@m.output()
|
||||||
def W_received(self, phase, plaintext):
|
def W_received(self, phase, plaintext):
|
||||||
self._W.received(phase, plaintext)
|
# we call Wormhole.received() in strict phase order, with no gaps
|
||||||
|
self._rx_phases[phase] = plaintext
|
||||||
|
while self._next_rx_phase in self._rx_phases:
|
||||||
|
self._W.received(self._next_rx_phase,
|
||||||
|
self._rx_phases.pop(self._next_rx_phase))
|
||||||
|
self._next_rx_phase += 1
|
||||||
|
|
||||||
@m.output()
|
@m.output()
|
||||||
def W_closed(self):
|
def W_closed(self):
|
||||||
result = "???"
|
result = "???"
|
||||||
self._W.closed(result)
|
self._W.closed(result)
|
||||||
|
|
||||||
|
S0_empty.upon(close, enter=S3_closing, outputs=[close_lonely])
|
||||||
S0_empty.upon(send, enter=S0_empty, outputs=[S_send])
|
S0_empty.upon(send, enter=S0_empty, outputs=[S_send])
|
||||||
S0_empty.upon(got_code, enter=S1_lonely, outputs=[do_got_code])
|
S0_empty.upon(got_code, enter=S1_lonely, outputs=[do_got_code])
|
||||||
S1_lonely.upon(happy, enter=S2_happy, outputs=[])
|
S1_lonely.upon(happy, enter=S2_happy, outputs=[])
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
from zope.interface import Interface
|
from zope.interface import Interface
|
||||||
|
|
||||||
|
class IWormhole(Interface):
|
||||||
|
pass
|
||||||
class IBoss(Interface):
|
class IBoss(Interface):
|
||||||
pass
|
pass
|
||||||
class IMailbox(Interface):
|
class IMailbox(Interface):
|
||||||
|
|
|
@ -22,15 +22,12 @@ class Mailbox(object):
|
||||||
self._RC = _interfaces.IRendezvousConnector(rendezvous_connector)
|
self._RC = _interfaces.IRendezvousConnector(rendezvous_connector)
|
||||||
self._O = _interfaces.IOrder(ordering)
|
self._O = _interfaces.IOrder(ordering)
|
||||||
|
|
||||||
@m.state(initial=True)
|
|
||||||
def initial(self): pass
|
|
||||||
|
|
||||||
# all -A states: not connected
|
# all -A states: not connected
|
||||||
# all -B states: yes connected
|
# all -B states: yes connected
|
||||||
# B states serialize as A, so they deserialize as unconnected
|
# B states serialize as A, so they deserialize as unconnected
|
||||||
|
|
||||||
# S0: know nothing
|
# S0: know nothing
|
||||||
@m.state()
|
@m.state(initial=True)
|
||||||
def S0A(self): pass
|
def S0A(self): pass
|
||||||
@m.state()
|
@m.state()
|
||||||
def S0B(self): pass
|
def S0B(self): pass
|
||||||
|
@ -87,11 +84,6 @@ class Mailbox(object):
|
||||||
def Ss(self): pass
|
def Ss(self): pass
|
||||||
|
|
||||||
|
|
||||||
@m.input()
|
|
||||||
def start_unconnected(self): pass
|
|
||||||
@m.input()
|
|
||||||
def start_connected(self): pass
|
|
||||||
|
|
||||||
# from Boss
|
# from Boss
|
||||||
@m.input()
|
@m.input()
|
||||||
def set_nameplate(self, nameplate): pass
|
def set_nameplate(self, nameplate): pass
|
||||||
|
@ -211,12 +203,12 @@ class Mailbox(object):
|
||||||
@m.output()
|
@m.output()
|
||||||
def RC_stop(self):
|
def RC_stop(self):
|
||||||
self._RC_stop()
|
self._RC_stop()
|
||||||
|
def _RC_stop(self):
|
||||||
|
self._RC.stop()
|
||||||
@m.output()
|
@m.output()
|
||||||
def W_closed(self):
|
def W_closed(self):
|
||||||
self._B.closed()
|
self._B.closed()
|
||||||
|
|
||||||
initial.upon(start_unconnected, enter=S0A, outputs=[])
|
|
||||||
initial.upon(start_connected, enter=S0B, outputs=[])
|
|
||||||
S0A.upon(connected, enter=S0B, outputs=[])
|
S0A.upon(connected, enter=S0B, outputs=[])
|
||||||
S0A.upon(set_nameplate, enter=S1A, outputs=[record_nameplate])
|
S0A.upon(set_nameplate, enter=S1A, outputs=[record_nameplate])
|
||||||
S0A.upon(add_message, enter=S0A, outputs=[queue])
|
S0A.upon(add_message, enter=S0A, outputs=[queue])
|
||||||
|
|
|
@ -61,7 +61,7 @@ class RendezvousConnector(object):
|
||||||
_journal = attrib(validator=provides(_interfaces.IJournal))
|
_journal = attrib(validator=provides(_interfaces.IJournal))
|
||||||
_timing = attrib(validator=provides(_interfaces.ITiming))
|
_timing = attrib(validator=provides(_interfaces.ITiming))
|
||||||
|
|
||||||
def __init__(self):
|
def __attrs_post_init__(self):
|
||||||
self._ws = None
|
self._ws = None
|
||||||
f = WSFactory(self, self._url)
|
f = WSFactory(self, self._url)
|
||||||
f.setProtocolOptions(autoPingInterval=60, autoPingTimeout=600)
|
f.setProtocolOptions(autoPingInterval=60, autoPingTimeout=600)
|
||||||
|
|
28
src/wormhole/test/test_wormhole_new.py
Normal file
28
src/wormhole/test/test_wormhole_new.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
from __future__ import print_function, unicode_literals
|
||||||
|
from twisted.trial import unittest
|
||||||
|
from twisted.internet import reactor
|
||||||
|
from .common import ServerBase
|
||||||
|
from .. import wormhole
|
||||||
|
|
||||||
|
APPID = "appid"
|
||||||
|
|
||||||
|
class Delegate:
|
||||||
|
def __init__(self):
|
||||||
|
self.code = None
|
||||||
|
self.verifier = None
|
||||||
|
self.messages = []
|
||||||
|
self.closed = None
|
||||||
|
def wormhole_got_code(self, code):
|
||||||
|
self.code = code
|
||||||
|
def wormhole_got_verifier(self, verifier):
|
||||||
|
self.verifier = verifier
|
||||||
|
def wormhole_receive(self, data):
|
||||||
|
self.messages.append(data)
|
||||||
|
def wormhole_closed(self, result):
|
||||||
|
self.closed = result
|
||||||
|
|
||||||
|
class New(ServerBase, unittest.TestCase):
|
||||||
|
def test_basic(self):
|
||||||
|
dg = Delegate()
|
||||||
|
w = wormhole.delegated_wormhole(APPID, self.relayurl, reactor, dg)
|
||||||
|
w.close()
|
|
@ -1,5 +1,7 @@
|
||||||
from __future__ import print_function, absolute_import, unicode_literals
|
from __future__ import print_function, absolute_import, unicode_literals
|
||||||
import json, time
|
import json, time
|
||||||
|
from zope.interface import implementer
|
||||||
|
from ._interfaces import ITiming
|
||||||
|
|
||||||
class Event:
|
class Event:
|
||||||
def __init__(self, name, when, **details):
|
def __init__(self, name, when, **details):
|
||||||
|
@ -33,6 +35,7 @@ class Event:
|
||||||
else:
|
else:
|
||||||
self.finish()
|
self.finish()
|
||||||
|
|
||||||
|
@implementer(ITiming)
|
||||||
class DebugTiming:
|
class DebugTiming:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._events = []
|
self._events = []
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
from __future__ import print_function, absolute_import, unicode_literals
|
from __future__ import print_function, absolute_import, unicode_literals
|
||||||
import sys
|
import os, sys
|
||||||
from attr import attrs, attrib
|
from attr import attrs, attrib
|
||||||
|
from zope.interface import implementer
|
||||||
|
from twisted.internet import defer
|
||||||
|
from ._interfaces import IWormhole
|
||||||
|
from .util import bytes_to_hexstr
|
||||||
from .timing import DebugTiming
|
from .timing import DebugTiming
|
||||||
from .journal import ImmediateJournal
|
from .journal import ImmediateJournal
|
||||||
from ._boss import Boss
|
from ._boss import Boss
|
||||||
|
@ -16,6 +20,7 @@ from ._boss import Boss
|
||||||
# w = wormhole(delegate=app)
|
# w = wormhole(delegate=app)
|
||||||
# w.send(data)
|
# w.send(data)
|
||||||
# app.wormhole_got_code(code)
|
# app.wormhole_got_code(code)
|
||||||
|
# app.wormhole_got_verifier(verifier)
|
||||||
# app.wormhole_receive(data)
|
# app.wormhole_receive(data)
|
||||||
# w.close()
|
# w.close()
|
||||||
# app.wormhole_closed()
|
# app.wormhole_closed()
|
||||||
|
@ -25,6 +30,7 @@ from ._boss import Boss
|
||||||
# delegate_args=(args, kwargs))
|
# delegate_args=(args, kwargs))
|
||||||
|
|
||||||
@attrs
|
@attrs
|
||||||
|
@implementer(IWormhole)
|
||||||
class _DelegatedWormhole(object):
|
class _DelegatedWormhole(object):
|
||||||
_delegate = attrib()
|
_delegate = attrib()
|
||||||
|
|
||||||
|
@ -32,8 +38,8 @@ class _DelegatedWormhole(object):
|
||||||
self._boss = boss
|
self._boss = boss
|
||||||
|
|
||||||
# from above
|
# from above
|
||||||
def send(self, phase, plaintext):
|
def send(self, plaintext):
|
||||||
self._boss.send(phase, plaintext)
|
self._boss.send(plaintext)
|
||||||
def close(self):
|
def close(self):
|
||||||
self._boss.close()
|
self._boss.close()
|
||||||
|
|
||||||
|
@ -48,6 +54,7 @@ class _DelegatedWormhole(object):
|
||||||
def closed(self, result):
|
def closed(self, result):
|
||||||
self._delegate.wormhole_closed(result)
|
self._delegate.wormhole_closed(result)
|
||||||
|
|
||||||
|
@implementer(IWormhole)
|
||||||
class _DeferredWormhole(object):
|
class _DeferredWormhole(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._code = None
|
self._code = None
|
||||||
|
@ -73,8 +80,8 @@ class _DeferredWormhole(object):
|
||||||
self._verifier_observers.append(d)
|
self._verifier_observers.append(d)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def send(self, phase, plaintext):
|
def send(self, plaintext):
|
||||||
self._boss.send(phase, plaintext)
|
self._boss.send(plaintext)
|
||||||
def close(self):
|
def close(self):
|
||||||
self._boss.close()
|
self._boss.close()
|
||||||
|
|
||||||
|
@ -130,5 +137,5 @@ def deferred_wormhole(appid, relay_url, reactor,
|
||||||
journal=None,
|
journal=None,
|
||||||
stderr=sys.stderr,
|
stderr=sys.stderr,
|
||||||
):
|
):
|
||||||
return _wormhole(appid, relay_url, reactor, delegate=None,
|
return _wormhole(appid, relay_url, reactor, None,
|
||||||
tor_manager, timing, journal, stderr)
|
tor_manager, timing, journal, stderr)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user