c0f3e12483
statfs fsclass helper (network/autofs/stub/unknown, fail-open); probe not_network_fs assertion (stub can never verify — red-proven); deploy-time stub refusal (idle autofs proceeds — red-proven); distinct stub badge, stub wins over unreachable (unreachable line byte-identical); deployed select shows stored HDD_PATH (red-proven vs IsDefault-only). MinAgent unchanged 0.81.0. Gates green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
69 lines
2.6 KiB
Go
69 lines
2.6 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|