Files
pulse/internal/api/multi_tenant_setters_additional_test.go
T
rcourtman c73e78aeea Stabilize RC runtime ownership
Contract-Neutral: RC qualification fixes preserve existing public API, tenant, monitoring, and organization contracts while correcting canonical runtime ownership and test fixtures.
2026-07-20 07:50:22 +01:00

168 lines
5.8 KiB
Go

package api
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"github.com/rcourtman/pulse-go-rewrite/internal/config"
"github.com/rcourtman/pulse-go-rewrite/internal/monitoring"
)
func TestConfigHandlersSetMultiTenantMonitor(t *testing.T) {
handler := &ConfigHandlers{}
handler.SetMultiTenantMonitor(nil)
if handler.mtMonitor != nil {
t.Fatalf("mtMonitor should be nil after SetMultiTenantMonitor(nil)")
}
}
func TestRouterSetMultiTenantMonitor(t *testing.T) {
router := &Router{
alertHandlers: &AlertHandlers{},
notificationHandlers: &NotificationHandlers{},
configHandlers: &ConfigHandlers{},
dockerAgentHandlers: &DockerAgentHandlers{},
unifiedAgentHandlers: &UnifiedAgentHandlers{},
kubernetesAgentHandlers: &KubernetesAgentHandlers{},
systemSettingsHandler: &SystemSettingsHandler{},
resourceHandlers: NewResourceHandlers(nil),
}
router.SetMultiTenantMonitor(nil)
if router.mtMonitor != nil {
t.Fatalf("mtMonitor should be nil after SetMultiTenantMonitor(nil)")
}
if router.resourceHandlers.tenantStateProvider == nil {
t.Fatalf("tenantStateProvider should be set on resource handlers")
}
}
func TestRouterSetMultiTenantMonitorRefreshesConfigHandlerMonitorSource(t *testing.T) {
oldMonitor, _, _ := newTestMonitor(t)
newMonitor, _, _ := newTestMonitor(t)
oldConfig := &config.Config{DataPath: t.TempDir(), ConfigPath: t.TempDir()}
newConfig := &config.Config{DataPath: t.TempDir(), ConfigPath: t.TempDir()}
setUnexportedField(t, oldMonitor, "config", oldConfig)
setUnexportedField(t, newMonitor, "config", newConfig)
oldMTM := &monitoring.MultiTenantMonitor{}
setUnexportedField(t, oldMTM, "monitors", map[string]*monitoring.Monitor{
"default": oldMonitor,
})
newMTM := &monitoring.MultiTenantMonitor{}
setUnexportedField(t, newMTM, "monitors", map[string]*monitoring.Monitor{
"default": newMonitor,
})
router := &Router{
configHandlers: &ConfigHandlers{},
}
router.configHandlers.SetMultiTenantMonitor(oldMTM)
if got := router.configHandlers.getMonitor(context.Background()); got != oldMonitor {
t.Fatalf("precondition monitor = %#v, want old monitor %#v", got, oldMonitor)
}
router.SetMultiTenantMonitor(newMTM)
if got := router.configHandlers.getMonitor(context.Background()); got != newMonitor {
t.Fatalf("config handler monitor = %#v, want reloaded monitor %#v", got, newMonitor)
}
if got := router.configHandlers.getConfig(context.Background()); got != newConfig {
t.Fatalf("config handler config = %#v, want reloaded config %#v", got, newConfig)
}
}
func TestConfigHandlersNonDefaultMissingTenantMonitorFailsClosed(t *testing.T) {
defaultConfig := &config.Config{DataPath: t.TempDir(), ConfigPath: t.TempDir()}
defaultMonitor, _, _ := newTestMonitor(t)
mtp := config.NewMultiTenantPersistence(t.TempDir())
mtm := monitoring.NewMultiTenantMonitor(defaultConfig, mtp, nil)
defer mtm.Stop()
handler := &ConfigHandlers{
defaultConfig: defaultConfig,
defaultPersistence: config.NewConfigPersistence(defaultConfig.ConfigPath),
defaultMonitor: defaultMonitor,
}
handler.SetMultiTenantMonitor(mtm)
ctx := context.WithValue(context.Background(), OrgIDContextKey, "tenant-missing")
cfg, persistence, monitor := handler.getContextState(ctx)
if cfg != nil || persistence != nil || monitor != nil {
t.Fatalf("expected missing non-default tenant state to fail closed, got cfg=%#v persistence=%#v monitor=%#v", cfg, persistence, monitor)
}
}
func TestConfigHandlersDefaultContextUsesPrimaryRuntimeState(t *testing.T) {
tenantCopyConfig := &config.Config{DataPath: t.TempDir(), ConfigPath: t.TempDir()}
tenantCopyMonitor, _, _ := newTestMonitor(t)
setUnexportedField(t, tenantCopyMonitor, "config", tenantCopyConfig)
mtm := &monitoring.MultiTenantMonitor{}
setUnexportedField(t, mtm, "monitors", map[string]*monitoring.Monitor{
"default": tenantCopyMonitor,
})
primaryConfig := &config.Config{DataPath: t.TempDir(), ConfigPath: t.TempDir()}
primaryMonitor, _, _ := newTestMonitor(t)
setUnexportedField(t, primaryMonitor, "config", primaryConfig)
primaryPersistence := config.NewConfigPersistence(primaryConfig.ConfigPath)
handler := &ConfigHandlers{
defaultConfig: primaryConfig,
defaultPersistence: primaryPersistence,
defaultMonitor: primaryMonitor,
mtMonitor: mtm,
}
cfg, persistence, monitor := handler.getContextState(context.Background())
if cfg != primaryConfig {
t.Fatalf("default config = %#v, want primary config %#v", cfg, primaryConfig)
}
if persistence != primaryPersistence {
t.Fatalf("default persistence = %#v, want primary persistence %#v", persistence, primaryPersistence)
}
if monitor != primaryMonitor {
t.Fatalf("default monitor = %#v, want primary monitor %#v", monitor, primaryMonitor)
}
}
func TestNewRouterWiresTenantResourceStateProvider(t *testing.T) {
cfg := &config.Config{
DataPath: t.TempDir(),
ConfigPath: t.TempDir(),
}
mtm := &monitoring.MultiTenantMonitor{}
router := NewRouter(cfg, nil, mtm, nil, nil, "1.0.0")
if router.resourceHandlers == nil {
t.Fatal("expected resource handlers to be initialized")
}
if router.resourceHandlers.tenantStateProvider == nil {
t.Fatal("expected NewRouter to wire the tenant resource state provider when a multi-tenant monitor is provided")
}
}
func TestNewRouterServesTenantResourceListWithMultiTenantMonitor(t *testing.T) {
cfg := &config.Config{
DataPath: t.TempDir(),
ConfigPath: t.TempDir(),
}
mtm := &monitoring.MultiTenantMonitor{}
router := NewRouter(cfg, nil, mtm, nil, nil, "1.0.0")
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/api/resources?page=1&limit=100", nil)
req = req.WithContext(context.WithValue(req.Context(), OrgIDContextKey, "tenant-a"))
router.resourceHandlers.HandleListResources(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status = %d, body=%s", rec.Code, rec.Body.String())
}
}