package storage import ( "testing" "gitea.dooplex.hu/admin/felhom-agent/internal/hub" ) // Role classification is AGENT-AUTHORITATIVE (the agent's own storage view + host topology). These // assert the demo storages map to the right protection tier, and that ambiguity fails safe to the // MOST-PROTECTED role (system) — never silently user-data. // demoHost models the demo N100: the OS disk /dev/sda (ESP at /dev/sda1, root at /dev/sda2) plus an // external data disk /dev/sdb (felhom-usb at /dev/sdb1). func demoHost() *fakeHostReader { return &fakeHostReader{ mounts: []Mount{ {Device: "/dev/sda2", MountPoint: "/", FSType: "ext4"}, {Device: "/dev/sda1", MountPoint: "/boot/efi", FSType: "vfat"}, {Device: "/dev/sdb1", MountPoint: "/mnt/hdd_1", FSType: "ext4"}, }, } } func TestSystemDisks_FromBootMounts(t *testing.T) { sys, ok := SystemDisks(demoHost()) if !ok { t.Fatal("SystemDisks should resolve the OS disk from / and /boot/efi") } if !sys["/dev/sda"] { t.Fatalf("OS whole-disk /dev/sda not in system set: %v", sys) } if sys["/dev/sdb"] { t.Fatalf("external data disk /dev/sdb wrongly classified as system: %v", sys) } } func TestRoleForStorage_DemoMapping(t *testing.T) { sys, ok := SystemDisks(demoHost()) cases := []struct { name string typ string device string want DeviceRole }{ {"builtin local (root fs)", hub.StorageTypeLocal, "", RoleSystem}, {"local-lvm (lvmthin)", hub.StorageTypeLVMThin, "", RoleSystem}, {"felhom-pbs (backup net)", hub.StorageTypePBS, "", RoleBackup}, {"nfs share", hub.StorageTypeNFS, "", RoleSystem}, {"felhom-usb on external /dev/sdb1", hub.StorageTypeUSB, "/dev/sdb1", RoleUserData}, {"local-dir on external /dev/sdb1", hub.StorageTypeLocalDir, "/dev/sdb1", RoleUserData}, {"usb-typed but ON the system disk", hub.StorageTypeUSB, "/dev/sda2", RoleSystem}, {"local-dir with no device (on root)", hub.StorageTypeLocalDir, "", RoleSystem}, } for _, c := range cases { if got := RoleForStorage(c.typ, c.device, sys, ok); got != c.want { t.Errorf("%s: got role %q, want %q", c.name, got, c.want) } } } func TestRoleForRawDevice_SystemVsUserData(t *testing.T) { sys, ok := SystemDisks(demoHost()) if got := RoleForRawDevice("/dev/sdb1", sys, ok); got != RoleUserData { t.Errorf("external /dev/sdb1: got %q, want user-data", got) } if got := RoleForRawDevice("/dev/sda2", sys, ok); got != RoleSystem { t.Errorf("system /dev/sda2: got %q, want system", got) } // A partition on the OS disk is treated as system (protected), not user-data. if got := RoleForRawDevice("/dev/sda3", sys, ok); got != RoleSystem { t.Errorf("OS-disk partition /dev/sda3: got %q, want system", got) } } // Ambiguity fails safe: if the system disks cannot be determined, EVERY candidate is system. func TestRole_FailsSafeWhenSystemUnknown(t *testing.T) { noMounts := &fakeHostReader{mountsErr: errFake} sys, ok := SystemDisks(noMounts) if ok { t.Fatal("SystemDisks should report not-ok when mounts cannot be read") } if got := RoleForRawDevice("/dev/sdb1", sys, ok); got != RoleSystem { t.Errorf("unknown system disks → external device must default to system, got %q", got) } if got := RoleForStorage(hub.StorageTypeUSB, "/dev/sdb1", sys, ok); got != RoleSystem { t.Errorf("unknown system disks → usb target must default to system, got %q", got) } } var errFake = &fakeErr{} type fakeErr struct{} func (*fakeErr) Error() string { return "fake" }