Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: v2 services helpers and demo using x/bank #23057

Open
wants to merge 38 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
dab4f61
header service
aljo242 Dec 20, 2024
ccdbad4
update
aljo242 Dec 20, 2024
ef438eb
basic env
aljo242 Dec 20, 2024
9dfae05
transaction service
aljo242 Dec 20, 2024
779bd84
refit
aljo242 Dec 20, 2024
2e7ca6d
register
aljo242 Dec 20, 2024
6161b6a
utd
aljo242 Dec 20, 2024
7355259
Merge branch 'main' into feat/services-helpers
aljo242 Dec 20, 2024
46a30d3
bank
aljo242 Dec 20, 2024
89e5b26
no more sdk.context
aljo242 Dec 20, 2024
05a8577
working
aljo242 Dec 20, 2024
f827e73
lint fixes
aljo242 Dec 20, 2024
6c7dc2a
format
aljo242 Dec 20, 2024
ed63aca
Merge branch 'main' into feat/services-helpers
aljo242 Jan 3, 2025
c8b7460
Merge branch 'main' into feat/services-helpers
aljo242 Jan 3, 2025
4956083
lint
aljo242 Jan 3, 2025
b5703d4
Merge branch 'main' into feat/services-helpers
aljo242 Jan 3, 2025
c7bc69d
tidy all
aljo242 Jan 3, 2025
1442dc2
Merge branch 'main' into feat/services-helpers
aljo242 Jan 6, 2025
9d98953
Merge branch 'main' into feat/services-helpers
aljo242 Jan 6, 2025
d29ed65
Merge branch 'main' into feat/services-helpers
aljo242 Jan 6, 2025
d42ac1f
clean
aljo242 Jan 6, 2025
a6ffa04
use mocked query client
aljo242 Jan 6, 2025
fb55664
clean up
aljo242 Jan 6, 2025
87fb4f9
lint
aljo242 Jan 6, 2025
e18d809
server check
aljo242 Jan 6, 2025
4f56126
Merge branch 'main' into feat/services-helpers
aljo242 Jan 7, 2025
f67b33f
lint-fix
aljo242 Jan 7, 2025
997bf85
Merge branch 'main' into feat/services-helpers
aljo242 Jan 7, 2025
ed61ace
Merge branch 'main' into feat/services-helpers
aljo242 Jan 7, 2025
47a681e
init test
aljo242 Jan 8, 2025
9f54324
rm
aljo242 Jan 8, 2025
0cea6dd
Merge branch 'main' into feat/services-helpers
aljo242 Jan 8, 2025
1838bbf
Update testutil/queryclient/queryclient.go
aljo242 Jan 9, 2025
31198b6
Merge branch 'main' into feat/services-helpers
aljo242 Jan 9, 2025
e932ea5
q
aljo242 Jan 9, 2025
d17569e
Merge branch 'main' into feat/services-helpers
aljo242 Jan 9, 2025
71ad965
Merge branch 'main' into feat/services-helpers
aljo242 Jan 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created the TestContext wrapper so that we can extend with methods to modify it like the ones here

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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Address potential memory aliasing in loop iteration.

The loop variable listener is being passed by reference to batch.apply, which could lead to unexpected behavior if the batch processing modifies the listener state.

Apply this diff to create a local copy of the listener:

-err := batch.apply(&listener)
+listenerCopy := listener
+err := batch.apply(&listenerCopy)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
err := batch.apply(&listener)
listenerCopy := listener
err := batch.apply(&listenerCopy)
🧰 Tools
🪛 golangci-lint (1.62.2)

[medium] 142-142: G601: Implicit memory aliasing in for loop.

(gosec)

if err != nil {
return err
}
Expand Down
Loading
Loading