package api import ( "io" "log" "path/filepath" "strings" "testing" "gitea.dooplex.hu/admin/felhom-controller/internal/settings" "gitea.dooplex.hu/admin/felhom-controller/internal/system" ) func newDeployGateRouter(t *testing.T, class string) *Router { t.Helper() lg := log.New(io.Discard, "", 0) sett, err := settings.Load(filepath.Join(t.TempDir(), "settings.json"), lg) if err != nil { t.Fatal(err) } if err := sett.AddStoragePath(settings.StoragePath{ Path: "/mnt/felhom-drives/nas-media", Label: "NAS", Schedulable: true, Kind: settings.StorageKindNetwork, }); err != nil { t.Fatal(err) } if err := sett.AddStoragePath(settings.StoragePath{ Path: "/mnt/felhom-drives/felhom-usb", Label: "USB", Schedulable: true, }); err != nil { t.Fatal(err) } r := &Router{sett: sett, logger: lg} r.classifyFSPath = func(string) string { return class } return r } // The deploy-time stub gate (RCA fix 2): a registered network HDD_PATH that classifies as a STUB // in this namespace refuses with the §2.3 Hungarian message; the healthy idle autofs trigger, a // live mount, an unknown verdict (fail open), local paths and empty paths all proceed. // Companion red-proofs: // - remove the gate call from deployStack → the refusal test fails (deploy proceeds onto a stub); // - an impl requiring MOUNTED-only (refusing autofs) → the idle-autofs row fails (it would // wrongly block deploying onto a healthy idle share). func TestRefuseNetworkStubDeploy_Table(t *testing.T) { cases := []struct { name string class string hdd string refuse bool }{ {"stub on network path → REFUSE", system.FSClassStub, "/mnt/felhom-drives/nas-media", true}, {"idle autofs on network path → proceed (healthy)", system.FSClassAutofs, "/mnt/felhom-drives/nas-media", false}, {"live network fs → proceed", system.FSClassNetwork, "/mnt/felhom-drives/nas-media", false}, {"unknown (timeout) → proceed (fail open)", system.FSClassUnknown, "/mnt/felhom-drives/nas-media", false}, {"local path → proceed even when classifier says stub", system.FSClassStub, "/mnt/felhom-drives/felhom-usb", false}, {"unregistered path → proceed", system.FSClassStub, "/mnt/elsewhere", false}, {"empty HDD_PATH (SSD app) → proceed", system.FSClassStub, "", false}, } for _, c := range cases { r := newDeployGateRouter(t, c.class) msg := r.refuseNetworkStubDeploy(c.hdd) if c.refuse && !strings.Contains(msg, "a telepítés nem indítható") { t.Errorf("%s: want the refusal message, got %q", c.name, msg) } if !c.refuse && msg != "" { t.Errorf("%s: must proceed, got refusal %q", c.name, msg) } } }