@@ -14,18 +14,6 @@ import (
1414)
1515
1616func  TestUDPConn (t  * testing.T ) {
17- 	staleTime  :=  func () time.Time  {
18- 		return  time .Now ().Add (- (bindingRefreshInterval  +  1 * time .Minute ))
19- 	}
20- 
21- 	staleNonceMsg  :=  func () * stun.Message  {
22- 		return  stun .MustBuild (
23- 			stun .NewType (stun .MethodChannelBind , stun .ClassErrorResponse ),
24- 			stun .CodeStaleNonce ,
25- 			stun .NewNonce ("new-nonce-123" ),
26- 		)
27- 	}
28- 
2917	makeConn  :=  func (client  * mockClient , bm  * bindingManager ) UDPConn  {
3018		return  UDPConn {
3119			allocation : allocation {
@@ -36,77 +24,68 @@ func TestUDPConn(t *testing.T) {
3624		}
3725	}
3826
39- 	t . Run ( "maybeBind()" ,  func (t   * testing. T )  {
40- 		makeClient   :=   func ( shouldSucceed   bool )  * mockClient  { 
41- 			return   & mockClient { 
42- 				 performTransaction :  func ( msg   * stun.Message ,  addr  net. Addr ,  dontWait   bool ) ( TransactionResult ,  error ) { 
43- 					 if   shouldSucceed  { 
44- 						 return   TransactionResult { Msg :  new (stun. Message )},  nil 
45- 					 }
27+ 	staleNonceMsg   :=   func ()  * stun. Message  {
28+ 		return   stun . MustBuild ( 
29+ 			stun . NewType ( stun . MethodChannelBind ,  stun . ClassErrorResponse ), 
30+ 			stun .CodeStaleNonce , 
31+ 			stun . NewNonce ( "new-nonce-123" ), 
32+ 		) 
33+ 	}
4634
47- 					return  TransactionResult {Msg : staleNonceMsg ()}, nil 
48- 				},
49- 			}
35+ 	t .Run ("maybeBind()" , func (t  * testing.T ) {
36+ 		tests  :=  []struct  {
37+ 			name           string 
38+ 			initialState   bindingState 
39+ 			interimState   bindingState 
40+ 			finalState     bindingState 
41+ 			pastInterval   bool 
42+ 			shouldSucceed  bool 
43+ 		}{
44+ 			{"idle -> request -> ready" , bindingStateIdle , bindingStateRequest , bindingStateReady , false , true },
45+ 			{"idle -> request -> failed" , bindingStateIdle , bindingStateRequest , bindingStateFailed , false , false },
46+ 			{"ready (stale) -> refresh -> ready" , bindingStateReady , bindingStateRefresh , bindingStateReady , true , true },
47+ 			{"ready (stale) -> refresh -> failed" , bindingStateReady , bindingStateRefresh , bindingStateFailed , true , false },
48+ 
49+ 			// Noop cases: 
50+ 			{"ready (noop)" , bindingStateReady , bindingStateReady , bindingStateReady , false , true },
51+ 			{"request (noop)" , bindingStateRequest , bindingStateRequest , bindingStateRequest , false , true },
52+ 			{"refresh (noop)" , bindingStateRefresh , bindingStateRefresh , bindingStateRefresh , false , true },
53+ 			{"failed (noop)" , bindingStateFailed , bindingStateFailed , bindingStateFailed , false , true },
5054		}
5155
52- 		t .Run ("state transitions" , func (t  * testing.T ) {
53- 			bm  :=  newBindingManager ()
54- 			bound  :=  bm .create (& net.UDPAddr {IP : net .ParseIP ("127.0.0.1" ), Port : 1234 })
55- 			conn  :=  makeConn (makeClient (true ), bm )
56+ 		for  _ , tt  :=  range  tests  {
57+ 			t .Run (tt .name , func (t  * testing.T ) {
58+ 				unblock  :=  make (chan  struct {})
5659
57- 			t .Run ("idle to request" , func (t  * testing.T ) {
58- 				bound .setState (bindingStateIdle )
59- 				conn .maybeBind (bound )
60- 				assert .Equal (t , bindingStateRequest , bound .state (), "should be request" )
61- 			})
60+ 				bm  :=  newBindingManager ()
61+ 				bound  :=  bm .create (& net.UDPAddr {IP : net .ParseIP ("127.0.0.1" ), Port : 1234 })
62+ 				conn  :=  makeConn (& mockClient {
63+ 					performTransaction : func (msg  * stun.Message , addr  net.Addr , dontWait  bool ) (TransactionResult , error ) {
64+ 						<- unblock 
65+ 						if  tt .shouldSucceed  {
66+ 							return  TransactionResult {Msg : new (stun.Message )}, nil 
67+ 						}
68+ 
69+ 						return  TransactionResult {Msg : staleNonceMsg ()}, nil 
70+ 					},
71+ 				}, bm )
72+ 
73+ 				bound .setState (tt .initialState )
74+ 				if  tt .pastInterval  {
75+ 					bound .setRefreshedAt (time .Now ().Add (- (bindingRefreshInterval  +  1 * time .Minute )))
76+ 				}
6277
63- 			t .Run ("ready to refresh (past interval)" , func (t  * testing.T ) {
64- 				bound .setState (bindingStateReady )
65- 				bound .setRefreshedAt (staleTime ())
6678				conn .maybeBind (bound )
67- 				assert .Equal (t , bindingStateRefresh , bound .state (), "should be refresh" )
68- 			})
79+ 				assert .Equal (t , tt .interimState , bound .state ())
6980
70- 			t .Run ("ready to ready (not past interval)" , func (t  * testing.T ) {
71- 				bound .setState (bindingStateReady )
72- 				bound .setRefreshedAt (time .Now ())
73- 				conn .maybeBind (bound )
74- 				assert .Equal (t , bindingStateReady , bound .state (), "should remain ready" )
81+ 				// Release barrier so inner bind() can move forward. 
82+ 				close (unblock )
83+ 
84+ 				assert .Eventually (t , func () bool  {
85+ 					return  bound .state () ==  tt .finalState 
86+ 				}, 5 * time .Second , 10 * time .Millisecond )
7587			})
76- 		})
77- 
78- 		t .Run ("outcomes" , func (t  * testing.T ) {
79- 			tests  :=  []struct  {
80- 				name           string 
81- 				initialState   bindingState 
82- 				pastInterval   bool 
83- 				shouldSucceed  bool 
84- 				expectState    bindingState 
85- 			}{
86- 				{"idle bind success" , bindingStateIdle , false , true , bindingStateReady },
87- 				{"idle bind fail" , bindingStateIdle , false , false , bindingStateFailed },
88- 				{"refresh success" , bindingStateReady , true , true , bindingStateReady },
89- 				{"refresh fail" , bindingStateReady , true , false , bindingStateFailed },
90- 			}
91- 
92- 			for  _ , tt  :=  range  tests  {
93- 				t .Run (tt .name , func (t  * testing.T ) {
94- 					bm  :=  newBindingManager ()
95- 					bound  :=  bm .create (& net.UDPAddr {IP : net .ParseIP ("127.0.0.1" ), Port : 1234 })
96- 					conn  :=  makeConn (makeClient (tt .shouldSucceed ), bm )
97- 
98- 					bound .setState (tt .initialState )
99- 					if  tt .pastInterval  {
100- 						bound .setRefreshedAt (staleTime ())
101- 					}
102- 
103- 					conn .maybeBind (bound )
104- 					assert .Eventually (t , func () bool  {
105- 						return  bound .state () ==  tt .expectState 
106- 					}, 5 * time .Second , 10 * time .Millisecond )
107- 				})
108- 			}
109- 		})
88+ 		}
11089	})
11190
11291	t .Run ("bind()" , func (t  * testing.T ) {
@@ -124,16 +103,14 @@ func TestUDPConn(t *testing.T) {
124103				},
125104				expectErr :            errFake ,
126105				expectBindingDeleted : true ,
127- 				expectNonceChanged :   false ,
128106			},
129107			{
130108				name : "ErrorResponse with CodeStaleNonce triggers nonce update" ,
131109				transactionFn : func (* stun.Message , net.Addr , bool ) (TransactionResult , error ) {
132110					return  TransactionResult {Msg : staleNonceMsg ()}, nil 
133111				},
134- 				expectErr :            errTryAgain ,
135- 				expectBindingDeleted : false ,
136- 				expectNonceChanged :   true ,
112+ 				expectErr :          errTryAgain ,
113+ 				expectNonceChanged : true ,
137114			},
138115		}
139116
0 commit comments