diff --git a/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/integration_test.go b/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/integration_test.go index 09d21fa0..ce7132fd 100644 --- a/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/integration_test.go +++ b/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/integration_test.go @@ -662,8 +662,9 @@ func TestIndexerKeepsManifestsAtAMerge(t *testing.T) { // 1444/AC4, 1449/AC4, 15 js, ctx, _, modules := startIndexer(t, func(ctx context.Context, builds buildLog) { builds.end(t, "novox/mesh-catalog", "avahi", "modules/avahi") }, func(ctx context.Context, js jetstream.JetStream) { - // The verdicts state and the stream of the indexer's events, as the controller makes them from its manifest. - if _, err := js.CreateKeyValue(ctx, jetstream.KeyValueConfig{Bucket: index.VerdictsBucket, History: index.VerdictsHistory}); err != nil { + // The indexer's state unjudged, as the controller makes it from its manifest; the verdicts state is made only once + // the merge is taken in (issue 1966 note 154: a take-in at the start, before the verdicts state's bind). + if _, err := js.CreateKeyValue(ctx, jetstream.KeyValueConfig{Bucket: index.UnjudgedBucket, History: 1}); err != nil { t.Fatal(err) } }) @@ -707,7 +708,20 @@ func TestIndexerKeepsManifestsAtAMerge(t *testing.T) { // 1444/AC4, 1449/AC4, 15 t.Errorf("manifest = %+v err %v, want avahi and the file's bytes", got, err) } - verdicts, err := js.KeyValue(ctx, index.VerdictsBucket) + // 1966 (ADR 0668 §4, note 154): the take-in wrote its four manifests with no verdicts state on the bus, so it keeps + // them in its state unjudged; when the verdicts state binds, each is judged as new (bad refused in full, never as a + // warning), every accepted one is said as manifest-accepted, and the state is left empty. + unjudged, err := js.KeyValue(ctx, index.UnjudgedBucket) + if err != nil { + t.Fatal(err) + } + kept, _ := unjudged.Keys(ctx) + for _, raw := range []string{string(manifest), judged["good"], judged["bad"], judged["later"]} { + if !slices.Contains(kept, meshcatalogclient.ManifestDigest([]byte(raw))) { + t.Errorf("the take-in's new manifest %s is not kept unjudged: the state holds %v", meshcatalogclient.ManifestDigest([]byte(raw)), kept) + } + } + verdicts, err := js.CreateKeyValue(ctx, jetstream.KeyValueConfig{Bucket: index.VerdictsBucket, History: index.VerdictsHistory}) if err != nil { t.Fatal(err) } @@ -732,12 +746,20 @@ func TestIndexerKeepsManifestsAtAMerge(t *testing.T) { // 1444/AC4, 1449/AC4, 15 if !strings.Contains(strings.Join(got["bad"].Problems, " "), `provides "amqp"`) || strings.Join(got["later"].Unknown, " ") != "a-field-from-later" { t.Errorf("the refusal names no problem or the wait no field: %+v", got) } + // The pass ends the state's keys after it wrote and said every verdict. + left, _ := unjudged.Keys(ctx) + for deadline := time.Now().Add(10 * time.Second); len(left) != 0 && time.Now().Before(deadline); time.Sleep(50 * time.Millisecond) { + left, _ = unjudged.Keys(ctx) + } + if len(left) != 0 { + t.Errorf("the state unjudged still holds %v within 10 s, once every manifest has its verdict", left) + } // manifest-refused, said once for each refusal (a wait is no refusal). events, err := js.Stream(ctx, "EVENTS") if err != nil { t.Fatal(err) } - said := map[string]bool{} + said, acceptedSaid := map[string]bool{}, map[string]bool{} for seq := uint64(1); ; seq++ { msg, err := events.GetMsg(ctx, seq) if err != nil { @@ -747,10 +769,17 @@ func TestIndexerKeepsManifestsAtAMerge(t *testing.T) { // 1444/AC4, 1449/AC4, 15 if msg.Subject == "mesh.seat.mesh-catalog.event."+meshcatalog.EventManifestRefused && json.Unmarshal(msg.Data, &r) == nil { said[r.Module] = true } + var a meshcatalog.ManifestAcceptedEvent + if msg.Subject == "mesh.seat.mesh-catalog.event."+meshcatalog.EventManifestAccepted && json.Unmarshal(msg.Data, &a) == nil { + acceptedSaid[a.Module] = true + } } if !said["bad"] || said["later"] || said["good"] { t.Errorf("manifest-refused said for %v, want bad only", said) } + if !acceptedSaid["good"] || acceptedSaid["bad"] || acceptedSaid["later"] { + t.Errorf("manifest-accepted said for %v, want good and no refused or waiting one", acceptedSaid) + } // How a composer holds a refused module by these verdicts is the node-engine's to test (ADR 0593 §7: the composer // and its bus reader are its own). }