Skip to content

Commit f54eb30

Browse files
authored
test: localtxsubmission client tests (#566)
Fixes #320
1 parent aed6b08 commit f54eb30

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// Copyright 2024 Blink Labs Software
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package localtxsubmission_test
16+
17+
import (
18+
"fmt"
19+
"testing"
20+
"time"
21+
22+
ouroboros "github.com/blinklabs-io/gouroboros"
23+
"github.com/blinklabs-io/gouroboros/internal/test"
24+
"github.com/blinklabs-io/gouroboros/ledger"
25+
"github.com/blinklabs-io/gouroboros/protocol"
26+
"github.com/blinklabs-io/gouroboros/protocol/localtxsubmission"
27+
ouroboros_mock "github.com/blinklabs-io/ouroboros-mock"
28+
"go.uber.org/goleak"
29+
)
30+
31+
var conversationHandshakeSubmitTx = []ouroboros_mock.ConversationEntry{
32+
ouroboros_mock.ConversationEntryHandshakeRequestGeneric,
33+
ouroboros_mock.ConversationEntryHandshakeNtCResponse,
34+
ouroboros_mock.ConversationEntryInput{
35+
ProtocolId: localtxsubmission.ProtocolId,
36+
MessageType: localtxsubmission.MessageTypeSubmitTx,
37+
},
38+
}
39+
40+
type testInnerFunc func(*testing.T, *ouroboros.Connection)
41+
42+
func runTest(t *testing.T, conversation []ouroboros_mock.ConversationEntry, innerFunc testInnerFunc) {
43+
defer goleak.VerifyNone(t)
44+
mockConn := ouroboros_mock.NewConnection(
45+
ouroboros_mock.ProtocolRoleClient,
46+
conversation,
47+
)
48+
// Async mock connection error handler
49+
asyncErrChan := make(chan error, 1)
50+
go func() {
51+
err := <-mockConn.(*ouroboros_mock.Connection).ErrorChan()
52+
if err != nil {
53+
asyncErrChan <- fmt.Errorf("received unexpected error: %s", err)
54+
}
55+
close(asyncErrChan)
56+
}()
57+
oConn, err := ouroboros.New(
58+
ouroboros.WithConnection(mockConn),
59+
ouroboros.WithNetworkMagic(ouroboros_mock.MockNetworkMagic),
60+
)
61+
if err != nil {
62+
t.Fatalf("unexpected error when creating Ouroboros object: %s", err)
63+
}
64+
// Async error handler
65+
go func() {
66+
err, ok := <-oConn.ErrorChan()
67+
if !ok {
68+
return
69+
}
70+
// We can't call t.Fatalf() from a different Goroutine, so we panic instead
71+
panic(fmt.Sprintf("unexpected Ouroboros error: %s", err))
72+
}()
73+
// Run test inner function
74+
innerFunc(t, oConn)
75+
// Wait for mock connection shutdown
76+
select {
77+
case err, ok := <-asyncErrChan:
78+
if ok {
79+
t.Fatal(err.Error())
80+
}
81+
case <-time.After(2 * time.Second):
82+
t.Fatalf("did not complete within timeout")
83+
}
84+
// Close Ouroboros connection
85+
if err := oConn.Close(); err != nil {
86+
t.Fatalf("unexpected error when closing Ouroboros object: %s", err)
87+
}
88+
// Wait for connection shutdown
89+
select {
90+
case <-oConn.ErrorChan():
91+
case <-time.After(10 * time.Second):
92+
t.Errorf("did not shutdown within timeout")
93+
}
94+
}
95+
96+
func TestSubmitTxAccept(t *testing.T) {
97+
testTx := test.DecodeHexString("abcdef0123456789")
98+
conversation := append(
99+
conversationHandshakeSubmitTx,
100+
ouroboros_mock.ConversationEntryOutput{
101+
ProtocolId: localtxsubmission.ProtocolId,
102+
IsResponse: true,
103+
Messages: []protocol.Message{
104+
localtxsubmission.NewMsgAcceptTx(),
105+
},
106+
},
107+
)
108+
runTest(
109+
t,
110+
conversation,
111+
func(t *testing.T, oConn *ouroboros.Connection) {
112+
err := oConn.LocalTxSubmission().Client.SubmitTx(ledger.TxTypeBabbage, testTx)
113+
if err != nil {
114+
t.Fatalf("received unexpected error: %s", err)
115+
}
116+
},
117+
)
118+
}
119+
120+
func TestSubmitTxRject(t *testing.T) {
121+
testTx := test.DecodeHexString("abcdef0123456789")
122+
expectedErr := localtxsubmission.TransactionRejectedError{
123+
// [0, [1, ["foo"]]]
124+
ReasonCbor: test.DecodeHexString("820082018163666f6f"),
125+
Reason: fmt.Errorf("GenericError ([0 [1 [foo]]])"),
126+
}
127+
conversation := append(
128+
conversationHandshakeSubmitTx,
129+
ouroboros_mock.ConversationEntryOutput{
130+
ProtocolId: localtxsubmission.ProtocolId,
131+
IsResponse: true,
132+
Messages: []protocol.Message{
133+
localtxsubmission.NewMsgRejectTx(expectedErr.ReasonCbor),
134+
},
135+
},
136+
)
137+
runTest(
138+
t,
139+
conversation,
140+
func(t *testing.T, oConn *ouroboros.Connection) {
141+
err := oConn.LocalTxSubmission().Client.SubmitTx(ledger.TxTypeBabbage, testTx)
142+
if err == nil {
143+
t.Fatalf("did not receive expected error")
144+
}
145+
if err.Error() != expectedErr.Error() {
146+
t.Fatalf("did not receive expected error\n got: %s\n wanted: %s", err, expectedErr)
147+
}
148+
},
149+
)
150+
}

0 commit comments

Comments
 (0)