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>
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user