refactor: replace context.WithCancel with t.Context#3284
refactor: replace context.WithCancel with t.Context#3284julienrbrt merged 1 commit intoevstack:mainfrom
Conversation
Signed-off-by: purelualight <purelualight@outlook.com>
📝 WalkthroughWalkthroughTests in the submitter module are refactored to use Go's built-in test context ( Changes
Possibly related PRs
Poem
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
block/internal/submitting/submitter_test.go (2)
450-450: Good use of t.Context() for test lifecycle integration.The change to use
t.Context()correctly aligns with the PR objectives and improves test robustness by ensuring the context is automatically cancelled when the test completes.However, consider using
t.Cleanup()to ensureStop()is always called, even if the test fails or panics before line 529. This pattern is already used inTestSubmitter_daSubmissionLoopat line 396.🛡️ Recommended: Add t.Cleanup for guaranteed Stop() execution
func TestSubmitter_CacheClearedOnHeightInclusion(t *testing.T) { ctx := t.Context() cm, st := newTestCacheAndStore(t) cfg := config.DefaultConfig() cfg.DA.BlockTime.Duration = 5 * time.Millisecond metrics := common.NopMetrics() exec := testmocks.NewMockExecutor(t) exec.On("SetFinal", mock.Anything, uint64(1)).Return(nil).Once() exec.On("SetFinal", mock.Anything, uint64(2)).Return(nil).Once() daClient := testmocks.NewMockClient(t) daClient.On("GetHeaderNamespace").Return([]byte(cfg.DA.Namespace)).Maybe() daClient.On("GetDataNamespace").Return([]byte(cfg.DA.DataNamespace)).Maybe() daClient.On("GetForcedInclusionNamespace").Return([]byte(nil)).Maybe() daClient.On("HasForcedInclusionNamespace").Return(false).Maybe() daSub := NewDASubmitter(daClient, cfg, genesis.Genesis{}, common.BlockOptions{}, metrics, zerolog.Nop(), nil, nil) s := NewSubmitter(st, exec, cm, metrics, cfg, genesis.Genesis{}, daSub, nil, nil, zerolog.Nop(), nil) // Create test blocks h1, d1 := newHeaderAndData("chain", 1, true) h2, d2 := newHeaderAndData("chain", 2, true) h3, d3 := newHeaderAndData("chain", 3, true) sig := types.Signature([]byte("sig")) // Save blocks to store blocks := []struct { header *types.SignedHeader data *types.Data height uint64 }{ {h1, d1, 1}, {h2, d2, 2}, {h3, d3, 3}, } for _, block := range blocks { batch, err := st.NewBatch(ctx) require.NoError(t, err) require.NoError(t, batch.SaveBlockData(block.header, block.data, &sig)) require.NoError(t, batch.SetHeight(block.height)) require.NoError(t, batch.Commit()) } // Set up cache with headers and data seen for all heights cm.SetHeaderSeen(h1.Hash().String(), 1) cm.SetDataSeen(d1.DACommitment().String(), 1) cm.SetHeaderSeen(h2.Hash().String(), 2) cm.SetDataSeen(d2.DACommitment().String(), 2) cm.SetHeaderSeen(h3.Hash().String(), 3) cm.SetDataSeen(d3.DACommitment().String(), 3) // Verify items are seen in cache before processing assert.True(t, cm.IsHeaderSeen(h1.Hash().String())) assert.True(t, cm.IsDataSeen(d1.DACommitment().String())) assert.True(t, cm.IsHeaderSeen(h2.Hash().String())) assert.True(t, cm.IsDataSeen(d2.DACommitment().String())) assert.True(t, cm.IsHeaderSeen(h3.Hash().String())) assert.True(t, cm.IsDataSeen(d3.DACommitment().String())) // Set DA inclusion for heights 1 and 2 only (height 3 will remain unprocessed) cm.SetHeaderDAIncluded(h1.Hash().String(), 100, 1) cm.SetDataDAIncluded(d1.DACommitment().String(), 100, 1) cm.SetHeaderDAIncluded(h2.Hash().String(), 101, 2) cm.SetDataDAIncluded(d2.DACommitment().String(), 101, 2) require.NoError(t, s.initializeDAIncludedHeight(ctx)) require.Equal(t, uint64(0), s.GetDAIncludedHeight()) // Start submitter to process DA inclusions require.NoError(t, s.Start(ctx)) + t.Cleanup(func() { _ = s.Stop() }) // Wait for heights 1 and 2 to be processed require.Eventually(t, func() bool { return s.GetDAIncludedHeight() == 2 }, 1*time.Second, 10*time.Millisecond) - require.NoError(t, s.Stop())As per coding guidelines: Be mindful of goroutine leaks in Go code.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@block/internal/submitting/submitter_test.go` at line 450, Add a t.Cleanup registration to guarantee Stop() is invoked even on test failure: after you create the submitter instance (the variable used in this test, e.g., s) and before the test can fail, call t.Cleanup to schedule s.Stop() so the submitter is always stopped; follow the same pattern used in TestSubmitter_daSubmissionLoop to place the t.Cleanup call immediately after submitter setup and before starting goroutines or long-running operations.
238-238: Good use of t.Context() for test lifecycle integration.The change to use
t.Context()correctly aligns with the PR objectives and improves test robustness by ensuring the context is automatically cancelled when the test completes.However, consider using
t.Cleanup()to ensureStop()is always called, even if the test fails or panics before line 300. This pattern is already used inTestSubmitter_daSubmissionLoopat line 396.🛡️ Recommended: Add t.Cleanup for guaranteed Stop() execution
func TestSubmitter_processDAInclusionLoop_advances(t *testing.T) { ctx := t.Context() // Clean up any existing visualization server defer server.SetDAVisualizationServer(nil) server.SetDAVisualizationServer(nil) cm, st := newTestCacheAndStore(t) // small block time to tick quickly cfg := config.DefaultConfig() cfg.DA.BlockTime.Duration = 5 * time.Millisecond cfg.RPC.EnableDAVisualization = false // Ensure visualization is disabled metrics := common.PrometheusMetrics("test") exec := testmocks.NewMockExecutor(t) exec.On("SetFinal", mock.Anything, uint64(1)).Return(nil).Once() exec.On("SetFinal", mock.Anything, uint64(2)).Return(nil).Once() daClient := testmocks.NewMockClient(t) daClient.On("GetHeaderNamespace").Return([]byte(cfg.DA.Namespace)).Maybe() daClient.On("GetDataNamespace").Return([]byte(cfg.DA.DataNamespace)).Maybe() daClient.On("GetForcedInclusionNamespace").Return([]byte(nil)).Maybe() daClient.On("HasForcedInclusionNamespace").Return(false).Maybe() daSub := NewDASubmitter(daClient, cfg, genesis.Genesis{}, common.BlockOptions{}, metrics, zerolog.Nop(), nil, nil) s := NewSubmitter(st, exec, cm, metrics, cfg, genesis.Genesis{}, daSub, nil, nil, zerolog.Nop(), nil) // prepare two consecutive blocks in store with DA included in cache h1, d1 := newHeaderAndData("chain", 1, true) h2, d2 := newHeaderAndData("chain", 2, true) require.NotEqual(t, h1.Hash(), h2.Hash()) require.NotEqual(t, d1.DACommitment(), d2.DACommitment()) sig := types.Signature([]byte("sig")) // Save block 1 batch1, err := st.NewBatch(ctx) require.NoError(t, err) require.NoError(t, batch1.SaveBlockData(h1, d1, &sig)) require.NoError(t, batch1.SetHeight(1)) require.NoError(t, batch1.Commit()) // Save block 2 batch2, err := st.NewBatch(ctx) require.NoError(t, err) require.NoError(t, batch2.SaveBlockData(h2, d2, &sig)) require.NoError(t, batch2.SetHeight(2)) require.NoError(t, batch2.Commit()) cm.SetHeaderDAIncluded(h1.Hash().String(), 100, 1) cm.SetDataDAIncluded(d1.DACommitment().String(), 100, 1) cm.SetHeaderDAIncluded(h2.Hash().String(), 101, 2) cm.SetDataDAIncluded(d2.DACommitment().String(), 101, 2) require.NoError(t, s.initializeDAIncludedHeight(ctx)) require.Equal(t, uint64(0), s.GetDAIncludedHeight()) // when require.NoError(t, s.Start(ctx)) + t.Cleanup(func() { _ = s.Stop() }) require.Eventually(t, func() bool { return s.GetDAIncludedHeight() == 2 }, 1*time.Second, 10*time.Millisecond) - require.NoError(t, s.Stop())As per coding guidelines: Be mindful of goroutine leaks in Go code.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@block/internal/submitting/submitter_test.go` at line 238, The test currently uses ctx := t.Context() but does not guarantee submitter Stop() runs on failure; register a t.Cleanup to always call s.Stop() (or the appropriate teardown method) after the submitter is created so Stop() is invoked even on panic/failure—locate the submitter instance (e.g., variable s in the test) and add t.Cleanup(func(){ s.Stop() }) similar to the pattern used in TestSubmitter_daSubmissionLoop to prevent goroutine leaks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@block/internal/submitting/submitter_test.go`:
- Line 450: Add a t.Cleanup registration to guarantee Stop() is invoked even on
test failure: after you create the submitter instance (the variable used in this
test, e.g., s) and before the test can fail, call t.Cleanup to schedule s.Stop()
so the submitter is always stopped; follow the same pattern used in
TestSubmitter_daSubmissionLoop to place the t.Cleanup call immediately after
submitter setup and before starting goroutines or long-running operations.
- Line 238: The test currently uses ctx := t.Context() but does not guarantee
submitter Stop() runs on failure; register a t.Cleanup to always call s.Stop()
(or the appropriate teardown method) after the submitter is created so Stop() is
invoked even on panic/failure—locate the submitter instance (e.g., variable s in
the test) and add t.Cleanup(func(){ s.Stop() }) similar to the pattern used in
TestSubmitter_daSubmissionLoop to prevent goroutine leaks.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 8093ac73-6447-46b1-b41b-874c1b4914f5
📒 Files selected for processing (1)
block/internal/submitting/submitter_test.go
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3284 +/- ##
==========================================
+ Coverage 61.84% 62.61% +0.77%
==========================================
Files 122 122
Lines 16241 13029 -3212
==========================================
- Hits 10044 8158 -1886
+ Misses 5312 3985 -1327
- Partials 885 886 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Overview
Inspired by #3183 and replace all of the case.
The addition of the Context method to Go's testing.T provides significant improvements for writing concurrent tests. It allows better management of goroutines, ensuring they properly exit and preventing issues like deadlocks and unfinished processes.
More info: golang/go#18368
Summary by CodeRabbit