test(routes): cover exact local handoffs
- commit
- 4be85cc9fd0732689d780eaca25d2676273852e4
- author
- brice · · 2026-08-11 08:15 UTC
- parent
- 9db7f4b
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +44 -0
M internal/ports/wire_final_test.go +23 -0
| @@ -211,6 +211,29 @@ func TestFinalAttachTargetGoldenStrict(t *testing.T) { | |||
| 211 | 211 | } | |
| 212 | 212 | } | |
| 213 | 213 | ||
| 214 | + | func TestAttachTargetExactTargetWireStrict(t *testing.T) { | |
| 215 | + | var lifecycle domain.SessionLifecycleID | |
| 216 | + | lifecycle[0] = 1 | |
| 217 | + | target := AttachTarget{Session: "work", Intent: IntentAttach, ExactTarget: &ExactSessionTarget{LifecycleID: lifecycle, SessionName: "work"}} | |
| 218 | + | payload := MarshalAttachTarget(target) | |
| 219 | + | want := append([]byte{0, 0, 0, 4, 'w', 'o', 'r', 'k', IntentAttach, 0, 0, 1, 1}, make([]byte, 15)...) | |
| 220 | + | want = append(want, 0, 4, 'w', 'o', 'r', 'k') | |
| 221 | + | if !bytes.Equal(payload, want) { | |
| 222 | + | t.Fatalf("exact target bytes = %x, want %x", payload, want) | |
| 223 | + | } | |
| 224 | + | back, err := UnmarshalAttachTarget(payload) | |
| 225 | + | if err != nil || !reflect.DeepEqual(back, target) { | |
| 226 | + | t.Fatalf("exact target = %+v, error %v, want %+v", back, err, target) | |
| 227 | + | } | |
| 228 | + | assertAllPrefixesFail(t, payload, UnmarshalAttachTarget) | |
| 229 | + | assertTrailingGarbageFails(t, payload, UnmarshalAttachTarget) | |
| 230 | + | mismatched := target | |
| 231 | + | mismatched.ExactTarget = &ExactSessionTarget{LifecycleID: lifecycle, SessionName: "other"} | |
| 232 | + | if got := MarshalAttachTarget(mismatched); got != nil { | |
| 233 | + | t.Fatalf("MarshalAttachTarget accepted mismatched target: %x", got) | |
| 234 | + | } | |
| 235 | + | } | |
| 236 | + | ||
| 214 | 237 | func TestFinalClosedWireValuesRejectUnknownEnumsAndBooleans(t *testing.T) { | |
| 215 | 238 | tests := []struct { | |
| 216 | 239 | name string | |
| @@ -211,6 +211,29 @@ func TestFinalAttachTargetGoldenStrict(t *testing.T) { | |||||
| 211 | } | 211 | } | ||
| 212 | } | 212 | } | ||
| 213 | 213 | ||||
| 214 | + | func TestAttachTargetExactTargetWireStrict(t *testing.T) { | |||
| 215 | + | var lifecycle domain.SessionLifecycleID | |||
| 216 | + | lifecycle[0] = 1 | |||
| 217 | + | target := AttachTarget{Session: "work", Intent: IntentAttach, ExactTarget: &ExactSessionTarget{LifecycleID: lifecycle, SessionName: "work"}} | |||
| 218 | + | payload := MarshalAttachTarget(target) | |||
| 219 | + | want := append([]byte{0, 0, 0, 4, 'w', 'o', 'r', 'k', IntentAttach, 0, 0, 1, 1}, make([]byte, 15)...) | |||
| 220 | + | want = append(want, 0, 4, 'w', 'o', 'r', 'k') | |||
| 221 | + | if !bytes.Equal(payload, want) { | |||
| 222 | + | t.Fatalf("exact target bytes = %x, want %x", payload, want) | |||
| 223 | + | } | |||
| 224 | + | back, err := UnmarshalAttachTarget(payload) | |||
| 225 | + | if err != nil || !reflect.DeepEqual(back, target) { | |||
| 226 | + | t.Fatalf("exact target = %+v, error %v, want %+v", back, err, target) | |||
| 227 | + | } | |||
| 228 | + | assertAllPrefixesFail(t, payload, UnmarshalAttachTarget) | |||
| 229 | + | assertTrailingGarbageFails(t, payload, UnmarshalAttachTarget) | |||
| 230 | + | mismatched := target | |||
| 231 | + | mismatched.ExactTarget = &ExactSessionTarget{LifecycleID: lifecycle, SessionName: "other"} | |||
| 232 | + | if got := MarshalAttachTarget(mismatched); got != nil { | |||
| 233 | + | t.Fatalf("MarshalAttachTarget accepted mismatched target: %x", got) | |||
| 234 | + | } | |||
| 235 | + | } | |||
| 236 | + | ||||
| 214 | func TestFinalClosedWireValuesRejectUnknownEnumsAndBooleans(t *testing.T) { | 237 | func TestFinalClosedWireValuesRejectUnknownEnumsAndBooleans(t *testing.T) { | ||
| 215 | tests := []struct { | 238 | tests := []struct { | ||
| 216 | name string | 239 | name string | ||
M internal/usecase/daemon/remote_attach_test.go +21 -0
| @@ -17,6 +17,27 @@ func remoteLifecycleForTest() domain.SessionLifecycleID { | |||
| 17 | 17 | return id | |
| 18 | 18 | } | |
| 19 | 19 | ||
| 20 | + | func TestLocalPickerHandoffCarriesExactLifecycle(t *testing.T) { | |
| 21 | + | d := newRemotePickerDaemon(nil) | |
| 22 | + | source, ac, sends := addRemoteRefreshPickerOwner(t, d, "source") | |
| 23 | + | target, _, _ := addRemoteRefreshPickerOwner(t, d, "target") | |
| 24 | + | target.incarnation = remoteLifecycleForTest() | |
| 25 | + | token := source.attachmentToken(ac, ac.transport()) | |
| 26 | + | effect, admitted := ac.beginAttachmentEffect(token) | |
| 27 | + | require.True(t, admitted) | |
| 28 | + | token.effect = effect | |
| 29 | + | defer effect.End() | |
| 30 | + | ||
| 31 | + | require.NoError(t, d.sendLocalAttachTargetForAttachment(token, picker.Target{Session: target.id}, sessionHandoffGuard{}, "picker-select")) | |
| 32 | + | frame := receiveRemotePicker(t, sends, "local attach target") | |
| 33 | + | got, err := ports.UnmarshalAttachTarget(frame.Payload) | |
| 34 | + | require.NoError(t, err) | |
| 35 | + | require.Empty(t, got.Endpoint) | |
| 36 | + | require.Equal(t, ports.IntentAttach, got.Intent) | |
| 37 | + | require.Equal(t, &ports.ExactSessionTarget{LifecycleID: target.incarnation, SessionName: target.name}, got.ExactTarget) | |
| 38 | + | require.Nil(t, ac.currentAttachmentSession()) | |
| 39 | + | } | |
| 40 | + | ||
| 20 | 41 | func TestRemotePickerRichHandoffCarriesLifecycleTabAndPolicy(t *testing.T) { | |
| 21 | 42 | d := newRemotePickerDaemon(nil) | |
| 22 | 43 | lifecycle := remoteLifecycleForTest() | |
| @@ -17,6 +17,27 @@ func remoteLifecycleForTest() domain.SessionLifecycleID { | |||||
| 17 | return id | 17 | return id | ||
| 18 | } | 18 | } | ||
| 19 | 19 | ||||
| 20 | + | func TestLocalPickerHandoffCarriesExactLifecycle(t *testing.T) { | |||
| 21 | + | d := newRemotePickerDaemon(nil) | |||
| 22 | + | source, ac, sends := addRemoteRefreshPickerOwner(t, d, "source") | |||
| 23 | + | target, _, _ := addRemoteRefreshPickerOwner(t, d, "target") | |||
| 24 | + | target.incarnation = remoteLifecycleForTest() | |||
| 25 | + | token := source.attachmentToken(ac, ac.transport()) | |||
| 26 | + | effect, admitted := ac.beginAttachmentEffect(token) | |||
| 27 | + | require.True(t, admitted) | |||
| 28 | + | token.effect = effect | |||
| 29 | + | defer effect.End() | |||
| 30 | + | ||||
| 31 | + | require.NoError(t, d.sendLocalAttachTargetForAttachment(token, picker.Target{Session: target.id}, sessionHandoffGuard{}, "picker-select")) | |||
| 32 | + | frame := receiveRemotePicker(t, sends, "local attach target") | |||
| 33 | + | got, err := ports.UnmarshalAttachTarget(frame.Payload) | |||
| 34 | + | require.NoError(t, err) | |||
| 35 | + | require.Empty(t, got.Endpoint) | |||
| 36 | + | require.Equal(t, ports.IntentAttach, got.Intent) | |||
| 37 | + | require.Equal(t, &ports.ExactSessionTarget{LifecycleID: target.incarnation, SessionName: target.name}, got.ExactTarget) | |||
| 38 | + | require.Nil(t, ac.currentAttachmentSession()) | |||
| 39 | + | } | |||
| 40 | + | ||||
| 20 | func TestRemotePickerRichHandoffCarriesLifecycleTabAndPolicy(t *testing.T) { | 41 | func TestRemotePickerRichHandoffCarriesLifecycleTabAndPolicy(t *testing.T) { | ||
| 21 | d := newRemotePickerDaemon(nil) | 42 | d := newRemotePickerDaemon(nil) | ||
| 22 | lifecycle := remoteLifecycleForTest() | 43 | lifecycle := remoteLifecycleForTest() | ||