Files
fn_registry/functions/infra/vault_index_write_test.go
T
egutierrez e3c8979e8d chore: auto-commit (95 archivos)
- cmd/fn/doctor.go
- cmd/fn/main.go
- cpp/apps/primitives_gallery/playground/tables/CMakeLists.txt
- cpp/apps/primitives_gallery/playground/tables/data_table.cpp
- cpp/apps/primitives_gallery/playground/tables/data_table_logic.cpp
- cpp/apps/primitives_gallery/playground/tables/data_table_logic.h
- cpp/apps/primitives_gallery/playground/tables/self_test.cpp
- cpp/apps/primitives_gallery/playground/tables/tql.cpp
- cpp/apps/primitives_gallery/playground/tables/viz.cpp
- cpp/apps/primitives_gallery/playground/tables/viz.h
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 00:50:34 +02:00

211 lines
5.3 KiB
Go

package infra
import (
"testing"
"time"
)
// makeTestVaultFile creates a minimal VaultFile for testing.
func makeTestVaultFile(relPath, mime, bucket, subBucket string) VaultFile {
return VaultFile{
VaultID: "test_vault",
VaultName: "test",
RelPath: relPath,
Size: 100,
Mtime: time.Now().Unix(),
Sha256: "abc123def456abc123def456abc123def456abc123def456abc123def456abc1",
Mime: mime,
Ext: ".csv",
Bucket: bucket,
SubBucket: subBucket,
}
}
func openInMemoryVaultIndex(t *testing.T) interface{ Close() error } {
t.Helper()
dir := t.TempDir()
db, err := VaultIndexOpen(dir)
if err != nil {
t.Fatalf("VaultIndexOpen: %v", err)
}
return db
}
func TestVaultIndexWrite_FreshInsert(t *testing.T) {
t.Run("N archivos nuevos — Inserted=N", func(t *testing.T) {
dir := t.TempDir()
db, err := VaultIndexOpen(dir)
if err != nil {
t.Fatal(err)
}
defer db.Close()
files := []VaultFile{
makeTestVaultFile("data/raw/a.csv", "text/csv", "data", "raw"),
makeTestVaultFile("data/raw/b.csv", "text/csv", "data", "raw"),
makeTestVaultFile("knowledge/decisions/x.md", "text/markdown", "knowledge", "decisions"),
}
report, err := VaultIndexWrite(db, files, false)
if err != nil {
t.Fatalf("VaultIndexWrite: %v", err)
}
if report.Inserted != 3 {
t.Errorf("Inserted = %d, want 3", report.Inserted)
}
if report.Updated != 0 {
t.Errorf("Updated = %d, want 0", report.Updated)
}
if report.Pruned != 0 {
t.Errorf("Pruned = %d, want 0", report.Pruned)
}
if report.FTS != 3 {
t.Errorf("FTS = %d, want 3", report.FTS)
}
})
}
func TestVaultIndexWrite_Upsert(t *testing.T) {
t.Run("re-escritura con mtime distinto — Updated=N", func(t *testing.T) {
dir := t.TempDir()
db, err := VaultIndexOpen(dir)
if err != nil {
t.Fatal(err)
}
defer db.Close()
files := []VaultFile{
makeTestVaultFile("data/raw/a.csv", "text/csv", "data", "raw"),
makeTestVaultFile("data/raw/b.csv", "text/csv", "data", "raw"),
}
if _, err := VaultIndexWrite(db, files, false); err != nil {
t.Fatalf("first write: %v", err)
}
// Modify mtime to simulate file change.
files[0].Mtime = time.Now().Unix() + 100
files[1].Mtime = time.Now().Unix() + 200
report, err := VaultIndexWrite(db, files, false)
if err != nil {
t.Fatalf("second write: %v", err)
}
if report.Inserted != 0 {
t.Errorf("Inserted = %d, want 0", report.Inserted)
}
if report.Updated != 2 {
t.Errorf("Updated = %d, want 2", report.Updated)
}
})
}
func TestVaultIndexWrite_Prune(t *testing.T) {
t.Run("prune elimina filas ausentes", func(t *testing.T) {
dir := t.TempDir()
db, err := VaultIndexOpen(dir)
if err != nil {
t.Fatal(err)
}
defer db.Close()
// Write A and B.
ab := []VaultFile{
makeTestVaultFile("data/raw/a.csv", "text/csv", "data", "raw"),
makeTestVaultFile("data/raw/b.csv", "text/csv", "data", "raw"),
}
if _, err := VaultIndexWrite(db, ab, false); err != nil {
t.Fatalf("first write: %v", err)
}
// Write only A with prune=true — B should be deleted.
onlyA := []VaultFile{ab[0]}
report, err := VaultIndexWrite(db, onlyA, true)
if err != nil {
t.Fatalf("prune write: %v", err)
}
if report.Pruned != 1 {
t.Errorf("Pruned = %d, want 1", report.Pruned)
}
// Verify B is gone.
var count int
err = db.QueryRow(`SELECT count(*) FROM files WHERE rel_path = 'data/raw/b.csv'`).Scan(&count)
if err != nil {
t.Fatalf("query: %v", err)
}
if count != 0 {
t.Errorf("b.csv still present after prune")
}
})
}
func TestVaultIndexWrite_NoPrune(t *testing.T) {
t.Run("sin prune, filas previas persisten", func(t *testing.T) {
dir := t.TempDir()
db, err := VaultIndexOpen(dir)
if err != nil {
t.Fatal(err)
}
defer db.Close()
ab := []VaultFile{
makeTestVaultFile("data/raw/a.csv", "text/csv", "data", "raw"),
makeTestVaultFile("data/raw/b.csv", "text/csv", "data", "raw"),
}
if _, err := VaultIndexWrite(db, ab, false); err != nil {
t.Fatalf("first write: %v", err)
}
// Write only A without prune — B must remain.
onlyA := []VaultFile{ab[0]}
report, err := VaultIndexWrite(db, onlyA, false)
if err != nil {
t.Fatalf("second write: %v", err)
}
if report.Pruned != 0 {
t.Errorf("Pruned = %d, want 0", report.Pruned)
}
var count int
err = db.QueryRow(`SELECT count(*) FROM files`).Scan(&count)
if err != nil {
t.Fatalf("query: %v", err)
}
if count != 2 {
t.Errorf("files count = %d, want 2", count)
}
})
}
func TestVaultIndexWrite_FTSMatch(t *testing.T) {
t.Run("FTS5 MATCH funciona tras escritura", func(t *testing.T) {
dir := t.TempDir()
db, err := VaultIndexOpen(dir)
if err != nil {
t.Fatal(err)
}
defer db.Close()
files := []VaultFile{
makeTestVaultFile("data/raw/foo_report.csv", "text/csv", "data", "raw"),
makeTestVaultFile("data/raw/bar_data.csv", "text/csv", "data", "raw"),
}
if _, err := VaultIndexWrite(db, files, false); err != nil {
t.Fatalf("write: %v", err)
}
// FTS5 on rel_path column: MATCH 'foo*'
var count int
err = db.QueryRow(
`SELECT count(*) FROM files_fts WHERE files_fts MATCH 'rel_path:foo*'`,
).Scan(&count)
if err != nil {
t.Fatalf("FTS MATCH query: %v", err)
}
if count != 1 {
t.Errorf("FTS MATCH rel_path:foo* = %d rows, want 1", count)
}
})
}