a43d0423d5
gates / gates (push) Successful in 46s
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
91 lines
4.0 KiB
Go
91 lines
4.0 KiB
Go
package web
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gitea.dooplex.hu/admin/felhom-controller/internal/agentapi"
|
|
"gitea.dooplex.hu/admin/felhom-controller/internal/settings"
|
|
)
|
|
|
|
// R-1084 (v0.318.0, felhom.eu architecture/16 §4): the whole-box backup offer promises survival of a DISK failure only
|
|
// for a drive the agent proves is another disk than the system data. Seen on Tester 1 (a VM): the promise stood next to
|
|
// build A's „cannot check" notice.
|
|
|
|
func offerHarness(t *testing.T, rel map[string]offerRelation, paths ...string) *Server {
|
|
t.Helper()
|
|
var disks []agentapi.DiskInfo
|
|
for _, p := range paths {
|
|
disks = append(disks, agentapi.DiskInfo{Name: p, GuestPath: p, MountPath: "/mnt/" + strings.TrimPrefix(p, "/mnt/felhom-drives/"), Role: "user-data"})
|
|
}
|
|
s := absentHarness(t, "local", disks, "")
|
|
for _, p := range paths {
|
|
if err := s.settings.AddStoragePath(settings.StoragePath{Path: p, Label: "Meghajtó " + p}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
s.sameDiskFn = func(_ context.Context, drive, sysData string) offerRelation {
|
|
if sysData != "/mnt/sys_drive" {
|
|
t.Errorf("the offer must compare against the system data path, got %q", sysData)
|
|
}
|
|
return rel[drive]
|
|
}
|
|
return s
|
|
}
|
|
|
|
const drvA, drvB = "/mnt/felhom-drives/hdd_1", "/mnt/felhom-drives/hdd_2"
|
|
|
|
func TestR1084_ProvenDifferentDiskKeepsThePromise(t *testing.T) {
|
|
s := offerHarness(t, map[string]offerRelation{drvA: offerDifferent}, drvA)
|
|
v := s.backupTargetView(context.Background(), "hu")
|
|
if v == nil || v.OfferPath != drvA || v.OfferText != huText(t, backupTargetOfferKey) {
|
|
t.Fatalf("a proven different disk: want today's offer, got %+v", v)
|
|
}
|
|
}
|
|
|
|
func TestR1084_UnprovenDiskIsOfferedWithoutThePromise(t *testing.T) {
|
|
s := offerHarness(t, map[string]offerRelation{drvA: offerUnknown}, drvA)
|
|
v := s.backupTargetView(context.Background(), "hu")
|
|
if v == nil || v.OfferPath != drvA {
|
|
t.Fatalf("an unproven disk is still offered, got %+v", v)
|
|
}
|
|
if strings.Contains(v.OfferText, "így egy lemezhiba után is vissza tudod") || !strings.Contains(v.OfferText, "nem tudja ellenőrizni") {
|
|
t.Fatalf("an unproven disk must not carry the disk-failure promise; got %q", v.OfferText)
|
|
}
|
|
}
|
|
|
|
func TestR1084_SameDiskIsNeverOffered(t *testing.T) {
|
|
s := offerHarness(t, map[string]offerRelation{drvA: offerSame}, drvA)
|
|
if v := s.backupTargetView(context.Background(), "hu"); v == nil || v.OfferPath != "" {
|
|
t.Fatalf("a drive on the system disk must not be offered as the backup place, got %+v", v)
|
|
}
|
|
}
|
|
|
|
func TestR1084_AProvenDiskWinsOverAnUnprovenOne(t *testing.T) {
|
|
s := offerHarness(t, map[string]offerRelation{drvA: offerUnknown, drvB: offerDifferent}, drvA, drvB)
|
|
if v := s.backupTargetView(context.Background(), "hu"); v == nil || v.OfferPath != drvB || v.OfferText != huText(t, backupTargetOfferKey) {
|
|
t.Fatalf("the proven different disk must be offered first, got %+v", v)
|
|
}
|
|
}
|
|
|
|
// An agent older than 0.157.0 cannot judge: today's offer stays (build A's rule for an older agent).
|
|
func TestR1084_OlderAgentKeepsTodaysOffer(t *testing.T) {
|
|
s := offerHarness(t, map[string]offerRelation{drvA: offerLegacy}, drvA)
|
|
if v := s.backupTargetView(context.Background(), "hu"); v == nil || v.OfferPath != drvA || v.OfferText != huText(t, backupTargetOfferKey) {
|
|
t.Fatalf("an older agent: want today's offer, got %+v", v)
|
|
}
|
|
}
|
|
|
|
// The internal place is never the whole-box backup place (it is the system disk).
|
|
func TestR1084_InternalPlaceIsNeverOffered(t *testing.T) {
|
|
s := absentHarness(t, "local", []agentapi.DiskInfo{{Name: "belso", GuestPath: "/mnt/felhom-drives/belso", MountPath: "/mnt/belso", Role: "user-data", Kind: agentapi.PlaceKindInternal}}, "")
|
|
if err := s.settings.AddStoragePath(settings.StoragePath{Path: "/mnt/felhom-drives/belso", Kind: settings.StorageKindInternal}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
s.sameDiskFn = func(context.Context, string, string) offerRelation { return offerLegacy } // even an old judge
|
|
if v := s.backupTargetView(context.Background(), "hu"); v == nil || v.OfferPath != "" {
|
|
t.Fatalf("the internal place must not be offered, got %+v", v)
|
|
}
|
|
}
|