1package ports
2
3import (
4 "errors"
5 "strings"
6 "testing"
7
8 "github.com/bnema/vev/internal/domain"
9 "github.com/stretchr/testify/require"
10)
11
12func TestBrokerPolicyTokens(t *testing.T) {
13 for _, field := range []string{"trust", "launch", "isolation"} {
14 for _, value := range []string{"", "bad token", "\xff", "bad\u202e", strings.Repeat("x", BrokerMaxPolicyTokenBytes+1), strings.Repeat("x", BrokerMaxPolicyTokenBytes)} {
15 t.Run(field+"/"+value, func(t *testing.T) {
16 p := testBrokerPolicy()
17 switch field {
18 case "trust":
19 p.Trust = value
20 case "launch":
21 p.Launch = value
22 case "isolation":
23 p.Isolation = value
24 }
25 err := p.Validate()
26 if len(value) == BrokerMaxPolicyTokenBytes {
27 require.NoError(t, err)
28 } else {
29 require.ErrorContains(t, err, "policy "+field)
30 }
31 })
32 }
33 }
34}
35
36func TestBrokerDialTargetValidation(t *testing.T) {
37 for _, tc := range []struct {
38 name, address string
39 valid bool
40 }{
41 {"valid", "route", true}, {"bound", strings.Repeat("x", BrokerMaxAddressBytes), true},
42 {"empty", "", false}, {"over", strings.Repeat("x", BrokerMaxAddressBytes+1), false},
43 {"utf8", "\xff", false}, {"control", "route\n", false},
44 } {
45 t.Run(tc.name, func(t *testing.T) {
46 target := BrokerDialTarget{Fence: BrokerEndpointFence{Local: true}, Policy: testBrokerPolicy(), Address: tc.address, StartMode: BrokerDaemonExistingOnly, ExpectedIdentity: BrokerExpectedIdentity{Identity: "daemon", Bound: true}}
47 require.Equal(t, tc.valid, target.Validate() == nil)
48 })
49 }
50 target := BrokerDialTarget{Fence: BrokerEndpointFence{Local: true}, Policy: testBrokerPolicy(), Address: "route", StartMode: BrokerDaemonExistingOnly, ExpectedIdentity: BrokerExpectedIdentity{Identity: "daemon", Bound: true}}
51 target.ExpectedIdentity.Identity = ""
52 require.Error(t, target.Validate())
53 target.ExpectedIdentity.Identity = "daemon"
54 target.Policy.Trust = ""
55 require.Error(t, target.Validate())
56}
57
58func TestBrokerStreamLostErrorChain(t *testing.T) {
59 cause := errors.New("transport diagnostic")
60 loss := BrokerStreamLost{Epoch: 1, Connection: BrokerConnectionID{1}, Stream: 1, Cause: domain.RemoteFailureTrust, Err: cause}
61 require.NoError(t, loss.Validate())
62 require.Equal(t, "broker attachment_lost", loss.Error())
63 require.ErrorIs(t, loss, cause)
64 var typed BrokerError
65 require.ErrorAs(t, loss, &typed)
66 require.Equal(t, BrokerErrorAttachmentLost, typed.Code)
67 loss.Cause = domain.RemoteFailureNone
68 require.Error(t, loss.Validate())
69 loss.Cause = 99
70 require.Error(t, loss.Validate())
71}
72
73func TestBrokerRequestLocalRemoteFencing(t *testing.T) {
74 for _, tc := range []struct {
75 name string
76 mutate func(*BrokerOpenStreamRequest)
77 valid bool
78 }{
79 {"local", func(*BrokerOpenStreamRequest) {}, true},
80 {"local endpoint", func(r *BrokerOpenStreamRequest) { r.Endpoint = "user@host" }, false},
81 {"local registration", func(r *BrokerOpenStreamRequest) { r.Registration = testBrokerRegistration("user@host", 1, 1) }, false},
82 {"remote missing", func(r *BrokerOpenStreamRequest) { r.Local = false }, false},
83 {"remote valid", func(r *BrokerOpenStreamRequest) {
84 r.Local = false
85 r.Endpoint = "user@host"
86 r.Registration = testBrokerRegistration(r.Endpoint, 1, 1)
87 }, true},
88 {"remote mismatch", func(r *BrokerOpenStreamRequest) {
89 r.Local = false
90 r.Endpoint = "user@other"
91 r.Registration = testBrokerRegistration("user@host", 1, 1)
92 }, false},
93 } {
94 t.Run(tc.name, func(t *testing.T) {
95 r := BrokerOpenStreamRequest{Epoch: 1, Connection: BrokerConnectionID{1}, Stream: 1, Local: true, Purpose: BrokerStreamControl, Policy: testBrokerPolicy(), StartMode: BrokerDaemonStartIfNeeded}
96 tc.mutate(&r)
97 require.Equal(t, tc.valid, r.Validate() == nil)
98 })
99 }
100}