Skip to content

Commit

Permalink
chore: update after review
Browse files Browse the repository at this point in the history
  • Loading branch information
kulikthebird committed Dec 20, 2024
1 parent 6113b1a commit a37fd43
Showing 1 changed file with 132 additions and 111 deletions.
243 changes: 132 additions & 111 deletions x/wasm/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2187,143 +2187,164 @@ type replierExecMsg struct {
Messages []replierExecMsg `json:"messages"`
}

var repliesMsgTemplate = replierExecMsg{
MsgId: 1,
SetDataInExecAndReply: true,
ReturnOrderInReply: false,
ExecError: false,
ReplyError: false,
ReplyOnNever: false,
Messages: []replierExecMsg{
replierExecMsg{
MsgId: 2,
SetDataInExecAndReply: true,
ReturnOrderInReply: false,
ExecError: false,
ReplyError: false,
ReplyOnNever: false,
Messages: []replierExecMsg{
replierExecMsg{
MsgId: 3,
SetDataInExecAndReply: true,
ReturnOrderInReply: false,
ExecError: false,
ReplyError: false,
ReplyOnNever: false,
Messages: []replierExecMsg{},
func defaultRepliesMsgTemplate() replierExecMsg {
return replierExecMsg{
MsgId: 1,
SetDataInExecAndReply: true,
ReturnOrderInReply: false,
ExecError: false,
ReplyError: false,
ReplyOnNever: false,
Messages: []replierExecMsg{
replierExecMsg{
MsgId: 2,
SetDataInExecAndReply: true,
ReturnOrderInReply: false,
ExecError: false,
ReplyError: false,
ReplyOnNever: false,
Messages: []replierExecMsg{
replierExecMsg{
MsgId: 3,
SetDataInExecAndReply: true,
ReturnOrderInReply: false,
ExecError: false,
ReplyError: false,
ReplyOnNever: false,
Messages: []replierExecMsg{},
},
},
},
},
replierExecMsg{
MsgId: 4,
SetDataInExecAndReply: true,
ReturnOrderInReply: false,
ExecError: false,
ReplyError: false,
ReplyOnNever: false,
Messages: []replierExecMsg{
replierExecMsg{
MsgId: 5,
SetDataInExecAndReply: true,
ReturnOrderInReply: false,
ExecError: false,
ReplyError: false,
ReplyOnNever: false,
Messages: []replierExecMsg{},
replierExecMsg{
MsgId: 4,
SetDataInExecAndReply: true,
ReturnOrderInReply: false,
ExecError: false,
ReplyError: false,
ReplyOnNever: false,
Messages: []replierExecMsg{
replierExecMsg{
MsgId: 5,
SetDataInExecAndReply: true,
ReturnOrderInReply: false,
ExecError: false,
ReplyError: false,
ReplyOnNever: false,
Messages: []replierExecMsg{},
},
},
},
},
},
}
}

func TestMultipleReplies(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, AvailableCapabilities)
_, keeper, _ := keepers.AccountKeeper, keepers.ContractKeeper, keepers.BankKeeper

deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := DeterministicAccountAddress(t, 1)
keepers.Faucet.Fund(ctx, creator, deposit.Add(deposit...)...)
creatorAddr := RandomAccountAddress(t)
func repliesMsgTemplateReturnOrder() replierExecMsg {
var repliesMsgTemplate = defaultRepliesMsgTemplate()
repliesMsgTemplate.ReturnOrderInReply = true
return repliesMsgTemplate
}

contractID, _, err := keeper.Create(ctx, creator, replierWasm, nil)
require.NoError(t, err)
func repliesMsgTemplateReplyNever() replierExecMsg {
var repliesMsgTemplate = defaultRepliesMsgTemplate()
repliesMsgTemplate.Messages[1].ReplyOnNever = true
return repliesMsgTemplate
}

require.NoError(t, err)
addr, _, err := keepers.ContractKeeper.Instantiate(ctx, contractID, creator, nil, []byte("{}"), "demo contract replier", deposit)
require.NoError(t, err)
func repliesMsgTemplateNoDataInResp() replierExecMsg {
var repliesMsgTemplate = defaultRepliesMsgTemplate()
repliesMsgTemplate.Messages[1].SetDataInExecAndReply = false
return repliesMsgTemplate
}

// Assert the depth-first order of message handling
func repliesMsgTemplateExecError() replierExecMsg {
var repliesMsgTemplate = defaultRepliesMsgTemplate()
repliesMsgTemplate.Messages[0].Messages[0].ExecError = true
repliesMsgTemplate.ReturnOrderInReply = true
execMsg, err := json.Marshal(repliesMsgTemplate)
require.NoError(t, err)
em := sdk.NewEventManager()
res, err := keepers.ContractKeeper.Execute(ctx.WithEventManager(em), addr, creatorAddr, execMsg, nil)
require.NoError(t, err)
require.NotNil(t, res)
assert.Equal(t, []byte{0xee, 0x1, 0xee, 0x2, 0xee, 0x3, 0xbb, 0x2, 0xbb, 0x1, 0xee, 0x4, 0xee, 0x5, 0xbb, 0x4, 0xbb, 0x1}, res)
repliesMsgTemplate.ReturnOrderInReply = false
return repliesMsgTemplate
}

// Assert that with a list of submessages the `data` field will be set by the
// last submessage.
execMsg, err = json.Marshal(repliesMsgTemplate)
require.NoError(t, err)
em = sdk.NewEventManager()
res, err = keepers.ContractKeeper.Execute(ctx.WithEventManager(em), addr, creatorAddr, execMsg, nil)
require.NoError(t, err)
require.NotNil(t, res)
assert.Equal(t, []byte{0xa, 0x6, 0xa, 0x2, 0xee, 0x5, 0xbb, 0x4, 0xbb, 0x1}, res)
func repliesMsgTemplateReplyError() replierExecMsg {
var repliesMsgTemplate = defaultRepliesMsgTemplate()
repliesMsgTemplate.Messages[0].ReplyError = true
repliesMsgTemplate.ReturnOrderInReply = true
return repliesMsgTemplate
}

// Assert that with a list of submessages the `data` field will be
// set by the last submessage that overrides it.
repliesMsgTemplate.Messages[1].ReplyOnNever = true
execMsg, err = json.Marshal(repliesMsgTemplate)
require.NoError(t, err)
em = sdk.NewEventManager()
res, err = keepers.ContractKeeper.Execute(ctx.WithEventManager(em), addr, creatorAddr, execMsg, nil)
require.NoError(t, err)
require.NotNil(t, res)
assert.Equal(t, []byte{0xa, 0x6, 0xa, 0x2, 0xee, 0x3, 0xbb, 0x2, 0xbb, 0x1}, res)
repliesMsgTemplate.Messages[1].ReplyOnNever = false
var repliesTestScenarios = []struct {
name string
in replierExecMsg
out []byte
}{
{
"Assert the depth-first order of message handling",
repliesMsgTemplateReturnOrder(),
[]byte{0xee, 0x1, 0xee, 0x2, 0xee, 0x3, 0xbb, 0x2, 0xbb, 0x1, 0xee, 0x4, 0xee, 0x5, 0xbb, 0x4, 0xbb, 0x1},
},
{
"Assert that with a list of submessages the `data` field will be set by the last submessage",
defaultRepliesMsgTemplate(),
[]byte{0xa, 0x6, 0xa, 0x2, 0xee, 0x5, 0xbb, 0x4, 0xbb, 0x1},
},
{
"Assert that with a list of submessages the `data` field will be set by the last submessage that overrides it.",
repliesMsgTemplateReplyNever(),
[]byte{0xa, 0x6, 0xa, 0x2, 0xee, 0x3, 0xbb, 0x2, 0xbb, 0x1},
},

// Assert that in scenario C1 -> C4 -> C5 if C4 doesn't set `data`,
// the `data` set by C5 **is not forwarded** to the result of C1.
repliesMsgTemplate.Messages[1].SetDataInExecAndReply = false
execMsg, err = json.Marshal(repliesMsgTemplate)
require.NoError(t, err)
em = sdk.NewEventManager()
res, err = keepers.ContractKeeper.Execute(ctx.WithEventManager(em), addr, creatorAddr, execMsg, nil)
require.NoError(t, err)
require.NotNil(t, res)
assert.Equal(t, []byte{0xbb, 0x1}, res)
repliesMsgTemplate.Messages[1].SetDataInExecAndReply = true
{
"Check data field forwarding",
repliesMsgTemplateNoDataInResp(),
[]byte{0xbb, 0x1},
},

// In this example we have the following scenario:
// `C1 -> C2 -> C3 -> reply(C2) -> reply(C1) -> C4 -> C5 -> reply(C4) -> reply(C1)`.
// The `C3` contract returns an error that is handled by reply entrypoint of `C2`.
// It means that the changes done by `C3` are reverted, but the rest of the changes are kept.
repliesMsgTemplate.Messages[0].Messages[0].ExecError = true
repliesMsgTemplate.ReturnOrderInReply = true
execMsg, err = json.Marshal(repliesMsgTemplate)
require.NoError(t, err)
em = sdk.NewEventManager()
res, err = keepers.ContractKeeper.Execute(ctx.WithEventManager(em), addr, creatorAddr, execMsg, nil)
require.NoError(t, err)
assert.Equal(t, []byte{0xee, 0x1, 0xee, 0x2, 0xbb, 0x2, 0xbb, 0x1, 0xee, 0x4, 0xee, 0x5, 0xbb, 0x4, 0xbb, 0x1}, res)
repliesMsgTemplate.Messages[0].Messages[0].ExecError = false
repliesMsgTemplate.ReturnOrderInReply = false
{
"Check error handling when execute fails",
repliesMsgTemplateExecError(),
[]byte{0xee, 0x1, 0xee, 0x2, 0xbb, 0x2, 0xbb, 0x1, 0xee, 0x4, 0xee, 0x5, 0xbb, 0x4, 0xbb, 0x1},
},

// The `C2` contract returns an error in reply entry-point that is handled by reply entrypoint of `C1`.
// It means that the changes done by either `C2` and `C3` are reverted, but the rest of the changes are kept.
repliesMsgTemplate.Messages[0].ReplyError = true
repliesMsgTemplate.ReturnOrderInReply = true
execMsg, err = json.Marshal(repliesMsgTemplate)
{
"Check error handling when reply fails",
repliesMsgTemplateReplyError(),
[]byte{0xee, 0x1, 0xbb, 0x1, 0xee, 0x4, 0xee, 0x5, 0xbb, 0x4, 0xbb, 0x1},
},
}

func TestMultipleReplies(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, AvailableCapabilities)
_, keeper, _ := keepers.AccountKeeper, keepers.ContractKeeper, keepers.BankKeeper

deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := DeterministicAccountAddress(t, 1)
keepers.Faucet.Fund(ctx, creator, deposit.Add(deposit...)...)
creatorAddr := RandomAccountAddress(t)

contractID, _, err := keeper.Create(ctx, creator, replierWasm, nil)
require.NoError(t, err)
em = sdk.NewEventManager()
res, err = keepers.ContractKeeper.Execute(ctx.WithEventManager(em), addr, creatorAddr, execMsg, nil)

require.NoError(t, err)
addr, _, err := keepers.ContractKeeper.Instantiate(ctx, contractID, creator, nil, []byte("{}"), "demo contract replier", deposit)
require.NoError(t, err)
assert.Equal(t, []byte{0xee, 0x1, 0xbb, 0x1, 0xee, 0x4, 0xee, 0x5, 0xbb, 0x4, 0xbb, 0x1}, res)
repliesMsgTemplate.Messages[0].ReplyError = false
repliesMsgTemplate.ReturnOrderInReply = false

for _, tt := range repliesTestScenarios {
t.Run(tt.name, func(t *testing.T) {
execMsg, err := json.Marshal(tt.in)
require.NoError(t, err)
em := sdk.NewEventManager()
res, err := keepers.ContractKeeper.Execute(ctx.WithEventManager(em), addr, creatorAddr, execMsg, nil)
require.NoError(t, err)
require.NotNil(t, res)
assert.Equal(t, tt.out, res)
})
}
}

func TestQueryIsolation(t *testing.T) {
Expand Down

0 comments on commit a37fd43

Please sign in to comment.