1package daemon
2
3import (
4 "testing"
5
6 "github.com/bnema/vev/internal/domain"
7 "github.com/bnema/vev/internal/protocol"
8 "github.com/stretchr/testify/require"
9)
10
11func TestBackSessionUsesClientPreviousRouteAfterSnapshotPublication(t *testing.T) {
12 d, source, ac, _ := newManualSessionWithPTYs(t, nil)
13 transport := &closeTrackingTransport{}
14 ac.replaceTransport(transport)
15 rc := d.attachCoordinator(source, nil, ac, true)
16 token := source.captureAttachmentCapability(ac, transport)
17 token.lease = rc.attachmentLease(ac)
18 ac.installTestAttachmentCapability(token)
19 effect, admitted := ac.beginAttachmentEffect(token)
20 require.True(t, admitted)
21 defer effect.End()
22 previous := protocol.RouteRef{Key: 7, Generation: 3}
23 ac.setRouteSnapshot(protocol.RecentRouteSnapshot{
24 Generation: 5,
25 Active: protocol.RouteRef{Key: 9, Generation: 5},
26 Previous: previous,
27 Entries: []protocol.RecentRouteEntry{testRouteEntry(7, 3, "previous", 7, protocol.RouteKindLocal)},
28 })
29 ac.setRouteAttentionSubscription(protocol.RouteAttentionSubscription{
30 Targets: []protocol.RouteAttentionTarget{{Ref: previous, Target: testRouteTarget("previous", 7)}},
31 }, ac.transportSnapshot(), d.clock.Now())
32
33 require.NoError(t, d.backSessionForAttachment(effect))
34 frames := transport.Sends()
35 require.NotEmpty(t, frames)
36 var action protocol.RouteNavigationAction
37 found := false
38 for _, frame := range frames {
39 decoded, ok := decodeServerMessage(t, frame).(protocol.RouteNavigationAction)
40 if !ok {
41 continue
42 }
43 action, found = decoded, true
44 }
45 require.True(t, found)
46 require.Equal(t, protocol.RouteNavigationAction{SnapshotGeneration: 5, Key: 7, Generation: 3}, action)
47}
48
49func TestBackSessionOffersPreviousRouteOnCurrentDaemon(t *testing.T) {
50 d, source, ac, _ := newManualSessionWithPTYs(t, nil)
51 target := &session{
52 sessionCore: sessionCore{
53 id: "target", name: "target", incarnation: testRouteTarget("target", 7).LifecycleID,
54 attachments: make(map[*attachedClient]struct{}),
55 },
56 ctx: source.ctx, cancel: func() {},
57 tabs: []*tab{newTab(nil, domain.Size{Cols: 80, Rows: 23})},
58 }
59 publishTiledPaneOwners(target, target.tabs[0])
60 d.mu.Lock()
61 d.sessions[target.id] = target
62 d.mu.Unlock()
63
64 transport := &closeTrackingTransport{}
65 ac.replaceTransport(transport)
66 rc := d.attachCoordinator(source, nil, ac, true)
67 token := source.captureAttachmentCapability(ac, transport)
68 token.lease = rc.attachmentLease(ac)
69 ac.installTestAttachmentCapability(token)
70 effect, admitted := ac.beginAttachmentEffect(token)
71 require.True(t, admitted)
72 defer effect.End()
73 previous := protocol.RouteRef{Key: 7, Generation: 3}
74 exact := protocol.ExactSessionTarget{LifecycleID: target.incarnation, SessionName: target.name}
75 ac.setRouteSnapshot(protocol.RecentRouteSnapshot{
76 Generation: 5,
77 Active: protocol.RouteRef{Key: 9, Generation: 5},
78 Previous: previous,
79 Entries: []protocol.RecentRouteEntry{testRouteEntry(7, 3, target.name, 7, protocol.RouteKindRemote)},
80 })
81 ac.setRouteAttentionSubscription(protocol.RouteAttentionSubscription{
82 Targets: []protocol.RouteAttentionTarget{{Ref: previous, Target: exact}},
83 }, ac.transportSnapshot(), d.clock.Now())
84
85 require.NoError(t, d.backSessionForAttachment(effect))
86 frames := transport.Sends()
87 require.Len(t, frames, 1)
88 require.Equal(t, "AttachTarget", envelopeMessageName(t, frames[0].Payload))
89 handoff, ok := decodeServerMessage(t, frames[0]).(protocol.AttachTarget)
90 require.True(t, ok)
91 require.Equal(t, protocol.AttachTarget{
92 Session: target.name, Intent: protocol.IntentAttach, ExactTarget: &exact,
93 EnvironmentPolicy: protocol.EnvironmentPolicyDaemonOwned, SamePeer: true,
94 }, handoff)
95}