main ece7682

binding_test.go RawHistoryFolder

1package daemonmux
2
3import (
4	"testing"
5
6	"github.com/stretchr/testify/require"
7
8	"github.com/bnema/vev/internal/ports"
9	"github.com/bnema/vev/internal/protocol"
10)
11
12// TestServerBindingValidatesAndExposesAuthority proves the immutable binding
13// rejects every invalid field once, at construction, and exposes exactly the
14// validated authority through its accessors.
15func TestServerBindingValidatesAndExposesAuthority(t *testing.T) {
16	binding, err := NewServerBinding(testIdentity(), testIncarnation(), testPolicy())
17	require.NoError(t, err)
18	require.NoError(t, binding.Validate())
19	require.Equal(t, testIdentity(), binding.Identity())
20	require.Equal(t, testIncarnation(), binding.Incarnation())
21	require.Equal(t, testPolicy(), binding.Policy())
22}
23
24// TestServerBindingRefusesInvalidAuthority proves an empty identity, a zero
25// incarnation, and every invalid policy shape are refused with the binding's
26// single sentinel.
27func TestServerBindingRefusesInvalidAuthority(t *testing.T) {
28	invalidPolicy := testPolicy()
29	invalidPolicy.ProtocolVersion = 0
30
31	tests := []struct {
32		name        string
33		identity    ports.BrokerDaemonIdentity
34		incarnation ports.BrokerDaemonIncarnation
35		policy      ports.BrokerPolicy
36	}{
37		{name: "empty identity", identity: "", incarnation: testIncarnation(), policy: testPolicy()},
38		{name: "zero incarnation", identity: testIdentity(), incarnation: ports.BrokerDaemonIncarnation{}, policy: testPolicy()},
39		{name: "zero policy", identity: testIdentity(), incarnation: testIncarnation(), policy: ports.BrokerPolicy{}},
40		{name: "policy without protocol version", identity: testIdentity(), incarnation: testIncarnation(), policy: invalidPolicy},
41	}
42	for _, test := range tests {
43		t.Run(test.name, func(t *testing.T) {
44			_, err := NewServerBinding(test.identity, test.incarnation, test.policy)
45			require.ErrorIs(t, err, ErrInvalidBinding)
46		})
47	}
48}
49
50// TestServerBindingAcceptsOnlyExactPolicy proves the binding accepts the exact
51// policy and refuses a request differing in a single field.
52func TestServerBindingAcceptsOnlyExactPolicy(t *testing.T) {
53	binding, err := NewServerBinding(testIdentity(), testIncarnation(), testPolicy())
54	require.NoError(t, err)
55	require.True(t, binding.Accepts(testPolicy()))
56
57	tests := []struct {
58		name   string
59		mutate func(*ports.BrokerPolicy)
60	}{
61		{name: "protocol version", mutate: func(p *ports.BrokerPolicy) { p.ProtocolVersion++ }},
62		{name: "catalogue schema version", mutate: func(p *ports.BrokerPolicy) { p.CatalogSchemaVersion++ }},
63		{name: "environment policy", mutate: func(p *ports.BrokerPolicy) {
64			p.EnvironmentPolicy = protocol.EnvironmentPolicyClientOwned
65		}},
66		{name: "transport", mutate: func(p *ports.BrokerPolicy) { p.Transport = "stdio" }},
67		{name: "trust", mutate: func(p *ports.BrokerPolicy) { p.Trust = "tofu" }},
68		{name: "launch", mutate: func(p *ports.BrokerPolicy) { p.Launch = "manual" }},
69		{name: "isolation", mutate: func(p *ports.BrokerPolicy) { p.Isolation = "system" }},
70	}
71	for _, test := range tests {
72		t.Run(test.name, func(t *testing.T) {
73			requested := testPolicy()
74			test.mutate(&requested)
75			require.False(t, binding.Accepts(requested))
76		})
77	}
78}
79
80// TestServerBindingIsImmutable proves the binding copied its inputs at
81// construction: mutating the caller's local policy afterwards never changes
82// what the binding enforces.
83func TestServerBindingIsImmutable(t *testing.T) {
84	local := testPolicy()
85	binding, err := NewServerBinding(testIdentity(), testIncarnation(), local)
86	require.NoError(t, err)
87
88	local.Transport = "mutated"
89	local.Trust = "mutated"
90	require.Equal(t, testPolicy(), binding.Policy())
91	require.True(t, binding.Accepts(testPolicy()))
92}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close