package vectorstore_test import ( "context" "os" "testing" "time" "github.com/mathiasbq/hyperguild/ingestion/internal/vectorstore" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // integration tests run against a real postgres18 + pgvector. Gated by // BRAIN_PG_TEST_DSN so `task check` stays hermetic on hosts without a // reachable database. // // To run: // BRAIN_PG_TEST_DSN='postgres://brain_app:pwd@127.0.0.1:5432/brain' \ // go test ./internal/vectorstore/... -run Integration func dsn(t *testing.T) string { t.Helper() v := os.Getenv("BRAIN_PG_TEST_DSN") if v == "" { t.Skip("BRAIN_PG_TEST_DSN not set; skipping pgvector integration tests") } return v } func freshStore(t *testing.T) (*vectorstore.PGStore, context.Context) { t.Helper() ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) t.Cleanup(cancel) s, err := vectorstore.New(ctx, dsn(t)) require.NoError(t, err) t.Cleanup(s.Close) require.NoError(t, s.Init(ctx)) // Clean slate per test. _, _ = s.KnownPathsWithTime(ctx) require.NoError(t, s.Delete(ctx, "%test-fixture%")) return s, ctx } func vec(dim int, fill float32) []float32 { v := make([]float32, dim) for i := range v { v[i] = fill } return v } func TestIntegration_UpsertAndSearch(t *testing.T) { s, ctx := freshStore(t) require.NoError(t, s.Upsert(ctx, "wiki/a.md", vec(768, 1.0))) require.NoError(t, s.Upsert(ctx, "wiki/b.md", vec(768, -1.0))) hits, err := s.Search(ctx, vec(768, 1.0), 2) require.NoError(t, err) require.GreaterOrEqual(t, len(hits), 1) assert.Equal(t, "wiki/a.md", hits[0].Path) assert.InDelta(t, 0.0, hits[0].Distance, 1e-5) t.Cleanup(func() { _ = s.Delete(ctx, "wiki/a.md") _ = s.Delete(ctx, "wiki/b.md") }) } func TestIntegration_KnownPathsWithTime(t *testing.T) { s, ctx := freshStore(t) before := time.Now() require.NoError(t, s.Upsert(ctx, "wiki/k.md", vec(768, 0.5))) t.Cleanup(func() { _ = s.Delete(ctx, "wiki/k.md") }) paths, err := s.KnownPathsWithTime(ctx) require.NoError(t, err) at, ok := paths["wiki/k.md"] require.True(t, ok) assert.False(t, at.IsZero(), "updated_at must not be zero") assert.WithinDuration(t, before, at, 5*time.Second, "updated_at must be recent") } func TestUpsert_RejectsWrongDimension(t *testing.T) { s := &vectorstore.PGStore{} err := s.Upsert(context.Background(), "x", vec(100, 0)) require.Error(t, err) } func TestSearch_RejectsWrongDimension(t *testing.T) { s := &vectorstore.PGStore{} _, err := s.Search(context.Background(), vec(100, 0), 5) require.Error(t, err) }