Skip to content

Commit 09d79f4

Browse files
authored
test: localtxmonitor client tests (#569)
Fixes #322
1 parent f594bdc commit 09d79f4

File tree

1 file changed

+267
-0
lines changed

1 file changed

+267
-0
lines changed
Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
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 localtxmonitor_test
16+
17+
import (
18+
"fmt"
19+
"reflect"
20+
"testing"
21+
"time"
22+
23+
ouroboros "github.com/blinklabs-io/gouroboros"
24+
"github.com/blinklabs-io/gouroboros/internal/test"
25+
"github.com/blinklabs-io/gouroboros/ledger"
26+
"github.com/blinklabs-io/gouroboros/protocol"
27+
"github.com/blinklabs-io/gouroboros/protocol/localtxmonitor"
28+
29+
ouroboros_mock "github.com/blinklabs-io/ouroboros-mock"
30+
"go.uber.org/goleak"
31+
)
32+
33+
var conversationHandshakeAcquire = []ouroboros_mock.ConversationEntry{
34+
ouroboros_mock.ConversationEntryHandshakeRequestGeneric,
35+
ouroboros_mock.ConversationEntryHandshakeNtCResponse,
36+
ouroboros_mock.ConversationEntryInput{
37+
ProtocolId: localtxmonitor.ProtocolId,
38+
MessageType: localtxmonitor.MessageTypeAcquire,
39+
},
40+
ouroboros_mock.ConversationEntryOutput{
41+
ProtocolId: localtxmonitor.ProtocolId,
42+
IsResponse: true,
43+
Messages: []protocol.Message{
44+
localtxmonitor.NewMsgAcquired(12345),
45+
},
46+
},
47+
}
48+
49+
type testInnerFunc func(*testing.T, *ouroboros.Connection)
50+
51+
func runTest(t *testing.T, conversation []ouroboros_mock.ConversationEntry, innerFunc testInnerFunc) {
52+
defer goleak.VerifyNone(t)
53+
mockConn := ouroboros_mock.NewConnection(
54+
ouroboros_mock.ProtocolRoleClient,
55+
conversation,
56+
)
57+
// Async mock connection error handler
58+
asyncErrChan := make(chan error, 1)
59+
go func() {
60+
err := <-mockConn.(*ouroboros_mock.Connection).ErrorChan()
61+
if err != nil {
62+
asyncErrChan <- fmt.Errorf("received unexpected error: %s", err)
63+
}
64+
close(asyncErrChan)
65+
}()
66+
oConn, err := ouroboros.New(
67+
ouroboros.WithConnection(mockConn),
68+
ouroboros.WithNetworkMagic(ouroboros_mock.MockNetworkMagic),
69+
)
70+
if err != nil {
71+
t.Fatalf("unexpected error when creating Ouroboros object: %s", err)
72+
}
73+
// Async error handler
74+
go func() {
75+
err, ok := <-oConn.ErrorChan()
76+
if !ok {
77+
return
78+
}
79+
// We can't call t.Fatalf() from a different Goroutine, so we panic instead
80+
panic(fmt.Sprintf("unexpected Ouroboros error: %s", err))
81+
}()
82+
// Run test inner function
83+
innerFunc(t, oConn)
84+
// Wait for mock connection shutdown
85+
select {
86+
case err, ok := <-asyncErrChan:
87+
if ok {
88+
t.Fatal(err.Error())
89+
}
90+
case <-time.After(2 * time.Second):
91+
t.Fatalf("did not complete within timeout")
92+
}
93+
// Close Ouroboros connection
94+
if err := oConn.Close(); err != nil {
95+
t.Fatalf("unexpected error when closing Ouroboros object: %s", err)
96+
}
97+
// Wait for connection shutdown
98+
select {
99+
case <-oConn.ErrorChan():
100+
case <-time.After(10 * time.Second):
101+
t.Errorf("did not shutdown within timeout")
102+
}
103+
}
104+
105+
func TestHasTxTrue(t *testing.T) {
106+
testTxId := test.DecodeHexString("abcdef0123456789")
107+
expectedResult := true
108+
conversation := append(
109+
conversationHandshakeAcquire,
110+
ouroboros_mock.ConversationEntryInput{
111+
ProtocolId: localtxmonitor.ProtocolId,
112+
MessageType: localtxmonitor.MessageTypeHasTx,
113+
},
114+
ouroboros_mock.ConversationEntryOutput{
115+
ProtocolId: localtxmonitor.ProtocolId,
116+
IsResponse: true,
117+
Messages: []protocol.Message{
118+
localtxmonitor.NewMsgReplyHasTx(expectedResult),
119+
},
120+
},
121+
)
122+
runTest(
123+
t,
124+
conversation,
125+
func(t *testing.T, oConn *ouroboros.Connection) {
126+
hasTx, err := oConn.LocalTxMonitor().Client.HasTx(testTxId)
127+
if err != nil {
128+
t.Fatalf("received unexpected error: %s", err)
129+
}
130+
if hasTx != expectedResult {
131+
t.Fatalf("did not receive expected HasTx result: got %v, wanted %v", hasTx, expectedResult)
132+
}
133+
},
134+
)
135+
}
136+
137+
func TestHasTxFalse(t *testing.T) {
138+
testTxId := test.DecodeHexString("abcdef0123456789")
139+
expectedResult := false
140+
conversation := append(
141+
conversationHandshakeAcquire,
142+
ouroboros_mock.ConversationEntryInput{
143+
ProtocolId: localtxmonitor.ProtocolId,
144+
MessageType: localtxmonitor.MessageTypeHasTx,
145+
},
146+
ouroboros_mock.ConversationEntryOutput{
147+
ProtocolId: localtxmonitor.ProtocolId,
148+
IsResponse: true,
149+
Messages: []protocol.Message{
150+
localtxmonitor.NewMsgReplyHasTx(expectedResult),
151+
},
152+
},
153+
)
154+
runTest(
155+
t,
156+
conversation,
157+
func(t *testing.T, oConn *ouroboros.Connection) {
158+
hasTx, err := oConn.LocalTxMonitor().Client.HasTx(testTxId)
159+
if err != nil {
160+
t.Fatalf("received unexpected error: %s", err)
161+
}
162+
if hasTx != expectedResult {
163+
t.Fatalf("did not receive expected HasTx result: got %v, wanted %v", hasTx, expectedResult)
164+
}
165+
},
166+
)
167+
}
168+
169+
func TestGetSizes(t *testing.T) {
170+
var expectedCapacity uint32 = 100000
171+
var expectedSize uint32 = 12345
172+
var expectedTxCount uint32 = 5
173+
conversation := append(
174+
conversationHandshakeAcquire,
175+
ouroboros_mock.ConversationEntryInput{
176+
ProtocolId: localtxmonitor.ProtocolId,
177+
MessageType: localtxmonitor.MessageTypeGetSizes,
178+
},
179+
ouroboros_mock.ConversationEntryOutput{
180+
ProtocolId: localtxmonitor.ProtocolId,
181+
IsResponse: true,
182+
Messages: []protocol.Message{
183+
localtxmonitor.NewMsgReplyGetSizes(
184+
expectedCapacity,
185+
expectedSize,
186+
expectedTxCount,
187+
),
188+
},
189+
},
190+
)
191+
runTest(
192+
t,
193+
conversation,
194+
func(t *testing.T, oConn *ouroboros.Connection) {
195+
capacity, size, txCount, err := oConn.LocalTxMonitor().Client.GetSizes()
196+
if err != nil {
197+
t.Fatalf("received unexpected error: %s", err)
198+
}
199+
if capacity != expectedCapacity {
200+
t.Fatalf("did not receive expected capacity result: got %d, wanted %d", capacity, expectedCapacity)
201+
}
202+
if size != expectedSize {
203+
t.Fatalf("did not receive expected size result: got %d, wanted %d", size, expectedSize)
204+
}
205+
if txCount != expectedTxCount {
206+
t.Fatalf("did not receive expected TX count result: got %d, wanted %d", txCount, expectedTxCount)
207+
}
208+
},
209+
)
210+
}
211+
212+
func TestNextTx(t *testing.T) {
213+
expectedTxEra := ledger.TxTypeBabbage
214+
expectedTx1 := test.DecodeHexString("abcdef0123456789")
215+
expectedTx2 := test.DecodeHexString("bcdef0123456789a")
216+
conversation := append(
217+
conversationHandshakeAcquire,
218+
ouroboros_mock.ConversationEntryInput{
219+
ProtocolId: localtxmonitor.ProtocolId,
220+
MessageType: localtxmonitor.MessageTypeNextTx,
221+
},
222+
ouroboros_mock.ConversationEntryOutput{
223+
ProtocolId: localtxmonitor.ProtocolId,
224+
IsResponse: true,
225+
Messages: []protocol.Message{
226+
localtxmonitor.NewMsgReplyNextTx(
227+
uint8(expectedTxEra),
228+
expectedTx1,
229+
),
230+
},
231+
},
232+
ouroboros_mock.ConversationEntryInput{
233+
ProtocolId: localtxmonitor.ProtocolId,
234+
MessageType: localtxmonitor.MessageTypeNextTx,
235+
},
236+
ouroboros_mock.ConversationEntryOutput{
237+
ProtocolId: localtxmonitor.ProtocolId,
238+
IsResponse: true,
239+
Messages: []protocol.Message{
240+
localtxmonitor.NewMsgReplyNextTx(
241+
uint8(expectedTxEra),
242+
expectedTx2,
243+
),
244+
},
245+
},
246+
)
247+
runTest(
248+
t,
249+
conversation,
250+
func(t *testing.T, oConn *ouroboros.Connection) {
251+
tx1, err := oConn.LocalTxMonitor().Client.NextTx()
252+
if err != nil {
253+
t.Fatalf("received unexpected error: %s", err)
254+
}
255+
if !reflect.DeepEqual(tx1, expectedTx1) {
256+
t.Fatalf("did not get expected TX content\n got: %x\n wanted: %x", tx1, expectedTx1)
257+
}
258+
tx2, err := oConn.LocalTxMonitor().Client.NextTx()
259+
if err != nil {
260+
t.Fatalf("received unexpected error: %s", err)
261+
}
262+
if !reflect.DeepEqual(tx2, expectedTx2) {
263+
t.Fatalf("did not get expected TX content\n got: %x\n wanted: %x", tx2, expectedTx2)
264+
}
265+
},
266+
)
267+
}

0 commit comments

Comments
 (0)