verstak/internal/core/files/file_test.go

159 lines
3.8 KiB
Go

package files
import (
"os"
"path/filepath"
"testing"
"verstak/internal/core/storage"
)
func openTestDB(t *testing.T) *storage.DB {
t.Helper()
dir := t.TempDir()
db, err := storage.Open(filepath.Join(dir, "test.db"))
if err != nil {
t.Fatalf("open db: %v", err)
}
t.Cleanup(func() { db.Close() })
return db
}
func TestAddExternal(t *testing.T) {
db := openTestDB(t)
// Run migration 002 manually since storage.Open already applied it.
// We can verify the table exists by inserting.
filesSvc := NewService(db, t.TempDir())
// Create a real temp file to register.
tmpDir := t.TempDir()
tmpFile := filepath.Join(tmpDir, "test.txt")
if err := os.WriteFile(tmpFile, []byte("hello world"), 0o640); err != nil {
t.Fatal(err)
}
rec, err := filesSvc.AddExternal("node-1", tmpFile)
if err != nil {
t.Fatalf("AddExternal: %v", err)
}
if rec.ID == "" {
t.Fatal("empty id")
}
if rec.Filename != "test.txt" {
t.Errorf("filename = %q", rec.Filename)
}
if rec.StorageMode != "external" {
t.Errorf("mode = %q", rec.StorageMode)
}
if rec.Size != 11 {
t.Errorf("size = %d, want 11", rec.Size)
}
// Verify stored.
got, err := filesSvc.Get(rec.ID)
if err != nil {
t.Fatal(err)
}
if got.Filename != "test.txt" {
t.Errorf("got filename = %q", got.Filename)
}
}
func TestCopyIntoVault(t *testing.T) {
db := openTestDB(t)
vaultRoot := t.TempDir()
svc := NewService(db, vaultRoot)
// Source file.
srcDir := t.TempDir()
srcFile := filepath.Join(srcDir, "doc.pdf")
os.WriteFile(srcFile, []byte("PDF content here"), 0o640)
rec, err := svc.CopyIntoVault("node-1", srcFile, "my-node")
if err != nil {
t.Fatalf("CopyIntoVault: %v", err)
}
if rec.SHA256 == "" {
t.Error("expected sha256")
}
if rec.StorageMode != "vault" {
t.Errorf("mode = %q", rec.StorageMode)
}
// Verify file on disk.
if _, err := os.Stat(filepath.Join(vaultRoot, rec.Path)); err != nil {
t.Errorf("file on disk: %v", err)
}
}
func TestListByNode(t *testing.T) {
db := openTestDB(t)
svc := NewService(db, t.TempDir())
os.WriteFile(filepath.Join(t.TempDir(), "a.txt"), []byte("a"), 0o640)
f1 := filepath.Join(t.TempDir(), "a1.txt")
f2 := filepath.Join(t.TempDir(), "a2.txt")
os.WriteFile(f1, []byte("a"), 0o640)
os.WriteFile(f2, []byte("bb"), 0o640)
svc.AddExternal("node-a", f1)
svc.AddExternal("node-a", f2)
list, err := svc.ListByNode("node-a")
if err != nil {
t.Fatal(err)
}
if len(list) != 2 {
t.Errorf("list len = %d, want 2", len(list))
}
}
func TestDeleteToTrash(t *testing.T) {
db := openTestDB(t)
vaultRoot := t.TempDir()
svc := NewService(db, vaultRoot)
src := filepath.Join(t.TempDir(), "important.pdf")
os.WriteFile(src, []byte("important data"), 0o640)
rec, _ := svc.CopyIntoVault("node-x", src, "node-x")
if err := svc.DeleteToTrash(rec.ID); err != nil {
t.Fatalf("DeleteToTrash: %v", err)
}
// File record should be gone.
if _, err := svc.Get(rec.ID); err == nil {
t.Error("expected error after trash")
}
// Original file should not exist anymore (moved to trash).
if _, err := os.Stat(filepath.Join(vaultRoot, rec.Path)); !os.IsNotExist(err) {
t.Error("expected file to be moved from original location")
}
// Trash dir should have it.
trashDir := filepath.Join(vaultRoot, ".verstak", "trash")
entries, _ := os.ReadDir(trashDir)
if len(entries) != 1 {
t.Errorf("trash entries = %d, want 1", len(entries))
}
}
func TestGuessMIME(t *testing.T) {
cases := map[string]string{
"a.md": "text/plain",
"a.png": "image/png",
"a.pdf": "application/pdf",
"a.docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"a.go": "text/plain",
"a.unknown": "application/octet-stream",
}
for name, want := range cases {
got := guessMIME(name)
if got != want {
t.Errorf("guessMIME(%q) = %q, want %q", name, got, want)
}
}
}