Files

74 lines
2.8 KiB
Go

package api
import (
"context"
"git.misaka.ren/m1saka/dsh-web/internal/store"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestOrphanReclaimGuards(t *testing.T) {
for _, kind := range []string{"safe", "legacy", "shared", "running", "foreign-mount", "reference", "upgrade", "confirmation", "nonadmin"} {
t.Run(kind, func(t *testing.T) {
t.Setenv("HOST_DATA_ROOT", "/host/data")
id, inst, owner := strings.Repeat("a", 64), strings.Repeat("b", 32), strings.Repeat("c", 32)
deleted := false
a, sid := runtimeTestAPI(t, func(w http.ResponseWriter, r *http.Request) {
if r.Method == "DELETE" {
if r.URL.Query().Get("force") != "false" || r.URL.Query().Get("v") != "false" {
t.Fatal("unsafe deletion")
}
deleted = true
w.WriteHeader(204)
return
}
source := "/host/data/workspaces/" + owner + "/instances/" + inst + "/home"
if kind == "foreign-mount" {
source = "/unrelated"
}
mounts := []map[string]string{{"Type": "bind", "Source": source, "Destination": "/workspace"}}
if kind == "legacy" {
mounts[0]["Destination"] = "/data/dsh-home"
mounts = append(mounts, map[string]string{"Type": "bind", "Source": "/host/data/workspaces/" + owner + "/files", "Destination": "/workspace"})
}
if kind == "shared" {
mounts = append(mounts, map[string]string{"Type": "bind", "Source": "/host/data/workspaces/" + owner + "/files", "Destination": "/shared"})
}
writeJSON(w, map[string]any{"Id": id, "Name": "/dsh-inst-" + inst, "Config": map[string]any{"Labels": map[string]string{"dsh-mgr.role": "dsh", "dsh-mgr.instance": inst, "dsh-mgr.owner": owner}}, "State": map[string]any{"Status": "exited", "Running": kind == "running"}, "Mounts": mounts})
})
if err := a.s.CreateUser(store.User{ID: owner, Username: "orphan-owner"}, "unused"); err != nil {
t.Fatal(err)
}
if kind != "nonadmin" {
if _, err := a.s.DB.Exec("UPDATE users SET admin=1 WHERE id='owner'"); err != nil {
t.Fatal(err)
}
}
if kind == "reference" {
if err := a.s.AddInstance(store.Instance{ID: inst, UID: owner, ContainerID: id}); err != nil {
t.Fatal(err)
}
}
if kind == "upgrade" {
if _, err := a.s.DB.Exec("CREATE TABLE upgrade_journal(instance_id TEXT,old_container TEXT,new_container TEXT); INSERT INTO upgrade_journal VALUES(?,?,'')", inst, id); err != nil {
t.Fatal(err)
}
}
if kind == "safe" && a.checkOrphan(context.Background(), id) != nil {
t.Fatal("safe orphan rejected")
}
confirm := id
if kind == "confirmation" {
confirm = "wrong"
}
w := httptest.NewRecorder()
a.orphans(w, runtimeRequest("DELETE", "/api/orphans?id="+id+"&confirm="+confirm, "", sid))
if (w.Code == 200) != (kind == "safe") || deleted != (kind == "safe") {
t.Fatalf("status=%d deleted=%v body=%s", w.Code, deleted, w.Body.String())
}
})
}
}