a802f59f55
- 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>
176 lines
4.9 KiB
Go
176 lines
4.9 KiB
Go
package infra
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// setupAggregateTestRepo creates a minimal repo layout:
|
|
//
|
|
// <root>/
|
|
// registry.db (SQLite, empty)
|
|
// projects/<project>/vaults/vault.yaml
|
|
// <vaultPath>/ (optionally with vault_index.db populated)
|
|
func setupAggregateTestRepo(t *testing.T, vaultName, projectID, vaultPath string, withIndex bool) string {
|
|
t.Helper()
|
|
root := t.TempDir()
|
|
|
|
// Create registry.db
|
|
regDB, err := SQLiteOpen(filepath.Join(root, "registry.db"), "")
|
|
if err != nil {
|
|
t.Fatalf("create registry.db: %v", err)
|
|
}
|
|
regDB.Close()
|
|
|
|
// Create project vault manifest
|
|
projVaultsDir := filepath.Join(root, "projects", projectID, "vaults")
|
|
if err := os.MkdirAll(projVaultsDir, 0755); err != nil {
|
|
t.Fatalf("mkdir projects: %v", err)
|
|
}
|
|
manifestYAML := "vaults:\n - name: " + vaultName + "\n description: test\n path: " + vaultPath + "\n tags: []\n"
|
|
if err := os.WriteFile(filepath.Join(projVaultsDir, "vault.yaml"), []byte(manifestYAML), 0644); err != nil {
|
|
t.Fatalf("write vault.yaml: %v", err)
|
|
}
|
|
|
|
// Create vault dir
|
|
if err := os.MkdirAll(vaultPath, 0755); err != nil {
|
|
t.Fatalf("mkdir vault: %v", err)
|
|
}
|
|
|
|
if withIndex {
|
|
// Create a vault_index.db with one file row
|
|
vdb, err := VaultIndexOpen(vaultPath)
|
|
if err != nil {
|
|
t.Fatalf("VaultIndexOpen: %v", err)
|
|
}
|
|
now := time.Now().UTC().Unix()
|
|
_, err = vdb.Exec(`INSERT INTO files (rel_path, size, mtime, sha256, mime, ext, bucket, sub_bucket, indexed_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
"data/raw/sample.csv", 1024, now, "deadbeef", "text/csv", ".csv", "data", "raw", now)
|
|
if err != nil {
|
|
t.Fatalf("insert test file: %v", err)
|
|
}
|
|
vdb.Close()
|
|
}
|
|
|
|
return root
|
|
}
|
|
|
|
func TestVaultAggregateIndex_NoVaults(t *testing.T) {
|
|
root := t.TempDir()
|
|
// No manifests, just registry.db
|
|
regDB, err := SQLiteOpen(filepath.Join(root, "registry.db"), "")
|
|
if err != nil {
|
|
t.Fatalf("create registry.db: %v", err)
|
|
}
|
|
regDB.Close()
|
|
|
|
report, err := VaultAggregateIndex(root)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if report.VaultsProcessed != 0 {
|
|
t.Errorf("VaultsProcessed: want 0, got %d", report.VaultsProcessed)
|
|
}
|
|
if len(report.Errors) != 0 {
|
|
t.Errorf("Errors: want empty, got %v", report.Errors)
|
|
}
|
|
}
|
|
|
|
func TestVaultAggregateIndex_VaultWithoutIndex(t *testing.T) {
|
|
vaultDir := t.TempDir()
|
|
root := setupAggregateTestRepo(t, "my_vault", "my_proj", vaultDir, false /* no vault_index.db */)
|
|
|
|
report, err := VaultAggregateIndex(root)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if report.VaultsSkipped != 1 {
|
|
t.Errorf("VaultsSkipped: want 1, got %d", report.VaultsSkipped)
|
|
}
|
|
if report.VaultsProcessed != 0 {
|
|
t.Errorf("VaultsProcessed: want 0, got %d", report.VaultsProcessed)
|
|
}
|
|
}
|
|
|
|
func TestVaultAggregateIndex_HappyPath(t *testing.T) {
|
|
vaultDir := t.TempDir()
|
|
root := setupAggregateTestRepo(t, "my_vault", "my_proj", vaultDir, true)
|
|
|
|
report, err := VaultAggregateIndex(root)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if report.VaultsProcessed != 1 {
|
|
t.Errorf("VaultsProcessed: want 1, got %d", report.VaultsProcessed)
|
|
}
|
|
if report.TotalFiles != 1 {
|
|
t.Errorf("TotalFiles: want 1, got %d", report.TotalFiles)
|
|
}
|
|
|
|
// Verify row exists in registry.db
|
|
regDB, err := SQLiteOpen(filepath.Join(root, "registry.db"), "")
|
|
if err != nil {
|
|
t.Fatalf("open registry.db: %v", err)
|
|
}
|
|
defer regDB.Close()
|
|
|
|
var count int
|
|
if err := regDB.QueryRow(`SELECT COUNT(*) FROM vault_files`).Scan(&count); err != nil {
|
|
t.Fatalf("count vault_files: %v", err)
|
|
}
|
|
if count != 1 {
|
|
t.Errorf("vault_files count: want 1, got %d", count)
|
|
}
|
|
}
|
|
|
|
func TestVaultAggregateIndex_ReRunReplaces(t *testing.T) {
|
|
vaultDir := t.TempDir()
|
|
root := setupAggregateTestRepo(t, "my_vault", "my_proj", vaultDir, true)
|
|
|
|
// First run
|
|
if _, err := VaultAggregateIndex(root); err != nil {
|
|
t.Fatalf("first run: %v", err)
|
|
}
|
|
|
|
// Add a second file to vault_index.db
|
|
vdb, err := VaultIndexOpen(vaultDir)
|
|
if err != nil {
|
|
t.Fatalf("reopen vault index: %v", err)
|
|
}
|
|
now := time.Now().UTC().Unix()
|
|
_, err = vdb.Exec(`INSERT INTO files (rel_path, size, mtime, sha256, mime, ext, bucket, sub_bucket, indexed_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
"data/raw/extra.csv", 512, now, "cafebabe", "text/csv", ".csv", "data", "raw", now)
|
|
if err != nil {
|
|
t.Fatalf("insert second file: %v", err)
|
|
}
|
|
vdb.Close()
|
|
|
|
// Second run
|
|
report, err := VaultAggregateIndex(root)
|
|
if err != nil {
|
|
t.Fatalf("second run: %v", err)
|
|
}
|
|
if report.TotalFiles != 2 {
|
|
t.Errorf("TotalFiles: want 2, got %d", report.TotalFiles)
|
|
}
|
|
|
|
// Verify no duplicates — exactly 2 rows
|
|
regDB, err := SQLiteOpen(filepath.Join(root, "registry.db"), "")
|
|
if err != nil {
|
|
t.Fatalf("open registry.db: %v", err)
|
|
}
|
|
defer regDB.Close()
|
|
|
|
var count int
|
|
if err := regDB.QueryRow(`SELECT COUNT(*) FROM vault_files`).Scan(&count); err != nil {
|
|
t.Fatalf("count vault_files: %v", err)
|
|
}
|
|
if count != 2 {
|
|
t.Errorf("vault_files count after re-run: want 2, got %d", count)
|
|
}
|
|
}
|