Search Apps Documentation Source Content File Folder Download Copy Actions Download

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}