1package broker
2
3import (
4 "errors"
5 "testing"
6
7 "github.com/stretchr/testify/require"
8
9 "github.com/bnema/vev/internal/ports"
10)
11
12func daemonStartTarget(mode ports.BrokerDaemonStartMode, launch string) ports.BrokerDialTarget {
13 return ports.BrokerDialTarget{StartMode: mode, Policy: ports.BrokerPolicy{Launch: launch}}
14}
15
16func requireBrokerCode(t *testing.T, err error, code ports.BrokerErrorCode) {
17 t.Helper()
18 var typed ports.BrokerError
19 require.ErrorAs(t, err, &typed)
20 require.Equal(t, code, typed.Code)
21}
22
23func TestClassifyDaemonDialFailure(t *testing.T) {
24 dialErr := errors.New("dial failed")
25 tests := []struct {
26 name string
27 mode ports.BrokerDaemonStartMode
28 dialErr error
29 absent bool
30 wantCode ports.BrokerErrorCode
31 wantSame bool // the dial error is reported unchanged
32 wantOK bool
33 }{
34 {name: "running daemon is never started", mode: ports.BrokerDaemonStartIfNeeded},
35 {name: "existing-only absence is no daemon", mode: ports.BrokerDaemonExistingOnly, dialErr: dialErr, absent: true, wantCode: ports.BrokerErrorNoDaemon},
36 {name: "existing-only other failure is unchanged", mode: ports.BrokerDaemonExistingOnly, dialErr: dialErr, wantSame: true},
37 {name: "start-if-needed non-absence is never repaired", mode: ports.BrokerDaemonStartIfNeeded, dialErr: dialErr, wantSame: true},
38 {name: "start-if-needed absence may continue", mode: ports.BrokerDaemonStartIfNeeded, dialErr: dialErr, absent: true, wantOK: true},
39 }
40 for _, tt := range tests {
41 t.Run(tt.name, func(t *testing.T) {
42 err := ClassifyDaemonDialFailure(daemonStartTarget(tt.mode, DaemonLaunchAuthority), tt.dialErr, tt.absent)
43 switch {
44 case tt.wantOK:
45 require.NoError(t, err)
46 case tt.wantSame:
47 require.Same(t, tt.dialErr, err)
48 case tt.wantCode != 0:
49 requireBrokerCode(t, err, tt.wantCode)
50 default:
51 require.Error(t, err)
52 }
53 })
54 }
55}
56
57func TestAuthorizeDaemonLaunch(t *testing.T) {
58 tests := []struct {
59 name string
60 target ports.BrokerDialTarget
61 wantOK bool
62 }{
63 {name: "start-if-needed with launch authority", target: daemonStartTarget(ports.BrokerDaemonStartIfNeeded, DaemonLaunchAuthority), wantOK: true},
64 {name: "policy without launch authority refuses", target: daemonStartTarget(ports.BrokerDaemonStartIfNeeded, "sandbox-private")},
65 {name: "unknown mode refuses", target: daemonStartTarget(ports.BrokerDaemonStartMode(99), DaemonLaunchAuthority)},
66 }
67 for _, tt := range tests {
68 t.Run(tt.name, func(t *testing.T) {
69 err := AuthorizeDaemonLaunch(tt.target)
70 if tt.wantOK {
71 require.NoError(t, err)
72 return
73 }
74 requireBrokerCode(t, err, ports.BrokerErrorConflictingPolicy)
75 })
76 }
77}
78
79func TestRequireLocalDaemonTarget(t *testing.T) {
80 require.NoError(t, RequireLocalDaemonTarget(ports.BrokerDialTarget{Fence: ports.BrokerEndpointFence{Local: true}}))
81 requireBrokerCode(t, RequireLocalDaemonTarget(ports.BrokerDialTarget{}), ports.BrokerErrorConflictingPolicy)
82}