core_async_test.gno
6.79 Kb · 237 lines
1package core
2
3import (
4 "bytes"
5 "testing"
6
7 "gno.land/p/aib/ibc/lightclient"
8 "gno.land/p/aib/ibc/types"
9 "gno.land/p/nt/uassert/v0"
10)
11
12const asyncAckTestCallerPath = "gno.land/r/aib/ibc/core"
13
14func TestWriteAcknowledgementSuccess(cur realm, t *testing.T) {
15 c := newAsyncAckTestClient()
16 packet := newAsyncAckTestPacket(c.id, 1)
17 ack := newAsyncAckTestAck()
18
19 c.savePendingAsyncAck(packet, asyncAckTestCallerPath)
20
21 WriteAcknowledgement(cross(cur), c.id, packet.Sequence, ack)
22
23 uassert.False(t, c.hasPendingAsyncAck(packet.Sequence))
24 uassert.True(t, c.hasPacketAcknowledgement(packet.Sequence))
25 if !bytes.Equal(types.CommitAcknowledgement(ack), c.getPacketAcknowledgement(packet.Sequence)) {
26 t.Fatal("unexpected acknowledgement commitment")
27 }
28}
29
30func TestWriteAcknowledgementWithoutAsyncRejected(cur realm, t *testing.T) {
31 c := newAsyncAckTestClient()
32
33 uassert.AbortsContains(t, cur, "no pending async ack", func() {
34 WriteAcknowledgement(cross(cur), c.id, 1, newAsyncAckTestAck())
35 })
36}
37
38func TestWriteAcknowledgementWrongCallerPreservesPending(cur realm, t *testing.T) {
39 c := newAsyncAckTestClient()
40 packet := newAsyncAckTestPacket(c.id, 1)
41 c.savePendingAsyncAck(packet, "gno.land/r/aib/ibc/not-the-caller")
42
43 uassert.AbortsContains(t, cur, "is not authorized to write ack", func() {
44 WriteAcknowledgement(cross(cur), c.id, packet.Sequence, newAsyncAckTestAck())
45 })
46
47 uassert.True(t, c.hasPendingAsyncAck(packet.Sequence))
48 uassert.False(t, c.hasPacketAcknowledgement(packet.Sequence))
49}
50
51func TestWriteAcknowledgementDuplicateRejected(cur realm, t *testing.T) {
52 c := newAsyncAckTestClient()
53 packet := newAsyncAckTestPacket(c.id, 1)
54 c.savePendingAsyncAck(packet, asyncAckTestCallerPath)
55
56 WriteAcknowledgement(cross(cur), c.id, packet.Sequence, newAsyncAckTestAck())
57
58 uassert.AbortsContains(t, cur, "no pending async ack", func() {
59 WriteAcknowledgement(cross(cur), c.id, packet.Sequence, newAsyncAckTestAck())
60 })
61}
62
63func TestWriteAcknowledgementAlreadyAckedRejected(cur realm, t *testing.T) {
64 c := newAsyncAckTestClient()
65 packet := newAsyncAckTestPacket(c.id, 1)
66 ack := newAsyncAckTestAck()
67 c.savePendingAsyncAck(packet, asyncAckTestCallerPath)
68 c.setPacketAcknowledgement(packet.Sequence, types.CommitAcknowledgement(ack))
69
70 uassert.AbortsContains(t, cur, "acknowledgement already written", func() {
71 WriteAcknowledgement(cross(cur), c.id, packet.Sequence, ack)
72 })
73
74 uassert.True(t, c.hasPendingAsyncAck(packet.Sequence))
75}
76
77func TestPendingAsyncAckStoreRoundTrip(t *testing.T) {
78 c := newAsyncAckTestClient()
79 packet := newAsyncAckTestPacket(c.id, 7)
80
81 c.savePendingAsyncAck(packet, asyncAckTestCallerPath)
82
83 pending, found := c.getPendingAsyncAck(packet.Sequence)
84 uassert.True(t, found)
85 uassert.Equal(t, asyncAckTestCallerPath, pending.appPkgPath)
86 uassert.Equal(t, packet.Sequence, pending.packet.Sequence)
87 uassert.Equal(t, packet.SourceClient, pending.packet.SourceClient)
88 uassert.Equal(t, packet.DestinationClient, pending.packet.DestinationClient)
89
90 c.deletePendingAsyncAck(packet.Sequence)
91 uassert.False(t, c.hasPendingAsyncAck(packet.Sequence))
92}
93
94func TestRecvPacketAsyncDefersAck(cur realm, t *testing.T) {
95 c := newAsyncAckTestClient()
96 packet := newAsyncAckTestPacket(c.id, 1)
97 store.routes["appID"] = ibcApp{
98 IBCApp: &asyncAckTestApp{res: types.RecvPacketResult{
99 Status: types.PacketStatus_Async,
100 }},
101 pkgPath: asyncAckTestCallerPath,
102 }
103
104 c.writeRecvPacketAcknowledgement(0, cur, packet)
105
106 uassert.True(t, c.hasPendingAsyncAck(packet.Sequence))
107 uassert.False(t, c.hasPacketAcknowledgement(packet.Sequence))
108}
109
110func TestRecvPacketMultiPayloadAsyncRejected(cur realm, t *testing.T) {
111 c := newAsyncAckTestClient()
112 packet := newAsyncAckTestPacket(c.id, 1)
113 packet.Payloads = append(packet.Payloads, packet.Payloads[0])
114 store.routes["appID"] = ibcApp{
115 IBCApp: &asyncAckTestApp{res: types.RecvPacketResult{
116 Status: types.PacketStatus_Async,
117 }},
118 pkgPath: asyncAckTestCallerPath,
119 }
120
121 uassert.PanicsContains(t, cur, "async ack not supported for multi-payload packets", func() {
122 c.writeRecvPacketAcknowledgement(0, cur, packet)
123 })
124}
125
126func TestRecvPacketSuccessWritesAck(cur realm, t *testing.T) {
127 c := newAsyncAckTestClient()
128 packet := newAsyncAckTestPacket(c.id, 1)
129 ack := []byte{0x02}
130 store.routes["appID"] = ibcApp{
131 IBCApp: &asyncAckTestApp{res: types.RecvPacketResult{
132 Status: types.PacketStatus_Success,
133 Acknowledgement: ack,
134 }},
135 pkgPath: asyncAckTestCallerPath,
136 }
137
138 c.writeRecvPacketAcknowledgement(0, cur, packet)
139
140 uassert.False(t, c.hasPendingAsyncAck(packet.Sequence))
141 uassert.True(t, c.hasPacketAcknowledgement(packet.Sequence))
142}
143
144func TestSavePendingAsyncAckRejectsDuplicate(cur realm, t *testing.T) {
145 c := newAsyncAckTestClient()
146 packet := newAsyncAckTestPacket(c.id, 1)
147 c.savePendingAsyncAck(packet, asyncAckTestCallerPath)
148
149 uassert.PanicsContains(t, cur, "pending async ack already exists", func() {
150 c.savePendingAsyncAck(packet, asyncAckTestCallerPath)
151 })
152}
153
154func TestSavePendingAsyncAckRejectsAlreadyAcked(cur realm, t *testing.T) {
155 c := newAsyncAckTestClient()
156 packet := newAsyncAckTestPacket(c.id, 1)
157 ack := newAsyncAckTestAck()
158 c.setPacketAcknowledgement(packet.Sequence, types.CommitAcknowledgement(ack))
159
160 uassert.PanicsContains(t, cur, "acknowledgement already written", func() {
161 c.savePendingAsyncAck(packet, asyncAckTestCallerPath)
162 })
163}
164
165func newAsyncAckTestClient() *client {
166 store = newStore()
167 c := store.addClient(lightclient.Tendermint, address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"))
168 c.counterpartyClientID = "07-tendermint-42"
169 return c
170}
171
172func newAsyncAckTestPacket(destinationClient string, sequence uint64) types.Packet {
173 return types.Packet{
174 Sequence: sequence,
175 SourceClient: "07-tendermint-42",
176 DestinationClient: destinationClient,
177 TimeoutTimestamp: 1234567890,
178 Payloads: []types.Payload{{
179 SourcePort: "appID",
180 DestinationPort: "appID",
181 Version: "v1",
182 Encoding: "application/json",
183 Value: []byte("{}"),
184 }},
185 }
186}
187
188func newAsyncAckTestAck() types.Acknowledgement {
189 return types.Acknowledgement{
190 AppAcknowledgements: [][]byte{{0x01}},
191 }
192}
193
194type asyncAckTestApp struct {
195 res types.RecvPacketResult
196}
197
198func (a *asyncAckTestApp) OnSendPacket(
199 _ realm,
200 sourceClient string,
201 destinationClient string,
202 sequence uint64,
203 payload types.Payload,
204) error {
205 return nil
206}
207
208func (a *asyncAckTestApp) OnRecvPacket(
209 _ realm,
210 sourceClient string,
211 destinationClient string,
212 sequence uint64,
213 payload types.Payload,
214) types.RecvPacketResult {
215 return a.res
216}
217
218func (a *asyncAckTestApp) OnTimeoutPacket(
219 _ realm,
220 sourceClient string,
221 destinationClient string,
222 sequence uint64,
223 payload types.Payload,
224) error {
225 return nil
226}
227
228func (a *asyncAckTestApp) OnAcknowledgementPacket(
229 _ realm,
230 sourceClient string,
231 destinationClient string,
232 sequence uint64,
233 acknowledgement []byte,
234 payload types.Payload,
235) error {
236 return nil
237}