Files
felhom-controller/controller/internal/web/internal_place_test.go
T
admin a43d0423d5
gates / gates (push) Successful in 46s
v0.318.0: the internal data place, partitions, an honest whole-box backup offer (R-1084), sys_drive never offered (R-1082)
felhom.eu architecture/16 §4-§6 (build B). MinAgent 0.157.0 — the internal place and the partitions appear only when
agent >= 0.158.0 reports them. Tests red-proved; four parity fixtures refreshed (only the new lines).

Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
2026-10-16 03:57:49 +02:00

104 lines
4.1 KiB
Go

package web
import (
"context"
"net/http/httptest"
"path/filepath"
"strings"
"testing"
"gitea.dooplex.hu/admin/felhom-controller/internal/agentapi"
"gitea.dooplex.hu/admin/felhom-controller/internal/settings"
)
// The internal data place (felhom.eu architecture/16 §5, v0.318.0): bound and registered with no press, the default
// drive when there is no other, never ejected, retired or formatted.
func internalRow(gp string, bound bool) agentapi.DiskInfo {
return agentapi.DiskInfo{Name: "belso", Kind: agentapi.PlaceKindInternal, MountPath: "/mnt/belso", GuestPath: gp,
BoundUnderParent: bound, Role: "user-data"}
}
func TestInternalPlace_UnboundIsBoundNotYetRegistered(t *testing.T) {
s := testServer(t)
gp := filepath.Join(t.TempDir(), "belso")
ag := &mockAgent{}
s.ensureInternalPlace(context.Background(), ag, []agentapi.DiskInfo{internalRow(gp, false)})
if len(ag.guestAttachCalls) != 1 || ag.guestAttachCalls[0] != "/mnt/belso" {
t.Fatalf("want one guest bind of /mnt/belso, got %v", ag.guestAttachCalls)
}
if n := len(s.settings.GetStoragePaths()); n != 0 {
t.Fatalf("an unbound place must not be registered yet, got %d path(s)", n)
}
}
func TestInternalPlace_BoundIsRegisteredAsTheDefaultDrive(t *testing.T) {
s := testServer(t)
gp := filepath.Join(t.TempDir(), "belso")
ag := &mockAgent{}
s.ensureInternalPlace(context.Background(), ag, []agentapi.DiskInfo{internalRow(gp, true)})
paths := s.settings.GetStoragePaths()
if len(paths) != 1 {
t.Fatalf("want the internal place registered once, got %+v", paths)
}
sp := paths[0]
if sp.Path != gp || !sp.IsInternal() || !sp.IsDefault || !sp.Schedulable || sp.Label == "" || strings.Contains(sp.Label, ".") {
t.Fatalf("registered as: %+v", sp)
}
if len(ag.guestAttachCalls) != 0 {
t.Fatalf("a bound place needs no new bind, got %v", ag.guestAttachCalls)
}
// Idempotent: the next tick changes nothing.
s.ensureInternalPlace(context.Background(), ag, []agentapi.DiskInfo{internalRow(gp, true)})
if n := len(s.settings.GetStoragePaths()); n != 1 {
t.Fatalf("a second tick must not register it again, got %d", n)
}
}
func TestInternalPlace_HouseholdDefaultStaysDefault(t *testing.T) {
s := testServer(t)
usb := filepath.Join(t.TempDir(), "hdd_1")
if err := s.settings.AddStoragePath(settings.StoragePath{Path: usb, IsDefault: true, Schedulable: true}); err != nil {
t.Fatal(err)
}
gp := filepath.Join(t.TempDir(), "belso")
s.ensureInternalPlace(context.Background(), &mockAgent{}, []agentapi.DiskInfo{internalRow(gp, true)})
for _, sp := range s.settings.GetStoragePaths() {
if sp.Path == gp && sp.IsDefault {
t.Fatalf("the household's own default drive must stay the default")
}
if sp.Path == usb && !sp.IsDefault {
t.Fatalf("the USB default was taken away")
}
}
}
func TestInternalPlace_OtherKindsAreNotTouched(t *testing.T) {
s := testServer(t)
ag := &mockAgent{}
usb := agentapi.DiskInfo{Name: "hdd_1", Kind: "disk", MountPath: "/mnt/hdd_1", GuestPath: filepath.Join(t.TempDir(), "hdd_1"), BoundUnderParent: false}
s.ensureInternalPlace(context.Background(), ag, []agentapi.DiskInfo{usb})
if len(ag.guestAttachCalls) != 0 || len(s.settings.GetStoragePaths()) != 0 {
t.Fatalf("a household drive is enrolled only by the household: attach=%v paths=%v", ag.guestAttachCalls, s.settings.GetStoragePaths())
}
}
// Eject, decommission and wipe of the internal place are refused in words. Positive control: a normal drive path is
// not refused by this gate.
func TestInternalPlace_LifecycleRefused(t *testing.T) {
s := testServer(t)
gp := filepath.Join(t.TempDir(), "belso")
s.ensureInternalPlace(context.Background(), &mockAgent{}, []agentapi.DiskInfo{internalRow(gp, true)})
r := httptest.NewRequest("POST", "/api/storage/eject", nil)
w := httptest.NewRecorder()
if !s.refuseInternalLifecycle(w, r, gp+"/") {
t.Fatalf("the internal place must be refused")
}
if w.Code != 400 || !strings.Contains(w.Body.String(), "lemez") {
t.Fatalf("refusal: %d %s", w.Code, w.Body.String())
}
if s.refuseInternalLifecycle(httptest.NewRecorder(), r, "/mnt/felhom-drives/hdd_1") {
t.Fatalf("positive control: a household drive is not refused by this gate")
}
}