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