159 lines
3.8 KiB
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)
|
|
}
|
|
}
|
|
}
|