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>
212 lines
5.8 KiB
Go
212 lines
5.8 KiB
Go
package infra
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// setupDoctorRepo creates a repo layout with one vault in a project manifest.
|
|
// vaultPath must be an absolute path that already exists (or not, for missing tests).
|
|
func setupDoctorRepo(t *testing.T, vaultName, projectID, vaultPath string) string {
|
|
t.Helper()
|
|
root := t.TempDir()
|
|
projVaultsDir := filepath.Join(root, "projects", projectID, "vaults")
|
|
if err := os.MkdirAll(projVaultsDir, 0755); err != nil {
|
|
t.Fatalf("mkdir projects: %v", err)
|
|
}
|
|
manifest := "vaults:\n - name: " + vaultName + "\n description: test vault\n path: " + vaultPath + "\n tags: []\n"
|
|
if err := os.WriteFile(filepath.Join(projVaultsDir, "vault.yaml"), []byte(manifest), 0644); err != nil {
|
|
t.Fatalf("write vault.yaml: %v", err)
|
|
}
|
|
return root
|
|
}
|
|
|
|
func TestVaultDoctor_OK(t *testing.T) {
|
|
vaultDir := t.TempDir()
|
|
|
|
// Proper layout
|
|
if err := os.MkdirAll(filepath.Join(vaultDir, "data", "raw"), 0755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.MkdirAll(filepath.Join(vaultDir, "knowledge"), 0755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Create a file with a past mtime so the index is not stale
|
|
samplePath := filepath.Join(vaultDir, "data", "raw", "sample.csv")
|
|
if err := os.WriteFile(samplePath, []byte("a,b\n1,2\n"), 0644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
pastTime := time.Now().Add(-1 * time.Hour)
|
|
if err := os.Chtimes(samplePath, pastTime, pastTime); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Create vault_index.db with the file indexed after its mtime
|
|
vdb, err := VaultIndexOpen(vaultDir)
|
|
if err != nil {
|
|
t.Fatalf("VaultIndexOpen: %v", err)
|
|
}
|
|
futureIndexed := time.Now().Unix() // indexed_at is now — after file mtime
|
|
_, err = vdb.Exec(`INSERT INTO files (rel_path, size, mtime, sha256, mime, ext, bucket, sub_bucket, indexed_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
"data/raw/sample.csv", 8, pastTime.Unix(), "deadbeef", "text/csv", ".csv", "data", "raw", futureIndexed)
|
|
if err != nil {
|
|
t.Fatalf("insert: %v", err)
|
|
}
|
|
vdb.Close()
|
|
|
|
root := setupDoctorRepo(t, "my_vault", "my_proj", vaultDir)
|
|
entries, err := VaultDoctor(root)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(entries) != 1 {
|
|
t.Fatalf("expected 1 entry, got %d", len(entries))
|
|
}
|
|
e := entries[0]
|
|
if e.Status != "ok" {
|
|
t.Errorf("Status: want ok, got %s (issues: %v)", e.Status, e.Issues)
|
|
}
|
|
if len(e.Issues) != 0 {
|
|
t.Errorf("Issues: want empty, got %v", e.Issues)
|
|
}
|
|
if e.DiskFiles != 1 {
|
|
t.Errorf("DiskFiles: want 1, got %d", e.DiskFiles)
|
|
}
|
|
if e.IndexedFiles != 1 {
|
|
t.Errorf("IndexedFiles: want 1, got %d", e.IndexedFiles)
|
|
}
|
|
}
|
|
|
|
func TestVaultDoctor_MissingDir(t *testing.T) {
|
|
missingPath := filepath.Join(t.TempDir(), "does_not_exist")
|
|
root := setupDoctorRepo(t, "missing_vault", "my_proj", missingPath)
|
|
|
|
entries, err := VaultDoctor(root)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(entries) != 1 {
|
|
t.Fatalf("expected 1 entry, got %d", len(entries))
|
|
}
|
|
e := entries[0]
|
|
if e.Status != "error" {
|
|
t.Errorf("Status: want error, got %s", e.Status)
|
|
}
|
|
found := false
|
|
for _, issue := range e.Issues {
|
|
if issue == "directory_missing" {
|
|
found = true
|
|
}
|
|
}
|
|
if !found {
|
|
t.Errorf("Expected directory_missing issue, got %v", e.Issues)
|
|
}
|
|
}
|
|
|
|
func TestVaultDoctor_NoIndex(t *testing.T) {
|
|
vaultDir := t.TempDir()
|
|
// Proper layout but no vault_index.db
|
|
if err := os.MkdirAll(filepath.Join(vaultDir, "data", "raw"), 0755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(vaultDir, "data", "raw", "a.csv"), []byte("x"), 0644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
root := setupDoctorRepo(t, "no_index_vault", "my_proj", vaultDir)
|
|
entries, err := VaultDoctor(root)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(entries) != 1 {
|
|
t.Fatalf("expected 1 entry, got %d", len(entries))
|
|
}
|
|
e := entries[0]
|
|
if e.Status != "warning" {
|
|
t.Errorf("Status: want warning, got %s", e.Status)
|
|
}
|
|
found := false
|
|
for _, issue := range e.Issues {
|
|
if issue == "index_missing" {
|
|
found = true
|
|
}
|
|
}
|
|
if !found {
|
|
t.Errorf("Expected index_missing issue, got %v", e.Issues)
|
|
}
|
|
}
|
|
|
|
func TestVaultDoctor_LayoutDrift(t *testing.T) {
|
|
vaultDir := t.TempDir()
|
|
// No data/ or knowledge/ — just a random file at root
|
|
if err := os.WriteFile(filepath.Join(vaultDir, "something.txt"), []byte("hi"), 0644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
root := setupDoctorRepo(t, "layout_vault", "my_proj", vaultDir)
|
|
entries, err := VaultDoctor(root)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(entries) != 1 {
|
|
t.Fatalf("expected 1 entry, got %d", len(entries))
|
|
}
|
|
e := entries[0]
|
|
if e.Status != "warning" {
|
|
t.Errorf("Status: want warning, got %s", e.Status)
|
|
}
|
|
foundLayout := false
|
|
for _, issue := range e.Issues {
|
|
if issue == "layout_missing" || issue == "non_standard_layout" {
|
|
foundLayout = true
|
|
}
|
|
}
|
|
if !foundLayout {
|
|
t.Errorf("Expected layout_missing or non_standard_layout, got %v", e.Issues)
|
|
}
|
|
}
|
|
|
|
func TestVaultDoctor_EmptyVault(t *testing.T) {
|
|
vaultDir := t.TempDir()
|
|
// data/ and knowledge/ exist but are empty
|
|
if err := os.MkdirAll(filepath.Join(vaultDir, "data"), 0755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.MkdirAll(filepath.Join(vaultDir, "knowledge"), 0755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Create vault_index.db (empty)
|
|
vdb, err := VaultIndexOpen(vaultDir)
|
|
if err != nil {
|
|
t.Fatalf("VaultIndexOpen: %v", err)
|
|
}
|
|
vdb.Close()
|
|
|
|
root := setupDoctorRepo(t, "empty_vault", "my_proj", vaultDir)
|
|
entries, err := VaultDoctor(root)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(entries) != 1 {
|
|
t.Fatalf("expected 1 entry, got %d", len(entries))
|
|
}
|
|
e := entries[0]
|
|
if e.Status != "warning" {
|
|
t.Errorf("Status: want warning, got %s (issues: %v)", e.Status, e.Issues)
|
|
}
|
|
found := false
|
|
for _, issue := range e.Issues {
|
|
if issue == "empty_vault" {
|
|
found = true
|
|
}
|
|
}
|
|
if !found {
|
|
t.Errorf("Expected empty_vault issue, got %v", e.Issues)
|
|
}
|
|
}
|