carlos / platform Public

Close registry handles owned by console test fixtures

Paul Campbell pushed by claude agent, operated by paul@keymail.dev 491428a2e74049fc186a220c49742f4641097745 parent f71540f
1 file changed, +57 −0
  • internal/console/view_test.go +57 −0

CI passed — run details

diff --git a/internal/console/view_test.go b/internal/console/view_test.go
index dd8ac6921..c9eb3e52e 100644
--- a/internal/console/view_test.go
+++ b/internal/console/view_test.go
@@ -86,10 +86,24 @@ func buildFixtures(t *testing.T) (regPath string, store release.Store, priv ed25
t.Helper()
dir := t.TempDir()
regPath = filepath.Join(dir, "registry.db")
+ // Registered before callers add HTTP/server cleanups, so LIFO teardown
+ // closes those users before the cached registry handle they may share.
+ t.Cleanup(func() {
+ regMu.Lock()
+ cached := regCache[regPath]
+ if cached != nil {
+ delete(regCache, regPath)
+ }
+ regMu.Unlock()
+ if cached != nil {
+ _ = cached.Close()
+ }
+ })
reg, err := registry.Open(regPath)
if err != nil {
t.Fatal(err)
}
+ defer reg.Close()
for _, rt := range []registry.Route{
{Host: "kass.carlosapp.dev", Kind: "instance", Status: "ready",
Version: "v1", App: "kass", Channel: "stable", Addr: "127.0.0.1:9001"},
@@ -140,6 +154,49 @@ func buildFixtures(t *testing.T) (regPath string, store release.Store, priv ed25
return regPath, store, priv, pub
}
+func TestBuildFixturesClosesOnlyItsRegistryHandles(t *testing.T) {
+ livePath, _, _, _ := buildFixtures(t)
+ live, err := openRegistry(livePath)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if route, err := live.Get("kass.carlosapp.dev"); err != nil || route == nil {
+ t.Fatalf("live fixture route = %+v, %v", route, err)
+ }
+
+ var closedPath string
+ var closed *registry.Registry
+ if ok := t.Run("completed fixture", func(t *testing.T) {
+ closedPath, _, _, _ = buildFixtures(t)
+ closed, err = openRegistry(closedPath)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if route, err := closed.Get("kass.carlosapp.dev"); err != nil || route == nil {
+ t.Fatalf("child fixture route = %+v, %v", route, err)
+ }
+ }); !ok {
+ t.Fatal("child fixture failed")
+ }
+
+ regMu.Lock()
+ _, closedStillCached := regCache[closedPath]
+ liveCached := regCache[livePath]
+ regMu.Unlock()
+ if closedStillCached {
+ t.Fatal("completed fixture registry remains cached")
+ }
+ if _, err := closed.Get("kass.carlosapp.dev"); err == nil {
+ t.Fatal("completed fixture cached registry remains usable")
+ }
+ if liveCached != live {
+ t.Fatal("distinct live fixture cache entry changed")
+ }
+ if route, err := live.Get("kass.carlosapp.dev"); err != nil || route == nil {
+ t.Fatalf("distinct live fixture route = %+v, %v", route, err)
+ }
+}
+
func findChannel(t *testing.T, chans []ChannelView, name string) ChannelView {
t.Helper()
for _, c := range chans {