detached f7c33a7

test(app): run broker client tests against the production layout

commit
f7c33a77d7519b17383c799b123043b88c18c383
author
brice · · 2026-09-23 15:16 UTC
parent
52bb3d7
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +28 -79
M internal/app/broker_offline_client_test.go +22 -74
@@ -19,9 +19,9 @@ import (
1919 "github.com/coder/websocket"
2020 "github.com/stretchr/testify/require"
2121
22- "github.com/bnema/vev/internal/adapters/brokerconfig"
2322 "github.com/bnema/vev/internal/adapters/brokeripc"
2423 "github.com/bnema/vev/internal/adapters/clock"
24+ "github.com/bnema/vev/internal/adapters/daemonidentity"
2525 "github.com/bnema/vev/internal/adapters/daemonmux"
2626 "github.com/bnema/vev/internal/adapters/ipc"
2727 "github.com/bnema/vev/internal/adapters/pty"
@@ -30,6 +30,7 @@ import (
3030 "github.com/bnema/vev/internal/adapters/webterm"
3131 "github.com/bnema/vev/internal/domain"
3232 "github.com/bnema/vev/internal/persist"
33+ "github.com/bnema/vev/internal/platform"
3334 "github.com/bnema/vev/internal/ports"
3435 "github.com/bnema/vev/internal/protocol"
3536 "github.com/bnema/vev/internal/usecase/daemon"
@@ -55,13 +56,13 @@ type offlineClientFixture struct {
5556
5657 func startOfflineClientFixture(t *testing.T) offlineClientFixture {
5758 t.Helper()
58- // The default sandbox shell prints one marker and then parks on read, so a
59+ // The default isolated production fixture shell prints one marker and then parks on read, so a
5960 // client proves it reached a session without depending on shell echo of
6061 // injected input.
6162 return startOfflineClientFixtureWithShell(t, "/bin/sh", []string{"-c", "sleep 0.1; printf offline-ready; trap : TERM; while :; do read line || exit; done"})
6263 }
6364
64-// startOfflineClientFixtureWithShell starts the same private broker sandbox with
65+// startOfflineClientFixtureWithShell starts the same isolated production broker with
6566 // an explicitly supplied daemon shell, so a browser test can drive real session
6667 // content and real session actions (echo and command output) through the
6768 // ordinary client path instead of a parked shell.
@@ -70,38 +71,29 @@ func startOfflineClientFixtureWithShell(t *testing.T, shell string, shellArgs []
7071 return startPersistentOfflineClientFixture(t, shell, shellArgs, false)
7172 }
7273
73-// startPersistentOfflineClientFixture starts the same private broker sandbox but
74-// additionally binds the daemon to real session persistence under the sandbox
74+// startPersistentOfflineClientFixture starts the same isolated production broker but
75+// additionally binds the daemon to real session persistence under the production daemon
7576 // state directory. It exists so a test can prove which lifecycle state the
7677 // daemon actually persists: a named session appears in the durable catalogue,
7778 // while an ephemeral one is never written.
7879 func startPersistentOfflineClientFixture(t *testing.T, shell string, shellArgs []string, persistEnabled bool) offlineClientFixture {
7980 t.Helper()
80- root, prodRuntime, prodState := isolateSandboxEnv(t)
81- require.NoError(t, os.MkdirAll(root, 0o700))
82- route := filepath.Join(root, "local-mux.sock")
83- policy := brokerTestPolicy()
84- writeSandboxConfig(t, root, map[string]any{
85- "marker": brokerconfig.Marker, "registrations": []any{},
86- "local": map[string]any{
87- "identity": brokerLocalTestIdentity, "displayOrigin": "local", "route": route,
88- "policy": map[string]any{"protocolVersion": policy.ProtocolVersion, "catalogSchemaVersion": policy.CatalogSchemaVersion, "environmentPolicy": "client-owned", "transport": policy.Transport, "trust": policy.Trust, "launch": policy.Launch, "isolation": policy.Isolation},
89- },
90- })
91- layout, err := offlineLayout(root)
81+ layout := emptyProductionBrokerLayout(t, "")
82+ root := layout.Root
83+ prodRuntime, prodState := os.Getenv("XDG_RUNTIME_DIR"), os.Getenv("XDG_STATE_HOME")
84+ identity, err := daemonidentity.LoadOrCreate(platform.StateDir())
9285 require.NoError(t, err)
93- for _, dir := range []string{layout.Root, layout.Runtime, layout.State, layout.Log} {
94- require.NoError(t, safedir.EnsurePrivate(dir))
95- }
96- require.NoError(t, layout.VerifyCreated())
97-
86+ require.NoError(t, ensureProductionBrokerConfig())
87+ route := daemonmux.SocketPath(ipc.SocketDir())
88+ policy := localDaemonPolicy()
89+ require.NoError(t, safedir.EnsurePrivate(ipc.SocketDir()))
9890 rawListener, err := ipc.ListenMux(route)
9991 require.NoError(t, err)
10092 physicalSeen := make(chan struct{}, 8)
10193 var physicalMu sync.Mutex
10294 var physicalConnections []io.Closer
10395 aggregate := daemonmux.NewAggregateListener()
104- binding, err := daemonmux.NewServerBinding(brokerLocalTestIdentity, ports.BrokerDaemonIncarnation{1}, policy)
96+ binding, err := daemonmux.NewServerBinding(identity, ports.BrokerDaemonIncarnation{1}, policy)
10597 require.NoError(t, err)
10698 mux, err := daemonmux.NewServerSupervisor(aggregate, binding, daemonmux.DefaultMuxCeilings(), 8)
10799 require.NoError(t, err)
@@ -127,7 +119,7 @@ func startPersistentOfflineClientFixture(t *testing.T, shell string, shellArgs [
127119 daemonOpts := []daemon.Option{daemon.WithShell(shell, shellArgs)}
128120 var fixtureCatalogue *persist.Persister
129121 if persistEnabled {
130- stateDir := filepath.Join(root, "state")
122+ stateDir := platform.StateDir()
131123 opened, err := persist.OpenOrCreate(stateDir)
132124 require.NoError(t, err)
133125 repository := snapshot.NewRepository(filepath.Join(stateDir, "snapshots"))
@@ -146,16 +138,16 @@ func startPersistentOfflineClientFixture(t *testing.T, shell string, shellArgs [
146138 // a manual clock rooted at Unix zero would correctly make the observation
147139 // stale to the real client clock before initial navigation resolves.
148140 deps, ready := testBrokerServeDeps(clock.New())
149- brokerDone := runSandbox(ctx, brokerServeOptions{offlineRoot: root, idleGrace: time.Hour}, deps)
141+ brokerDone := runSandbox(ctx, brokerServeOptions{production: true, idleGrace: time.Hour}, deps)
150142 var socket string
151143 select {
152144 case socket = <-ready:
153145 case serveErr := <-brokerDone:
154- t.Fatalf("offline broker exited before readiness: %v", serveErr)
146+ t.Fatalf("production broker exited before readiness: %v", serveErr)
155147 case <-time.After(brokerTestWait):
156- t.Fatal("offline broker did not become ready")
148+ t.Fatal("production broker did not become ready")
157149 }
158- // The sandbox broker becomes socket-ready before its first local daemon
150+ // The production broker becomes socket-ready before its first local daemon
159151 // observation is committed. Product clients start from a committed local
160152 // authority; wait for the fixture to provide the same contract so one-shot
161153 // initial navigation is not consumed against an artificial empty catalogue.
@@ -174,7 +166,7 @@ func startPersistentOfflineClientFixture(t *testing.T, shell string, shellArgs [
174166 default:
175167 }
176168 return false
177- }, brokerTestWait, 5*time.Millisecond, "offline broker never committed its local daemon authority")
169+ }, brokerTestWait, 5*time.Millisecond, "production broker never committed its local daemon authority")
178170 subscription.Close()
179171 require.NoError(t, probe.Close())
180172 t.Cleanup(func() {
@@ -185,9 +177,8 @@ func startPersistentOfflineClientFixture(t *testing.T, shell string, shellArgs [
185177 select {
186178 case <-brokerDone:
187179 case <-time.After(brokerTestWait):
188- t.Error("offline broker did not stop")
180+ t.Error("production broker did not stop")
189181 }
190- requireProductionUntouched(t, prodRuntime, prodState)
191182 })
192183 losePhysical := func() {
193184 physicalMu.Lock()
@@ -261,49 +252,6 @@ func awaitUITerminalMarker(t *testing.T, terminal *uiterm.Terminal, marker strin
261252 }
262253 }
263254
264-func TestParseBrokerClientArgsAndProductionDispatchIsolation(t *testing.T) {
265- parsed, err := parseArgs([]string{brokerClientCommand, "--offline-root", "/tmp/offline", "--harness", offlineClientUIDriver})
266- require.NoError(t, err)
267- require.Equal(t, kindBrokerClient, parsed.kind)
268- require.Equal(t, connectivityLocalOnly, mustConnectivityOwner(t, "kindBrokerClient"))
269-
270- ordinary := []struct {
271- args []string
272- kind cmdKind
273- }{{nil, kindAttach}, {[]string{"list"}, kindList}, {[]string{"--ui-driver"}, kindUIDriver}, {[]string{"--web-daemon"}, kindWebDaemon}}
274- for _, test := range ordinary {
275- command, parseErr := parseArgs(test.args)
276- require.NoError(t, parseErr)
277- require.Equal(t, test.kind, command.kind)
278- require.NotEqual(t, kindBrokerClient, command.kind)
279- }
280-
281- rejections := []struct {
282- name string
283- args []string
284- }{
285- {name: "missing root", args: []string{brokerClientCommand}},
286- {name: "missing root value", args: []string{brokerClientCommand, "--offline-root"}},
287- {name: "duplicate root", args: []string{brokerClientCommand, "--offline-root", "/tmp/a", "--offline-root", "/tmp/b"}},
288- {name: "unknown flag", args: []string{brokerClientCommand, "--offline-root", "/tmp/a", "--unknown"}},
289- {name: "positional", args: []string{brokerClientCommand, "--offline-root", "/tmp/a", "extra"}},
290- {name: "bad harness", args: []string{brokerClientCommand, "--offline-root", "/tmp/a", "--harness", "other"}},
291- }
292- for _, test := range rejections {
293- t.Run(test.name, func(t *testing.T) {
294- _, parseErr := parseArgs(test.args)
295- require.Error(t, parseErr)
296- })
297- }
298-}
299-
300-func mustConnectivityOwner(t *testing.T, kind string) connectivityOwner {
301- t.Helper()
302- owner, ok := testConnectivityOwnerFor(kind)
303- require.True(t, ok)
304- return owner
305-}
306-
307255 // TestOfflineEphemeralSessionIsNotPersistedViaBroker proves the daemon-owned
308256 // broker fixture persists a named session but never an ephemeral one: the
309257 // durable catalogue holds exactly the named record after both lifecycles, so
@@ -19,9 +19,9 @@ import (
19 "github.com/coder/websocket"19 "github.com/coder/websocket"
20 "github.com/stretchr/testify/require"20 "github.com/stretchr/testify/require"
21 21
22- "github.com/bnema/vev/internal/adapters/brokerconfig"
23 "github.com/bnema/vev/internal/adapters/brokeripc"22 "github.com/bnema/vev/internal/adapters/brokeripc"
24 "github.com/bnema/vev/internal/adapters/clock"23 "github.com/bnema/vev/internal/adapters/clock"
24+ "github.com/bnema/vev/internal/adapters/daemonidentity"
25 "github.com/bnema/vev/internal/adapters/daemonmux"25 "github.com/bnema/vev/internal/adapters/daemonmux"
26 "github.com/bnema/vev/internal/adapters/ipc"26 "github.com/bnema/vev/internal/adapters/ipc"
27 "github.com/bnema/vev/internal/adapters/pty"27 "github.com/bnema/vev/internal/adapters/pty"
@@ -30,6 +30,7 @@ import (
30 "github.com/bnema/vev/internal/adapters/webterm"30 "github.com/bnema/vev/internal/adapters/webterm"
31 "github.com/bnema/vev/internal/domain"31 "github.com/bnema/vev/internal/domain"
32 "github.com/bnema/vev/internal/persist"32 "github.com/bnema/vev/internal/persist"
33+ "github.com/bnema/vev/internal/platform"
33 "github.com/bnema/vev/internal/ports"34 "github.com/bnema/vev/internal/ports"
34 "github.com/bnema/vev/internal/protocol"35 "github.com/bnema/vev/internal/protocol"
35 "github.com/bnema/vev/internal/usecase/daemon"36 "github.com/bnema/vev/internal/usecase/daemon"
@@ -55,13 +56,13 @@ type offlineClientFixture struct {
55 56
56 func startOfflineClientFixture(t *testing.T) offlineClientFixture {57 func startOfflineClientFixture(t *testing.T) offlineClientFixture {
57 t.Helper()58 t.Helper()
58- // The default sandbox shell prints one marker and then parks on read, so a59+ // The default isolated production fixture shell prints one marker and then parks on read, so a
59 // client proves it reached a session without depending on shell echo of60 // client proves it reached a session without depending on shell echo of
60 // injected input.61 // injected input.
61 return startOfflineClientFixtureWithShell(t, "/bin/sh", []string{"-c", "sleep 0.1; printf offline-ready; trap : TERM; while :; do read line || exit; done"})62 return startOfflineClientFixtureWithShell(t, "/bin/sh", []string{"-c", "sleep 0.1; printf offline-ready; trap : TERM; while :; do read line || exit; done"})
62 }63 }
63 64
64-// startOfflineClientFixtureWithShell starts the same private broker sandbox with65+// startOfflineClientFixtureWithShell starts the same isolated production broker with
65 // an explicitly supplied daemon shell, so a browser test can drive real session66 // an explicitly supplied daemon shell, so a browser test can drive real session
66 // content and real session actions (echo and command output) through the67 // content and real session actions (echo and command output) through the
67 // ordinary client path instead of a parked shell.68 // ordinary client path instead of a parked shell.
@@ -70,38 +71,29 @@ func startOfflineClientFixtureWithShell(t *testing.T, shell string, shellArgs []
70 return startPersistentOfflineClientFixture(t, shell, shellArgs, false)71 return startPersistentOfflineClientFixture(t, shell, shellArgs, false)
71 }72 }
72 73
73-// startPersistentOfflineClientFixture starts the same private broker sandbox but74+// startPersistentOfflineClientFixture starts the same isolated production broker but
74-// additionally binds the daemon to real session persistence under the sandbox75+// additionally binds the daemon to real session persistence under the production daemon
75 // state directory. It exists so a test can prove which lifecycle state the76 // state directory. It exists so a test can prove which lifecycle state the
76 // daemon actually persists: a named session appears in the durable catalogue,77 // daemon actually persists: a named session appears in the durable catalogue,
77 // while an ephemeral one is never written.78 // while an ephemeral one is never written.
78 func startPersistentOfflineClientFixture(t *testing.T, shell string, shellArgs []string, persistEnabled bool) offlineClientFixture {79 func startPersistentOfflineClientFixture(t *testing.T, shell string, shellArgs []string, persistEnabled bool) offlineClientFixture {
79 t.Helper()80 t.Helper()
80- root, prodRuntime, prodState := isolateSandboxEnv(t)81+ layout := emptyProductionBrokerLayout(t, "")
81- require.NoError(t, os.MkdirAll(root, 0o700))82+ root := layout.Root
82- route := filepath.Join(root, "local-mux.sock")83+ prodRuntime, prodState := os.Getenv("XDG_RUNTIME_DIR"), os.Getenv("XDG_STATE_HOME")
83- policy := brokerTestPolicy()84+ identity, err := daemonidentity.LoadOrCreate(platform.StateDir())
84- writeSandboxConfig(t, root, map[string]any{
85- "marker": brokerconfig.Marker, "registrations": []any{},
86- "local": map[string]any{
87- "identity": brokerLocalTestIdentity, "displayOrigin": "local", "route": route,
88- "policy": map[string]any{"protocolVersion": policy.ProtocolVersion, "catalogSchemaVersion": policy.CatalogSchemaVersion, "environmentPolicy": "client-owned", "transport": policy.Transport, "trust": policy.Trust, "launch": policy.Launch, "isolation": policy.Isolation},
89- },
90- })
91- layout, err := offlineLayout(root)
92 require.NoError(t, err)85 require.NoError(t, err)
93- for _, dir := range []string{layout.Root, layout.Runtime, layout.State, layout.Log} {86+ require.NoError(t, ensureProductionBrokerConfig())
94- require.NoError(t, safedir.EnsurePrivate(dir))87+ route := daemonmux.SocketPath(ipc.SocketDir())
95- }88+ policy := localDaemonPolicy()
96- require.NoError(t, layout.VerifyCreated())89+ require.NoError(t, safedir.EnsurePrivate(ipc.SocketDir()))
97-
98 rawListener, err := ipc.ListenMux(route)90 rawListener, err := ipc.ListenMux(route)
99 require.NoError(t, err)91 require.NoError(t, err)
100 physicalSeen := make(chan struct{}, 8)92 physicalSeen := make(chan struct{}, 8)
101 var physicalMu sync.Mutex93 var physicalMu sync.Mutex
102 var physicalConnections []io.Closer94 var physicalConnections []io.Closer
103 aggregate := daemonmux.NewAggregateListener()95 aggregate := daemonmux.NewAggregateListener()
104- binding, err := daemonmux.NewServerBinding(brokerLocalTestIdentity, ports.BrokerDaemonIncarnation{1}, policy)96+ binding, err := daemonmux.NewServerBinding(identity, ports.BrokerDaemonIncarnation{1}, policy)
105 require.NoError(t, err)97 require.NoError(t, err)
106 mux, err := daemonmux.NewServerSupervisor(aggregate, binding, daemonmux.DefaultMuxCeilings(), 8)98 mux, err := daemonmux.NewServerSupervisor(aggregate, binding, daemonmux.DefaultMuxCeilings(), 8)
107 require.NoError(t, err)99 require.NoError(t, err)
@@ -127,7 +119,7 @@ func startPersistentOfflineClientFixture(t *testing.T, shell string, shellArgs [
127 daemonOpts := []daemon.Option{daemon.WithShell(shell, shellArgs)}119 daemonOpts := []daemon.Option{daemon.WithShell(shell, shellArgs)}
128 var fixtureCatalogue *persist.Persister120 var fixtureCatalogue *persist.Persister
129 if persistEnabled {121 if persistEnabled {
130- stateDir := filepath.Join(root, "state")122+ stateDir := platform.StateDir()
131 opened, err := persist.OpenOrCreate(stateDir)123 opened, err := persist.OpenOrCreate(stateDir)
132 require.NoError(t, err)124 require.NoError(t, err)
133 repository := snapshot.NewRepository(filepath.Join(stateDir, "snapshots"))125 repository := snapshot.NewRepository(filepath.Join(stateDir, "snapshots"))
@@ -146,16 +138,16 @@ func startPersistentOfflineClientFixture(t *testing.T, shell string, shellArgs [
146 // a manual clock rooted at Unix zero would correctly make the observation138 // a manual clock rooted at Unix zero would correctly make the observation
147 // stale to the real client clock before initial navigation resolves.139 // stale to the real client clock before initial navigation resolves.
148 deps, ready := testBrokerServeDeps(clock.New())140 deps, ready := testBrokerServeDeps(clock.New())
149- brokerDone := runSandbox(ctx, brokerServeOptions{offlineRoot: root, idleGrace: time.Hour}, deps)141+ brokerDone := runSandbox(ctx, brokerServeOptions{production: true, idleGrace: time.Hour}, deps)
150 var socket string142 var socket string
151 select {143 select {
152 case socket = <-ready:144 case socket = <-ready:
153 case serveErr := <-brokerDone:145 case serveErr := <-brokerDone:
154- t.Fatalf("offline broker exited before readiness: %v", serveErr)146+ t.Fatalf("production broker exited before readiness: %v", serveErr)
155 case <-time.After(brokerTestWait):147 case <-time.After(brokerTestWait):
156- t.Fatal("offline broker did not become ready")148+ t.Fatal("production broker did not become ready")
157 }149 }
158- // The sandbox broker becomes socket-ready before its first local daemon150+ // The production broker becomes socket-ready before its first local daemon
159 // observation is committed. Product clients start from a committed local151 // observation is committed. Product clients start from a committed local
160 // authority; wait for the fixture to provide the same contract so one-shot152 // authority; wait for the fixture to provide the same contract so one-shot
161 // initial navigation is not consumed against an artificial empty catalogue.153 // initial navigation is not consumed against an artificial empty catalogue.
@@ -174,7 +166,7 @@ func startPersistentOfflineClientFixture(t *testing.T, shell string, shellArgs [
174 default:166 default:
175 }167 }
176 return false168 return false
177- }, brokerTestWait, 5*time.Millisecond, "offline broker never committed its local daemon authority")169+ }, brokerTestWait, 5*time.Millisecond, "production broker never committed its local daemon authority")
178 subscription.Close()170 subscription.Close()
179 require.NoError(t, probe.Close())171 require.NoError(t, probe.Close())
180 t.Cleanup(func() {172 t.Cleanup(func() {
@@ -185,9 +177,8 @@ func startPersistentOfflineClientFixture(t *testing.T, shell string, shellArgs [
185 select {177 select {
186 case <-brokerDone:178 case <-brokerDone:
187 case <-time.After(brokerTestWait):179 case <-time.After(brokerTestWait):
188- t.Error("offline broker did not stop")180+ t.Error("production broker did not stop")
189 }181 }
190- requireProductionUntouched(t, prodRuntime, prodState)
191 })182 })
192 losePhysical := func() {183 losePhysical := func() {
193 physicalMu.Lock()184 physicalMu.Lock()
@@ -261,49 +252,6 @@ func awaitUITerminalMarker(t *testing.T, terminal *uiterm.Terminal, marker strin
261 }252 }
262 }253 }
263 254
264-func TestParseBrokerClientArgsAndProductionDispatchIsolation(t *testing.T) {
265- parsed, err := parseArgs([]string{brokerClientCommand, "--offline-root", "/tmp/offline", "--harness", offlineClientUIDriver})
266- require.NoError(t, err)
267- require.Equal(t, kindBrokerClient, parsed.kind)
268- require.Equal(t, connectivityLocalOnly, mustConnectivityOwner(t, "kindBrokerClient"))
269-
270- ordinary := []struct {
271- args []string
272- kind cmdKind
273- }{{nil, kindAttach}, {[]string{"list"}, kindList}, {[]string{"--ui-driver"}, kindUIDriver}, {[]string{"--web-daemon"}, kindWebDaemon}}
274- for _, test := range ordinary {
275- command, parseErr := parseArgs(test.args)
276- require.NoError(t, parseErr)
277- require.Equal(t, test.kind, command.kind)
278- require.NotEqual(t, kindBrokerClient, command.kind)
279- }
280-
281- rejections := []struct {
282- name string
283- args []string
284- }{
285- {name: "missing root", args: []string{brokerClientCommand}},
286- {name: "missing root value", args: []string{brokerClientCommand, "--offline-root"}},
287- {name: "duplicate root", args: []string{brokerClientCommand, "--offline-root", "/tmp/a", "--offline-root", "/tmp/b"}},
288- {name: "unknown flag", args: []string{brokerClientCommand, "--offline-root", "/tmp/a", "--unknown"}},
289- {name: "positional", args: []string{brokerClientCommand, "--offline-root", "/tmp/a", "extra"}},
290- {name: "bad harness", args: []string{brokerClientCommand, "--offline-root", "/tmp/a", "--harness", "other"}},
291- }
292- for _, test := range rejections {
293- t.Run(test.name, func(t *testing.T) {
294- _, parseErr := parseArgs(test.args)
295- require.Error(t, parseErr)
296- })
297- }
298-}
299-
300-func mustConnectivityOwner(t *testing.T, kind string) connectivityOwner {
301- t.Helper()
302- owner, ok := testConnectivityOwnerFor(kind)
303- require.True(t, ok)
304- return owner
305-}
306-
307 // TestOfflineEphemeralSessionIsNotPersistedViaBroker proves the daemon-owned255 // TestOfflineEphemeralSessionIsNotPersistedViaBroker proves the daemon-owned
308 // broker fixture persists a named session but never an ephemeral one: the256 // broker fixture persists a named session but never an ephemeral one: the
309 // durable catalogue holds exactly the named record after both lifecycles, so257 // durable catalogue holds exactly the named record after both lifecycles, so
M internal/app/ui_driver_client_test.go +6 -5
@@ -7,6 +7,7 @@ import (
77 "encoding/json"
88 "errors"
99 "io"
10+ "path/filepath"
1011 "sync"
1112 "testing"
1213 "time"
@@ -337,12 +338,12 @@ func TestUIDriverClientKeepsSharedDaemonOnEOF(t *testing.T) {
337338 second.EOF(t)
338339 }
339340
340-// TestUIDriverFixtureKeepsProductionUntouched pins the fixture isolation: the
341-// driver fixture uses its own private roots and never creates a production
342-// runtime or state entry.
343-func TestUIDriverFixtureKeepsProductionUntouched(t *testing.T) {
341+// TestUIDriverFixtureUsesIsolatedProductionBroker pins the fixture isolation:
342+// the driver reaches the broker within its private production XDG roots.
343+func TestUIDriverFixtureUsesIsolatedProductionBroker(t *testing.T) {
344344 fixture := startUIDriverBrokerFixture(t)
345- requireProductionUntouched(t, fixture.prodRuntime, fixture.prodState)
345+ require.DirExists(t, filepath.Join(fixture.prodRuntime, "vev", "broker"))
346+ require.FileExists(t, filepath.Join(fixture.prodState, "vev", "broker", "state", "state.json"))
346347 connector := fixture.Connector()
347348 require.NotNil(t, connector)
348349 service, err := connector.Connect(t.Context())
@@ -7,6 +7,7 @@ import (
7 "encoding/json"7 "encoding/json"
8 "errors"8 "errors"
9 "io"9 "io"
10+ "path/filepath"
10 "sync"11 "sync"
11 "testing"12 "testing"
12 "time"13 "time"
@@ -337,12 +338,12 @@ func TestUIDriverClientKeepsSharedDaemonOnEOF(t *testing.T) {
337 second.EOF(t)338 second.EOF(t)
338 }339 }
339 340
340-// TestUIDriverFixtureKeepsProductionUntouched pins the fixture isolation: the341+// TestUIDriverFixtureUsesIsolatedProductionBroker pins the fixture isolation:
341-// driver fixture uses its own private roots and never creates a production342+// the driver reaches the broker within its private production XDG roots.
342-// runtime or state entry.343+func TestUIDriverFixtureUsesIsolatedProductionBroker(t *testing.T) {
343-func TestUIDriverFixtureKeepsProductionUntouched(t *testing.T) {
344 fixture := startUIDriverBrokerFixture(t)344 fixture := startUIDriverBrokerFixture(t)
345- requireProductionUntouched(t, fixture.prodRuntime, fixture.prodState)345+ require.DirExists(t, filepath.Join(fixture.prodRuntime, "vev", "broker"))
346+ require.FileExists(t, filepath.Join(fixture.prodState, "vev", "broker", "state", "state.json"))
346 connector := fixture.Connector()347 connector := fixture.Connector()
347 require.NotNil(t, connector)348 require.NotNil(t, connector)
348 service, err := connector.Connect(t.Context())349 service, err := connector.Connect(t.Context())

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