Files
hanzoai_agent/control-plane/pkg/agents/store_test.go
zeekay 0ecdb7fbdb feat(pkg/agents): canonical Embed contract + per-org store view
Adds the cross-binary contract every Hanzo Go service follows
(see ~/work/hanzo/HANZO_BINARY.md):

- pkg/agents.EmbedConfig — DataDir, HTTPAddr, PostgresDSN,
  IAMEndpoint, JWTKeySource, RequireIdentity, Logger,
  ShutdownTimeout, Bootstrap. Same shape as
  github.com/hanzoai/tasks/pkg/tasks.EmbedConfig.
- pkg/agents.Embed/Stop — singleton-guarded process lifecycle
  the future fused 'hanzo' binary calls.
- pkg/agents.Store + OrgView — narrow interface-driven store
  wrapper. WithOrg(orgID) returns a per-org view; SQL builders
  read OrgFromContext to add WHERE org_id = $1.
- BootstrapFunc keeps internal/server out of the canonical
  contract — entrypoint plugs the actual server.Start() in.

Tests cover defaults, singleton guard, bootstrap success/failure,
and OrgView round-trip.
2026-04-27 18:40:40 -07:00

70 lines
1.8 KiB
Go

// Copyright © 2026 Hanzo AI. MIT License.
package agents
import (
"context"
"testing"
)
func TestOrgFromContext_Empty(t *testing.T) {
if got := OrgFromContext(context.Background()); got != "" {
t.Errorf("OrgFromContext(empty): want empty, got %q", got)
}
}
func TestWithOrgContext_RoundTrip(t *testing.T) {
ctx := WithOrgContext(context.Background(), "hanzo")
if got := OrgFromContext(ctx); got != "hanzo" {
t.Errorf("OrgFromContext: want hanzo, got %q", got)
}
}
func TestWithOrgContext_EmptyDoesNotPin(t *testing.T) {
// Solo mode: passing "" should not poison ctx with a sentinel.
ctx := WithOrgContext(context.Background(), "")
if got := OrgFromContext(ctx); got != "" {
t.Errorf("OrgFromContext(empty pin): want empty, got %q", got)
}
}
func TestStore_WithOrg(t *testing.T) {
st := NewStore(nil)
view := st.WithOrg("hanzo")
if view.OrgID() != "hanzo" {
t.Errorf("OrgID: want hanzo, got %q", view.OrgID())
}
ctx := view.Context(context.Background())
if got := OrgFromContext(ctx); got != "hanzo" {
t.Errorf("OrgFromContext via OrgView.Context: want hanzo, got %q", got)
}
}
func TestStore_WithOrg_EmptyView(t *testing.T) {
// An OrgView with "" represents the solo path. Context propagation
// must keep it unscoped, not poisoned with an empty sentinel.
st := NewStore(nil)
view := st.WithOrg("")
if view.OrgID() != "" {
t.Errorf("OrgID: want empty, got %q", view.OrgID())
}
ctx := view.Context(context.Background())
if got := OrgFromContext(ctx); got != "" {
t.Errorf("OrgFromContext on empty view: want empty, got %q", got)
}
}
func TestStore_NilSafe(t *testing.T) {
// Defensive: nil Store should not panic when callers chain.
var s *Store
if s.Storage() != nil {
t.Error("nil Store.Storage(): want nil")
}
v := s.WithOrg("hanzo")
if v.OrgID() != "hanzo" {
t.Errorf("nil Store.WithOrg: want hanzo, got %q", v.OrgID())
}
}