84 lines
2.8 KiB
Go
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)
|
|
}
|
|
}
|