test(remote): cover picker incarnation fence
- commit
- 01e78fbb7987944775ebe720cbc589c9cfc3165a
- author
- brice · · 2026-07-31 21:26 UTC
- parent
- 7dbc84a
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
1 file · +24 -0
M internal/usecase/daemon/proxy_input_test.go +24 -0
| @@ -747,6 +747,30 @@ func TestRemotePickerRejectsReplacedLocalLifecycle(t *testing.T) { | |||
| 747 | 747 | require.Same(t, proxy, ac.currentAttachmentSession(), "stale picker lifecycle must not redirect the attachment") | |
| 748 | 748 | } | |
| 749 | 749 | ||
| 750 | + | func TestRemotePickerRejectsReplacedLocalIncarnation(t *testing.T) { | |
| 751 | + | d, proxy, ac, _, handler := newProxyInputHarness(t) | |
| 752 | + | tb := newTab(newQuietPTY(), domain.Size{Cols: 80, Rows: 22}) | |
| 753 | + | tb.stableID = "local-tab" | |
| 754 | + | local := &session{sessionCore: sessionCore{id: "local", name: "local", ephemeral: true, incarnation: domain.IncarnationID{1}}, tabs: []*tab{tb}} | |
| 755 | + | publishTiledPaneOwners(local, tb) | |
| 756 | + | d.mu.Lock() | |
| 757 | + | require.True(t, d.registerSessionLocked(local)) | |
| 758 | + | d.mu.Unlock() | |
| 759 | + | ||
| 760 | + | model := d.newPickerModel(proxy, pickerNavigate, moveSourceLocator{}, picker.SourceFilter{Session: local.id, Incarnation: local.incarnation, TabID: domain.TabStableID(tb.stableID)}) | |
| 761 | + | target, selectable := model.Selected() | |
| 762 | + | require.True(t, selectable) | |
| 763 | + | d.afterRoleEffectsFrozen = func() { | |
| 764 | + | d.afterRoleEffectsFrozen = nil | |
| 765 | + | local.mu.Lock() | |
| 766 | + | local.incarnation = domain.IncarnationID{2} | |
| 767 | + | local.mu.Unlock() | |
| 768 | + | } | |
| 769 | + | ||
| 770 | + | require.Error(t, d.switchToTargetForRole(handler.roleToken, target, sessionHandoffGuard{}, "picker-select")) | |
| 771 | + | require.Same(t, proxy, ac.currentAttachmentSession(), "stale picker incarnation must not redirect the attachment") | |
| 772 | + | } | |
| 773 | + | ||
| 750 | 774 | func TestRemotePickerRejectsReplacedLocalTab(t *testing.T) { | |
| 751 | 775 | d, proxy, ac, _, handler := newProxyInputHarness(t) | |
| 752 | 776 | first := newTab(newQuietPTY(), domain.Size{Cols: 80, Rows: 22}) | |
| @@ -747,6 +747,30 @@ func TestRemotePickerRejectsReplacedLocalLifecycle(t *testing.T) { | |||||
| 747 | require.Same(t, proxy, ac.currentAttachmentSession(), "stale picker lifecycle must not redirect the attachment") | 747 | require.Same(t, proxy, ac.currentAttachmentSession(), "stale picker lifecycle must not redirect the attachment") | ||
| 748 | } | 748 | } | ||
| 749 | 749 | ||||
| 750 | + | func TestRemotePickerRejectsReplacedLocalIncarnation(t *testing.T) { | |||
| 751 | + | d, proxy, ac, _, handler := newProxyInputHarness(t) | |||
| 752 | + | tb := newTab(newQuietPTY(), domain.Size{Cols: 80, Rows: 22}) | |||
| 753 | + | tb.stableID = "local-tab" | |||
| 754 | + | local := &session{sessionCore: sessionCore{id: "local", name: "local", ephemeral: true, incarnation: domain.IncarnationID{1}}, tabs: []*tab{tb}} | |||
| 755 | + | publishTiledPaneOwners(local, tb) | |||
| 756 | + | d.mu.Lock() | |||
| 757 | + | require.True(t, d.registerSessionLocked(local)) | |||
| 758 | + | d.mu.Unlock() | |||
| 759 | + | ||||
| 760 | + | model := d.newPickerModel(proxy, pickerNavigate, moveSourceLocator{}, picker.SourceFilter{Session: local.id, Incarnation: local.incarnation, TabID: domain.TabStableID(tb.stableID)}) | |||
| 761 | + | target, selectable := model.Selected() | |||
| 762 | + | require.True(t, selectable) | |||
| 763 | + | d.afterRoleEffectsFrozen = func() { | |||
| 764 | + | d.afterRoleEffectsFrozen = nil | |||
| 765 | + | local.mu.Lock() | |||
| 766 | + | local.incarnation = domain.IncarnationID{2} | |||
| 767 | + | local.mu.Unlock() | |||
| 768 | + | } | |||
| 769 | + | ||||
| 770 | + | require.Error(t, d.switchToTargetForRole(handler.roleToken, target, sessionHandoffGuard{}, "picker-select")) | |||
| 771 | + | require.Same(t, proxy, ac.currentAttachmentSession(), "stale picker incarnation must not redirect the attachment") | |||
| 772 | + | } | |||
| 773 | + | ||||
| 750 | func TestRemotePickerRejectsReplacedLocalTab(t *testing.T) { | 774 | func TestRemotePickerRejectsReplacedLocalTab(t *testing.T) { | ||
| 751 | d, proxy, ac, _, handler := newProxyInputHarness(t) | 775 | d, proxy, ac, _, handler := newProxyInputHarness(t) | ||
| 752 | first := newTab(newQuietPTY(), domain.Size{Cols: 80, Rows: 22}) | 776 | first := newTab(newQuietPTY(), domain.Size{Cols: 80, Rows: 22}) | ||