212 lines
7.6 KiB
Go
212 lines
7.6 KiB
Go
package simsx
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"math/rand"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"cosmossdk.io/log"
|
|
|
|
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
|
)
|
|
|
|
func TestSimsMsgRegistryAdapter(t *testing.T) {
|
|
senderAcc := SimAccountFixture()
|
|
accs := []simtypes.Account{senderAcc.Account}
|
|
ak := MockAccountSourceX{GetAccountFn: MemoryAccountSource(senderAcc).GetAccount}
|
|
myMsg := testdata.NewTestMsg(senderAcc.Address)
|
|
ctx := sdk.Context{}.WithContext(context.Background())
|
|
futureTime := time.Now().Add(time.Second)
|
|
|
|
specs := map[string]struct {
|
|
factory SimMsgFactoryX
|
|
expFactoryMsg sdk.Msg
|
|
expFactoryErr error
|
|
expDeliveryErr error
|
|
expFutureOpsCount int
|
|
}{
|
|
"successful execution": {
|
|
factory: SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) {
|
|
return []SimAccount{senderAcc}, myMsg
|
|
}),
|
|
expFactoryMsg: myMsg,
|
|
},
|
|
"skip execution": {
|
|
factory: SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) {
|
|
reporter.Skip("testing")
|
|
return nil, nil
|
|
}),
|
|
},
|
|
"future ops registration": {
|
|
factory: NewSimMsgFactoryWithFutureOps[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter, fOpsReg FutureOpsRegistry) (signer []SimAccount, msg *testdata.TestMsg) {
|
|
fOpsReg.Add(futureTime, SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) {
|
|
return []SimAccount{senderAcc}, myMsg
|
|
}))
|
|
return []SimAccount{senderAcc}, myMsg
|
|
}),
|
|
expFactoryMsg: myMsg,
|
|
expFutureOpsCount: 1,
|
|
},
|
|
"error in factory execution": {
|
|
factory: NewSimMsgFactoryWithFutureOps[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter, fOpsReg FutureOpsRegistry) (signer []SimAccount, msg *testdata.TestMsg) {
|
|
reporter.Fail(errors.New("testing"))
|
|
return nil, nil
|
|
}),
|
|
expFactoryErr: errors.New("testing"),
|
|
},
|
|
"missing senders": {
|
|
factory: SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) {
|
|
return nil, myMsg
|
|
}),
|
|
expDeliveryErr: errors.New("no senders"),
|
|
},
|
|
"error in delivery execution": {
|
|
factory: SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) {
|
|
return []SimAccount{senderAcc}, myMsg
|
|
}),
|
|
expDeliveryErr: errors.New("testing"),
|
|
},
|
|
}
|
|
for name, spec := range specs {
|
|
t.Run(name, func(t *testing.T) {
|
|
r := NewBasicSimulationReporter()
|
|
reg := NewSimsMsgRegistryAdapter(r, ak, nil, txConfig(), log.NewNopLogger())
|
|
// when
|
|
reg.Add(100, spec.factory)
|
|
// then
|
|
gotOps := reg.ToLegacyObjects()
|
|
require.Len(t, gotOps, 1)
|
|
assert.Equal(t, 100, gotOps[0].Weight())
|
|
|
|
// and when ops executed
|
|
var capturedTXs []sdk.Tx
|
|
captureTXApp := AppEntrypointFn(func(_txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) {
|
|
capturedTXs = append(capturedTXs, tx)
|
|
return sdk.GasInfo{}, &sdk.Result{}, spec.expDeliveryErr
|
|
})
|
|
fn := gotOps[0].Op()
|
|
gotOpsResult, gotFOps, gotErr := fn(rand.New(rand.NewSource(1)), captureTXApp, ctx, accs, "testchain")
|
|
// then
|
|
if spec.expFactoryErr != nil {
|
|
require.Equal(t, spec.expFactoryErr, gotErr)
|
|
assert.Empty(t, gotFOps)
|
|
assert.Equal(t, gotOpsResult.OK, spec.expFactoryErr == nil)
|
|
assert.Empty(t, gotOpsResult.Comment)
|
|
require.Empty(t, capturedTXs)
|
|
}
|
|
if spec.expDeliveryErr != nil {
|
|
require.Equal(t, spec.expDeliveryErr, gotErr)
|
|
}
|
|
// and verify TX delivery
|
|
if spec.expFactoryMsg != nil {
|
|
require.Len(t, capturedTXs, 1)
|
|
require.Len(t, capturedTXs[0].GetMsgs(), 1)
|
|
assert.Equal(t, spec.expFactoryMsg, capturedTXs[0].GetMsgs()[0])
|
|
}
|
|
assert.Len(t, gotFOps, spec.expFutureOpsCount)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUniqueTypeRegistry(t *testing.T) {
|
|
exampleFactory := SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) {
|
|
return []SimAccount{}, nil
|
|
})
|
|
exampleFactory2 := SimMsgFactoryFn[*testdata.MsgCreateDog](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.MsgCreateDog) {
|
|
return []SimAccount{}, nil
|
|
})
|
|
|
|
specs := map[string]struct {
|
|
src []WeightedFactory
|
|
exp []WeightedFactoryMethod
|
|
expErr bool
|
|
}{
|
|
"unique": {
|
|
src: []WeightedFactory{{Weight: 1, Factory: exampleFactory}},
|
|
exp: []WeightedFactoryMethod{{Weight: 1, Factory: exampleFactory.Create()}},
|
|
},
|
|
"sorted": {
|
|
src: []WeightedFactory{{Weight: 2, Factory: exampleFactory2}, {Weight: 1, Factory: exampleFactory}},
|
|
exp: []WeightedFactoryMethod{{Weight: 1, Factory: exampleFactory.Create()}, {Weight: 2, Factory: exampleFactory2.Create()}},
|
|
},
|
|
"duplicate": {
|
|
src: []WeightedFactory{{Weight: 1, Factory: exampleFactory}, {Weight: 2, Factory: exampleFactory}},
|
|
expErr: true,
|
|
},
|
|
}
|
|
for name, spec := range specs {
|
|
t.Run(name, func(t *testing.T) {
|
|
reg := NewUniqueTypeRegistry()
|
|
if spec.expErr {
|
|
require.Panics(t, func() {
|
|
for _, v := range spec.src {
|
|
reg.Add(v.Weight, v.Factory)
|
|
}
|
|
})
|
|
return
|
|
}
|
|
for _, v := range spec.src {
|
|
reg.Add(v.Weight, v.Factory)
|
|
}
|
|
// then
|
|
got := readAll(reg.Iterator())
|
|
require.Len(t, got, len(spec.exp))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWeightedFactories(t *testing.T) {
|
|
r := NewWeightedFactoryMethods()
|
|
f1 := func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) {
|
|
panic("not implemented")
|
|
}
|
|
f2 := func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) {
|
|
panic("not implemented")
|
|
}
|
|
r.Add(1, f1)
|
|
r.Add(2, f2)
|
|
got := readAll(r.Iterator())
|
|
require.Len(t, got, 2)
|
|
|
|
assert.Equal(t, uint32(1), r[0].Weight)
|
|
assert.Equal(t, uint32(2), r[1].Weight)
|
|
}
|
|
|
|
func TestAppendIterators(t *testing.T) {
|
|
r1 := NewWeightedFactoryMethods()
|
|
r1.Add(2, func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) {
|
|
panic("not implemented")
|
|
})
|
|
r1.Add(2, func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) {
|
|
panic("not implemented")
|
|
})
|
|
r1.Add(3, func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) {
|
|
panic("not implemented")
|
|
})
|
|
r2 := NewUniqueTypeRegistry()
|
|
r2.Add(1, SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) {
|
|
panic("not implemented")
|
|
}))
|
|
// when
|
|
all := readAll(AppendIterators(r1.Iterator(), r2.Iterator()))
|
|
// then
|
|
require.Len(t, all, 4)
|
|
gotWeights := Collect(all, func(a WeightedFactoryMethod) uint32 { return a.Weight })
|
|
assert.Equal(t, []uint32{2, 2, 3, 1}, gotWeights)
|
|
}
|
|
|
|
func readAll(iterator WeightedProposalMsgIter) []WeightedFactoryMethod {
|
|
var ret []WeightedFactoryMethod
|
|
for w, f := range iterator {
|
|
ret = append(ret, WeightedFactoryMethod{Weight: w, Factory: f})
|
|
}
|
|
return ret
|
|
}
|