detached c00536e

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

commit
c00536eab682de0f82f8cadd9a59e01608dac974
author
brice · · 2026-09-23 15:00 UTC
parent
b5b719e
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
1 file · +36 -121
M internal/app/broker_offline_test.go +36 -121
@@ -215,101 +215,26 @@ func TestDrainBrokerAcceptClassifiesTerminalFailure(t *testing.T) {
215215 }
216216 }
217217
218-func TestParseBrokerServeArgs(t *testing.T) {
219- tests := []struct {
220- name string
221- args []string
222- want brokerServeOptions
223- wantErr string
224- }{
225- {name: "root only", args: []string{"--offline-root", "/srv/sandbox"}, want: brokerServeOptions{offlineRoot: "/srv/sandbox"}},
226- {
227- name: "root and grace",
228- args: []string{"--offline-root", "/srv/sandbox", "--idle-grace", "90s"},
229- want: brokerServeOptions{offlineRoot: "/srv/sandbox", idleGrace: 90 * time.Second},
230- },
231- {name: "missing root", args: nil, wantErr: "requires --offline-root"},
232- {name: "missing root value", args: []string{"--offline-root"}, wantErr: "requires a path"},
233- {name: "empty root value", args: []string{"--offline-root", ""}, wantErr: "requires a path"},
234- {name: "duplicate root", args: []string{"--offline-root", "/a", "--offline-root", "/b"}, wantErr: "duplicate --offline-root"},
235- {name: "duplicate grace", args: []string{"--offline-root", "/a", "--idle-grace", "1s", "--idle-grace", "2s"}, wantErr: "duplicate --idle-grace"},
236- {name: "missing grace value", args: []string{"--offline-root", "/a", "--idle-grace"}, wantErr: "requires a duration"},
237- {name: "invalid duration", args: []string{"--offline-root", "/a", "--idle-grace", "soon"}, wantErr: "not a duration"},
238- {name: "zero duration", args: []string{"--offline-root", "/a", "--idle-grace", "0s"}, wantErr: "must be positive"},
239- {name: "negative duration", args: []string{"--offline-root", "/a", "--idle-grace", "-1s"}, wantErr: "must be positive"},
240- {name: "unknown flag", args: []string{"--offline-root", "/a", "--verbose"}, wantErr: "unknown flag"},
241- {name: "positional", args: []string{"--offline-root", "/a", "extra"}, wantErr: "positional"},
242- {name: "equals form is refused", args: []string{"--offline-root=/a"}, wantErr: "unknown flag"},
243- }
244- for _, tt := range tests {
245- t.Run(tt.name, func(t *testing.T) {
246- command, err := parseBrokerServeArgs(tt.args)
247- if tt.wantErr != "" {
248- require.Error(t, err)
249- require.Contains(t, err.Error(), tt.wantErr)
250- return
251- }
252- require.NoError(t, err)
253- require.Equal(t, kindBrokerServe, command.kind)
254- require.Equal(t, tt.want, command.brokerServe)
255- })
256- }
257-}
258-
259-func TestBrokerServeIsHiddenFromPublicHelp(t *testing.T) {
260- require.NotContains(t, usageText, brokerServeCommand)
261- _, err := parseArgs([]string{brokerServeCommand, "--offline-root", "/srv/sandbox"})
262- require.NoError(t, err)
263- _, err = parseArgs([]string{"--help"})
264- require.NoError(t, err)
265-}
266-
267-func TestBrokerServeRejectsUnsafeRoot(t *testing.T) {
268- root, _, _ := isolateSandboxEnv(t)
269- ctx := context.Background()
218+func TestProductionBrokerServeRejectsUnsafeRoot(t *testing.T) {
219+ layout := emptyProductionBrokerLayout(t, "")
220+ require.NoError(t, os.MkdirAll(layout.Root, 0o755))
270221 deps, _ := testBrokerServeDeps(newSandboxClock())
271-
272- t.Run("relative root", func(t *testing.T) {
273- err := runBrokerServe(ctx, brokerServeOptions{offlineRoot: "relative"}, deps)
274- require.Error(t, err)
275- require.Contains(t, err.Error(), "not absolute")
276- })
277- t.Run("unclean root", func(t *testing.T) {
278- err := runBrokerServe(ctx, brokerServeOptions{offlineRoot: root + "/../sandbox"}, deps)
279- require.Error(t, err)
280- require.Contains(t, err.Error(), "not clean")
281- })
282- t.Run("production overlap", func(t *testing.T) {
283- err := runBrokerServe(ctx, brokerServeOptions{offlineRoot: ipc.SocketDir()}, deps)
284- require.Error(t, err)
285- require.Contains(t, err.Error(), "overlaps production path")
286- })
287- t.Run("symlinked root", func(t *testing.T) {
288- link := filepath.Join(t.TempDir(), "link")
289- require.NoError(t, os.Symlink(t.TempDir(), link))
290- err := runBrokerServe(ctx, brokerServeOptions{offlineRoot: link}, deps)
291- require.Error(t, err)
292- require.Contains(t, err.Error(), "symlink")
293- })
294- t.Run("missing config", func(t *testing.T) {
295- err := runBrokerServe(ctx, brokerServeOptions{offlineRoot: root}, deps)
296- require.Error(t, err)
297- require.Contains(t, err.Error(), brokerconfig.ConfigFileName)
298- })
222+ err := runBrokerServe(context.Background(), brokerServeOptions{production: true}, deps)
223+ require.ErrorContains(t, err, "0755")
224+ require.NoFileExists(t, filepath.Join(layout.Runtime, "lifecycle.lock"))
299225 }
300226
301227 func TestBrokerServeRoundTrip(t *testing.T) {
302- root, prodRuntime, prodState := isolateSandboxEnv(t)
228+ emptyProductionBrokerLayout(t, "")
303229 policy := brokerTestPolicy()
304230 fixture := newBrokerMuxFixture(t, policy)
305- require.NoError(t, os.MkdirAll(root, 0o700))
306- writeSandboxConfig(t, root, sandboxRegistrationDocument(fixture.route))
231+ writeProductionBrokerDocument(t, sandboxRegistrationDocument(fixture.route))
307232
308233 clk := newSandboxClock()
309234 deps, ready := testBrokerServeDeps(clk)
310235 ctx, cancel := context.WithCancel(context.Background())
311236 defer cancel()
312- done := runSandbox(ctx, brokerServeOptions{offlineRoot: root}, deps)
237+ done := runSandbox(ctx, brokerServeOptions{production: true}, deps)
313238
314239 socketPath := awaitSandboxReady(t, ready, done)
315240
@@ -356,7 +281,14 @@ func TestBrokerServeRoundTrip(t *testing.T) {
356281
357282 awaitSandboxCancel(t, cancel, done)
358283 requireSocketRemoved(t, socketPath)
359- requireProductionUntouched(t, prodRuntime, prodState)
284+}
285+
286+// writeProductionBrokerDocument replaces only the private per-test bootstrap.
287+func writeProductionBrokerDocument(t *testing.T, document any) {
288+ t.Helper()
289+ raw, err := json.Marshal(document)
290+ require.NoError(t, err)
291+ require.NoError(t, os.WriteFile(productionBrokerConfigPath(), raw, 0o600))
360292 }
361293
362294 // awaitSandboxReady waits for the sandbox readiness hook and returns the
@@ -402,51 +334,47 @@ func waitForSandboxShutdown(t *testing.T, clk *sandboxClock, done <-chan error)
402334 }
403335
404336 func TestBrokerServeIdleShutdownOnEmptyConfig(t *testing.T) {
405- root, prodRuntime, prodState := isolateSandboxEnv(t)
337+ layout := emptyProductionBrokerLayout(t, "")
406338 clk := newSandboxClock()
407- require.NoError(t, os.MkdirAll(root, 0o700))
408- writeSandboxConfig(t, root, map[string]any{"marker": brokerconfig.Marker, "registrations": []any{}})
409339
410340 deps, ready := testBrokerServeDeps(clk)
411341 ctx, cancel := context.WithCancel(context.Background())
412342 defer cancel()
413- done := runSandbox(ctx, brokerServeOptions{offlineRoot: root}, deps)
343+ done := runSandbox(ctx, brokerServeOptions{production: true}, deps)
414344
415345 socketPath := awaitSandboxReady(t, ready, done)
416346 waitForSandboxShutdown(t, clk, done)
417347
418348 requireSocketRemoved(t, socketPath)
419- requireOwnerLockReleased(t, root)
420- requireProductionUntouched(t, prodRuntime, prodState)
349+ requireOwnerLockReleased(t, layout.Runtime)
350+
421351 }
422352
423353 // requireOwnerLockReleased proves the lifetime lock is no longer held.
424-func requireOwnerLockReleased(t *testing.T, root string) {
354+func requireOwnerLockReleased(t *testing.T, runtimeDir string) {
425355 t.Helper()
426- owner, err := lifecycle.TryAcquire(filepath.Join(root, brokerconfig.RuntimeDirName))
356+ owner, err := lifecycle.TryAcquire(runtimeDir)
427357 require.NoError(t, err)
428358 require.NoError(t, owner.Release())
429359 }
430360
431361 func TestBrokerServeCancelCleanup(t *testing.T) {
432- root, prodRuntime, prodState := isolateSandboxEnv(t)
362+ layout := emptyProductionBrokerLayout(t, "")
433363 clk := newSandboxClock()
434- require.NoError(t, os.MkdirAll(root, 0o700))
435- writeSandboxConfig(t, root, map[string]any{"marker": brokerconfig.Marker, "registrations": []any{}})
436364
437365 deps, ready := testBrokerServeDeps(clk)
438366 ctx, cancel := context.WithCancel(context.Background())
439367 defer cancel()
440- done := runSandbox(ctx, brokerServeOptions{offlineRoot: root}, deps)
368+ done := runSandbox(ctx, brokerServeOptions{production: true}, deps)
441369
442370 socketPath := awaitSandboxReady(t, ready, done)
443371 awaitSandboxCancel(t, cancel, done)
444372
445373 requireSocketRemoved(t, socketPath)
446- requireOwnerLockReleased(t, root)
447- _, err := os.Lstat(filepath.Join(root, brokerconfig.StateDirName, "state.json"))
448- require.NoError(t, err, "durable sandbox state must remain after shutdown")
449- requireProductionUntouched(t, prodRuntime, prodState)
374+ requireOwnerLockReleased(t, layout.Runtime)
375+ _, err := os.Lstat(filepath.Join(layout.State, "state.json"))
376+ require.NoError(t, err, "durable broker state must remain after shutdown")
377+
450378 }
451379
452380 // wedgedListener is a ports.BrokerListener whose Accept always reports one
@@ -469,10 +397,8 @@ func (l *wedgedListener) Addr() string { return l.addr }
469397 // terminal accept failure commits shutdown and drains the listener, instead of
470398 // leaving a bound broker whose socket can no longer admit work.
471399 func TestBrokerServeShutsDownOnUnexpectedAcceptFailure(t *testing.T) {
472- root, prodRuntime, prodState := isolateSandboxEnv(t)
400+ layout := emptyProductionBrokerLayout(t, "")
473401 clk := newSandboxClock()
474- require.NoError(t, os.MkdirAll(root, 0o700))
475- writeSandboxConfig(t, root, map[string]any{"marker": brokerconfig.Marker, "registrations": []any{}})
476402
477403 listener := &wedgedListener{err: errors.New("carriage accept failed"), addr: "wedged"}
478404 deps, ready := testBrokerServeDeps(clk)
@@ -481,7 +407,7 @@ func TestBrokerServeShutsDownOnUnexpectedAcceptFailure(t *testing.T) {
481407 }
482408 ctx, cancel := context.WithCancel(context.Background())
483409 defer cancel()
484- done := runSandbox(ctx, brokerServeOptions{offlineRoot: root}, deps)
410+ done := runSandbox(ctx, brokerServeOptions{production: true}, deps)
485411
486412 awaitSandboxReady(t, ready, done)
487413 select {
@@ -491,25 +417,23 @@ func TestBrokerServeShutsDownOnUnexpectedAcceptFailure(t *testing.T) {
491417 t.Fatal("the broker wedged on an unexpected accept failure")
492418 }
493419 require.True(t, listener.closed.Load(), "shutdown must close the wedged listener")
494- requireOwnerLockReleased(t, root)
495- requireProductionUntouched(t, prodRuntime, prodState)
420+ requireOwnerLockReleased(t, layout.Runtime)
421+
496422 }
497423
498424 func TestBrokerServeRefusesDuplicateOwnership(t *testing.T) {
499- root, _, _ := isolateSandboxEnv(t)
425+ emptyProductionBrokerLayout(t, "")
500426 clk := newSandboxClock()
501- require.NoError(t, os.MkdirAll(root, 0o700))
502- writeSandboxConfig(t, root, map[string]any{"marker": brokerconfig.Marker, "registrations": []any{}})
503427
504428 deps, ready := testBrokerServeDeps(clk)
505429 ctx, cancel := context.WithCancel(context.Background())
506430 defer cancel()
507- done := runSandbox(ctx, brokerServeOptions{offlineRoot: root}, deps)
431+ done := runSandbox(ctx, brokerServeOptions{production: true}, deps)
508432 socketPath := awaitSandboxReady(t, ready, done)
509433
510434 // A second foreground owner fails fast on the lifetime lock.
511435 secondDeps, _ := testBrokerServeDeps(newSandboxClock())
512- err := runBrokerServe(context.Background(), brokerServeOptions{offlineRoot: root}, secondDeps)
436+ err := runBrokerServe(context.Background(), brokerServeOptions{production: true}, secondDeps)
513437 require.ErrorIs(t, err, lifecycle.ErrBusy)
514438
515439 // A duplicate listener on the live socket is refused as well.
@@ -713,12 +637,3 @@ func TestSandboxClockFiresOnAdvance(t *testing.T) {
713637 t.Fatal("manual timer did not fire")
714638 }
715639 }
716-
717-// Ensure the fixture and registration helpers stay coherent.
718-func TestBrokerSandboxFixtures(t *testing.T) {
719- require.NoError(t, brokerTestRegistration().Validate())
720- require.NoError(t, brokerTestPolicy().Validate())
721- document := sandboxRegistrationDocument("/tmp/mux.sock")
722- require.Equal(t, brokerconfig.Marker, document["marker"])
723- require.Len(t, document["registrations"], 1)
724-}
@@ -215,101 +215,26 @@ func TestDrainBrokerAcceptClassifiesTerminalFailure(t *testing.T) {
215 }215 }
216 }216 }
217 217
218-func TestParseBrokerServeArgs(t *testing.T) {218+func TestProductionBrokerServeRejectsUnsafeRoot(t *testing.T) {
219- tests := []struct {219+ layout := emptyProductionBrokerLayout(t, "")
220- name string220+ require.NoError(t, os.MkdirAll(layout.Root, 0o755))
221- args []string
222- want brokerServeOptions
223- wantErr string
224- }{
225- {name: "root only", args: []string{"--offline-root", "/srv/sandbox"}, want: brokerServeOptions{offlineRoot: "/srv/sandbox"}},
226- {
227- name: "root and grace",
228- args: []string{"--offline-root", "/srv/sandbox", "--idle-grace", "90s"},
229- want: brokerServeOptions{offlineRoot: "/srv/sandbox", idleGrace: 90 * time.Second},
230- },
231- {name: "missing root", args: nil, wantErr: "requires --offline-root"},
232- {name: "missing root value", args: []string{"--offline-root"}, wantErr: "requires a path"},
233- {name: "empty root value", args: []string{"--offline-root", ""}, wantErr: "requires a path"},
234- {name: "duplicate root", args: []string{"--offline-root", "/a", "--offline-root", "/b"}, wantErr: "duplicate --offline-root"},
235- {name: "duplicate grace", args: []string{"--offline-root", "/a", "--idle-grace", "1s", "--idle-grace", "2s"}, wantErr: "duplicate --idle-grace"},
236- {name: "missing grace value", args: []string{"--offline-root", "/a", "--idle-grace"}, wantErr: "requires a duration"},
237- {name: "invalid duration", args: []string{"--offline-root", "/a", "--idle-grace", "soon"}, wantErr: "not a duration"},
238- {name: "zero duration", args: []string{"--offline-root", "/a", "--idle-grace", "0s"}, wantErr: "must be positive"},
239- {name: "negative duration", args: []string{"--offline-root", "/a", "--idle-grace", "-1s"}, wantErr: "must be positive"},
240- {name: "unknown flag", args: []string{"--offline-root", "/a", "--verbose"}, wantErr: "unknown flag"},
241- {name: "positional", args: []string{"--offline-root", "/a", "extra"}, wantErr: "positional"},
242- {name: "equals form is refused", args: []string{"--offline-root=/a"}, wantErr: "unknown flag"},
243- }
244- for _, tt := range tests {
245- t.Run(tt.name, func(t *testing.T) {
246- command, err := parseBrokerServeArgs(tt.args)
247- if tt.wantErr != "" {
248- require.Error(t, err)
249- require.Contains(t, err.Error(), tt.wantErr)
250- return
251- }
252- require.NoError(t, err)
253- require.Equal(t, kindBrokerServe, command.kind)
254- require.Equal(t, tt.want, command.brokerServe)
255- })
256- }
257-}
258-
259-func TestBrokerServeIsHiddenFromPublicHelp(t *testing.T) {
260- require.NotContains(t, usageText, brokerServeCommand)
261- _, err := parseArgs([]string{brokerServeCommand, "--offline-root", "/srv/sandbox"})
262- require.NoError(t, err)
263- _, err = parseArgs([]string{"--help"})
264- require.NoError(t, err)
265-}
266-
267-func TestBrokerServeRejectsUnsafeRoot(t *testing.T) {
268- root, _, _ := isolateSandboxEnv(t)
269- ctx := context.Background()
270 deps, _ := testBrokerServeDeps(newSandboxClock())221 deps, _ := testBrokerServeDeps(newSandboxClock())
271-222+ err := runBrokerServe(context.Background(), brokerServeOptions{production: true}, deps)
272- t.Run("relative root", func(t *testing.T) {223+ require.ErrorContains(t, err, "0755")
273- err := runBrokerServe(ctx, brokerServeOptions{offlineRoot: "relative"}, deps)224+ require.NoFileExists(t, filepath.Join(layout.Runtime, "lifecycle.lock"))
274- require.Error(t, err)
275- require.Contains(t, err.Error(), "not absolute")
276- })
277- t.Run("unclean root", func(t *testing.T) {
278- err := runBrokerServe(ctx, brokerServeOptions{offlineRoot: root + "/../sandbox"}, deps)
279- require.Error(t, err)
280- require.Contains(t, err.Error(), "not clean")
281- })
282- t.Run("production overlap", func(t *testing.T) {
283- err := runBrokerServe(ctx, brokerServeOptions{offlineRoot: ipc.SocketDir()}, deps)
284- require.Error(t, err)
285- require.Contains(t, err.Error(), "overlaps production path")
286- })
287- t.Run("symlinked root", func(t *testing.T) {
288- link := filepath.Join(t.TempDir(), "link")
289- require.NoError(t, os.Symlink(t.TempDir(), link))
290- err := runBrokerServe(ctx, brokerServeOptions{offlineRoot: link}, deps)
291- require.Error(t, err)
292- require.Contains(t, err.Error(), "symlink")
293- })
294- t.Run("missing config", func(t *testing.T) {
295- err := runBrokerServe(ctx, brokerServeOptions{offlineRoot: root}, deps)
296- require.Error(t, err)
297- require.Contains(t, err.Error(), brokerconfig.ConfigFileName)
298- })
299 }225 }
300 226
301 func TestBrokerServeRoundTrip(t *testing.T) {227 func TestBrokerServeRoundTrip(t *testing.T) {
302- root, prodRuntime, prodState := isolateSandboxEnv(t)228+ emptyProductionBrokerLayout(t, "")
303 policy := brokerTestPolicy()229 policy := brokerTestPolicy()
304 fixture := newBrokerMuxFixture(t, policy)230 fixture := newBrokerMuxFixture(t, policy)
305- require.NoError(t, os.MkdirAll(root, 0o700))231+ writeProductionBrokerDocument(t, sandboxRegistrationDocument(fixture.route))
306- writeSandboxConfig(t, root, sandboxRegistrationDocument(fixture.route))
307 232
308 clk := newSandboxClock()233 clk := newSandboxClock()
309 deps, ready := testBrokerServeDeps(clk)234 deps, ready := testBrokerServeDeps(clk)
310 ctx, cancel := context.WithCancel(context.Background())235 ctx, cancel := context.WithCancel(context.Background())
311 defer cancel()236 defer cancel()
312- done := runSandbox(ctx, brokerServeOptions{offlineRoot: root}, deps)237+ done := runSandbox(ctx, brokerServeOptions{production: true}, deps)
313 238
314 socketPath := awaitSandboxReady(t, ready, done)239 socketPath := awaitSandboxReady(t, ready, done)
315 240
@@ -356,7 +281,14 @@ func TestBrokerServeRoundTrip(t *testing.T) {
356 281
357 awaitSandboxCancel(t, cancel, done)282 awaitSandboxCancel(t, cancel, done)
358 requireSocketRemoved(t, socketPath)283 requireSocketRemoved(t, socketPath)
359- requireProductionUntouched(t, prodRuntime, prodState)284+}
285+
286+// writeProductionBrokerDocument replaces only the private per-test bootstrap.
287+func writeProductionBrokerDocument(t *testing.T, document any) {
288+ t.Helper()
289+ raw, err := json.Marshal(document)
290+ require.NoError(t, err)
291+ require.NoError(t, os.WriteFile(productionBrokerConfigPath(), raw, 0o600))
360 }292 }
361 293
362 // awaitSandboxReady waits for the sandbox readiness hook and returns the294 // awaitSandboxReady waits for the sandbox readiness hook and returns the
@@ -402,51 +334,47 @@ func waitForSandboxShutdown(t *testing.T, clk *sandboxClock, done <-chan error)
402 }334 }
403 335
404 func TestBrokerServeIdleShutdownOnEmptyConfig(t *testing.T) {336 func TestBrokerServeIdleShutdownOnEmptyConfig(t *testing.T) {
405- root, prodRuntime, prodState := isolateSandboxEnv(t)337+ layout := emptyProductionBrokerLayout(t, "")
406 clk := newSandboxClock()338 clk := newSandboxClock()
407- require.NoError(t, os.MkdirAll(root, 0o700))
408- writeSandboxConfig(t, root, map[string]any{"marker": brokerconfig.Marker, "registrations": []any{}})
409 339
410 deps, ready := testBrokerServeDeps(clk)340 deps, ready := testBrokerServeDeps(clk)
411 ctx, cancel := context.WithCancel(context.Background())341 ctx, cancel := context.WithCancel(context.Background())
412 defer cancel()342 defer cancel()
413- done := runSandbox(ctx, brokerServeOptions{offlineRoot: root}, deps)343+ done := runSandbox(ctx, brokerServeOptions{production: true}, deps)
414 344
415 socketPath := awaitSandboxReady(t, ready, done)345 socketPath := awaitSandboxReady(t, ready, done)
416 waitForSandboxShutdown(t, clk, done)346 waitForSandboxShutdown(t, clk, done)
417 347
418 requireSocketRemoved(t, socketPath)348 requireSocketRemoved(t, socketPath)
419- requireOwnerLockReleased(t, root)349+ requireOwnerLockReleased(t, layout.Runtime)
420- requireProductionUntouched(t, prodRuntime, prodState)350+
421 }351 }
422 352
423 // requireOwnerLockReleased proves the lifetime lock is no longer held.353 // requireOwnerLockReleased proves the lifetime lock is no longer held.
424-func requireOwnerLockReleased(t *testing.T, root string) {354+func requireOwnerLockReleased(t *testing.T, runtimeDir string) {
425 t.Helper()355 t.Helper()
426- owner, err := lifecycle.TryAcquire(filepath.Join(root, brokerconfig.RuntimeDirName))356+ owner, err := lifecycle.TryAcquire(runtimeDir)
427 require.NoError(t, err)357 require.NoError(t, err)
428 require.NoError(t, owner.Release())358 require.NoError(t, owner.Release())
429 }359 }
430 360
431 func TestBrokerServeCancelCleanup(t *testing.T) {361 func TestBrokerServeCancelCleanup(t *testing.T) {
432- root, prodRuntime, prodState := isolateSandboxEnv(t)362+ layout := emptyProductionBrokerLayout(t, "")
433 clk := newSandboxClock()363 clk := newSandboxClock()
434- require.NoError(t, os.MkdirAll(root, 0o700))
435- writeSandboxConfig(t, root, map[string]any{"marker": brokerconfig.Marker, "registrations": []any{}})
436 364
437 deps, ready := testBrokerServeDeps(clk)365 deps, ready := testBrokerServeDeps(clk)
438 ctx, cancel := context.WithCancel(context.Background())366 ctx, cancel := context.WithCancel(context.Background())
439 defer cancel()367 defer cancel()
440- done := runSandbox(ctx, brokerServeOptions{offlineRoot: root}, deps)368+ done := runSandbox(ctx, brokerServeOptions{production: true}, deps)
441 369
442 socketPath := awaitSandboxReady(t, ready, done)370 socketPath := awaitSandboxReady(t, ready, done)
443 awaitSandboxCancel(t, cancel, done)371 awaitSandboxCancel(t, cancel, done)
444 372
445 requireSocketRemoved(t, socketPath)373 requireSocketRemoved(t, socketPath)
446- requireOwnerLockReleased(t, root)374+ requireOwnerLockReleased(t, layout.Runtime)
447- _, err := os.Lstat(filepath.Join(root, brokerconfig.StateDirName, "state.json"))375+ _, err := os.Lstat(filepath.Join(layout.State, "state.json"))
448- require.NoError(t, err, "durable sandbox state must remain after shutdown")376+ require.NoError(t, err, "durable broker state must remain after shutdown")
449- requireProductionUntouched(t, prodRuntime, prodState)377+
450 }378 }
451 379
452 // wedgedListener is a ports.BrokerListener whose Accept always reports one380 // wedgedListener is a ports.BrokerListener whose Accept always reports one
@@ -469,10 +397,8 @@ func (l *wedgedListener) Addr() string { return l.addr }
469 // terminal accept failure commits shutdown and drains the listener, instead of397 // terminal accept failure commits shutdown and drains the listener, instead of
470 // leaving a bound broker whose socket can no longer admit work.398 // leaving a bound broker whose socket can no longer admit work.
471 func TestBrokerServeShutsDownOnUnexpectedAcceptFailure(t *testing.T) {399 func TestBrokerServeShutsDownOnUnexpectedAcceptFailure(t *testing.T) {
472- root, prodRuntime, prodState := isolateSandboxEnv(t)400+ layout := emptyProductionBrokerLayout(t, "")
473 clk := newSandboxClock()401 clk := newSandboxClock()
474- require.NoError(t, os.MkdirAll(root, 0o700))
475- writeSandboxConfig(t, root, map[string]any{"marker": brokerconfig.Marker, "registrations": []any{}})
476 402
477 listener := &wedgedListener{err: errors.New("carriage accept failed"), addr: "wedged"}403 listener := &wedgedListener{err: errors.New("carriage accept failed"), addr: "wedged"}
478 deps, ready := testBrokerServeDeps(clk)404 deps, ready := testBrokerServeDeps(clk)
@@ -481,7 +407,7 @@ func TestBrokerServeShutsDownOnUnexpectedAcceptFailure(t *testing.T) {
481 }407 }
482 ctx, cancel := context.WithCancel(context.Background())408 ctx, cancel := context.WithCancel(context.Background())
483 defer cancel()409 defer cancel()
484- done := runSandbox(ctx, brokerServeOptions{offlineRoot: root}, deps)410+ done := runSandbox(ctx, brokerServeOptions{production: true}, deps)
485 411
486 awaitSandboxReady(t, ready, done)412 awaitSandboxReady(t, ready, done)
487 select {413 select {
@@ -491,25 +417,23 @@ func TestBrokerServeShutsDownOnUnexpectedAcceptFailure(t *testing.T) {
491 t.Fatal("the broker wedged on an unexpected accept failure")417 t.Fatal("the broker wedged on an unexpected accept failure")
492 }418 }
493 require.True(t, listener.closed.Load(), "shutdown must close the wedged listener")419 require.True(t, listener.closed.Load(), "shutdown must close the wedged listener")
494- requireOwnerLockReleased(t, root)420+ requireOwnerLockReleased(t, layout.Runtime)
495- requireProductionUntouched(t, prodRuntime, prodState)421+
496 }422 }
497 423
498 func TestBrokerServeRefusesDuplicateOwnership(t *testing.T) {424 func TestBrokerServeRefusesDuplicateOwnership(t *testing.T) {
499- root, _, _ := isolateSandboxEnv(t)425+ emptyProductionBrokerLayout(t, "")
500 clk := newSandboxClock()426 clk := newSandboxClock()
501- require.NoError(t, os.MkdirAll(root, 0o700))
502- writeSandboxConfig(t, root, map[string]any{"marker": brokerconfig.Marker, "registrations": []any{}})
503 427
504 deps, ready := testBrokerServeDeps(clk)428 deps, ready := testBrokerServeDeps(clk)
505 ctx, cancel := context.WithCancel(context.Background())429 ctx, cancel := context.WithCancel(context.Background())
506 defer cancel()430 defer cancel()
507- done := runSandbox(ctx, brokerServeOptions{offlineRoot: root}, deps)431+ done := runSandbox(ctx, brokerServeOptions{production: true}, deps)
508 socketPath := awaitSandboxReady(t, ready, done)432 socketPath := awaitSandboxReady(t, ready, done)
509 433
510 // A second foreground owner fails fast on the lifetime lock.434 // A second foreground owner fails fast on the lifetime lock.
511 secondDeps, _ := testBrokerServeDeps(newSandboxClock())435 secondDeps, _ := testBrokerServeDeps(newSandboxClock())
512- err := runBrokerServe(context.Background(), brokerServeOptions{offlineRoot: root}, secondDeps)436+ err := runBrokerServe(context.Background(), brokerServeOptions{production: true}, secondDeps)
513 require.ErrorIs(t, err, lifecycle.ErrBusy)437 require.ErrorIs(t, err, lifecycle.ErrBusy)
514 438
515 // A duplicate listener on the live socket is refused as well.439 // A duplicate listener on the live socket is refused as well.
@@ -713,12 +637,3 @@ func TestSandboxClockFiresOnAdvance(t *testing.T) {
713 t.Fatal("manual timer did not fire")637 t.Fatal("manual timer did not fire")
714 }638 }
715 }639 }
716-
717-// Ensure the fixture and registration helpers stay coherent.
718-func TestBrokerSandboxFixtures(t *testing.T) {
719- require.NoError(t, brokerTestRegistration().Validate())
720- require.NoError(t, brokerTestPolicy().Validate())
721- document := sandboxRegistrationDocument("/tmp/mux.sock")
722- require.Equal(t, brokerconfig.Marker, document["marker"])
723- require.Len(t, document["registrations"], 1)
724-}

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