package cfgservice import ( "context" "errors" "os" "testing" "github.com/jackc/pgx/v5/pgxpool" ) func setupStoreTest(t *testing.T) (*Store, func()) { t.Helper() adminDSN := os.Getenv("TEST_ADMIN_DSN") if adminDSN == "" { t.Skip("TEST_ADMIN_DSN nicht gesetzt, Integrationstest uebersprungen") } ctx := context.Background() pool, err := pgxpool.New(ctx, adminDSN) if err != nil { t.Fatalf("pool: %v", err) } if _, err := pool.Exec(ctx, ` CREATE TABLE IF NOT EXISTS config_values ( key TEXT NOT NULL, scope TEXT NOT NULL CHECK (scope <> ''), value TEXT NOT NULL, version INT NOT NULL, updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), PRIMARY KEY (key, scope) ); CREATE TABLE IF NOT EXISTS config_value_history ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), key TEXT NOT NULL, scope TEXT NOT NULL, value TEXT NOT NULL, version INT NOT NULL, changed_at TIMESTAMPTZ NOT NULL DEFAULT now() ); `); err != nil { t.Fatalf("schema: %v", err) } cleanup := func() { _, _ = pool.Exec(ctx, `DELETE FROM config_value_history WHERE key LIKE 'test\_%' ESCAPE '\'`) _, _ = pool.Exec(ctx, `DELETE FROM config_values WHERE key LIKE 'test\_%' ESCAPE '\'`) pool.Close() } return NewStore(pool), cleanup } func TestStore_SetIncrementsVersion(t *testing.T) { store, cleanup := setupStoreTest(t) defer cleanup() ctx := context.Background() v1, err := store.Set(ctx, "test_key", GlobalScope, "erster-wert") if err != nil { t.Fatalf("set 1: %v", err) } if v1.Version != 1 { t.Fatalf("erwartet version 1, habe %d", v1.Version) } v2, err := store.Set(ctx, "test_key", GlobalScope, "zweiter-wert") if err != nil { t.Fatalf("set 2: %v", err) } if v2.Version != 2 { t.Fatalf("erwartet version 2, habe %d", v2.Version) } got, err := store.Get(ctx, "test_key", GlobalScope) if err != nil { t.Fatalf("get: %v", err) } if got.Value != "zweiter-wert" || got.Version != 2 { t.Fatalf("aktueller wert unerwartet: %+v", got) } } // Akzeptanzkriterium 2 + Pruefung 3: Versionierungshistorie ueber mehrere // Aenderungen hinweg nachvollzogen. func TestStore_HistoryTracksAllChanges(t *testing.T) { store, cleanup := setupStoreTest(t) defer cleanup() ctx := context.Background() values := []string{"v1", "v2", "v3"} for _, v := range values { if _, err := store.Set(ctx, "test_history_key", GlobalScope, v); err != nil { t.Fatalf("set %q: %v", v, err) } } history, err := store.History(ctx, "test_history_key", GlobalScope) if err != nil { t.Fatalf("history: %v", err) } if len(history) != 3 { t.Fatalf("erwartet 3 historieneintraege, habe %d", len(history)) } for i, h := range history { if h.Version != i+1 || h.Value != values[i] { t.Fatalf("historieneintrag[%d] unerwartet: %+v", i, h) } } } func TestStore_GetUnknownKeyReturnsNotFound(t *testing.T) { store, cleanup := setupStoreTest(t) defer cleanup() ctx := context.Background() if _, err := store.Get(ctx, "test_nie_gesetzt", GlobalScope); !errors.Is(err, ErrNotFound) { t.Fatalf("erwartet ErrNotFound, habe %v", err) } }