Keep asking on an older bus module and name the real remedy for each grant not held (review of hq issue 353)
A bus module older than its in_force answer read as not held, so a merge before mesh-catalog #166 is live would silence every ask until a person's bus upgrade. Such an answer now falls back to the check main makes (is the list sent to the bus's machine the one composed now), says the reload is not confirmed, and each case names its own remedy: push <node> for a list behind or not allowing it, a ~5 s wait for a reload, the bus upgrade when an older module's list cannot be judged.
This commit is contained in:
@@ -871,24 +871,102 @@ func TestTheControllersOwnGrantToAskIsReadFromTheComposition(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// The bus module's answer: in force only when it says so in so many words.
|
||||
func TestTheBusModulesAnswerIsInForceOnlyWhenItSaysSo(t *testing.T) {
|
||||
// The bus module's answer, judged with the check before it as the floor (the review of PR 188): an answer
|
||||
// without in_force is an older module, judged by whether the list sent to its machine is the one composed now;
|
||||
// each way it is not held names its own remedy.
|
||||
func TestTheBusModulesAnswerNamesTheRemedyForEachCase(t *testing.T) {
|
||||
for _, c := range []struct {
|
||||
answer string
|
||||
want bool
|
||||
says string
|
||||
name, answer string
|
||||
behind bool
|
||||
behindErr error
|
||||
held bool
|
||||
says, not string
|
||||
}{
|
||||
{`{"allowed":true,"in_force":true}`, true, ""},
|
||||
{`{"allowed":true,"in_force":false,"why":"the server has not reloaded since it was written"}`, false, "not reloaded"},
|
||||
{`{"allowed":false,"in_force":false}`, false, "not in force"},
|
||||
{`{"allowed":true}`, false, "older than that answer"},
|
||||
{`{"allowed":false,"in_force":true}`, false, "not allowed"},
|
||||
{`not json`, false, "could not be read"},
|
||||
{"in force", `{"allowed":true,"in_force":true}`, false, nil, true, "", "push"},
|
||||
{"in force, list behind by the record", `{"allowed":true,"in_force":true}`, true, nil, true, "", "push"},
|
||||
{"written, not reloaded", `{"allowed":true,"in_force":false,"why":"the server has not reloaded since it was written"}`,
|
||||
false, nil, false, "within about 5 s", "push"},
|
||||
{"not allowed", `{"allowed":false,"in_force":false}`, false, nil, false, "`push anchor` carries it", "5 s"},
|
||||
{"in force and not allowed", `{"allowed":false,"in_force":true}`, false, nil, false, "`push anchor`", "5 s"},
|
||||
{"older module, list current", `{"allowed":true}`, false, nil, true, "not confirmed", "push"},
|
||||
{"older module, list behind", `{"allowed":true}`, true, nil, false, "`push anchor` carries it", "5 s"},
|
||||
{"older module, list not allowed", `{"allowed":false}`, false, nil, false, "`push anchor` carries it", "5 s"},
|
||||
{"older module, list unknown", `{"allowed":true}`, false, errors.New("the store is away"), false, "`bus upgrade`", "push"},
|
||||
{"not json", `not json`, false, nil, false, "could not be read", ""},
|
||||
} {
|
||||
if got, why := grantInForce(json.RawMessage(c.answer)); got != c.want || !strings.Contains(why, c.says) {
|
||||
t.Errorf("%s: %v %q", c.answer, got, why)
|
||||
judge := busGrantBy(
|
||||
func(context.Context) (string, json.RawMessage, error) {
|
||||
return "anchor", json.RawMessage(c.answer), nil
|
||||
},
|
||||
func(context.Context) (string, bool, error) { return "anchor", c.behind, c.behindErr })
|
||||
held, why, _ := judgeGrantOnce(judge)
|
||||
if held != c.held || !strings.Contains(why, c.says) || (c.not != "" && strings.Contains(why, c.not)) {
|
||||
t.Errorf("%s: held %v (%q)", c.name, held, why)
|
||||
}
|
||||
}
|
||||
none := busGrantBy(func(context.Context) (string, json.RawMessage, error) { return "", nil, nil }, nil)
|
||||
if held, why, _ := judgeGrantOnce(none); held || !strings.Contains(why, "no module holds the bus") {
|
||||
t.Errorf("no bus: held %v (%q)", held, why)
|
||||
}
|
||||
}
|
||||
|
||||
// judgeGrantOnce is the whole judgement with the composed grant held, as the asker makes it.
|
||||
func judgeGrantOnce(bus grantJudge) (bool, string, error) {
|
||||
yes := func(context.Context) (bool, string, error) { return true, "", nil }
|
||||
return grantHeldBy(yes, bus, time.Now)(context.Background())
|
||||
}
|
||||
|
||||
// The order the review of PR 188 found: this controller live before the bus module that answers in_force. An
|
||||
// older module with the list sent current asks; with the list behind it asks nothing and the condition names the
|
||||
// push; a new module that has not reloaded names the wait, not a push.
|
||||
func TestAnOlderBusModuleNeitherSilencesTheAsksNorNamesTheWrongRemedy(t *testing.T) {
|
||||
for _, c := range []struct {
|
||||
name, answer string
|
||||
behind bool
|
||||
asks bool
|
||||
says, not string
|
||||
}{
|
||||
{"older module, list current", `{"allowed":true}`, false, true, "", ""},
|
||||
{"older module, list behind", `{"allowed":true}`, true, false, "`push anchor` carries it", "5 s"},
|
||||
{"new module, not reloaded", `{"allowed":true,"in_force":false,"why":"the server has not reloaded since it was written"}`,
|
||||
false, false, "within about 5 s", "push"},
|
||||
} {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
r := newAskerRig(t)
|
||||
var raised [][]conditions.Observation
|
||||
r.a.raise = func(_ context.Context, obs []conditions.Observation) error {
|
||||
raised = append(raised, obs)
|
||||
return nil
|
||||
}
|
||||
yes := func(context.Context) (bool, string, error) { return true, "", nil }
|
||||
r.a.grantHeld = grantHeldBy(yes, busGrantBy(
|
||||
func(context.Context) (string, json.RawMessage, error) {
|
||||
return "anchor", json.RawMessage(c.answer), nil
|
||||
},
|
||||
func(context.Context) (string, bool, error) { return "anchor", c.behind, nil }),
|
||||
func() time.Time { return r.now })
|
||||
r.open = []conditions.Condition{heldCondition()}
|
||||
_ = r.a.reconcile(context.Background())
|
||||
sent := r.asksSent(t)
|
||||
if c.asks {
|
||||
if len(sent) != 1 || sent[0].About != heldCondition().Key {
|
||||
t.Fatalf("not asked: %+v", sent)
|
||||
}
|
||||
return
|
||||
}
|
||||
if len(sent) != 0 {
|
||||
t.Fatalf("asked while the bus does not hold the grant: %+v", sent)
|
||||
}
|
||||
if len(raised) == 0 || len(raised[len(raised)-1]) != 1 ||
|
||||
raised[len(raised)-1][0].Kind != "asks-undelivered" {
|
||||
t.Fatalf("not said as undelivered: %+v", raised)
|
||||
}
|
||||
summary := raised[len(raised)-1][0].Summary
|
||||
if !strings.Contains(summary, c.says) || (c.not != "" && strings.Contains(summary, c.not)) {
|
||||
t.Errorf("the condition names the wrong remedy: %q", summary)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// The serving asker is wired to the real judgement: with records and a bus it cannot read, the grant is not
|
||||
|
||||
Reference in New Issue
Block a user