Files
2026-06-22 16:06:57 +02:00

84 lines
2.8 KiB
Go

package storage
import (
"net/http"
"os"
"path/filepath"
"strings"
"testing"
"nadir/internal/oscmd"
"github.com/danielgtaylor/huma/v2"
"github.com/danielgtaylor/huma/v2/adapters/humago"
"github.com/danielgtaylor/huma/v2/humatest"
)
func TestStorageHandlers(t *testing.T) {
path := filepath.Join(t.TempDir(), "fstab")
if err := os.WriteFile(path, []byte("# seed\nUUID=root / ext4 defaults 0 1\n"), 0644); err != nil {
t.Fatal(err)
}
old := fstabFile
fstabFile = path
defer func() { fstabFile = old }()
mux := http.NewServeMux()
api := humatest.Wrap(t, humago.New(mux, huma.DefaultConfig("Test", "1.0.0")))
New().Register(api)
mountOK := true
oscmd.SetMock("mount", func([]string) oscmd.MockCommand {
if mountOK {
return oscmd.MockCommand{ExitCode: 0}
}
return oscmd.MockCommand{Stderr: "mount: wrong fs type", ExitCode: 32}
})
oscmd.SetMock("umount", func([]string) oscmd.MockCommand { return oscmd.MockCommand{ExitCode: 0} })
defer oscmd.ClearMocks()
body := map[string]any{"device": "/dev/sdb1", "mountpoint": "/mnt/data", "fstype": "ext4"}
// Add + mount succeeds.
if resp := api.Post("/api/storage/mounts", body); resp.Code != http.StatusOK {
t.Fatalf("add mount: got %d, body=%s", resp.Code, resp.Body.String())
}
if findEntry(mustReadFstab(t), "/mnt/data") == nil {
t.Fatal("entry not written to fstab")
}
// Duplicate mountpoint → 409.
if resp := api.Post("/api/storage/mounts", body); resp.Code != http.StatusConflict {
t.Errorf("duplicate: got %d, want 409", resp.Code)
}
// mount fails → 400 and the fstab line is rolled back.
mountOK = false
bad := map[string]any{"device": "/dev/sdc1", "mountpoint": "/mnt/bad", "fstype": "ext4"}
if resp := api.Post("/api/storage/mounts", bad); resp.Code != http.StatusBadRequest {
t.Errorf("failed mount: got %d, want 400", resp.Code)
}
if findEntry(mustReadFstab(t), "/mnt/bad") != nil {
t.Error("fstab entry not rolled back after mount failure")
}
// Invalid device is rejected before touching the system.
if resp := api.Post("/api/storage/mounts", map[string]any{"device": "/dev/x; rm", "mountpoint": "/mnt/x", "fstype": "ext4"}); resp.Code != http.StatusBadRequest {
t.Errorf("invalid device: got %d, want 400", resp.Code)
}
// Delete the good entry (not actually mounted, so no umount needed).
if resp := api.Delete("/api/storage/mounts?mountpoint=/mnt/data"); resp.Code != http.StatusOK {
t.Errorf("delete: got %d, body=%s", resp.Code, resp.Body.String())
}
data, _ := os.ReadFile(path)
if strings.Contains(string(data), "/mnt/data") || !strings.Contains(string(data), "# seed") {
t.Errorf("delete result wrong:\n%s", data)
}
// Deleting a nonexistent mountpoint → 404.
if resp := api.Delete("/api/storage/mounts?mountpoint=/mnt/none"); resp.Code != http.StatusNotFound {
t.Errorf("delete missing: got %d, want 404", resp.Code)
}
}