mavend: centralize action validation boundary (slice 4)
This commit is contained in:
@@ -149,3 +149,101 @@ func TestResolveActionCandidate_AliasMatch(t *testing.T) {
|
||||
t.Errorf("Args = %v, want [роутер]", c.Args)
|
||||
}
|
||||
}
|
||||
|
||||
// --- ValidateActionCandidate tests ---
|
||||
|
||||
// TestValidateActionCandidate_UnresolvedEmptyFn pins that an empty Fn
|
||||
// produces an unresolved result (not invalid).
|
||||
func TestValidateActionCandidate_UnresolvedEmptyFn(t *testing.T) {
|
||||
c := ActionCandidate{}
|
||||
v := ValidateActionCandidate(c)
|
||||
if !v.Unresolved {
|
||||
t.Error("expected unresolved for empty Fn")
|
||||
}
|
||||
if v.Valid {
|
||||
t.Error("unresolved must not be valid")
|
||||
}
|
||||
}
|
||||
|
||||
// TestValidateActionCandidate_UnresolvedMatcherMiss pins that a matcher-miss
|
||||
// candidate (Fn empty, source empty) is unresolved.
|
||||
func TestValidateActionCandidate_UnresolvedMatcherMiss(t *testing.T) {
|
||||
c := ActionCandidate{
|
||||
Producer: RouteProducerLLM,
|
||||
Confidence: 0.5,
|
||||
}
|
||||
v := ValidateActionCandidate(c)
|
||||
if !v.Unresolved {
|
||||
t.Error("expected unresolved for matcher miss")
|
||||
}
|
||||
}
|
||||
|
||||
// TestValidateActionCandidate_ValidRoute pins that a route-resolved candidate
|
||||
// with a non-empty Fn is valid.
|
||||
func TestValidateActionCandidate_ValidRoute(t *testing.T) {
|
||||
c := ActionCandidate{
|
||||
Fn: "restart",
|
||||
Args: []string{"nginx"},
|
||||
Source: ActionSourceRoute,
|
||||
}
|
||||
v := ValidateActionCandidate(c)
|
||||
if v.Unresolved {
|
||||
t.Error("expected resolved, not unresolved")
|
||||
}
|
||||
if !v.Valid {
|
||||
t.Errorf("expected valid, got issues: %v", v.Issues)
|
||||
}
|
||||
}
|
||||
|
||||
// TestValidateActionCandidate_ValidMatcher pins that a matcher-resolved
|
||||
// candidate with a non-empty Fn is valid.
|
||||
func TestValidateActionCandidate_ValidMatcher(t *testing.T) {
|
||||
c := ActionCandidate{
|
||||
Fn: "status",
|
||||
Source: ActionSourceMatcher,
|
||||
}
|
||||
v := ValidateActionCandidate(c)
|
||||
if v.Unresolved {
|
||||
t.Error("expected resolved, not unresolved")
|
||||
}
|
||||
if !v.Valid {
|
||||
t.Errorf("expected valid, got issues: %v", v.Issues)
|
||||
}
|
||||
}
|
||||
|
||||
// TestValidateActionCandidate_ValidNoArgs pins that a zero-arg tool is valid.
|
||||
func TestValidateActionCandidate_ValidNoArgs(t *testing.T) {
|
||||
c := ActionCandidate{
|
||||
Fn: "status",
|
||||
Source: ActionSourceRoute,
|
||||
}
|
||||
v := ValidateActionCandidate(c)
|
||||
if v.Unresolved {
|
||||
t.Error("expected resolved, not unresolved")
|
||||
}
|
||||
if !v.Valid {
|
||||
t.Errorf("expected valid, got issues: %v", v.Issues)
|
||||
}
|
||||
}
|
||||
|
||||
// TestValidateActionCandidate_BlankFn pins that a whitespace-only Fn is
|
||||
// structurally invalid (not unresolved).
|
||||
func TestValidateActionCandidate_BlankFn(t *testing.T) {
|
||||
c := ActionCandidate{
|
||||
Fn: " ",
|
||||
Source: ActionSourceRoute,
|
||||
}
|
||||
v := ValidateActionCandidate(c)
|
||||
if v.Unresolved {
|
||||
t.Error("blank Fn should be invalid, not unresolved")
|
||||
}
|
||||
if v.Valid {
|
||||
t.Error("blank Fn should be invalid")
|
||||
}
|
||||
if len(v.Issues) != 1 {
|
||||
t.Fatalf("expected 1 issue, got %d", len(v.Issues))
|
||||
}
|
||||
if v.Issues[0].Field != FieldFn {
|
||||
t.Errorf("issue field = %q, want fn", v.Issues[0].Field)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user