diff --git a/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/integration_test.go b/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/integration_test.go index 9ab48e5..40c299f 100644 --- a/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/integration_test.go +++ b/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/integration_test.go @@ -281,9 +281,11 @@ func (b *bed) get(t *testing.T, bucket, key string) []byte { return nil } -// 1297/B4 on the bus, 1906/D5: the controller sends ace and g14 builds while the canary ace does not run F healthy yet. -// Started whole, the assigner wants F on the canary, holds g14 back with no want, and writes no difference at all: there -// is no send to compare with (ADR 0539 §8). +// 1297/B4 on the bus, 1906/D5: the controller sends ace, g14 and shanks builds while the canary ace does not run F healthy yet. +// Started whole, the assigner wants F on the canary and writes no difference at all: there is no send to compare with (ADR 0539 +// §8). 1945/AC19, AC21: shanks, which runs the module with no want, gets its first want past the canary rule; g14, which does not +// run it, is held back with no want, so web is on neither list there and the assigner raises the condition naming g14, web and +// the canary rule. func TestWantsAreWrittenAndNoDifferenceIs(t *testing.T) { b := startBed(t, "") fNew, fOld := delivery.SourcePrefix2+strings.Repeat("b", 64), delivery.SourcePrefix2+strings.Repeat("a", 64) @@ -299,16 +301,16 @@ func TestWantsAreWrittenAndNoDifferenceIs(t *testing.T) { gkey, _ := delivery.ControllerGrantKey("web", fNew) grant, _ := delivery.EncodeControllerGrant(delivery.ControllerGrant{}) b.putJSON(t, delivery.ControllerGrantsBucket, gkey, grant) - b.compose(t, "ace", "web", fNew, 'c', delivery.JudgedNeither) - b.compose(t, "g14", "web", fNew, 'c', delivery.JudgedNeither) - for _, node := range []string{"ace", "g14"} { + for _, node := range []string{"ace", "g14", "shanks"} { + b.compose(t, node, "web", fNew, 'c', delivery.JudgedNeither) on, _ := delivery.EncodePresence(delivery.Presence{Online: true}) b.putJSON(t, delivery.PresenceBucket, node, on) - have, _ := delivery.EncodeHave(delivery.Have{FP: fOld, Phase: delivery.PhaseRunning, Health: delivery.HealthOK}) - b.putJSON(t, delivery.HaveBucket, node+".web", have) + if node != "g14" { + have, _ := delivery.EncodeHave(delivery.Have{FP: fOld, Phase: delivery.PhaseRunning, Health: delivery.HealthOK}) + b.putJSON(t, delivery.HaveBucket, node+".web", have) + } + b.putJSON(t, provider.AssignmentsBucket, node+".web", []byte(`{"node":"`+node+`","module":"web","build":"b-`+node+`"}`)) } - b.putJSON(t, provider.AssignmentsBucket, "ace.web", []byte(`{"node":"ace","module":"web","build":"b-8"}`)) - b.putJSON(t, provider.AssignmentsBucket, "g14.web", []byte(`{"node":"g14","module":"web","build":"b-9"}`)) b.start(t) wkey, _ := delivery.WantKey("ace", "web") @@ -316,12 +318,25 @@ func TestWantsAreWrittenAndNoDifferenceIs(t *testing.T) { if err != nil || want.FP != fNew { t.Fatalf("the canary ace's want = %+v, %v", want, err) } - time.Sleep(500 * time.Millisecond) + if w := b.wantNow(t, "shanks", "web", "shanks' first want past the canary rule", func(w delivery.Want) bool { return w.FP == fNew }); w.Composed != "sha256:"+strings.Repeat("c", 64) { + t.Errorf("shanks' want = %+v, want F naming its composition", w) + } + var neither asks.Condition + for deadline := time.Now().Add(10 * time.Second); time.Now().Before(deadline) && neither.Key == ""; time.Sleep(100 * time.Millisecond) { + for k, c := range b.conditionsSaid(t) { + if strings.Contains(k, ".neither.") && c.State == asks.StateRaised { + neither = c + } + } + } + if neither.Subject.Machine != "g14" || neither.Subject.ID != "web" || neither.Severity != asks.SeverityUrgent || !strings.Contains(neither.Explanation, "canary") { + t.Errorf("the condition of web on neither list on g14 = %+v", neither) + } if keys, err := b.buckets[delivery.AssignerDifferencesBucket].Keys(b.ctx); err == nil && len(keys) != 0 { t.Errorf("differences were written: %v", keys) } if e, err := b.buckets[delivery.AssignerWantsBucket].Get(b.ctx, "want.g14.web"); err == nil { - t.Errorf("g14, held back by the canary with no want before, was given one: %s", e.Value()) + t.Errorf("g14, which does not run web and is held back by the canary, was given a want: %s", e.Value()) } } @@ -415,7 +430,7 @@ func TestAFailedDataModuleIsAskedToRestore(t *testing.T) { key := "" for deadline := time.Now().Add(10 * time.Second); time.Now().Before(deadline) && key == ""; time.Sleep(100 * time.Millisecond) { for k, c := range b.conditionsSaid(t) { - if c.State == asks.StateRaised && c.Subject.ID == "mail" { + if c.State == asks.StateRaised && c.Subject.ID == "mail" && strings.Contains(k, ".held.") { if c.Subject.Machine != "ace" || !strings.Contains(c.Explanation, "connection refused") { t.Fatalf("the condition = %+v, want it to name ace and the check's words", c) } @@ -634,8 +649,8 @@ func TestAReleaseAnswerWritesTheWantAgain(t *testing.T) { } for deadline := time.Now().Add(10 * time.Second); time.Now().Before(deadline); time.Sleep(100 * time.Millisecond) { cleared := false - for _, c := range b.conditionsSaid(t) { - cleared = cleared || (c.Subject.ID == "web" && c.State == asks.StateCleared) + for k, c := range b.conditionsSaid(t) { + cleared = cleared || (c.Subject.ID == "web" && c.State == asks.StateCleared && strings.Contains(k, ".held.")) } if cleared { return @@ -805,8 +820,8 @@ func TestAHoldIsLiftedOnceEveryNodeRunsItHealthy(t *testing.T) { if b.hasKey(delivery.AssignerWantsBucket, hkey) || b.hasKey(delivery.AssignerAsksBucket, akey) { continue } - for _, c := range b.conditionsSaid(t) { - if c.Subject.ID == "web" && c.State == asks.StateCleared && strings.Contains(c.Resolved, "lifted its hold by itself") { + for k, c := range b.conditionsSaid(t) { + if c.Subject.ID == "web" && c.State == asks.StateCleared && strings.Contains(k, ".held.") && strings.Contains(c.Resolved, "lifted its hold by itself") { if w := b.wantNow(t, "ace", "web", "the want at the lifted fingerprint", func(w delivery.Want) bool { return w.FP == fNew }); w.Rule != 0 { t.Errorf("the want = %+v", w) }