-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
base: main
Are you sure you want to change the base?
Conversation
} | ||
|
||
// 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 { |
There was a problem hiding this comment.
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
core/testing/environment.go
Outdated
|
||
type TestEnvironment struct { | ||
env appmodulev2.Environment | ||
memEventsService MemEventsService |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Include the concrete types of our Mem
services so that we can use the additional helper methods (such as GetEvents
) in our tests
📝 WalkthroughWalkthroughThis pull request introduces a new testing framework for the Cosmos SDK, focusing on enhancing context management and service mocking. It establishes a Changes
Possibly related PRs
Suggested labels
Suggested reviewers
📜 Recent review detailsConfiguration used: .coderabbit.yml 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms (8)
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
var ErrNoHandler = errors.New("no handler") | ||
|
||
// NewMsgRouterBuilder is a router that routes messages to their respective handlers. | ||
func NewMsgRouterBuilder() *ReflectionRouterBuilder { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Core-only router builder that uses reflect
instead of protoreflect for test pathfinding
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (31)
core/testing/context.go (1)
22-36
: Constructor Naming ConsistencyThe
Context()
function creates aTestContext
instance with a backing dummy context. In Go, constructors for exported types conventionally follow theNewXxx
naming (e.g.,NewTestContext
). Changing the function name may improve discoverability and consistency.core/testing/router.go (1)
151-159
: Invoke Method and Reflection
Invoke
usesreflect.TypeOf(req).String()
as the message key. This is functional, though storing a type’s string name might risk collisions if two types share the same string. Typically, a type URL or fully qualified name is used. For test scenarios, it’s likely acceptable.core/testing/services_test.go (1)
9-15
: Prefer a no-op logger over nil for clarity and maintainability.Although supplying a
nil
logger may be acceptable in certain test scenarios, it can make debugging more difficult when tests fail unexpectedly. Consider using a no-op or in-memory logger so any logging statements can still be captured if needed for troubleshooting.core/testing/environment.go (2)
13-18
: Consider providing default routers or explanatory comments for nil values.The new
TestEnvironmentConfig
allows users to configure a logger and routers but defaults them tonil
. This is fine when certain services aren’t strictly required. However, adding default, no-op implementations or clarifying comments could help other contributors understand when and why anil
router is acceptable.
20-24
: Implement or document the missing MemStoreService.Currently,
MemStoreService
is set tonil
in the returnedappmodulev2.Environment
. This may be intentional if your module doesn’t require it. Otherwise, providing a minimal, concreteMemStoreService
would allow consistent usage with other memory-based services.Do you want help implementing a basic
MemStoreService
for uniform coverage in your test environment?x/bank/v2/keeper/handlers.go (1)
Line range hint
42-66
: Consolidate repeated authority checks into a helper.Your authority validation logic appears in both
MsgUpdateParams
andMsgMint
. Extracting this into a small helper method can improve maintainability and clarity by centralizing the checks (e.g., matching addresses, string conversion, and error handling).x/bank/types/send_authorization_test.go (1)
32-32
: No logic to handle non-zero gas consumption
The current implementation always returnsnil
. Consider tracking or logging gas usage to ensure correct metering in tests.x/bank/keeper/grpc_query_test.go (8)
104-104
: Empty request scenario
Raising errors for empty requests is correct. Consider adding negative tests to confirm robust handling of malformed queries.
145-145
: Second page logic
When retrieving the second page of results, verify that you handle edge cases where fewer results may exist.
183-185
: Combining test setup
Lines 183 and 185 definectx
andqueryClient
. Re-evaluate for consistent usage across all sub-tests (e.g., some tests may set up their own context).
213-214
: Use Unix timestamps
Casting block time toUnix()
is valid for vesting calculations. Confirm that all time-based logic consistently uses the same epoch reference.
237-240
: Initialize second test context
Settingctx
andqueryClient
again here might override previous test contexts. Ensure no state from prior tests is inadvertently shared.
Line range hint
296-305
: Testing total supply updates
Ensure correct supply increments after module minting. Verify no conflict with previously minted coins.
333-333
: Zero supply fallback
Returning zero supply for an unknown denom is standard. This is consistent with typical chain logic.
350-350
: Empty metadata slice
InitializingexpMetadata
as an empty slice ensures nonil
pointer usage. This improves test robustness.x/bank/types/restrictions_test.go (1)
392-392
: No-op minting restriction
Confirm that this function is intentionally lenient and won't impede future expansions to minted coins logic.x/bank/keeper/keeper_test.go (15)
21-21
: Added logging import
Usinglog
might be optional if no actual logs are emitted here. Keep the import if relevant logs may be added later.
132-137
: Initialize custom TestEnvironmentConfig
These lines define the environment config (logger, routers, etc.). Verify you have included all necessary modules in the router for advanced tests.
139-140
: Create environment
coretesting.NewTestEnvironment
is used. Check for concurrency issues if tests run in parallel, especially around shared static resources.
174-174
: Store encCfg
RetainingencCfg
in the suite helps additional test methods decode messages.
220-220
: mockSpendableCoins
Ensuring vesting accounts are retrieved from the new environment context is proper. Verify no usage of the oldersdk.Context
.
1406-1406
: Reset context
Ensure you reset any test state needed prior to the new multi-send tests.
1459-1459
: 25 events
The test scenario triggers multiple events. Make sure all event sources (like mint/spend/recv) are well-documented.
1493-1494
: Validate key match
Ensuring the attribute keys align with the expected static references from bank types.
1510-1510
: TestSpendableBalances
Setting up multiple vesting scenarios here is important. Confirm partial and fully vested cases are tested thoroughly.
1664-1664
: Additional periodic vesting test
Validates that new coins remain separated from the original vesting schedule, ensuring no accidental lumps in vesting logic.
1760-1760
: UndelegateCoins
The test ensures that previously delegated coins are returned to the correct account. Double-check partial undelegations as well.
1770-1770
: ContinuousVestingAccount usage
At line 1770, you retrieve the header info to initialize vesting. Confirm alignment with partial or periodic vesting tests.
1940-1940
: Handled coin mint
Add minted coins to your in-test supply tracking. This ensures minted amounts match keeper logic.
1947-1947
: Check address decode
At line 1947, verifying that the address can be parsed by the codec is crucial to avoid panics.
1957-1957
: Tracking final balances
Ensuring all local balances sum up correctly after each event is crucial for supply integrity checks.
📜 Review details
Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
x/bank/go.sum
is excluded by!**/*.sum
📒 Files selected for processing (14)
core/testing/context.go
(2 hunks)core/testing/environment.go
(1 hunks)core/testing/gas.go
(1 hunks)core/testing/header.go
(1 hunks)core/testing/router.go
(1 hunks)core/testing/services_test.go
(1 hunks)core/testing/transaction.go
(1 hunks)x/bank/go.mod
(2 hunks)x/bank/keeper/grpc_query_test.go
(17 hunks)x/bank/keeper/keeper_test.go
(21 hunks)x/bank/types/restrictions_test.go
(4 hunks)x/bank/types/send_authorization_test.go
(2 hunks)x/bank/v2/keeper/handlers.go
(2 hunks)x/bank/v2/module.go
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- x/bank/go.mod
🧰 Additional context used
📓 Path-based instructions (13)
core/testing/transaction.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
x/bank/keeper/grpc_query_test.go (2)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
Pattern **/*_test.go
: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"
core/testing/gas.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
core/testing/header.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
x/bank/types/send_authorization_test.go (2)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
Pattern **/*_test.go
: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"
x/bank/v2/keeper/handlers.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
x/bank/types/restrictions_test.go (2)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
Pattern **/*_test.go
: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"
core/testing/services_test.go (2)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
Pattern **/*_test.go
: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"
core/testing/context.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
core/testing/environment.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
x/bank/v2/module.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
x/bank/keeper/keeper_test.go (2)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
Pattern **/*_test.go
: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"
core/testing/router.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
🔇 Additional comments (65)
core/testing/context.go (6)
16-17
: Interfaces Confirmed ImplementedDeclaring
var _ context.Context = &TestContext{}
is a good practice to ensureTestContext
satisfies thecontext.Context
interface. No issues here.
38-52
: Interface Pass-Through Methods
Deadline()
,Done()
,Err()
, andValue()
correctly pass through to the underlyingcontext
. This approach cleanly preserves the original context behaviors. No concerns.
54-63
: Builder Pattern for Header
WithHeaderInfo
follows a fluent, builder-like pattern, returning a newTestContext
with updated header info. This pattern is clear and test-friendly. Ensure that any code depending on the old context references is aware that changes won't reflect retroactively.
64-72
: Builder Pattern for ExecMode
WithExecMode
also returns a newTestContext
, mirroringWithHeaderInfo
logic. This consistency is beneficial. No issues found.
74-82
: Builder Pattern for Gas
WithGas
retains the same pattern, setting gas config and meter in a newdummyCtx
. This approach is consistent with the rest of the file and supports test flexibility.
92-97
: Potential Concurrency Considerations for Maps
dummyCtx
stores data in maps which are not thread-safe. If test scenarios evolve to run in parallel, consider adding synchronization or clarifying usage in single-threaded tests to avoid data races.core/testing/router.go (9)
14-15
: Exported Error Variable
ErrNoHandler
is properly declared and used in error returns. This ensures consistent error signaling. No issues found.
16-23
: Reflection-Based Router Initialization
NewMsgRouterBuilder()
instantiates theReflectionRouterBuilder
along with handler maps. The approach is straightforward. If performance becomes critical, consider alternatives to reflection, but for a test or dev environment, it is adequate.
25-31
: ReflectionRouterBuilder Data StructuresStoring handlers in maps keyed by string is direct and easy to maintain. Avoid overriding already-registered handlers is a good safeguard. No immediate concerns.
33-40
: RegisterHandler Override CheckThe function panics on handler override, which can be beneficial to detect accidental re-registrations in tests. This explicit error handling is acceptable for testing scenarios.
42-56
: Global vs. Local HandlersThe builder allows both global pre/post handlers and msg-specific handlers. This design is flexible and well-structured for test-centric message routing. No issues found.
58-61
: HandlerExists Helper
HandlerExists
is a neat utility to verify registration status. Straightforward approach, no concerns.
63-98
: Build Method: Consolidated Handler AssemblyAggregating the global and per-message pre/post handlers into final
HandlerFunc
s is clean. Using closures for each built handler is a neat approach. Reflection overhead is likely acceptable in test contexts.
100-134
: buildHandler ImplementationSequentially running pre-handlers, calling the main handler, then post-handlers is logically grouped and easy to follow. The returning of
(nil, err)
ensures short-circuiting on failures. Looks good.
143-149
: CanInvoke MethodReports an error if there's no matching handler. This method is simple yet effective for verifying route coverage in tests.
core/testing/header.go (2)
9-10
: Interface Conformance
MemHeaderService
correctly implementsheader.Service
. The_ = &MemHeaderService{}
check ensures compile-time conformance.
13-15
: Header Retrieval via unwrap
HeaderInfo
returnsdummy.header
. For test usage, it’s straightforward. The usage ofpanic
inunwrap
is acceptable in a purely testing context.core/testing/transaction.go (2)
9-10
: Transaction Service Conformance
MemTransactionService
satisfies thetransaction.Service
interface. No issues with_ = &MemTransactionService{}
usage.
13-17
: ExecMode from ContextExtracting
execMode
from thedummyCtx
is consistent with other wrappers. Ensure that if parallel tests access the same context, there's no conflicting usage. Typically, each test should have its own context instance.core/testing/gas.go (3)
9-10
: Gas Service Conformance
MemGasService
fulfillsgas.Service
. The_ = &MemGasService{}
check is standard for interface compliance.
13-17
: GasMeter Getter
GasMeter
fetches the meter fromdummyCtx
. Straightforward approach. No issues found.
19-23
: GasConfig Getter
GasConfig
also delegates todummyCtx
. This is consistent with other services. Looks good.x/bank/v2/module.go (2)
97-97
: Modular registration of message handlers looks great.Delegating the registration process to
keeper.NewHandlers(am.keeper).RegisterMsgHandlers(router)
improves maintainability and promotes encapsulation.
103-103
: Query handlers are similarly well-encapsulated.Registering the queries through the keeper’s
RegisterQueryHandlers
method is consistent with the message handlers approach. This keeps logic for query routing cohesive and testable.x/bank/v2/keeper/handlers.go (1)
29-34
: Straightforward approach for registering message handlers.Using
appmodulev2.RegisterMsgHandler
to wire up your message endpoints is clear. Ensure you keep adding new messages here to avoid missing coverage.x/bank/types/send_authorization_test.go (2)
10-10
: Streamlined import usage
Importingcoretesting
aligns with the new testing framework and is consistent with best practices.
38-44
: New test environment configuration
Initializing aTestEnvironmentConfig
and injecting a mock gas meter is a suitable approach for modular tests. Verify that all required test services (e.g., event managers) are also configured as needed.x/bank/keeper/grpc_query_test.go (12)
86-86
: Validate error checking
Ensure that all expected errors are thoroughly tested when querying balances.
116-116
: Beware of pagination
Properly verify pagination in tests to ensure correct iteration over balances.
132-132
: Check result struct shape
Ensure the returned response structure matches the expected fields in gRPC stubs for multi-balance queries.
159-159
: Ensure non-empty 3rd page
Properly handle the scenario where the 3rd page might still contain valid results.
171-171
: Resolve denom
The final test checks IBC denom resolution. Ensure correct mapping between the resolution logic and the IBC coin metadata.
207-208
: Accessing currentBlockTime
Fetching the header time fromsuite.env.HeaderService().HeaderInfo(ctx).Time
is consistent with the new environment approach. Ensure synchronization with how vesting logic uses time.
222-223
: Updated context with new header
Modifying the context with a new time helps simulate the vesting mid-way. Confirm that subsequent calls indeed observe this updated time.
260-261
: BlockTime retrieval
Repeating the block time fetch. Make sure to keep usage consistent for multi-step vesting tests.
266-267
: Accurate vesting start & end
Double-check that the vesting intervals match expectations in the test scenario.
275-276
: Advance half vesting
After 30 minutes, verify partial vesting. The test coverage is good for progressive vesting checks.
324-327
: Query supply
At line 324 and 327, test partial supply queries by denom. Confirm error handling for nonexistent denoms.
340-341
: Params query
Lines 340,341 and 344 validate the bank params query. Confirm default param usage and non-empty param sets.Also applies to: 344-344
x/bank/types/restrictions_test.go (3)
86-86
: Resizing the calls slice
Resettings.Calls
before invocation is crucial. Ensure no leftover state pollutes subsequent assertions.
486-486
: Capturing function output
Storing returnedaddr
anderr
ensures test clarity. Good approach to isolate each call’s state.
915-915
: Testing NoOpSendRestriction
This test is straightforward. Confirm unexpected error scenarios are also tested if future modifications are introduced.x/bank/keeper/keeper_test.go (23)
114-115
: Switch to coretesting.TestContext
These changes replace standard contexts withcoretesting.TestContext
, aligning with the new test environment approach. This is consistent with the PR objective.
120-120
: QueryServer reference
Switching from aQueryClient
to aQueryServer
is consistent with the updated gRPC design. Confirm all client calls are updated accordingly.
156-156
: Set up BaseKeeper
Providing environment-based references is a better pattern than global singletons. Keep an eye on unauthorized usage of environment resources.
169-169
: Initialize QueryServer
keeper.NewQuerier
returns a QueryServer. Confirm that registry is up-to-date for all query endpoints.
171-171
: Attach MsgServer
Attaching aMsgServer
to the newly created keeper is crucial for covering message functionalities in tests.
1389-1396
: New event service usage
Shifting tosuite.env.MemEventsService()
to retrieve events is a modern approach. Carefully review event indexing for large or repeated tests.
1399-1401
: Comparing custom attributes
Ensuring that each event attribute matches the test expectation is correct. This thoroughly validates event emission.
1434-1434
: Events array length
You verify that no events appear yet. This ensures the test data is fully controlled.
1444-1444
: Check events after second transaction
Ensure no overlap from previous events. Good to confirm final length as 10 in this scenario.
1488-1491
: Comparing Transfer events
The test ensures that the event type is “transfer,” referencing the correct attributes (sender/recipient/amount). Good coverage.
1499-1502
: Second Transfer event
Similarly verifying the second transfer event’s attributes. Consistent approach to multi-send testing.
1504-1505
: Check final attributes
Ensuring the final comparisons match the expected attribute list for each transfer.
1566-1566
: Test vesting logic
The continuous vesting logic is tested halfway through the vesting period. Great approach to ensure partial unlocking is correct.
1596-1596
: Periodic vesting
Combining multiple vesting periods tests more complex logic. Check that newly minted or transferred coins do not unexpectedly vest.
1631-1631
: Test receiving coins
Verifies that newly received coins are immediately spendable even in vesting accounts—important difference from original vesting coins.
1702-1702
: DelegateCoins
Test includes delegating from both vesting and normal accounts. This coverage is crucial to ensure partial locked funds.
1712-1712
: Use of suite.env.HeaderService()
Line 1712 references the environment’s header data. It’s consistent with the new testing infrastructure.
1928-1928
: Event-based supply tracking
Reading all events fromsuite.env.MemEventsService().GetEvents(suite.ctx)
helps confirm supply is correctly minted and burned.
1930-1932
: Wrapping event attributes
Parsing event attributes carefully avoids indexing errors. Consider additional validations for event order or duplicates.
1935-1935
: Handled coin burn
Subtract burned coins from total supply. Good approach to reflect deflationary events in your test logic.
1945-1945
: Handled coin spent
Ensuring the spent coins are subtracted from the correct local address balance. Good for validating no misattribution.
1950-1950
: Decrement balance
Properly subtracting spent coins from the relevant address’s local tracking.
1953-1955
: Handled coin received
Adding coins to the address’s local tracking. Continues the event-driven verification approach.
core/testing/environment.go
Outdated
func NewTestEnvironment(cfg TestEnvironmentConfig) (TestContext, TestEnvironment) { | ||
ctx := Context() | ||
|
||
memEventService := EventsService(ctx, cfg.ModuleName) | ||
memHeaderService := MemHeaderService{} | ||
|
||
env := TestEnvironment{ | ||
env: appmodulev2.Environment{ | ||
Logger: cfg.Logger, | ||
BranchService: nil, | ||
EventService: memEventService, | ||
GasService: MemGasService{}, | ||
HeaderService: memHeaderService, | ||
QueryRouterService: cfg.QueryRouter, | ||
MsgRouterService: cfg.MsgRouter, | ||
TransactionService: MemTransactionService{}, | ||
KVStoreService: KVStoreService(ctx, cfg.ModuleName), | ||
MemStoreService: nil, | ||
}, | ||
memEventsService: memEventService, | ||
memHeaderService: memHeaderService, | ||
} | ||
|
||
// set internal context to point to environment | ||
ctx.ctx = context.WithValue(ctx.ctx, corecontext.EnvironmentContextKey, env.env) | ||
return ctx, env | ||
} |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
// RegisterQueryHandlers registers the query handlers to the router. | ||
func (h handlers) RegisterQueryHandlers(router appmodulev2.QueryRouter) { | ||
appmodulev2.RegisterMsgHandler(router, h.QueryParams) | ||
appmodulev2.RegisterMsgHandler(router, h.QueryBalance) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potentially incorrect usage of message-handling registration for queries.
Both QueryParams
and QueryBalance
are query endpoints, yet they're being registered with RegisterMsgHandler
. This can cause confusion and possibly route queries incorrectly. To align with naming conventions, use a dedicated query registration method, such as appmodulev2.RegisterQueryHandler(router, ...)
, to register query endpoints.
-func (h handlers) RegisterQueryHandlers(router appmodulev2.QueryRouter) {
- appmodulev2.RegisterMsgHandler(router, h.QueryParams)
- appmodulev2.RegisterMsgHandler(router, h.QueryBalance)
+func (h handlers) RegisterQueryHandlers(router appmodulev2.QueryRouter) {
+ appmodulev2.RegisterQueryHandler(router, h.QueryParams)
+ appmodulev2.RegisterQueryHandler(router, h.QueryBalance)
}
📝 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.
// RegisterQueryHandlers registers the query handlers to the router. | |
func (h handlers) RegisterQueryHandlers(router appmodulev2.QueryRouter) { | |
appmodulev2.RegisterMsgHandler(router, h.QueryParams) | |
appmodulev2.RegisterMsgHandler(router, h.QueryBalance) | |
} | |
// RegisterQueryHandlers registers the query handlers to the router. | |
func (h handlers) RegisterQueryHandlers(router appmodulev2.QueryRouter) { | |
appmodulev2.RegisterQueryHandler(router, h.QueryParams) | |
appmodulev2.RegisterQueryHandler(router, h.QueryBalance) | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK. Services mock makes sense to me!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
small nits and stuff
var ErrNoHandler = errors.New("no handler") | ||
|
||
// NewMsgRouterBuilder is a router that routes messages to their respective handlers. | ||
func NewMsgRouterBuilder() *ReflectionRouterBuilder { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my IDE says there are no usages of this function - is there an example usage of this somewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be used for an appmodulev2
module - which this task doesn't touch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
adding comment here from our conversation so we don't forget: resolution here is to add a test that utilizes this code in some way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🔭 Outside diff range comments (2)
core/testing/context.go (1)
Line range hint
1-10
: Fix import ordering to comply with linting rules.The imports need to be reordered using
gci
with the following configuration:
- standard
- default
- prefix(cosmossdk.io)
- prefix(github.com/cosmos/cosmos-sdk)
#!/bin/bash # Fix import ordering gci write --skip-generated -s standard -s default -s "prefix(cosmossdk.io)" -s "prefix(github.com/cosmos/cosmos-sdk)" core/testing/context.go🧰 Tools
🪛 golangci-lint (1.62.2)
4-4: File is not
gci
-ed with --skip-generated -s standard -s default -s prefix(cosmossdk.io) -s prefix(github.com/cosmos/cosmos-sdk) --custom-order(gci)
🪛 GitHub Actions: Lint
[error] 4-4: File is not
gci
-ed with --skip-generated -s standard -s default -s prefix(cosmossdk.io) -s prefix(github.com/cosmos/cosmos-sdk) --custom-orderx/bank/keeper/keeper_test.go (1)
Line range hint
1760-1770
: Replace time.Now() with deterministic timestamps in tests.Using time.Now() can lead to flaky tests. Consider using fixed timestamps for better test reliability.
-now := time.Now() -endTime := now.Add(24 * time.Hour) +baseTime := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC) +endTime := baseTime.Add(24 * time.Hour) -vacc, err := vesting.NewContinuousVestingAccount(acc0, origCoins, suite.env.HeaderService().HeaderInfo(ctx).Time.Unix(), endTime.Unix()) +vacc, err := vesting.NewContinuousVestingAccount(acc0, origCoins, baseTime.Unix(), endTime.Unix())
🧹 Nitpick comments (4)
core/testing/context.go (3)
20-34
: Add documentation for the Context() function.The function should be documented to explain:
- Its purpose in creating a new test context
- The initialization of default values
- The return value
+// Context creates a new TestContext initialized with default values. +// It returns a TestContext that wraps a context.Context with testing-specific values. func Context() TestContext {
36-64
: Consider refactoring common patterns and adding documentation.The context modification methods share a common pattern that could be abstracted to reduce code duplication. Additionally, each method should be documented.
Consider creating a helper function for the common pattern:
+// withValue is a helper function that unwraps the dummy context, applies the modifier function, +// and returns a new TestContext with the modified value. +func (t TestContext) withValue(modifier func(*dummyCtx)) TestContext { + dummy := unwrap(t.Context) + modifier(dummy) + return TestContext{ + Context: context.WithValue(t.Context, dummyKey{}, dummy), + } +} +// WithHeaderInfo sets the header information on the test context. func (t TestContext) WithHeaderInfo(info header.Info) TestContext { - dummy := unwrap(t.Context) - dummy.header = info - return TestContext{ - Context: context.WithValue(t.Context, dummyKey{}, dummy), - } + return t.withValue(func(dummy *dummyCtx) { + dummy.header = info + }) }
Line range hint
66-91
: Improve error handling and documentation in dummyCtx.Consider the following improvements:
- Replace panic with error return in unwrap function
- Add documentation for dummyCtx fields
type dummyCtx struct { + // stores maps store by actor stores map[string]store.KVStore + // events maps event emitted by actor events map[string][]event.Event + // protoEvents maps proto events emitted by actor protoEvents map[string][]transaction.Msg + // header contains the current header information header header.Info + // execMode defines the current execution mode execMode transaction.ExecMode + // gasMeter tracks gas consumption gasMeter gas.Meter + // gasConfig defines gas parameters gasConfig gas.GasConfig } -func unwrap(ctx context.Context) *dummyCtx { +func unwrap(ctx context.Context) (*dummyCtx, error) { dummy := ctx.Value(dummyKey{}) if dummy == nil { - panic("invalid ctx without dummy") + return nil, fmt.Errorf("invalid ctx without dummy") } - return dummy.(*dummyCtx) + return dummy.(*dummyCtx), nil }x/bank/keeper/keeper_test.go (1)
1389-1402
: Consider refactoring event assertions for better maintainability.The event assertions could be improved by:
- Creating a helper function to compare events
- Adding comments explaining the event offset (why events are shifted by 7)
+// assertEvent compares an expected event with an actual event +func (suite *KeeperTestSuite) assertEvent(expected, actual coreevent.Event) { + suite.Require().Equal(expected.Type, actual.Type) + expectedAttrs, err := expected.Attributes() + suite.Require().NoError(err) + actualAttrs, err := actual.Attributes() + suite.Require().NoError(err) + suite.Require().Equal(expectedAttrs, actualAttrs) +} events := suite.env.MemEventsService().GetEvents(suite.ctx) +// events[7] is the transfer event (previous events are from account funding) require.Equal(event1.Type, events[7].Type)
📜 Review details
Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
core/testing/context.go
(2 hunks)core/testing/environment.go
(1 hunks)tests/integration/distribution/genesis_test.go
(1 hunks)x/bank/keeper/keeper_test.go
(21 hunks)
✅ Files skipped from review due to trivial changes (1)
- tests/integration/distribution/genesis_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
- core/testing/environment.go
🧰 Additional context used
📓 Path-based instructions (2)
core/testing/context.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
x/bank/keeper/keeper_test.go (2)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
Pattern **/*_test.go
: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"
🪛 GitHub Actions: Lint
core/testing/context.go
[error] 4-4: File is not gci
-ed with --skip-generated -s standard -s default -s prefix(cosmossdk.io) -s prefix(github.com/cosmos/cosmos-sdk) --custom-order
⏰ Context from checks skipped due to timeout of 90000ms (4)
- GitHub Check: tests (00)
- GitHub Check: test-system-v2
- GitHub Check: Analyze
- GitHub Check: Summary
🔇 Additional comments (2)
core/testing/context.go (1)
14-18
: LGTM! Clean implementation of TestContext.The type definition correctly embeds context.Context and includes proper interface compliance checking.
x/bank/keeper/keeper_test.go (1)
132-140
: LGTM! Good adoption of the new testing framework.The test environment setup properly initializes the TestEnvironment with appropriate configuration and context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (4)
testutil/queryclient/queryclient.go (1)
68-71
: Improve error handling in NewStream method.Instead of using a panic, consider returning a proper error message indicating that streaming is not supported in the test utility.
-func (q *QueryHelper) NewStream(context.Context, *grpc.StreamDesc, string, ...grpc.CallOption) (grpc.ClientStream, error) { - panic("not implemented") +func (q *QueryHelper) NewStream(context.Context, *grpc.StreamDesc, string, ...grpc.CallOption) (grpc.ClientStream, error) { + return nil, fmt.Errorf("streaming is not supported in the test query helper") }schema/appdata/mux.go (1)
142-142
: Fix code formatting.Remove trailing whitespace after
batch.apply(&listener)
.- err := batch.apply(&listener) + err := batch.apply(&listener)🧰 Tools
🪛 golangci-lint (1.62.2)
142-142: File is not
gofumpt
-ed with-extra
(gofumpt)
x/bank/keeper/keeper_test.go (2)
1390-1394
: Improve event testing robustness.The test relies on magic numbers for event array indices (8 and 7). Consider creating helper functions to find specific events by type and attributes to make the tests more maintainable.
Example helper function:
func findEventByType(events []coreevent.Event, eventType string) (coreevent.Event, bool) { for _, event := range events { if event.Type == eventType { return event, true } } return coreevent.Event{}, false }
1445-1445
: Add comments explaining event counts.The test expects specific event counts (10 and 25) but doesn't explain why these numbers are expected. Add comments explaining the event breakdown to improve test maintainability.
+// 10 events: 2 mint + 2 coin_spent + 2 coin_recv + 2 transfer + 2 message events events = suite.env.MemEventsService().GetEvents(suite.ctx) require.Equal(10, len(events)) +// 25 events: previous 10 + 3 additional funding operations (5 events each) events = suite.env.MemEventsService().GetEvents(suite.ctx) require.Equal(25, len(events))Also applies to: 1460-1460
📜 Review details
Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
core/testing/context.go
(2 hunks)schema/appdata/mux.go
(1 hunks)testutil/queryclient/queryclient.go
(1 hunks)x/bank/keeper/grpc_query_test.go
(17 hunks)x/bank/keeper/keeper_test.go
(21 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- x/bank/keeper/grpc_query_test.go
🧰 Additional context used
📓 Path-based instructions (4)
schema/appdata/mux.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
core/testing/context.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
x/bank/keeper/keeper_test.go (2)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
Pattern **/*_test.go
: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"
testutil/queryclient/queryclient.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
🪛 golangci-lint (1.62.2)
schema/appdata/mux.go
142-142: File is not gofumpt
-ed with -extra
(gofumpt)
⏰ Context from checks skipped due to timeout of 90000ms (4)
- GitHub Check: tests (00)
- GitHub Check: test-system-v2
- GitHub Check: Analyze
- GitHub Check: Summary
🔇 Additional comments (1)
core/testing/context.go (1)
15-19
: LGTM! Well-structured context wrapper.The
TestContext
implementation is clean and follows good practices with proper interface checks and clear method documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (5)
core/testing/event.go (1)
16-21
: Consider adding validation for empty moduleName.While the implementation is correct, it might be worth adding validation to prevent empty module names.
func NewTestEventService(ctx context.Context, moduleName string) TestEventService { + if moduleName == "" { + panic("moduleName cannot be empty") + } unwrap(ctx).events[moduleName] = nil unwrap(ctx).protoEvents[moduleName] = nil return TestEventService{moduleName: moduleName} }core/testing/transaction.go (1)
13-17
: Consider documenting the default ExecMode behavior.While the implementation is correct, it would be helpful to document the default execution mode behavior for test scenarios.
+// ExecMode returns the execution mode from the test context. +// By default, it returns the mode set in the dummy context. func (m TestTransactionService) ExecMode(ctx context.Context) transaction.ExecMode { dummy := unwrap(ctx) return dummy.execMode }core/testing/gas.go (1)
13-23
: Consider adding panic recovery for unwrap failures.The implementation is correct, but it might be worth adding panic recovery when unwrapping fails to provide better error messages in tests.
func (m TestGasService) GasMeter(ctx context.Context) gas.Meter { + defer func() { + if r := recover(); r != nil { + panic(fmt.Sprintf("failed to get gas meter: %v", r)) + } + }() dummy := unwrap(ctx) return dummy.gasMeter }core/testing/environment.go (1)
36-38
: Document nil service implications.Some services are explicitly set to nil. Consider documenting the implications of these nil services for test scenarios.
type TestEnvironment struct { appmodulev2.Environment + // testEventService and testHeaderService are concrete implementations + // that provide additional testing capabilities testEventService TestEventService testHeaderService TestHeaderService }Also applies to: 44-44
core/testing/router.go (1)
85-92
: Consider documenting non-deterministic behavior.The map iteration in the
Build
method may produce non-deterministic results. While this is acceptable in test code, it should be documented to avoid confusion.Add a comment like:
+// Note: The order of handler registration is non-deterministic due to map iteration. for msgType, handler := range b.handlers {
📜 Review details
Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
core/testing/environment.go
(1 hunks)core/testing/event.go
(1 hunks)core/testing/gas.go
(1 hunks)core/testing/header.go
(1 hunks)core/testing/router.go
(1 hunks)core/testing/transaction.go
(1 hunks)schema/appdata/mux.go
(1 hunks)testutil/queryclient/queryclient.go
(1 hunks)x/bank/keeper/keeper_test.go
(21 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- core/testing/header.go
- testutil/queryclient/queryclient.go
🧰 Additional context used
📓 Path-based instructions (7)
core/testing/transaction.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
core/testing/gas.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
core/testing/environment.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
core/testing/event.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
x/bank/keeper/keeper_test.go (2)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
Pattern **/*_test.go
: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"
core/testing/router.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
schema/appdata/mux.go (1)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
🪛 golangci-lint (1.62.2)
schema/appdata/mux.go
[medium] 142-142: G601: Implicit memory aliasing in for loop.
(gosec)
⏰ Context from checks skipped due to timeout of 90000ms (4)
- GitHub Check: tests (00)
- GitHub Check: test-system-v2
- GitHub Check: Analyze
- GitHub Check: Summary
🔇 Additional comments (10)
core/testing/event.go (2)
12-14
: LGTM! Clean and focused type definition.The
TestEventService
type is well-defined with a clear purpose and minimal state.
24-33
: LGTM! Methods are concise and follow interface contract.The implementation of
EventManager
,GetEvents
, andGetProtoEvents
is clean and follows the interface contract correctly.core/testing/transaction.go (1)
9-11
: LGTM! Clean interface implementation.The type definition and interface compliance check are well-structured.
core/testing/gas.go (1)
9-11
: LGTM! Clean interface implementation.The type definition and interface compliance check are well-structured.
core/testing/environment.go (3)
13-25
: LGTM! Well-structured configuration types.The configuration and environment types are well-defined with clear separation of concerns.
55-65
: LGTM! Clean service accessor methods.The service accessor methods are well-implemented and provide clear access to the underlying services.
27-53
: 🛠️ Refactor suggestionConsider alternatives to context.WithValue for environment storage.
As noted in previous reviews, using
context.WithValue
can obscure type checking. Consider alternative approaches to store the environment reference.type TestContext struct { context.Context + environment appmodulev2.Environment } func NewTestEnvironment(cfg TestEnvironmentConfig) (TestContext, TestEnvironment) { ctx := Context() // ... existing setup code ... - ctx.Context = context.WithValue(ctx.Context, corecontext.EnvironmentContextKey, env.Environment) + ctx.environment = env.Environment return ctx, env }Likely invalid or redundant comment.
core/testing/router.go (1)
16-23
: LGTM! Well-structured router implementation.The router implementation follows good practices with proper initialization and error handling.
x/bank/keeper/keeper_test.go (2)
1390-1394
: LGTM! Event handling is properly updated.The event handling is correctly migrated to use the new environment service.
133-141
: LGTM! Test environment setup is well-structured.The test environment configuration and initialization is properly implemented using the new
coretesting
package.
@@ -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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
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)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (6)
x/bank/keeper/keeper_test.go (6)
154-162
: LGTM! Consider adding environment validation.The test environment setup looks good and aligns with the new testing framework. The configuration and initialization are properly structured.
Consider adding validation for required environment fields before initialization:
testEnironmentConfig := coretesting.TestEnvironmentConfig{ ModuleName: banktypes.ModuleName, Logger: log.NewNopLogger(), MsgRouter: nil, QueryRouter: nil, + // Add validation + if testEnironmentConfig.ModuleName == "" { + return nil, nil, fmt.Errorf("module name is required") + } }
1411-1415
: Improve test readability by explaining the event count.The magic number
8
in the event count check makes it difficult to understand why exactly 8 events are expected.Consider adding a comment explaining the event breakdown or use constants:
+// Expected events: +// 1. EventTypeMint from funding +// 2-7. EventTypeCoinSpent and EventTypeCoinReceived from funding +// 8. EventTypeTransfer from the actual transfer require.Equal(8, len(events))
Line range hint
1456-1466
: Improve consistency in event count handling.The test uses magic numbers (10, 25) for event count verification without explaining the breakdown of expected events.
Consider using constants or helper functions to make the event count expectations more maintainable:
+const ( + baseEventCount = 3 // mint + coin_spent + coin_recv + fundingEventCount = baseEventCount * 3 // for 3 funding operations + transferEventCount = 1 +) + -require.Equal(10, len(events)) +require.Equal(baseEventCount*3 + transferEventCount, len(events))Also applies to: 1481-1481
1572-1572
: Clarify context handling in test.The comment about context reassignment could be more explicit about why it's necessary.
Consider adding a more descriptive comment:
-// Go back to the suite's context since mockFundAccount uses that; FundAccount would fail for bad mocking otherwise. +// Reset to suite's context to ensure consistent mocking behavior. +// mockFundAccount expects the suite's context for proper mock setup, +// and FundAccount would fail with the modified context. ctx = suite.ctx
1734-1734
: Consider using explicit time handling.The test relies on the environment's header time, which is good for consistency but could be more explicit.
Consider using a helper function for time-related test setup:
+func (suite *KeeperTestSuite) getTestTime() time.Time { + return suite.env.HeaderService().HeaderInfo(suite.ctx).Time +} + -vacc, err := vesting.NewContinuousVestingAccount(acc0, origCoins, suite.env.HeaderService().HeaderInfo(suite.ctx).Time.Unix(), endTime.Unix()) +vacc, err := vesting.NewContinuousVestingAccount(acc0, origCoins, suite.getTestTime().Unix(), endTime.Unix())
136-137
: Consider adding specific tests for TestContext and TestEnvironment.While the existing tests implicitly verify the new testing framework, explicit tests would be valuable.
Consider adding dedicated test cases:
func (suite *KeeperTestSuite) TestEnvironmentSetup() { require := suite.Require() // Test environment initialization require.NotNil(suite.env) require.Equal(banktypes.ModuleName, suite.env.ModuleName()) // Test context initialization require.NotNil(suite.ctx) require.NotZero(suite.ctx.HeaderInfo().Time) }
📜 Review details
Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
x/bank/go.sum
is excluded by!**/*.sum
📒 Files selected for processing (3)
x/bank/go.mod
(2 hunks)x/bank/keeper/grpc_query_test.go
(17 hunks)x/bank/keeper/keeper_test.go
(21 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- x/bank/go.mod
- x/bank/keeper/grpc_query_test.go
🧰 Additional context used
📓 Path-based instructions (1)
x/bank/keeper/keeper_test.go (2)
Pattern **/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
Pattern **/*_test.go
: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"
⏰ Context from checks skipped due to timeout of 90000ms (4)
- GitHub Check: tests (00)
- GitHub Check: test-system-v2
- GitHub Check: Analyze
- GitHub Check: Summary
Description
Part of: #22903
core testing
package to return more services and aTestContext
andTestEnvironment
wrapper that can be used throughout module and keeper-level testsx/bank
test, removing all uses ofbaseapp
andsdk.Context
Author Checklist
All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.
I have...
!
in the type prefix if API or client breaking changeCHANGELOG.md
Reviewers Checklist
All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.
Please see Pull Request Reviewer section in the contributing guide for more information on how to review a pull request.
I have...
Summary by CodeRabbit
Release Notes
New Features
TestContext
andTestEnvironment
management.QueryHelper
struct for building query clients in a testing context.Improvements
These changes primarily focus on enhancing the testing capabilities and infrastructure for the Cosmos SDK, providing more robust and flexible testing mechanisms.