mukan-sdk/testutil/simsx/msg_factory.go
Mukan Erkin Törük 20afb5db80
Some checks failed
Build SimApp / build (amd64) (push) Waiting to run
Build SimApp / build (arm64) (push) Waiting to run
CodeQL / Analyze (push) Waiting to run
Build & Push / build (push) Waiting to run
Run Gosec / Gosec (push) Waiting to run
Lint / golangci-lint (push) Waiting to run
Checks dependencies and mocks generation / Check go mod tidy (push) Waiting to run
Checks dependencies and mocks generation / Check up to date mocks (push) Waiting to run
System Tests / setup (push) Waiting to run
System Tests / test-system (push) Blocked by required conditions
System Tests / test-system-legacy (push) Blocked by required conditions
Tests / Code Coverage / split-test-files (push) Waiting to run
Tests / Code Coverage / tests (00) (push) Blocked by required conditions
Tests / Code Coverage / tests (01) (push) Blocked by required conditions
Tests / Code Coverage / tests (02) (push) Blocked by required conditions
Tests / Code Coverage / tests (03) (push) Blocked by required conditions
Tests / Code Coverage / test-integration (push) Waiting to run
Tests / Code Coverage / test-e2e (push) Waiting to run
Tests / Code Coverage / repo-analysis (push) Blocked by required conditions
Tests / Code Coverage / test-sim-nondeterminism (push) Waiting to run
Tests / Code Coverage / test-clientv2 (push) Waiting to run
Tests / Code Coverage / test-core (push) Waiting to run
Tests / Code Coverage / test-depinject (push) Waiting to run
Tests / Code Coverage / test-errors (push) Waiting to run
Tests / Code Coverage / test-math (push) Waiting to run
Tests / Code Coverage / test-schema (push) Waiting to run
Tests / Code Coverage / test-collections (push) Waiting to run
Tests / Code Coverage / test-cosmovisor (push) Waiting to run
Tests / Code Coverage / test-confix (push) Waiting to run
Tests / Code Coverage / test-store (push) Waiting to run
Tests / Code Coverage / test-log (push) Waiting to run
Tests / Code Coverage / test-x-tx (push) Waiting to run
Tests / Code Coverage / test-x-nft (push) Waiting to run
Tests / Code Coverage / test-x-circuit (push) Waiting to run
Tests / Code Coverage / test-x-feegrant (push) Waiting to run
Tests / Code Coverage / test-x-evidence (push) Waiting to run
Tests / Code Coverage / test-x-upgrade (push) Waiting to run
Tests / Code Coverage / test-tools-benchmark (push) Waiting to run
Build & Push SDK Proto Builder / build (push) Has been cancelled
initial: sovereign Mukan Network fork
2026-05-11 03:18:24 +03:00

175 lines
6.4 KiB
Go

package simsx
import (
"context"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// SimMsgFactoryX is an interface for creating and handling fuzz test-like simulation messages in the system.
type SimMsgFactoryX interface {
// MsgType returns an empty instance of the concrete message type that the factory provides.
// This instance is primarily used for deduplication and reporting purposes.
// The result must not be nil
MsgType() sdk.Msg
// Create returns a FactoryMethod implementation which is responsible for constructing new instances of the message
// on each invocation.
Create() FactoryMethod
// DeliveryResultHandler returns a SimDeliveryResultHandler instance which processes the delivery
// response error object. While most simulation factories anticipate successful message delivery,
// certain factories employ this handler to validate execution errors, thereby covering negative
// test scenarios.
DeliveryResultHandler() SimDeliveryResultHandler
}
type (
// FactoryMethod is a method signature implemented by concrete message factories for SimMsgFactoryX
//
// This factory method is responsible for creating a new `sdk.Msg` instance and determining the
// proposed signers who are expected to successfully sign the message for delivery.
//
// Parameters:
// - ctx: The context for the operation
// - testData: A pointer to a `ChainDataSource` which provides helper methods and simple access to accounts
// and balances within the chain.
// - reporter: An instance of `SimulationReporter` used to report the results of the simulation.
// If no valid message can be provided, the factory method should call `reporter.Skip("some comment")`
// with both `signer` and `msg` set to nil.
//
// Returns:
// - signer: A slice of `SimAccount` representing the proposed signers.
// - msg: An instance of `sdk.Msg` representing the message to be delivered.
FactoryMethod func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg)
// FactoryMethodWithFutureOps extended message factory method for the gov module or others that have to schedule operations for a future block.
FactoryMethodWithFutureOps[T sdk.Msg] func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter, fOpsReg FutureOpsRegistry) ([]SimAccount, T)
// FactoryMethodWithDeliveryResultHandler extended factory method that can return a result handler, that is executed on the delivery tx error result.
// This is used in staking for example to validate negative execution results.
FactoryMethodWithDeliveryResultHandler[T sdk.Msg] func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg T, handler SimDeliveryResultHandler)
)
var _ SimMsgFactoryX = &ResultHandlingSimMsgFactory[sdk.Msg]{}
// ResultHandlingSimMsgFactory message factory with a delivery error result handler configured.
type ResultHandlingSimMsgFactory[T sdk.Msg] struct {
SimMsgFactoryFn[T]
resultHandler SimDeliveryResultHandler
}
// NewSimMsgFactoryWithDeliveryResultHandler constructor
func NewSimMsgFactoryWithDeliveryResultHandler[T sdk.Msg](f FactoryMethodWithDeliveryResultHandler[T]) *ResultHandlingSimMsgFactory[T] {
r := &ResultHandlingSimMsgFactory[T]{
resultHandler: expectNoError,
}
r.SimMsgFactoryFn = func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg T) {
signer, msg, r.resultHandler = f(ctx, testData, reporter)
if r.resultHandler == nil {
r.resultHandler = expectNoError
}
return signer, msg
}
return r
}
// DeliveryResultHandler result handler of the last msg factory invocation
func (f ResultHandlingSimMsgFactory[T]) DeliveryResultHandler() SimDeliveryResultHandler {
return f.resultHandler
}
var (
_ SimMsgFactoryX = &LazyStateSimMsgFactory[sdk.Msg]{}
_ HasFutureOpsRegistry = &LazyStateSimMsgFactory[sdk.Msg]{}
)
// LazyStateSimMsgFactory stateful message factory with weighted proposals and future operation
// registry initialized lazy before execution.
type LazyStateSimMsgFactory[T sdk.Msg] struct {
SimMsgFactoryFn[T]
fsOpsReg FutureOpsRegistry
}
func NewSimMsgFactoryWithFutureOps[T sdk.Msg](f FactoryMethodWithFutureOps[T]) *LazyStateSimMsgFactory[T] {
r := &LazyStateSimMsgFactory[T]{}
r.SimMsgFactoryFn = func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg T) {
signer, msg = f(ctx, testData, reporter, r.fsOpsReg)
return signer, msg
}
return r
}
func (c *LazyStateSimMsgFactory[T]) SetFutureOpsRegistry(registry FutureOpsRegistry) {
c.fsOpsReg = registry
}
// pass errors through and don't handle them
func expectNoError(err error) error {
return err
}
var _ SimMsgFactoryX = SimMsgFactoryFn[sdk.Msg](nil)
// SimMsgFactoryFn is the default factory for most cases. It does not create future operations but ensures successful message delivery.
type SimMsgFactoryFn[T sdk.Msg] func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg T)
// MsgType returns an empty instance of type T, which implements `sdk.Msg`.
func (f SimMsgFactoryFn[T]) MsgType() sdk.Msg {
var x T
return x
}
func (f SimMsgFactoryFn[T]) Create() FactoryMethod {
// adapter to return sdk.Msg instead of typed result to match FactoryMethod signature
return func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) ([]SimAccount, sdk.Msg) {
return f(ctx, testData, reporter)
}
}
func (f SimMsgFactoryFn[T]) DeliveryResultHandler() SimDeliveryResultHandler {
return expectNoError
}
func (f SimMsgFactoryFn[T]) Cast(msg sdk.Msg) T {
return msg.(T)
}
type tuple struct {
signer []SimAccount
msg sdk.Msg
}
// SafeRunFactoryMethod runs the factory method on a separate goroutine to abort early when the context is canceled via reporter skip
func SafeRunFactoryMethod(
ctx context.Context,
data *ChainDataSource,
reporter SimulationReporter,
f FactoryMethod,
) (signer []SimAccount, msg sdk.Msg) {
r := make(chan tuple)
go func() {
defer recoverPanicForSkipped(reporter, r)
signer, msg := f(ctx, data, reporter)
r <- tuple{signer: signer, msg: msg}
}()
select {
case t, ok := <-r:
if !ok {
return nil, nil
}
return t.signer, t.msg
case <-ctx.Done():
reporter.Skip("context closed")
return nil, nil
}
}
func recoverPanicForSkipped(reporter SimulationReporter, resultChan chan tuple) {
if r := recover(); r != nil {
if !reporter.IsSkipped() {
panic(r)
}
close(resultChan)
}
}