wip: testing
This commit is contained in:
		| @@ -1,143 +1,12 @@ | |||||||
| package peer | package peer | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"net/netip" |  | ||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" |  | ||||||
| 	"vppn/m" | 	"vppn/m" | ||||||
|  |  | ||||||
| 	"git.crumpington.com/lib/go/ratelimiter" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // ---------------------------------------------------------------------------- | // ---------------------------------------------------------------------------- | ||||||
|  |  | ||||||
| type PeerStateControlMsg struct { |  | ||||||
| 	Peer   remotePeer |  | ||||||
| 	Packet any |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type PeerStateTestHarness struct { |  | ||||||
| 	State     peerState |  | ||||||
| 	Published remotePeer |  | ||||||
| 	Sent      []PeerStateControlMsg |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func NewPeerStateTestHarness() *PeerStateTestHarness { |  | ||||||
| 	h := &PeerStateTestHarness{} |  | ||||||
|  |  | ||||||
| 	keys := generateKeys() |  | ||||||
|  |  | ||||||
| 	state := &peerData{ |  | ||||||
| 		publish: func(rp remotePeer) { |  | ||||||
| 			h.Published = rp |  | ||||||
| 		}, |  | ||||||
| 		sendControlPacket: func(rp remotePeer, pkt marshaller) { |  | ||||||
| 			h.Sent = append(h.Sent, PeerStateControlMsg{rp, pkt}) |  | ||||||
| 		}, |  | ||||||
| 		pingTimer: time.NewTicker(pingInterval), |  | ||||||
| 		localIP:   2, |  | ||||||
| 		remoteIP:  3, |  | ||||||
| 		privKey:   keys.PrivKey, |  | ||||||
| 		pubAddrs:  newPubAddrStore(netip.AddrPort{}), |  | ||||||
| 		limiter: ratelimiter.New(ratelimiter.Config{ |  | ||||||
| 			FillPeriod:   20 * time.Millisecond, |  | ||||||
| 			MaxWaitCount: 1, |  | ||||||
| 		}), |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	h.State = enterStateDisconnected(state) |  | ||||||
| 	return h |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (h *PeerStateTestHarness) PeerUpdate(p *m.Peer) { |  | ||||||
| 	h.State = h.State.OnMsg(peerUpdateMsg{p}) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (h *PeerStateTestHarness) OnInit(msg controlMsg[packetInit]) { |  | ||||||
| 	h.State = h.State.OnMsg(msg) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (h *PeerStateTestHarness) OnSyn(msg controlMsg[packetSyn]) { |  | ||||||
| 	h.State = h.State.OnMsg(msg) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (h *PeerStateTestHarness) OnProbe(msg controlMsg[packetProbe]) { |  | ||||||
| 	h.State = h.State.OnMsg(msg) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (h *PeerStateTestHarness) OnPingTimer() { |  | ||||||
| 	h.State = h.State.OnMsg(pingTimerMsg{}) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (h *PeerStateTestHarness) ConfigServer_Public(t *testing.T) *stateServer { |  | ||||||
| 	keys := generateKeys() |  | ||||||
|  |  | ||||||
| 	state := h.State.(*stateDisconnected) |  | ||||||
| 	state.localAddr = addrPort4(1, 1, 1, 2, 200) |  | ||||||
|  |  | ||||||
| 	peer := &m.Peer{ |  | ||||||
| 		PeerIP:     3, |  | ||||||
| 		PublicIP:   []byte{1, 1, 1, 3}, |  | ||||||
| 		Port:       456, |  | ||||||
| 		PubKey:     keys.PubKey, |  | ||||||
| 		PubSignKey: keys.PubSignKey, |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	h.PeerUpdate(peer) |  | ||||||
| 	assertEqual(t, h.Published.Up, false) |  | ||||||
| 	return assertType[*stateServer](t, h.State) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (h *PeerStateTestHarness) ConfigServer_Relayed(t *testing.T) *stateServer { |  | ||||||
| 	keys := generateKeys() |  | ||||||
| 	peer := &m.Peer{ |  | ||||||
| 		PeerIP:     3, |  | ||||||
| 		Port:       456, |  | ||||||
| 		PubKey:     keys.PubKey, |  | ||||||
| 		PubSignKey: keys.PubSignKey, |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	h.PeerUpdate(peer) |  | ||||||
| 	assertEqual(t, h.Published.Up, false) |  | ||||||
| 	return assertType[*stateServer](t, h.State) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (h *PeerStateTestHarness) ConfigClientDirect(t *testing.T) *stateClientDirect { |  | ||||||
| 	keys := generateKeys() |  | ||||||
| 	peer := &m.Peer{ |  | ||||||
| 		PeerIP:     3, |  | ||||||
| 		PublicIP:   []byte{1, 2, 3, 4}, |  | ||||||
| 		Port:       456, |  | ||||||
| 		PubKey:     keys.PubKey, |  | ||||||
| 		PubSignKey: keys.PubSignKey, |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	h.PeerUpdate(peer) |  | ||||||
| 	assertEqual(t, h.Published.Up, false) |  | ||||||
|  |  | ||||||
| 	return assertType[*stateClientDirect](t, h.State) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (h *PeerStateTestHarness) ConfigClientRelayed(t *testing.T) *stateClientRelayed { |  | ||||||
| 	keys := generateKeys() |  | ||||||
|  |  | ||||||
| 	state := h.State.(*stateDisconnected) |  | ||||||
| 	state.remoteIP = 1 |  | ||||||
|  |  | ||||||
| 	peer := &m.Peer{ |  | ||||||
| 		PeerIP:     3, |  | ||||||
| 		Port:       456, |  | ||||||
| 		PubKey:     keys.PubKey, |  | ||||||
| 		PubSignKey: keys.PubSignKey, |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	h.PeerUpdate(peer) |  | ||||||
| 	assertEqual(t, h.Published.Up, false) |  | ||||||
| 	return assertType[*stateClientRelayed](t, h.State) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // ---------------------------------------------------------------------------- |  | ||||||
|  |  | ||||||
| func TestPeerState_OnPeerUpdate_nilPeer(t *testing.T) { | func TestPeerState_OnPeerUpdate_nilPeer(t *testing.T) { | ||||||
| 	h := NewPeerStateTestHarness() | 	h := NewPeerStateTestHarness() | ||||||
| 	h.PeerUpdate(nil) | 	h.PeerUpdate(nil) | ||||||
| @@ -163,6 +32,7 @@ func TestPeerState_OnPeerUpdate_publicLocalIsServer(t *testing.T) { | |||||||
| 	assertType[*stateServer](t, h.State) | 	assertType[*stateServer](t, h.State) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
| func TestPeerState_OnPeerUpdate_serverDirect(t *testing.T) { | func TestPeerState_OnPeerUpdate_serverDirect(t *testing.T) { | ||||||
| 	h := NewPeerStateTestHarness() | 	h := NewPeerStateTestHarness() | ||||||
| 	h.ConfigServer_Public(t) | 	h.ConfigServer_Public(t) | ||||||
| @@ -178,11 +48,13 @@ func TestPeerState_OnPeerUpdate_clientDirect(t *testing.T) { | |||||||
| 	h.ConfigClientDirect(t) | 	h.ConfigClientDirect(t) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
| func TestPeerState_OnPeerUpdate_clientRelayed(t *testing.T) { | func TestPeerState_OnPeerUpdate_clientRelayed(t *testing.T) { | ||||||
| 	h := NewPeerStateTestHarness() | 	h := NewPeerStateTestHarness() | ||||||
| 	h.ConfigClientRelayed(t) | 	h.ConfigClientRelayed(t) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
| func TestStateServer_directSyn(t *testing.T) { | func TestStateServer_directSyn(t *testing.T) { | ||||||
| 	h := NewPeerStateTestHarness() | 	h := NewPeerStateTestHarness() | ||||||
| 	h.ConfigServer_Relayed(t) | 	h.ConfigServer_Relayed(t) | ||||||
| @@ -505,3 +377,4 @@ func TestStateClientRelayed_OnProbe_upgradeDirect(t *testing.T) { | |||||||
|  |  | ||||||
| 	assertType[*stateClientDirect](t, h.State) | 	assertType[*stateClientDirect](t, h.State) | ||||||
| } | } | ||||||
|  | */ | ||||||
|   | |||||||
							
								
								
									
										83
									
								
								peer/state-clientinit_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								peer/state-clientinit_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | |||||||
|  | package peer | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestPeerState_ClientInit_initWithIncorrectTraceID(t *testing.T) { | ||||||
|  | 	h := NewPeerStateTestHarness() | ||||||
|  | 	h.ConfigClientInit(t) | ||||||
|  |  | ||||||
|  | 	// Should have sent the first init packet. | ||||||
|  | 	assertEqual(t, len(h.Sent), 1) | ||||||
|  | 	init := assertType[packetInit](t, h.Sent[0].Packet) | ||||||
|  |  | ||||||
|  | 	init.TraceID = newTraceID() | ||||||
|  | 	h.OnInit(controlMsg[packetInit]{Packet: init}) | ||||||
|  |  | ||||||
|  | 	assertType[*stateClientInit](t, h.State) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestPeerState_ClientInit_init(t *testing.T) { | ||||||
|  | 	h := NewPeerStateTestHarness() | ||||||
|  | 	h.ConfigClientInit(t) | ||||||
|  |  | ||||||
|  | 	// Should have sent the first init packet. | ||||||
|  | 	assertEqual(t, len(h.Sent), 1) | ||||||
|  | 	init := assertType[packetInit](t, h.Sent[0].Packet) | ||||||
|  | 	h.OnInit(controlMsg[packetInit]{Packet: init}) | ||||||
|  |  | ||||||
|  | 	assertType[*stateClient](t, h.State) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestPeerState_ClientInit_onPing(t *testing.T) { | ||||||
|  | 	h := NewPeerStateTestHarness() | ||||||
|  | 	h.ConfigClientInit(t) | ||||||
|  |  | ||||||
|  | 	// Should have sent the first init packet. | ||||||
|  | 	assertEqual(t, len(h.Sent), 1) | ||||||
|  | 	h.Sent = h.Sent[:0] | ||||||
|  |  | ||||||
|  | 	for range 3 { | ||||||
|  | 		h.OnPingTimer() | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	assertEqual(t, len(h.Sent), 3) | ||||||
|  |  | ||||||
|  | 	for i := range h.Sent { | ||||||
|  | 		assertType[packetInit](t, h.Sent[i].Packet) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestPeerState_ClientInit_onPingTimeout(t *testing.T) { | ||||||
|  | 	h := NewPeerStateTestHarness() | ||||||
|  | 	h.ConfigClientInit(t) | ||||||
|  |  | ||||||
|  | 	state := assertType[*stateClientInit](t, h.State) | ||||||
|  | 	state.startedAt = time.Now().Add(-2 * timeoutInterval) | ||||||
|  |  | ||||||
|  | 	h.OnPingTimer() | ||||||
|  |  | ||||||
|  | 	// Should have moved into the client state due to timeout. | ||||||
|  | 	assertType[*stateClient](t, h.State) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestPeerState_ClientInit_onPeerUpdate(t *testing.T) { | ||||||
|  | 	h := NewPeerStateTestHarness() | ||||||
|  | 	h.ConfigClientInit(t) | ||||||
|  |  | ||||||
|  | 	h.PeerUpdate(nil) | ||||||
|  |  | ||||||
|  | 	// Should have moved into the client state due to timeout. | ||||||
|  | 	assertType[*stateDisconnected](t, h.State) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestPeerState_ClientInit_ignoreMessage(t *testing.T) { | ||||||
|  | 	h := NewPeerStateTestHarness() | ||||||
|  | 	h.ConfigClientInit(t) | ||||||
|  | 	h.OnProbe(controlMsg[packetProbe]{}) | ||||||
|  |  | ||||||
|  | 	// Shouldn't do anything. | ||||||
|  | 	assertType[*stateClientInit](t, h.State) | ||||||
|  | } | ||||||
| @@ -2,11 +2,11 @@ package peer | |||||||
|  |  | ||||||
| import "net/netip" | import "net/netip" | ||||||
|  |  | ||||||
| type stateDisconnected2 struct { | type stateDisconnected struct { | ||||||
| 	*peerData | 	*peerData | ||||||
| } | } | ||||||
|  |  | ||||||
| func enterStateDisconnected2(data *peerData) peerState { | func enterStateDisconnected(data *peerData) peerState { | ||||||
| 	data.staged.Up = false | 	data.staged.Up = false | ||||||
| 	data.staged.Relay = false | 	data.staged.Relay = false | ||||||
| 	data.staged.Direct = false | 	data.staged.Direct = false | ||||||
| @@ -19,10 +19,10 @@ func enterStateDisconnected2(data *peerData) peerState { | |||||||
|  |  | ||||||
| 	data.pingTimer.Stop() | 	data.pingTimer.Stop() | ||||||
|  |  | ||||||
| 	return &stateDisconnected2{data} | 	return &stateDisconnected{data} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *stateDisconnected2) OnMsg(raw any) peerState { | func (s *stateDisconnected) OnMsg(raw any) peerState { | ||||||
| 	switch msg := raw.(type) { | 	switch msg := raw.(type) { | ||||||
| 	case peerUpdateMsg: | 	case peerUpdateMsg: | ||||||
| 		return initPeerState(s.peerData, msg.Peer) | 		return initPeerState(s.peerData, msg.Peer) | ||||||
|   | |||||||
							
								
								
									
										146
									
								
								peer/state-util_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								peer/state-util_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,146 @@ | |||||||
|  | package peer | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"net/netip" | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  | 	"vppn/m" | ||||||
|  |  | ||||||
|  | 	"git.crumpington.com/lib/go/ratelimiter" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type PeerStateControlMsg struct { | ||||||
|  | 	Peer   remotePeer | ||||||
|  | 	Packet any | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type PeerStateTestHarness struct { | ||||||
|  | 	State     peerState | ||||||
|  | 	Published remotePeer | ||||||
|  | 	Sent      []PeerStateControlMsg | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func NewPeerStateTestHarness() *PeerStateTestHarness { | ||||||
|  | 	h := &PeerStateTestHarness{} | ||||||
|  |  | ||||||
|  | 	keys := generateKeys() | ||||||
|  |  | ||||||
|  | 	state := &peerData{ | ||||||
|  | 		publish: func(rp remotePeer) { | ||||||
|  | 			h.Published = rp | ||||||
|  | 		}, | ||||||
|  | 		sendControlPacket: func(rp remotePeer, pkt marshaller) { | ||||||
|  | 			h.Sent = append(h.Sent, PeerStateControlMsg{rp, pkt}) | ||||||
|  | 		}, | ||||||
|  | 		pingTimer: time.NewTicker(pingInterval), | ||||||
|  | 		localIP:   2, | ||||||
|  | 		remoteIP:  3, | ||||||
|  | 		privKey:   keys.PrivKey, | ||||||
|  | 		pubAddrs:  newPubAddrStore(netip.AddrPort{}), | ||||||
|  | 		limiter: ratelimiter.New(ratelimiter.Config{ | ||||||
|  | 			FillPeriod:   20 * time.Millisecond, | ||||||
|  | 			MaxWaitCount: 1, | ||||||
|  | 		}), | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	h.State = enterStateDisconnected(state) | ||||||
|  | 	return h | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *PeerStateTestHarness) PeerUpdate(p *m.Peer) { | ||||||
|  | 	h.State = h.State.OnMsg(peerUpdateMsg{p}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *PeerStateTestHarness) OnInit(msg controlMsg[packetInit]) { | ||||||
|  | 	h.State = h.State.OnMsg(msg) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *PeerStateTestHarness) OnSyn(msg controlMsg[packetSyn]) { | ||||||
|  | 	h.State = h.State.OnMsg(msg) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *PeerStateTestHarness) OnProbe(msg controlMsg[packetProbe]) { | ||||||
|  | 	h.State = h.State.OnMsg(msg) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *PeerStateTestHarness) OnPingTimer() { | ||||||
|  | 	h.State = h.State.OnMsg(pingTimerMsg{}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *PeerStateTestHarness) ConfigServer_Public(t *testing.T) *stateServer { | ||||||
|  | 	keys := generateKeys() | ||||||
|  |  | ||||||
|  | 	state := h.State.(*stateDisconnected) | ||||||
|  | 	state.localAddr = addrPort4(1, 1, 1, 2, 200) | ||||||
|  |  | ||||||
|  | 	peer := &m.Peer{ | ||||||
|  | 		PeerIP:     3, | ||||||
|  | 		PublicIP:   []byte{1, 1, 1, 3}, | ||||||
|  | 		Port:       456, | ||||||
|  | 		PubKey:     keys.PubKey, | ||||||
|  | 		PubSignKey: keys.PubSignKey, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	h.PeerUpdate(peer) | ||||||
|  | 	assertEqual(t, h.Published.Up, false) | ||||||
|  | 	return assertType[*stateServer](t, h.State) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *PeerStateTestHarness) ConfigServer_Relayed(t *testing.T) *stateServer { | ||||||
|  | 	keys := generateKeys() | ||||||
|  | 	peer := &m.Peer{ | ||||||
|  | 		PeerIP:     3, | ||||||
|  | 		Port:       456, | ||||||
|  | 		PubKey:     keys.PubKey, | ||||||
|  | 		PubSignKey: keys.PubSignKey, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	h.PeerUpdate(peer) | ||||||
|  | 	assertEqual(t, h.Published.Up, false) | ||||||
|  | 	return assertType[*stateServer](t, h.State) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *PeerStateTestHarness) ConfigClientInit(t *testing.T) *stateClientInit { | ||||||
|  | 	keys := generateKeys() | ||||||
|  | 	peer := &m.Peer{ | ||||||
|  | 		PeerIP:     3, | ||||||
|  | 		PublicIP:   []byte{1, 2, 3, 4}, | ||||||
|  | 		Port:       456, | ||||||
|  | 		PubKey:     keys.PubKey, | ||||||
|  | 		PubSignKey: keys.PubSignKey, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	h.PeerUpdate(peer) | ||||||
|  | 	assertEqual(t, h.Published.Up, false) | ||||||
|  | 	return assertType[*stateClientInit](t, h.State) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *PeerStateTestHarness) ConfigClientDirect(t *testing.T) *stateClient { | ||||||
|  | 	h.ConfigClientInit(t) | ||||||
|  | 	init := assertType[packetInit](t, h.Sent[0].Packet) | ||||||
|  | 	h.OnInit(controlMsg[packetInit]{ | ||||||
|  | 		Packet: init, | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	return assertType[*stateClient](t, h.State) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *PeerStateTestHarness) ConfigClientRelayed(t *testing.T) *stateClient { | ||||||
|  | 	keys := generateKeys() | ||||||
|  |  | ||||||
|  | 	state := h.State.(*stateDisconnected) | ||||||
|  | 	state.remoteIP = 1 | ||||||
|  |  | ||||||
|  | 	peer := &m.Peer{ | ||||||
|  | 		PeerIP:     3, | ||||||
|  | 		Port:       456, | ||||||
|  | 		PubKey:     keys.PubKey, | ||||||
|  | 		PubSignKey: keys.PubSignKey, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// TODO: Fix me. | ||||||
|  |  | ||||||
|  | 	h.PeerUpdate(peer) | ||||||
|  | 	assertEqual(t, h.Published.Up, false) | ||||||
|  | 	return assertType[*stateClient](t, h.State) | ||||||
|  | } | ||||||
| @@ -92,7 +92,7 @@ func initPeerState(data *peerData, peer *m.Peer) peerState { | |||||||
| 	data.peer = peer | 	data.peer = peer | ||||||
|  |  | ||||||
| 	if peer == nil { | 	if peer == nil { | ||||||
| 		return enterStateDisconnected2(data) | 		return enterStateDisconnected(data) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if _, isValid := netip.AddrFromSlice(peer.PublicIP); isValid { | 	if _, isValid := netip.AddrFromSlice(peer.PublicIP); isValid { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user