diff --git a/internal/selfcompose/entries_test.go b/internal/selfcompose/entries_test.go index ec56a5ce..15b6dd4e 100644 --- a/internal/selfcompose/entries_test.go +++ b/internal/selfcompose/entries_test.go @@ -7,6 +7,7 @@ import ( "strings" "sync" "testing" + "time" "git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient" "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner" @@ -57,7 +58,16 @@ func composeFromEntries(t *testing.T) { var held map[string]string env := b.env() env.Entry, env.ComposedState = EntryCall(ask), state - env.Refused = func(_ string, h map[string]string) { mu.Lock(); held = h; mu.Unlock() } + refused := make(chan struct{}, 1) // fed at each refusal the composer says, so a wait follows what it says, not a pause + env.Refused = func(_ string, h map[string]string) { + mu.Lock() + held = h + mu.Unlock() + select { + case refused <- struct{}{}: + default: + } + } told := map[string]bool{} env.EntryNotFound = func(fp string, notFound bool) { mu.Lock(); told[fp] = notFound; mu.Unlock() } c := New(env) @@ -93,9 +103,21 @@ func composeFromEntries(t *testing.T) { } b.mu.Unlock() // A want whose entry the half holds none of is held, saying entry-missing and the fingerprint; the rest is composed. - mu.Lock() - why := held["ghost"] - mu.Unlock() + // The ghost's entry is asked first and answered not found after: wait until the refusal says entry-missing. + var why string + for deadline := time.After(10 * time.Second); !strings.HasPrefix(why, agent.EntryMissing); { + mu.Lock() + why = held["ghost"] + mu.Unlock() + if strings.HasPrefix(why, agent.EntryMissing) { + break + } + select { + case <-refused: + case <-deadline: + t.Fatalf("the ghost's reason is still %q after 10 s, want %s", why, agent.EntryMissing) + } + } if !strings.HasPrefix(why, agent.EntryMissing) || !strings.Contains(why, ghost) || held["lemurs"] != "" { t.Errorf("held %q, want ghost held with %s naming %s", held, agent.EntryMissing, ghost) }