e3c8979e8d
- 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>
183 lines
5.3 KiB
Go
183 lines
5.3 KiB
Go
package infra
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func writeTestFile(t *testing.T, dir, rel, content string) {
|
|
t.Helper()
|
|
full := filepath.Join(dir, filepath.FromSlash(rel))
|
|
if err := os.MkdirAll(filepath.Dir(full), 0o755); err != nil {
|
|
t.Fatalf("mkdir %s: %v", filepath.Dir(full), err)
|
|
}
|
|
if err := os.WriteFile(full, []byte(content), 0o644); err != nil {
|
|
t.Fatalf("write %s: %v", full, err)
|
|
}
|
|
}
|
|
|
|
func TestVaultInventoryScan_Empty(t *testing.T) {
|
|
t.Run("tmpdir vacio retorna slice vacio", func(t *testing.T) {
|
|
dir := t.TempDir()
|
|
files, err := VaultInventoryScan(dir, "v1", "test")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(files) != 0 {
|
|
t.Errorf("expected 0 files, got %d", len(files))
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestVaultInventoryScan_DataLayout(t *testing.T) {
|
|
t.Run("data layout — bucket y sub_bucket correctos", func(t *testing.T) {
|
|
dir := t.TempDir()
|
|
writeTestFile(t, dir, "data/raw/a.csv", "col1,col2\n1,2\n")
|
|
writeTestFile(t, dir, "data/processed/b.parquet", "PAR1fakedata")
|
|
|
|
files, err := VaultInventoryScan(dir, "vid", "vname")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(files) != 2 {
|
|
t.Fatalf("expected 2 files, got %d", len(files))
|
|
}
|
|
|
|
// files are sorted: data/processed/b.parquet < data/raw/a.csv
|
|
b := files[0]
|
|
if b.RelPath != "data/processed/b.parquet" {
|
|
t.Errorf("files[0].RelPath = %q, want data/processed/b.parquet", b.RelPath)
|
|
}
|
|
if b.Bucket != "data" {
|
|
t.Errorf("files[0].Bucket = %q, want data", b.Bucket)
|
|
}
|
|
if b.SubBucket != "processed" {
|
|
t.Errorf("files[0].SubBucket = %q, want processed", b.SubBucket)
|
|
}
|
|
if b.Mime != "application/parquet" {
|
|
t.Errorf("files[0].Mime = %q, want application/parquet", b.Mime)
|
|
}
|
|
if b.Ext != ".parquet" {
|
|
t.Errorf("files[0].Ext = %q, want .parquet", b.Ext)
|
|
}
|
|
if b.VaultID != "vid" {
|
|
t.Errorf("VaultID = %q, want vid", b.VaultID)
|
|
}
|
|
|
|
a := files[1]
|
|
if a.RelPath != "data/raw/a.csv" {
|
|
t.Errorf("files[1].RelPath = %q, want data/raw/a.csv", a.RelPath)
|
|
}
|
|
if a.Mime != "text/csv" {
|
|
t.Errorf("files[1].Mime = %q, want text/csv", a.Mime)
|
|
}
|
|
if a.Bucket != "data" || a.SubBucket != "raw" {
|
|
t.Errorf("files[1]: bucket=%q subBucket=%q, want data/raw", a.Bucket, a.SubBucket)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestVaultInventoryScan_KnowledgeLayout(t *testing.T) {
|
|
t.Run("knowledge layout — bucket y sub_bucket correctos", func(t *testing.T) {
|
|
dir := t.TempDir()
|
|
writeTestFile(t, dir, "knowledge/decisions/x.md", "# Decision\n\ncontent")
|
|
|
|
files, err := VaultInventoryScan(dir, "vid", "vname")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(files) != 1 {
|
|
t.Fatalf("expected 1 file, got %d", len(files))
|
|
}
|
|
f := files[0]
|
|
if f.RelPath != "knowledge/decisions/x.md" {
|
|
t.Errorf("RelPath = %q", f.RelPath)
|
|
}
|
|
if f.Bucket != "knowledge" {
|
|
t.Errorf("Bucket = %q, want knowledge", f.Bucket)
|
|
}
|
|
if f.SubBucket != "decisions" {
|
|
t.Errorf("SubBucket = %q, want decisions", f.SubBucket)
|
|
}
|
|
if f.Mime != "text/markdown" {
|
|
t.Errorf("Mime = %q, want text/markdown", f.Mime)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestVaultInventoryScan_SkipsIndexAndGit(t *testing.T) {
|
|
t.Run("omite vault_index.db y .git", func(t *testing.T) {
|
|
dir := t.TempDir()
|
|
writeTestFile(t, dir, "vault_index.db", "sqlite data")
|
|
writeTestFile(t, dir, "vault_index.db-wal", "wal data")
|
|
writeTestFile(t, dir, ".git/HEAD", "ref: refs/heads/master")
|
|
writeTestFile(t, dir, "data/raw/real.csv", "a,b\n1,2\n")
|
|
|
|
files, err := VaultInventoryScan(dir, "vid", "vname")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(files) != 1 {
|
|
t.Fatalf("expected 1 file (real.csv), got %d: %v", len(files), relPaths(files))
|
|
}
|
|
if files[0].RelPath != "data/raw/real.csv" {
|
|
t.Errorf("unexpected file: %q", files[0].RelPath)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestVaultInventoryScan_Sha256Deterministic(t *testing.T) {
|
|
t.Run("sha256 determinista para mismo contenido", func(t *testing.T) {
|
|
dir1 := t.TempDir()
|
|
dir2 := t.TempDir()
|
|
content := "deterministic content 123\n"
|
|
writeTestFile(t, dir1, "data/raw/f.csv", content)
|
|
writeTestFile(t, dir2, "data/raw/f.csv", content)
|
|
|
|
files1, err := VaultInventoryScan(dir1, "v1", "vault1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
files2, err := VaultInventoryScan(dir2, "v2", "vault2")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if files1[0].Sha256 != files2[0].Sha256 {
|
|
t.Errorf("sha256 mismatch: %q vs %q", files1[0].Sha256, files2[0].Sha256)
|
|
}
|
|
if len(files1[0].Sha256) != 64 {
|
|
t.Errorf("sha256 length = %d, want 64", len(files1[0].Sha256))
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestVaultInventoryScan_Sorted(t *testing.T) {
|
|
t.Run("orden lexicografico del resultado", func(t *testing.T) {
|
|
dir := t.TempDir()
|
|
writeTestFile(t, dir, "knowledge/decisions/z.md", "z")
|
|
writeTestFile(t, dir, "data/raw/a.csv", "a")
|
|
writeTestFile(t, dir, "data/processed/m.parquet", "m")
|
|
writeTestFile(t, dir, "knowledge/domains/b.md", "b")
|
|
|
|
files, err := VaultInventoryScan(dir, "v", "v")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for i := 1; i < len(files); i++ {
|
|
if files[i].RelPath < files[i-1].RelPath {
|
|
t.Errorf("not sorted at index %d: %q < %q", i, files[i].RelPath, files[i-1].RelPath)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
// relPaths is a helper for test error messages.
|
|
func relPaths(files []VaultFile) []string {
|
|
out := make([]string, len(files))
|
|
for i, f := range files {
|
|
out[i] = f.RelPath
|
|
}
|
|
return out
|
|
}
|