package main import ( "errors" "strings" "testing" "github.com/novox/mesh-controller/internal/conditions" ) // The verbs of the condition store (novox/hq to-be 45 ยง2) as the console reaches them, and status led // by what is open. func TestTheConditionsVerbComposesEachShape(t *testing.T) { for _, c := range []struct { args map[string]any want string }{ {map[string]any{}, "conditions --json"}, {map[string]any{"severity": "urgent", "machine": "ace"}, "conditions --json --severity urgent --machine ace"}, {map[string]any{"key": "machine.ace.silent"}, "conditions show machine.ace.silent --json"}, {map[string]any{"history": "true", "days": "3", "key": "machine.ace.silent"}, "conditions history --json --days 3 --key machine.ace.silent"}, {map[string]any{"silence": "machine.ace.silent", "for": "2h", "why": "on the train"}, "conditions silence machine.ace.silent --for 2h --why on the train"}, {map[string]any{"run": "true"}, "doctor run --json"}, {map[string]any{}, "doctor --json"}, } { verb := "conditions" if strings.HasPrefix(c.want, "doctor") { verb = "doctor" } argv, err := argvFor(verb, c.args) if err != nil || strings.Join(argv, " ") != c.want { t.Errorf("%s %v composed %q (%v), want %q", verb, c.args, strings.Join(argv, " "), err, c.want) } } for _, c := range []struct { verb string args map[string]any }{ {"conditions", map[string]any{"silence": "machine.ace.silent", "why": "x"}}, // no for {"doctor", map[string]any{"run": "true", "signals": "true"}}, // two at once {"conditions", map[string]any{"silence": "machine.ace.silent", "for": "1h", "why": "x", "days": "3"}}, // passed over } { if argv, err := argvFor(c.verb, c.args); err == nil { t.Errorf("%s %v composed %v", c.verb, c.args, argv) } } if repairingCommand([]string{"conditions", "silence", "k"}) != "conditions silence" { t.Error("a silence is not a hand act") } } // **A silence through the verb is recorded and bounded**; the condition stays open. func TestASilenceThroughTheVerbHoldsAndTheConditionStaysOpen(t *testing.T) { k, _ := withConditionsInMemory(t) ctx := t.Context() if _, err := k.Observe(ctx, conditions.Observation{Scope: conditions.ScopeMachine, ID: "ace", Kind: "silent", Severity: conditions.Warning, Summary: "ace is silent", Source: "S1"}); err != nil { t.Fatal(err) } if err := conditionsCommand(ctx, []string{"silence", "machine.ace.silent", "--for", "2d"}); err == nil { t.Fatal("silenced without saying why") } if err := conditionsCommand(ctx, []string{"silence", "machine.ace.silent", "--for", "8d", "--why", "x"}); err == nil { t.Fatal("silenced for more than a week") } said := printed(t, func() error { return conditionsCommand(ctx, []string{"silence", "machine.ace.silent", "--for", "2d", "--why", "on the train"}) }) if !strings.Contains(said, "is silenced until") { t.Fatalf("%s", said) } c, found, _ := k.Get(ctx, "machine.ace.silent") if !found || c.Silenced == nil || c.Silenced.Why != "on the train" { t.Fatalf("%+v", c) } listed := printed(t, func() error { return conditionsCommand(ctx, nil) }) if !strings.Contains(listed, "machine.ace.silent") || !strings.Contains(listed, "silenced until") { t.Fatalf("%s", listed) } } // **Conditions that cannot be read are not none open**: status says so, and is not well. func TestUnreadableConditionsAreNotAWellMesh(t *testing.T) { open := aMesh(t) _, store := withConditionsInMemory(t) store.Fail = errors.New("the bus is away") asked, err := theThreeQuestions(t.Context(), open) if err != nil { t.Fatal(err) } if asked.well() || asked.conditionsUnread == "" { t.Fatalf("well with its conditions unread: %+v", asked.conditionsUnread) } said := printed(t, func() error { return printStatus(asked) }) if !strings.HasPrefix(said, "the open conditions could NOT be read") || strings.Contains(said, "no open conditions") { t.Fatalf("%s", said) } store.Fail = nil asked, _ = theThreeQuestions(t.Context(), open) said = printed(t, func() error { return printStatus(asked) }) if asked.well() && !strings.Contains(said, "no open conditions;") { t.Fatalf("the all-well sentence does not say no conditions are open:\n%s", said) } }