Skip to content

Commit

Permalink
test: v2 services helpers and demo using x/bank (#23057)
Browse files Browse the repository at this point in the history
Co-authored-by: Tyler <48813565+technicallyty@users.noreply.github.com>
  • Loading branch information
aljo242 and technicallyty authored Jan 14, 2025
1 parent 265cb94 commit b4e88cc
Show file tree
Hide file tree
Showing 17 changed files with 461 additions and 145 deletions.
56 changes: 53 additions & 3 deletions core/testing/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,65 @@ import (
"context"

"cosmossdk.io/core/event"
"cosmossdk.io/core/gas"
"cosmossdk.io/core/header"
"cosmossdk.io/core/store"
"cosmossdk.io/core/transaction"
)

type dummyKey struct{}

func Context() context.Context {
var _ context.Context = &TestContext{}

type TestContext struct {
context.Context
}

func Context() TestContext {
dummy := &dummyCtx{
stores: map[string]store.KVStore{},
events: map[string][]event.Event{},
protoEvents: map[string][]transaction.Msg{},
header: header.Info{},
execMode: transaction.ExecModeFinalize,
gasConfig: gas.GasConfig{},
gasMeter: nil,
}

return TestContext{
Context: context.WithValue(context.Background(), dummyKey{}, dummy),
}
}

// WithHeaderInfo sets the header on a testing ctx and returns the updated ctx.
func (t TestContext) WithHeaderInfo(info header.Info) TestContext {
dummy := unwrap(t.Context)
dummy.header = info

return TestContext{
Context: context.WithValue(t.Context, dummyKey{}, dummy),
}
}

// WithExecMode sets the exec mode on a testing ctx and returns the updated ctx.
func (t TestContext) WithExecMode(mode transaction.ExecMode) TestContext {
dummy := unwrap(t.Context)
dummy.execMode = mode

ctx := context.WithValue(context.Background(), dummyKey{}, dummy)
return ctx
return TestContext{
Context: context.WithValue(t.Context, dummyKey{}, dummy),
}
}

// WithGas sets the gas config and meter on a testing ctx and returns the updated ctx.
func (t TestContext) WithGas(gasConfig gas.GasConfig, gasMeter gas.Meter) TestContext {
dummy := unwrap(t.Context)
dummy.gasConfig = gasConfig
dummy.gasMeter = gasMeter

return TestContext{
Context: context.WithValue(t.Context, dummyKey{}, dummy),
}
}

type dummyCtx struct {
Expand All @@ -28,6 +72,12 @@ type dummyCtx struct {
events map[string][]event.Event
// maps proto events emitted by the actor.
protoEvents map[string][]transaction.Msg

header header.Info
execMode transaction.ExecMode

gasMeter gas.Meter
gasConfig gas.GasConfig
}

func unwrap(ctx context.Context) *dummyCtx {
Expand Down
65 changes: 65 additions & 0 deletions core/testing/environment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package coretesting

import (
"context"

appmodulev2 "cosmossdk.io/core/appmodule/v2"
corecontext "cosmossdk.io/core/context"
corelog "cosmossdk.io/core/log"
"cosmossdk.io/core/router"
"cosmossdk.io/core/store"
)

type TestEnvironmentConfig struct {
ModuleName string
Logger corelog.Logger
MsgRouter router.Service
QueryRouter router.Service
}

type TestEnvironment struct {
appmodulev2.Environment

testEventService TestEventService
testHeaderService TestHeaderService
}

func NewTestEnvironment(cfg TestEnvironmentConfig) (TestContext, TestEnvironment) {
ctx := Context()

testEventService := NewTestEventService(ctx, cfg.ModuleName)
testHeaderService := TestHeaderService{}

env := TestEnvironment{
Environment: appmodulev2.Environment{
Logger: cfg.Logger,
BranchService: nil,
EventService: testEventService,
GasService: TestGasService{},
HeaderService: testHeaderService,
QueryRouterService: cfg.QueryRouter,
MsgRouterService: cfg.MsgRouter,
TransactionService: TestTransactionService{},
KVStoreService: KVStoreService(ctx, cfg.ModuleName),
MemStoreService: nil,
},
testEventService: testEventService,
testHeaderService: testHeaderService,
}

// set internal context to point to environment
ctx.Context = context.WithValue(ctx.Context, corecontext.EnvironmentContextKey, env.Environment)
return ctx, env
}

func (env TestEnvironment) EventService() TestEventService {
return env.testEventService
}

func (env TestEnvironment) KVStoreService() store.KVStoreService {
return env.Environment.KVStoreService
}

func (env TestEnvironment) HeaderService() TestHeaderService {
return env.testHeaderService
}
22 changes: 11 additions & 11 deletions core/testing/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,29 @@ import (
"cosmossdk.io/core/transaction"
)

var _ event.Service = (*MemEventsService)(nil)
var _ event.Service = &TestEventService{}

// EventsService attaches an event service to the context.
type TestEventService struct {
moduleName string
}

// NewTestEventService attaches an event service to the context.
// Adding an existing module will reset the events.
func EventsService(ctx context.Context, moduleName string) MemEventsService {
func NewTestEventService(ctx context.Context, moduleName string) TestEventService {
unwrap(ctx).events[moduleName] = nil
unwrap(ctx).protoEvents[moduleName] = nil
return MemEventsService{moduleName: moduleName}
}

type MemEventsService struct {
moduleName string
return TestEventService{moduleName: moduleName}
}

func (e MemEventsService) EventManager(ctx context.Context) event.Manager {
func (e TestEventService) EventManager(ctx context.Context) event.Manager {
return eventManager{moduleName: e.moduleName, ctx: unwrap(ctx)}
}

func (e MemEventsService) GetEvents(ctx context.Context) []event.Event {
func (e TestEventService) GetEvents(ctx context.Context) []event.Event {
return unwrap(ctx).events[e.moduleName]
}

func (e MemEventsService) GetProtoEvents(ctx context.Context) []transaction.Msg {
func (e TestEventService) GetProtoEvents(ctx context.Context) []transaction.Msg {
return unwrap(ctx).protoEvents[e.moduleName]
}

Expand Down
23 changes: 23 additions & 0 deletions core/testing/gas.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package coretesting

import (
"context"

"cosmossdk.io/core/gas"
)

var _ gas.Service = &TestGasService{}

type TestGasService struct{}

func (m TestGasService) GasMeter(ctx context.Context) gas.Meter {
dummy := unwrap(ctx)

return dummy.gasMeter
}

func (m TestGasService) GasConfig(ctx context.Context) gas.GasConfig {
dummy := unwrap(ctx)

return dummy.gasConfig
}
15 changes: 15 additions & 0 deletions core/testing/header.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package coretesting

import (
"context"

"cosmossdk.io/core/header"
)

var _ header.Service = &TestHeaderService{}

type TestHeaderService struct{}

func (e TestHeaderService) HeaderInfo(ctx context.Context) header.Info {
return unwrap(ctx).header
}
10 changes: 8 additions & 2 deletions core/testing/services_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ import (
)

func TestKVStoreService(t *testing.T) {
ctx := Context()
svc1 := KVStoreService(ctx, "bank")
cfg := TestEnvironmentConfig{
ModuleName: "bank",
Logger: nil,
MsgRouter: nil,
QueryRouter: nil,
}
ctx, env := NewTestEnvironment(cfg)
svc1 := env.KVStoreService()

// must panic
t.Run("must panic on invalid ctx", func(t *testing.T) {
Expand Down
17 changes: 17 additions & 0 deletions core/testing/transaction.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package coretesting

import (
"context"

"cosmossdk.io/core/transaction"
)

var _ transaction.Service = &TestTransactionService{}

type TestTransactionService struct{}

func (m TestTransactionService) ExecMode(ctx context.Context) transaction.ExecMode {
dummy := unwrap(ctx)

return dummy.execMode
}
2 changes: 1 addition & 1 deletion schema/appdata/mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func ListenerMux(listeners ...Listener) Listener {

mux.onBatch = func(batch PacketBatch) error {
for _, listener := range listeners {
err := batch.apply(&listener) //nolint:gosec // aliasing is safe here
err := batch.apply(&listener)
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit b4e88cc

Please sign in to comment.