@@ -16,21 +16,85 @@ package handshake_test
1616
1717import (
1818 "fmt"
19+ "reflect"
1920 "testing"
2021 "time"
2122
2223 ouroboros "github.com/blinklabs-io/gouroboros"
2324 "github.com/blinklabs-io/gouroboros/internal/test/ouroboros_mock"
25+ "github.com/blinklabs-io/gouroboros/protocol"
26+ "github.com/blinklabs-io/gouroboros/protocol/handshake"
2427 "go.uber.org/goleak"
2528)
2629
27- func TestClientBasicHandshake (t * testing.T ) {
30+ const (
31+ mockProtocolVersionNtC uint16 = (14 + protocol .ProtocolVersionNtCOffset )
32+ mockProtocolVersionNtN uint16 = 13
33+ mockProtocolVersionNtNV11 uint16 = 11
34+ )
35+
36+ var conversationEntryNtCResponse = ouroboros_mock.ConversationEntry {
37+ Type : ouroboros_mock .EntryTypeOutput ,
38+ ProtocolId : handshake .ProtocolId ,
39+ IsResponse : true ,
40+ OutputMessages : []protocol.Message {
41+ handshake .NewMsgAcceptVersion (
42+ mockProtocolVersionNtC ,
43+ mockNtCVersionData (),
44+ ),
45+ },
46+ }
47+
48+ var conversationEntryNtNResponse = ouroboros_mock.ConversationEntry {
49+ Type : ouroboros_mock .EntryTypeOutput ,
50+ ProtocolId : handshake .ProtocolId ,
51+ IsResponse : true ,
52+ OutputMessages : []protocol.Message {
53+ handshake .NewMsgAcceptVersion (
54+ mockProtocolVersionNtN ,
55+ mockNtNVersionData (),
56+ ),
57+ },
58+ }
59+
60+ var conversationEntryNtNResponseV11 = ouroboros_mock.ConversationEntry {
61+ Type : ouroboros_mock .EntryTypeOutput ,
62+ ProtocolId : handshake .ProtocolId ,
63+ IsResponse : true ,
64+ OutputMessages : []protocol.Message {
65+ handshake .NewMsgAcceptVersion (
66+ mockProtocolVersionNtNV11 ,
67+ mockNtNVersionDataV11 (),
68+ ),
69+ },
70+ }
71+
72+ func mockNtCVersionData () protocol.VersionData {
73+ return protocol .VersionDataNtC9to14 (ouroboros_mock .MockNetworkMagic )
74+ }
75+
76+ func mockNtNVersionDataV11 () protocol.VersionData {
77+ return protocol.VersionDataNtN11to12 {
78+ CborNetworkMagic : ouroboros_mock .MockNetworkMagic ,
79+ CborInitiatorAndResponderDiffusionMode : protocol .DiffusionModeInitiatorOnly ,
80+ CborPeerSharing : protocol .PeerSharingModeNoPeerSharing ,
81+ CborQuery : protocol .QueryModeDisabled ,
82+ }
83+ }
84+
85+ func mockNtNVersionData () protocol.VersionData {
86+ return protocol.VersionDataNtN13andUp {
87+ VersionDataNtN11to12 : mockNtNVersionDataV11 ().(protocol.VersionDataNtN11to12 ),
88+ }
89+ }
90+
91+ func TestClientNtCAccept (t * testing.T ) {
2892 defer goleak .VerifyNone (t )
2993 mockConn := ouroboros_mock .NewConnection (
3094 ouroboros_mock .ProtocolRoleClient ,
3195 []ouroboros_mock.ConversationEntry {
3296 ouroboros_mock .ConversationEntryHandshakeRequestGeneric ,
33- ouroboros_mock . ConversationEntryHandshakeNtCResponse ,
97+ conversationEntryNtCResponse ,
3498 },
3599 )
36100 oConn , err := ouroboros .New (
@@ -49,6 +113,14 @@ func TestClientBasicHandshake(t *testing.T) {
49113 // We can't call t.Fatalf() from a different Goroutine, so we panic instead
50114 panic (fmt .Sprintf ("unexpected Ouroboros connection error: %s" , err ))
51115 }()
116+ // Check negotiated version and version data
117+ protoVersion , protoVersionData := oConn .ProtocolVersion ()
118+ if protoVersion != mockProtocolVersionNtC {
119+ t .Fatalf ("did not get expected protocol version: got %d, wanted %d" , protoVersion , mockProtocolVersionNtC )
120+ }
121+ if ! reflect .DeepEqual (protoVersionData , mockNtCVersionData ()) {
122+ t .Fatalf ("did not get expected protocol version data:\n got: %#v\n wanted: %#v" , protoVersionData , mockNtCVersionData ())
123+ }
52124 // Close Ouroboros connection
53125 if err := oConn .Close (); err != nil {
54126 t .Fatalf ("unexpected error when closing Ouroboros object: %s" , err )
@@ -61,18 +133,19 @@ func TestClientBasicHandshake(t *testing.T) {
61133 }
62134}
63135
64- func TestClientDoubleStart (t * testing.T ) {
136+ func TestClientNtNAccept (t * testing.T ) {
65137 defer goleak .VerifyNone (t )
66138 mockConn := ouroboros_mock .NewConnection (
67139 ouroboros_mock .ProtocolRoleClient ,
68140 []ouroboros_mock.ConversationEntry {
69141 ouroboros_mock .ConversationEntryHandshakeRequestGeneric ,
70- ouroboros_mock . ConversationEntryHandshakeNtCResponse ,
142+ conversationEntryNtNResponse ,
71143 },
72144 )
73145 oConn , err := ouroboros .New (
74146 ouroboros .WithConnection (mockConn ),
75147 ouroboros .WithNetworkMagic (ouroboros_mock .MockNetworkMagic ),
148+ ouroboros .WithNodeToNode (true ),
76149 )
77150 if err != nil {
78151 t .Fatalf ("unexpected error when creating Ouroboros object: %s" , err )
@@ -86,8 +159,14 @@ func TestClientDoubleStart(t *testing.T) {
86159 // We can't call t.Fatalf() from a different Goroutine, so we panic instead
87160 panic (fmt .Sprintf ("unexpected Ouroboros connection error: %s" , err ))
88161 }()
89- // Try to start the Handshake client again
90- oConn .Handshake ().Client .Start ()
162+ // Check negotiated version and version data
163+ protoVersion , protoVersionData := oConn .ProtocolVersion ()
164+ if protoVersion != mockProtocolVersionNtN {
165+ t .Fatalf ("did not get expected protocol version: got %d, wanted %d" , protoVersion , mockProtocolVersionNtN )
166+ }
167+ if ! reflect .DeepEqual (protoVersionData , mockNtNVersionData ()) {
168+ t .Fatalf ("did not get expected protocol version data:\n got: %#v\n wanted: %#v" , protoVersionData , mockNtNVersionData ())
169+ }
91170 // Close Ouroboros connection
92171 if err := oConn .Close (); err != nil {
93172 t .Fatalf ("unexpected error when closing Ouroboros object: %s" , err )
@@ -99,3 +178,156 @@ func TestClientDoubleStart(t *testing.T) {
99178 t .Errorf ("did not shutdown within timeout" )
100179 }
101180}
181+
182+ func TestClientNtNAcceptV11 (t * testing.T ) {
183+ defer goleak .VerifyNone (t )
184+ mockConn := ouroboros_mock .NewConnection (
185+ ouroboros_mock .ProtocolRoleClient ,
186+ []ouroboros_mock.ConversationEntry {
187+ ouroboros_mock .ConversationEntryHandshakeRequestGeneric ,
188+ conversationEntryNtNResponseV11 ,
189+ },
190+ )
191+ oConn , err := ouroboros .New (
192+ ouroboros .WithConnection (mockConn ),
193+ ouroboros .WithNetworkMagic (ouroboros_mock .MockNetworkMagic ),
194+ ouroboros .WithNodeToNode (true ),
195+ )
196+ if err != nil {
197+ t .Fatalf ("unexpected error when creating Ouroboros object: %s" , err )
198+ }
199+ // Async error handler
200+ go func () {
201+ err , ok := <- oConn .ErrorChan ()
202+ if ! ok {
203+ return
204+ }
205+ // We can't call t.Fatalf() from a different Goroutine, so we panic instead
206+ panic (fmt .Sprintf ("unexpected Ouroboros connection error: %s" , err ))
207+ }()
208+ // Check negotiated version and version data
209+ protoVersion , protoVersionData := oConn .ProtocolVersion ()
210+ if protoVersion != mockProtocolVersionNtNV11 {
211+ t .Fatalf ("did not get expected protocol version: got %d, wanted %d" , protoVersion , mockProtocolVersionNtNV11 )
212+ }
213+ if ! reflect .DeepEqual (protoVersionData , mockNtNVersionDataV11 ()) {
214+ t .Fatalf ("did not get expected protocol version data:\n got: %#v\n wanted: %#v" , protoVersionData , mockNtNVersionDataV11 ())
215+ }
216+ // Close Ouroboros connection
217+ if err := oConn .Close (); err != nil {
218+ t .Fatalf ("unexpected error when closing Ouroboros object: %s" , err )
219+ }
220+ // Wait for connection shutdown
221+ select {
222+ case <- oConn .ErrorChan ():
223+ case <- time .After (10 * time .Second ):
224+ t .Errorf ("did not shutdown within timeout" )
225+ }
226+ }
227+
228+ func TestClientNtCRefuseVersionMismatch (t * testing.T ) {
229+ defer goleak .VerifyNone (t )
230+ expectedErr := fmt .Sprintf ("%s: version mismatch" , handshake .ProtocolName )
231+ mockConn := ouroboros_mock .NewConnection (
232+ ouroboros_mock .ProtocolRoleClient ,
233+ []ouroboros_mock.ConversationEntry {
234+ ouroboros_mock .ConversationEntryHandshakeRequestGeneric ,
235+ ouroboros_mock.ConversationEntry {
236+ Type : ouroboros_mock .EntryTypeOutput ,
237+ ProtocolId : handshake .ProtocolId ,
238+ IsResponse : true ,
239+ OutputMessages : []protocol.Message {
240+ handshake .NewMsgRefuse (
241+ []any {
242+ handshake .RefuseReasonVersionMismatch ,
243+ []uint16 {1 , 2 , 3 },
244+ },
245+ ),
246+ },
247+ },
248+ },
249+ )
250+ _ , err := ouroboros .New (
251+ ouroboros .WithConnection (mockConn ),
252+ ouroboros .WithNetworkMagic (ouroboros_mock .MockNetworkMagic ),
253+ )
254+ if err == nil {
255+ t .Fatalf ("did not receive expected error" )
256+ } else {
257+ if err .Error () != expectedErr {
258+ t .Fatalf ("received unexpected error\n got: %v\n wanted: %v" , err , expectedErr )
259+ }
260+ }
261+ }
262+
263+ func TestClientNtCRefuseDecodeError (t * testing.T ) {
264+ defer goleak .VerifyNone (t )
265+ expectedErr := fmt .Sprintf ("%s: decode error: foo" , handshake .ProtocolName )
266+ mockConn := ouroboros_mock .NewConnection (
267+ ouroboros_mock .ProtocolRoleClient ,
268+ []ouroboros_mock.ConversationEntry {
269+ ouroboros_mock .ConversationEntryHandshakeRequestGeneric ,
270+ ouroboros_mock.ConversationEntry {
271+ Type : ouroboros_mock .EntryTypeOutput ,
272+ ProtocolId : handshake .ProtocolId ,
273+ IsResponse : true ,
274+ OutputMessages : []protocol.Message {
275+ handshake .NewMsgRefuse (
276+ []any {
277+ handshake .RefuseReasonDecodeError ,
278+ mockProtocolVersionNtC ,
279+ "foo" ,
280+ },
281+ ),
282+ },
283+ },
284+ },
285+ )
286+ _ , err := ouroboros .New (
287+ ouroboros .WithConnection (mockConn ),
288+ ouroboros .WithNetworkMagic (ouroboros_mock .MockNetworkMagic ),
289+ )
290+ if err == nil {
291+ t .Fatalf ("did not receive expected error" )
292+ } else {
293+ if err .Error () != expectedErr {
294+ t .Fatalf ("received unexpected error\n got: %v\n wanted: %v" , err , expectedErr )
295+ }
296+ }
297+ }
298+
299+ func TestClientNtCRefuseRefused (t * testing.T ) {
300+ defer goleak .VerifyNone (t )
301+ expectedErr := fmt .Sprintf ("%s: refused: foo" , handshake .ProtocolName )
302+ mockConn := ouroboros_mock .NewConnection (
303+ ouroboros_mock .ProtocolRoleClient ,
304+ []ouroboros_mock.ConversationEntry {
305+ ouroboros_mock .ConversationEntryHandshakeRequestGeneric ,
306+ ouroboros_mock.ConversationEntry {
307+ Type : ouroboros_mock .EntryTypeOutput ,
308+ ProtocolId : handshake .ProtocolId ,
309+ IsResponse : true ,
310+ OutputMessages : []protocol.Message {
311+ handshake .NewMsgRefuse (
312+ []any {
313+ handshake .RefuseReasonRefused ,
314+ mockProtocolVersionNtC ,
315+ "foo" ,
316+ },
317+ ),
318+ },
319+ },
320+ },
321+ )
322+ _ , err := ouroboros .New (
323+ ouroboros .WithConnection (mockConn ),
324+ ouroboros .WithNetworkMagic (ouroboros_mock .MockNetworkMagic ),
325+ )
326+ if err == nil {
327+ t .Fatalf ("did not receive expected error" )
328+ } else {
329+ if err .Error () != expectedErr {
330+ t .Fatalf ("received unexpected error\n got: %v\n wanted: %v" , err , expectedErr )
331+ }
332+ }
333+ }
0 commit comments