1package daemonmux
2
3import (
4 "testing"
5
6 "github.com/stretchr/testify/require"
7
8 "github.com/bnema/vev/internal/domain"
9 "github.com/bnema/vev/internal/ports"
10 "github.com/bnema/vev/internal/protocol"
11)
12
13// TestOpenMessageCarriesAttachmentAdmission proves the request-to-open
14// conversion preserves the attachment admission variant and its creation name,
15// all the way to the wire and back.
16//
17// The session daemon admits an attachment by the variant the stream declares, so
18// a conversion that drops it delivers every attachment as "no admission" and the
19// daemon refuses it: one-shot ephemeral creation, named creation, and exact
20// attach all fail before a session is ever accepted, which is exactly how it
21// presented from a real composition.
22func TestOpenMessageCarriesAttachmentAdmission(t *testing.T) {
23 base := ports.BrokerOpenStreamRequest{
24 Epoch: 1,
25 Purpose: ports.BrokerStreamAttachment,
26 Local: true,
27 Connection: ports.BrokerConnectionID{1},
28 Stream: ports.BrokerStreamID(1),
29 Policy: logicalTestPolicy(),
30 StartMode: ports.BrokerDaemonStartIfNeeded,
31 }
32 target := protocol.ExactSessionTarget{LifecycleID: domain.SessionLifecycleID{1}, SessionName: "alpha"}
33
34 tests := []struct {
35 name string
36 request ports.BrokerOpenStreamRequest
37 admission ports.BrokerStreamAdmission
38 createAs string
39 }{
40 {
41 name: "exact attach keeps its exact target",
42 request: func() ports.BrokerOpenStreamRequest {
43 r := base
44 r.Admission = ports.BrokerAdmissionExact
45 r.Target = target
46 return r
47 }(),
48 admission: ports.BrokerAdmissionExact,
49 },
50 {
51 name: "named creation keeps its name",
52 request: func() ports.BrokerOpenStreamRequest {
53 r := base
54 r.Admission = ports.BrokerAdmissionCreateNamed
55 r.Name = "work"
56 return r
57 }(),
58 admission: ports.BrokerAdmissionCreateNamed,
59 createAs: "work",
60 },
61 {
62 name: "ephemeral creation keeps its variant",
63 request: func() ports.BrokerOpenStreamRequest {
64 r := base
65 r.Admission = ports.BrokerAdmissionCreateEphemeral
66 return r
67 }(),
68 admission: ports.BrokerAdmissionCreateEphemeral,
69 },
70 {
71 name: "named attach keeps its name",
72 request: func() ports.BrokerOpenStreamRequest {
73 r := base
74 r.Admission = ports.BrokerAdmissionAttachNamed
75 r.Name = "work"
76 return r
77 }(),
78 admission: ports.BrokerAdmissionAttachNamed,
79 createAs: "work",
80 },
81 }
82
83 for _, tc := range tests {
84 t.Run(tc.name, func(t *testing.T) {
85 open := openMessage(1, tc.request)
86 require.Equal(t, tc.admission, open.Admission)
87 require.Equal(t, tc.createAs, open.Name)
88 require.Equal(t, tc.request.Target, open.Target)
89
90 // The same values must survive the ceiling-checked wire round trip
91 // the daemon actually decodes.
92 decoded, err := DecodeClient(mustEncodeClient(t, open), testEnvelopeCeiling, testChunkCeiling)
93 require.NoError(t, err)
94 admitting, ok := decoded.(Open)
95 require.True(t, ok)
96 require.Equal(t, tc.admission, admitting.Admission)
97 require.Equal(t, tc.createAs, admitting.Name)
98 })
99 }
100}