refactor(history): clarify snapshot ownership
- commit
- b23180e62994ab3b761ad9025d3271af1b115cc8
- author
- brice · · 2026-07-13 04:54 UTC
- parent
- 7913f91
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
6 files · +23 -40
M internal/usecase/copy/mode.go +2 -1
| @@ -53,7 +53,8 @@ func NewSnapshotFromRows(rows [][]renderer.Cell, width, height int) Snapshot { | |||
| 53 | 53 | // Len returns the number of document rows. | |
| 54 | 54 | func (s Snapshot) Len() int { return s.history.Len() + s.screen.Height } | |
| 55 | 55 | ||
| 56 | - | // Row returns document row i, or nil when i is out of range. | |
| 56 | + | // Row returns document row i, or nil when i is out of range. History rows | |
| 57 | + | // borrow immutable history storage and must be treated as read-only. | |
| 57 | 58 | func (s Snapshot) Row(i int) []renderer.Cell { | |
| 58 | 59 | if i < 0 { | |
| 59 | 60 | return nil | |
| @@ -53,7 +53,8 @@ func NewSnapshotFromRows(rows [][]renderer.Cell, width, height int) Snapshot { | |||||
| 53 | // Len returns the number of document rows. | 53 | // Len returns the number of document rows. | ||
| 54 | func (s Snapshot) Len() int { return s.history.Len() + s.screen.Height } | 54 | func (s Snapshot) Len() int { return s.history.Len() + s.screen.Height } | ||
| 55 | 55 | ||||
| 56 | - | // Row returns document row i, or nil when i is out of range. | 56 | + | // Row returns document row i, or nil when i is out of range. History rows |
| 57 | + | // borrow immutable history storage and must be treated as read-only. | |||
| 57 | func (s Snapshot) Row(i int) []renderer.Cell { | 58 | func (s Snapshot) Row(i int) []renderer.Cell { | ||
| 58 | if i < 0 { | 59 | if i < 0 { | ||
| 59 | return nil | 60 | return nil | ||
M internal/usecase/copy/mode_test.go +3 -3
| @@ -610,9 +610,9 @@ func BenchmarkNewSnapshot10KRows(b *testing.B) { | |||
| 610 | 610 | historyRows = 10_000 | |
| 611 | 611 | ) | |
| 612 | 612 | ||
| 613 | - | scrollback := newHistory(historyRows) | |
| 613 | + | history := newHistory(historyRows) | |
| 614 | 614 | for range historyRows { | |
| 615 | - | scrollback.Append(row(strings.Repeat("x", width))) | |
| 615 | + | history.Append(row(strings.Repeat("x", width))) | |
| 616 | 616 | } | |
| 617 | 617 | screen := renderer.NewFrame(width, height) | |
| 618 | 618 | for y := range height { | |
| @@ -622,7 +622,7 @@ func BenchmarkNewSnapshot10KRows(b *testing.B) { | |||
| 622 | 622 | b.ReportAllocs() | |
| 623 | 623 | b.ResetTimer() | |
| 624 | 624 | for b.Loop() { | |
| 625 | - | benchmarkSnapshotSink = NewSnapshot(scrollback, screen) | |
| 625 | + | benchmarkSnapshotSink = NewSnapshot(history, screen) | |
| 626 | 626 | } | |
| 627 | 627 | } | |
| 628 | 628 | ||
| @@ -610,9 +610,9 @@ func BenchmarkNewSnapshot10KRows(b *testing.B) { | |||||
| 610 | historyRows = 10_000 | 610 | historyRows = 10_000 | ||
| 611 | ) | 611 | ) | ||
| 612 | 612 | ||||
| 613 | - | scrollback := newHistory(historyRows) | 613 | + | history := newHistory(historyRows) |
| 614 | for range historyRows { | 614 | for range historyRows { | ||
| 615 | - | scrollback.Append(row(strings.Repeat("x", width))) | 615 | + | history.Append(row(strings.Repeat("x", width))) |
| 616 | } | 616 | } | ||
| 617 | screen := renderer.NewFrame(width, height) | 617 | screen := renderer.NewFrame(width, height) | ||
| 618 | for y := range height { | 618 | for y := range height { | ||
| @@ -622,7 +622,7 @@ func BenchmarkNewSnapshot10KRows(b *testing.B) { | |||||
| 622 | b.ReportAllocs() | 622 | b.ReportAllocs() | ||
| 623 | b.ResetTimer() | 623 | b.ResetTimer() | ||
| 624 | for b.Loop() { | 624 | for b.Loop() { | ||
| 625 | - | benchmarkSnapshotSink = NewSnapshot(scrollback, screen) | 625 | + | benchmarkSnapshotSink = NewSnapshot(history, screen) |
| 626 | } | 626 | } | ||
| 627 | } | 627 | } | ||
| 628 | 628 | ||||
M internal/usecase/daemon/daemon.go +1 -1
| @@ -373,7 +373,7 @@ func (d *Daemon) Serve(ctx context.Context, l ports.Listener) error { | |||
| 373 | 373 | }) | |
| 374 | 374 | } | |
| 375 | 375 | if d.snapsEnabled { | |
| 376 | - | d.startSnapshotEncodeWorker(d.serveCtx) | |
| 376 | + | d.startSnapshotEncodeWorker() | |
| 377 | 377 | d.sessWg.Go(func() { | |
| 378 | 378 | d.snapshotSaver(d.serveCtx) | |
| 379 | 379 | }) | |
| @@ -373,7 +373,7 @@ func (d *Daemon) Serve(ctx context.Context, l ports.Listener) error { | |||||
| 373 | }) | 373 | }) | ||
| 374 | } | 374 | } | ||
| 375 | if d.snapsEnabled { | 375 | if d.snapsEnabled { | ||
| 376 | - | d.startSnapshotEncodeWorker(d.serveCtx) | 376 | + | d.startSnapshotEncodeWorker() |
| 377 | d.sessWg.Go(func() { | 377 | d.sessWg.Go(func() { | ||
| 378 | d.snapshotSaver(d.serveCtx) | 378 | d.snapshotSaver(d.serveCtx) | ||
| 379 | }) | 379 | }) | ||
M internal/usecase/daemon/performance_benchmark_test.go +2 -7
| @@ -1,7 +1,6 @@ | |||
| 1 | 1 | package daemon | |
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | - | "context" | |
| 5 | 4 | "fmt" | |
| 6 | 5 | "io" | |
| 7 | 6 | "runtime" | |
| @@ -736,12 +735,8 @@ func newPerformanceFixture(t testing.TB, config performanceConfig) *performanceF | |||
| 736 | 735 | resizeSizes: [2]domain.Size{{Cols: 100, Rows: 30}, config.size}, | |
| 737 | 736 | } | |
| 738 | 737 | WithSnapshotStore(fixture.snaps)(d) | |
| 739 | - | snapshotCtx, cancelSnapshotWorker := context.WithCancel(context.Background()) | |
| 740 | - | d.startSnapshotEncodeWorker(snapshotCtx) | |
| 741 | - | t.Cleanup(func() { | |
| 742 | - | cancelSnapshotWorker() | |
| 743 | - | d.stopSnapshotEncodeWorker() | |
| 744 | - | }) | |
| 738 | + | d.startSnapshotEncodeWorker() | |
| 739 | + | t.Cleanup(d.stopSnapshotEncodeWorker) | |
| 745 | 740 | for tabIndex, tb := range sess.tabs { | |
| 746 | 741 | fixture.configureTab(tb, tabIndex, config.panes, config.historyRows, tabSize(config.size)) | |
| 747 | 742 | } | |
| @@ -1,7 +1,6 @@ | |||||
| 1 | package daemon | 1 | package daemon | ||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | - | "context" | |||
| 5 | "fmt" | 4 | "fmt" | ||
| 6 | "io" | 5 | "io" | ||
| 7 | "runtime" | 6 | "runtime" | ||
| @@ -736,12 +735,8 @@ func newPerformanceFixture(t testing.TB, config performanceConfig) *performanceF | |||||
| 736 | resizeSizes: [2]domain.Size{{Cols: 100, Rows: 30}, config.size}, | 735 | resizeSizes: [2]domain.Size{{Cols: 100, Rows: 30}, config.size}, | ||
| 737 | } | 736 | } | ||
| 738 | WithSnapshotStore(fixture.snaps)(d) | 737 | WithSnapshotStore(fixture.snaps)(d) | ||
| 739 | - | snapshotCtx, cancelSnapshotWorker := context.WithCancel(context.Background()) | 738 | + | d.startSnapshotEncodeWorker() |
| 740 | - | d.startSnapshotEncodeWorker(snapshotCtx) | 739 | + | t.Cleanup(d.stopSnapshotEncodeWorker) |
| 741 | - | t.Cleanup(func() { | |||
| 742 | - | cancelSnapshotWorker() | |||
| 743 | - | d.stopSnapshotEncodeWorker() | |||
| 744 | - | }) | |||
| 745 | for tabIndex, tb := range sess.tabs { | 740 | for tabIndex, tb := range sess.tabs { | ||
| 746 | fixture.configureTab(tb, tabIndex, config.panes, config.historyRows, tabSize(config.size)) | 741 | fixture.configureTab(tb, tabIndex, config.panes, config.historyRows, tabSize(config.size)) | ||
| 747 | } | 742 | } | ||
M internal/usecase/daemon/snapshot.go +2 -2
| @@ -504,8 +504,8 @@ func (d *Daemon) finishSnapshotCapture(capture *snapshotCapture, succeeded bool) | |||
| 504 | 504 | }) | |
| 505 | 505 | } | |
| 506 | 506 | ||
| 507 | - | func (d *Daemon) startSnapshotEncodeWorker(ctx context.Context) { | |
| 508 | - | if d == nil || ctx.Err() != nil { | |
| 507 | + | func (d *Daemon) startSnapshotEncodeWorker() { | |
| 508 | + | if d == nil { | |
| 509 | 509 | return | |
| 510 | 510 | } | |
| 511 | 511 | d.snapshotWorkerMu.Lock() | |
| @@ -504,8 +504,8 @@ func (d *Daemon) finishSnapshotCapture(capture *snapshotCapture, succeeded bool) | |||||
| 504 | }) | 504 | }) | ||
| 505 | } | 505 | } | ||
| 506 | 506 | ||||
| 507 | - | func (d *Daemon) startSnapshotEncodeWorker(ctx context.Context) { | 507 | + | func (d *Daemon) startSnapshotEncodeWorker() { |
| 508 | - | if d == nil || ctx.Err() != nil { | 508 | + | if d == nil { |
| 509 | return | 509 | return | ||
| 510 | } | 510 | } | ||
| 511 | d.snapshotWorkerMu.Lock() | 511 | d.snapshotWorkerMu.Lock() | ||
M internal/usecase/daemon/snapshot_test.go +13 -26
| @@ -25,12 +25,8 @@ func TestSnapshotEncodeWorkerDefersMarshalUntilAfterCapture(t *testing.T) { | |||
| 25 | 25 | store := &channelSnapshotStore{writes: make(chan []byte, 1)} | |
| 26 | 26 | d := newTestDaemon(t, portsmocks.NewMockPTYFactory(t), stubClock{}) | |
| 27 | 27 | WithSnapshotStore(store)(d) | |
| 28 | - | ctx, cancel := context.WithCancel(t.Context()) | |
| 29 | - | t.Cleanup(func() { | |
| 30 | - | cancel() | |
| 31 | - | d.stopSnapshotEncodeWorker() | |
| 32 | - | }) | |
| 33 | - | d.startSnapshotEncodeWorker(ctx) | |
| 28 | + | t.Cleanup(d.stopSnapshotEncodeWorker) | |
| 29 | + | d.startSnapshotEncodeWorker() | |
| 34 | 30 | ||
| 35 | 31 | entered := make(chan struct{}) | |
| 36 | 32 | release := make(chan struct{}) | |
| @@ -72,11 +68,9 @@ func exerciseBlockedSnapshotWorker(t *testing.T, blockEncode bool) { | |||
| 72 | 68 | store := newGatedSnapshotStore() | |
| 73 | 69 | d := newTestDaemon(t, portsmocks.NewMockPTYFactory(t), stubClock{}) | |
| 74 | 70 | WithSnapshotStore(store)(d) | |
| 75 | - | ctx, cancel := context.WithCancel(t.Context()) | |
| 76 | - | d.startSnapshotEncodeWorker(ctx) | |
| 71 | + | d.startSnapshotEncodeWorker() | |
| 77 | 72 | t.Cleanup(func() { | |
| 78 | 73 | store.unblock() | |
| 79 | - | cancel() | |
| 80 | 74 | d.stopSnapshotEncodeWorker() | |
| 81 | 75 | }) | |
| 82 | 76 | if blockEncode { | |
| @@ -157,9 +151,7 @@ func TestFinalSnapshotFlushPersistsNewestNamedSessionBeforeWorkerTeardown(t *tes | |||
| 157 | 151 | store := &channelSnapshotStore{writes: make(chan []byte, 1)} | |
| 158 | 152 | d := newTestDaemon(t, portsmocks.NewMockPTYFactory(t), clock) | |
| 159 | 153 | WithSnapshotStore(store)(d) | |
| 160 | - | ctx, cancel := context.WithCancel(t.Context()) | |
| 161 | - | defer cancel() | |
| 162 | - | d.startSnapshotEncodeWorker(ctx) | |
| 154 | + | d.startSnapshotEncodeWorker() | |
| 163 | 155 | ||
| 164 | 156 | entered := make(chan struct{}) | |
| 165 | 157 | release := make(chan struct{}) | |
| @@ -169,7 +161,8 @@ func TestFinalSnapshotFlushPersistsNewestNamedSessionBeforeWorkerTeardown(t *tes | |||
| 169 | 161 | return snapcodec.Marshal(s) | |
| 170 | 162 | } | |
| 171 | 163 | sess := newSnapshotTestSession(t, "final", false, "/work") | |
| 172 | - | pty := sess.tabs[0].panes["pane-1"].pty.(*portsmocks.MockPTY) | |
| 164 | + | pty, ok := sess.tabs[0].panes["pane-1"].pty.(*portsmocks.MockPTY) | |
| 165 | + | require.True(t, ok) | |
| 173 | 166 | pty.EXPECT().Close().Return(nil).Once() | |
| 174 | 167 | sess.tabs[0].panes["pane-1"].screen.Write([]byte("\rnewest")) | |
| 175 | 168 | d.sessions[sess.id] = sess | |
| @@ -202,9 +195,7 @@ func TestStopSnapshotEncodeWorkerDoesNotWaitForUncancellableWrite(t *testing.T) | |||
| 202 | 195 | clock := newFinalFlushClock() | |
| 203 | 196 | d := newTestDaemon(t, portsmocks.NewMockPTYFactory(t), clock) | |
| 204 | 197 | WithSnapshotStore(store)(d) | |
| 205 | - | ctx, cancel := context.WithCancel(t.Context()) | |
| 206 | - | defer cancel() | |
| 207 | - | d.startSnapshotEncodeWorker(ctx) | |
| 198 | + | d.startSnapshotEncodeWorker() | |
| 208 | 199 | ||
| 209 | 200 | sess := newSnapshotTestSession(t, "stuck-write", false, "/work") | |
| 210 | 201 | require.True(t, d.captureSession(sess)) | |
| @@ -240,10 +231,8 @@ func TestStoppedSnapshotWorkerLeavesCaptureRetryable(t *testing.T) { | |||
| 240 | 231 | store := &channelSnapshotStore{writes: make(chan []byte, 1)} | |
| 241 | 232 | d := newTestDaemon(t, portsmocks.NewMockPTYFactory(t), stubClock{}) | |
| 242 | 233 | WithSnapshotStore(store)(d) | |
| 243 | - | ctx, cancel := context.WithCancel(t.Context()) | |
| 244 | - | d.startSnapshotEncodeWorker(ctx) | |
| 234 | + | d.startSnapshotEncodeWorker() | |
| 245 | 235 | d.stopSnapshotEncodeWorker() | |
| 246 | - | t.Cleanup(cancel) | |
| 247 | 236 | ||
| 248 | 237 | sess := newSnapshotTestSession(t, "stopped", false, "/work") | |
| 249 | 238 | markSnapshotDirty(sess) | |
| @@ -326,7 +315,9 @@ func TestNamedFinalSnapshotSurvivesSaturatedQueue(t *testing.T) { | |||
| 326 | 315 | first := newSnapshotTestSession(t, "first", false, "/work") | |
| 327 | 316 | second := newSnapshotTestSession(t, "second", false, "/work") | |
| 328 | 317 | final := newSnapshotTestSession(t, "final", false, "/work") | |
| 329 | - | final.tabs[0].panes["pane-1"].pty.(*portsmocks.MockPTY).EXPECT().Close().Return(nil).Once() | |
| 318 | + | finalPTY, ok := final.tabs[0].panes["pane-1"].pty.(*portsmocks.MockPTY) | |
| 319 | + | require.True(t, ok) | |
| 320 | + | finalPTY.EXPECT().Close().Return(nil).Once() | |
| 330 | 321 | markSnapshotDirty(first) | |
| 331 | 322 | markSnapshotDirty(second) | |
| 332 | 323 | require.True(t, d.scheduleSnapshot(first)) | |
| @@ -915,12 +906,8 @@ func awaitSnapshotClean(t *testing.T, sess *session) { | |||
| 915 | 906 | ||
| 916 | 907 | func startSnapshotEncodeWorker(t *testing.T, d *Daemon) { | |
| 917 | 908 | t.Helper() | |
| 918 | - | ctx, cancel := context.WithCancel(t.Context()) | |
| 919 | - | d.startSnapshotEncodeWorker(ctx) | |
| 920 | - | t.Cleanup(func() { | |
| 921 | - | cancel() | |
| 922 | - | d.stopSnapshotEncodeWorker() | |
| 923 | - | }) | |
| 909 | + | d.startSnapshotEncodeWorker() | |
| 910 | + | t.Cleanup(d.stopSnapshotEncodeWorker) | |
| 924 | 911 | } | |
| 925 | 912 | ||
| 926 | 913 | type gatedSnapshotStore struct { | |
| @@ -25,12 +25,8 @@ func TestSnapshotEncodeWorkerDefersMarshalUntilAfterCapture(t *testing.T) { | |||||
| 25 | store := &channelSnapshotStore{writes: make(chan []byte, 1)} | 25 | store := &channelSnapshotStore{writes: make(chan []byte, 1)} | ||
| 26 | d := newTestDaemon(t, portsmocks.NewMockPTYFactory(t), stubClock{}) | 26 | d := newTestDaemon(t, portsmocks.NewMockPTYFactory(t), stubClock{}) | ||
| 27 | WithSnapshotStore(store)(d) | 27 | WithSnapshotStore(store)(d) | ||
| 28 | - | ctx, cancel := context.WithCancel(t.Context()) | 28 | + | t.Cleanup(d.stopSnapshotEncodeWorker) |
| 29 | - | t.Cleanup(func() { | 29 | + | d.startSnapshotEncodeWorker() |
| 30 | - | cancel() | |||
| 31 | - | d.stopSnapshotEncodeWorker() | |||
| 32 | - | }) | |||
| 33 | - | d.startSnapshotEncodeWorker(ctx) | |||
| 34 | 30 | ||||
| 35 | entered := make(chan struct{}) | 31 | entered := make(chan struct{}) | ||
| 36 | release := make(chan struct{}) | 32 | release := make(chan struct{}) | ||
| @@ -72,11 +68,9 @@ func exerciseBlockedSnapshotWorker(t *testing.T, blockEncode bool) { | |||||
| 72 | store := newGatedSnapshotStore() | 68 | store := newGatedSnapshotStore() | ||
| 73 | d := newTestDaemon(t, portsmocks.NewMockPTYFactory(t), stubClock{}) | 69 | d := newTestDaemon(t, portsmocks.NewMockPTYFactory(t), stubClock{}) | ||
| 74 | WithSnapshotStore(store)(d) | 70 | WithSnapshotStore(store)(d) | ||
| 75 | - | ctx, cancel := context.WithCancel(t.Context()) | 71 | + | d.startSnapshotEncodeWorker() |
| 76 | - | d.startSnapshotEncodeWorker(ctx) | |||
| 77 | t.Cleanup(func() { | 72 | t.Cleanup(func() { | ||
| 78 | store.unblock() | 73 | store.unblock() | ||
| 79 | - | cancel() | |||
| 80 | d.stopSnapshotEncodeWorker() | 74 | d.stopSnapshotEncodeWorker() | ||
| 81 | }) | 75 | }) | ||
| 82 | if blockEncode { | 76 | if blockEncode { | ||
| @@ -157,9 +151,7 @@ func TestFinalSnapshotFlushPersistsNewestNamedSessionBeforeWorkerTeardown(t *tes | |||||
| 157 | store := &channelSnapshotStore{writes: make(chan []byte, 1)} | 151 | store := &channelSnapshotStore{writes: make(chan []byte, 1)} | ||
| 158 | d := newTestDaemon(t, portsmocks.NewMockPTYFactory(t), clock) | 152 | d := newTestDaemon(t, portsmocks.NewMockPTYFactory(t), clock) | ||
| 159 | WithSnapshotStore(store)(d) | 153 | WithSnapshotStore(store)(d) | ||
| 160 | - | ctx, cancel := context.WithCancel(t.Context()) | 154 | + | d.startSnapshotEncodeWorker() |
| 161 | - | defer cancel() | |||
| 162 | - | d.startSnapshotEncodeWorker(ctx) | |||
| 163 | 155 | ||||
| 164 | entered := make(chan struct{}) | 156 | entered := make(chan struct{}) | ||
| 165 | release := make(chan struct{}) | 157 | release := make(chan struct{}) | ||
| @@ -169,7 +161,8 @@ func TestFinalSnapshotFlushPersistsNewestNamedSessionBeforeWorkerTeardown(t *tes | |||||
| 169 | return snapcodec.Marshal(s) | 161 | return snapcodec.Marshal(s) | ||
| 170 | } | 162 | } | ||
| 171 | sess := newSnapshotTestSession(t, "final", false, "/work") | 163 | sess := newSnapshotTestSession(t, "final", false, "/work") | ||
| 172 | - | pty := sess.tabs[0].panes["pane-1"].pty.(*portsmocks.MockPTY) | 164 | + | pty, ok := sess.tabs[0].panes["pane-1"].pty.(*portsmocks.MockPTY) |
| 165 | + | require.True(t, ok) | |||
| 173 | pty.EXPECT().Close().Return(nil).Once() | 166 | pty.EXPECT().Close().Return(nil).Once() | ||
| 174 | sess.tabs[0].panes["pane-1"].screen.Write([]byte("\rnewest")) | 167 | sess.tabs[0].panes["pane-1"].screen.Write([]byte("\rnewest")) | ||
| 175 | d.sessions[sess.id] = sess | 168 | d.sessions[sess.id] = sess | ||
| @@ -202,9 +195,7 @@ func TestStopSnapshotEncodeWorkerDoesNotWaitForUncancellableWrite(t *testing.T) | |||||
| 202 | clock := newFinalFlushClock() | 195 | clock := newFinalFlushClock() | ||
| 203 | d := newTestDaemon(t, portsmocks.NewMockPTYFactory(t), clock) | 196 | d := newTestDaemon(t, portsmocks.NewMockPTYFactory(t), clock) | ||
| 204 | WithSnapshotStore(store)(d) | 197 | WithSnapshotStore(store)(d) | ||
| 205 | - | ctx, cancel := context.WithCancel(t.Context()) | 198 | + | d.startSnapshotEncodeWorker() |
| 206 | - | defer cancel() | |||
| 207 | - | d.startSnapshotEncodeWorker(ctx) | |||
| 208 | 199 | ||||
| 209 | sess := newSnapshotTestSession(t, "stuck-write", false, "/work") | 200 | sess := newSnapshotTestSession(t, "stuck-write", false, "/work") | ||
| 210 | require.True(t, d.captureSession(sess)) | 201 | require.True(t, d.captureSession(sess)) | ||
| @@ -240,10 +231,8 @@ func TestStoppedSnapshotWorkerLeavesCaptureRetryable(t *testing.T) { | |||||
| 240 | store := &channelSnapshotStore{writes: make(chan []byte, 1)} | 231 | store := &channelSnapshotStore{writes: make(chan []byte, 1)} | ||
| 241 | d := newTestDaemon(t, portsmocks.NewMockPTYFactory(t), stubClock{}) | 232 | d := newTestDaemon(t, portsmocks.NewMockPTYFactory(t), stubClock{}) | ||
| 242 | WithSnapshotStore(store)(d) | 233 | WithSnapshotStore(store)(d) | ||
| 243 | - | ctx, cancel := context.WithCancel(t.Context()) | 234 | + | d.startSnapshotEncodeWorker() |
| 244 | - | d.startSnapshotEncodeWorker(ctx) | |||
| 245 | d.stopSnapshotEncodeWorker() | 235 | d.stopSnapshotEncodeWorker() | ||
| 246 | - | t.Cleanup(cancel) | |||
| 247 | 236 | ||||
| 248 | sess := newSnapshotTestSession(t, "stopped", false, "/work") | 237 | sess := newSnapshotTestSession(t, "stopped", false, "/work") | ||
| 249 | markSnapshotDirty(sess) | 238 | markSnapshotDirty(sess) | ||
| @@ -326,7 +315,9 @@ func TestNamedFinalSnapshotSurvivesSaturatedQueue(t *testing.T) { | |||||
| 326 | first := newSnapshotTestSession(t, "first", false, "/work") | 315 | first := newSnapshotTestSession(t, "first", false, "/work") | ||
| 327 | second := newSnapshotTestSession(t, "second", false, "/work") | 316 | second := newSnapshotTestSession(t, "second", false, "/work") | ||
| 328 | final := newSnapshotTestSession(t, "final", false, "/work") | 317 | final := newSnapshotTestSession(t, "final", false, "/work") | ||
| 329 | - | final.tabs[0].panes["pane-1"].pty.(*portsmocks.MockPTY).EXPECT().Close().Return(nil).Once() | 318 | + | finalPTY, ok := final.tabs[0].panes["pane-1"].pty.(*portsmocks.MockPTY) |
| 319 | + | require.True(t, ok) | |||
| 320 | + | finalPTY.EXPECT().Close().Return(nil).Once() | |||
| 330 | markSnapshotDirty(first) | 321 | markSnapshotDirty(first) | ||
| 331 | markSnapshotDirty(second) | 322 | markSnapshotDirty(second) | ||
| 332 | require.True(t, d.scheduleSnapshot(first)) | 323 | require.True(t, d.scheduleSnapshot(first)) | ||
| @@ -915,12 +906,8 @@ func awaitSnapshotClean(t *testing.T, sess *session) { | |||||
| 915 | 906 | ||||
| 916 | func startSnapshotEncodeWorker(t *testing.T, d *Daemon) { | 907 | func startSnapshotEncodeWorker(t *testing.T, d *Daemon) { | ||
| 917 | t.Helper() | 908 | t.Helper() | ||
| 918 | - | ctx, cancel := context.WithCancel(t.Context()) | 909 | + | d.startSnapshotEncodeWorker() |
| 919 | - | d.startSnapshotEncodeWorker(ctx) | 910 | + | t.Cleanup(d.stopSnapshotEncodeWorker) |
| 920 | - | t.Cleanup(func() { | |||
| 921 | - | cancel() | |||
| 922 | - | d.stopSnapshotEncodeWorker() | |||
| 923 | - | }) | |||
| 924 | } | 911 | } | ||
| 925 | 912 | ||||
| 926 | type gatedSnapshotStore struct { | 913 | type gatedSnapshotStore struct { | ||