the record's own tests: never-asked, bounds, fan-out (V-564)
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
package decision
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestFinishNamesTheNeverAsked(t *testing.T) {
|
||||
ctx, rec := With(context.Background(), "какая погода в риме?")
|
||||
Expect(ctx, StageQuery, []string{"calendar", "weather", "search", "kiwix"})
|
||||
Note(ctx, Claim{Stage: StageQuery, Claimant: "calendar", Outcome: Declined})
|
||||
Note(ctx, Claim{Stage: StageQuery, Claimant: "weather", Outcome: Won})
|
||||
|
||||
rec.Finish(time.Now())
|
||||
|
||||
outcomes := map[string]string{}
|
||||
for _, c := range rec.Claims {
|
||||
outcomes[c.Claimant] = c.Outcome
|
||||
}
|
||||
if outcomes["weather"] != Won || rec.Winner != StageQuery+":weather" {
|
||||
t.Errorf("winner = %q, weather = %q", rec.Winner, outcomes["weather"])
|
||||
}
|
||||
if outcomes["calendar"] != Declined {
|
||||
t.Errorf("calendar = %q, want a decline", outcomes["calendar"])
|
||||
}
|
||||
// The two below the winner never looked, and saying so is the whole point.
|
||||
for _, name := range []string{"search", "kiwix"} {
|
||||
if outcomes[name] != NeverAsked {
|
||||
t.Errorf("%s = %q, want %q", name, outcomes[name], NeverAsked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A real 0.0 confidence must not read as "this claimant has no score".
|
||||
func TestScoredKeepsAZeroScore(t *testing.T) {
|
||||
c := Scored(StageRoute, "classifier", "chat", 0, LostOnScore, "")
|
||||
if !c.HasScore || c.Score != 0 {
|
||||
t.Errorf("claim = %+v", c)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoteIfUnclaimedYieldsToARealWinner(t *testing.T) {
|
||||
ctx, rec := With(context.Background(), "x")
|
||||
Note(ctx, Claim{Stage: StageQuery, Claimant: "weather", Outcome: Won})
|
||||
rec.NoteIfUnclaimed(Claim{Stage: StageAction, Claimant: "action-handler"})
|
||||
if rec.Winner != StageQuery+":weather" {
|
||||
t.Errorf("winner = %q, want the query source", rec.Winner)
|
||||
}
|
||||
}
|
||||
|
||||
// A context with no record must cost nothing and crash nothing: that is what
|
||||
// makes the claim sites safe to leave in every test and every fixture run.
|
||||
func TestNoRecorderIsANoOp(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
Note(ctx, Claim{Claimant: "x", Outcome: Won})
|
||||
Expect(ctx, StageQuery, []string{"y"})
|
||||
if From(ctx) != nil {
|
||||
t.Error("bare context reported a record")
|
||||
}
|
||||
From(ctx).NoteIfUnclaimed(Claim{Claimant: "z"})
|
||||
if rec := From(ctx).Finish(time.Now()); rec != nil {
|
||||
t.Error("finishing a nil record produced one")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRingIsBoundedAndNewestFirst(t *testing.T) {
|
||||
r := NewRing()
|
||||
for i := 0; i < ringSize+5; i++ {
|
||||
r.Push(&Record{Utterance: string(rune('a' + i))})
|
||||
}
|
||||
got := r.Recent(ringSize + 10)
|
||||
if len(got) != ringSize {
|
||||
t.Fatalf("kept %d records, want %d", len(got), ringSize)
|
||||
}
|
||||
if got[0].Utterance != string(rune('a'+ringSize+4)) {
|
||||
t.Errorf("newest = %q", got[0].Utterance)
|
||||
}
|
||||
}
|
||||
|
||||
// A query source may fan out to goroutines of its own, so two of them noting at
|
||||
// once must not race. Run under -race, which is where this earns its keep.
|
||||
func TestConcurrentNotes(t *testing.T) {
|
||||
ctx, rec := With(context.Background(), "x")
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 8; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
Note(ctx, Claim{Stage: StageQuery, Claimant: "fanout", Outcome: Declined})
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
if len(rec.Claims) != 8 {
|
||||
t.Errorf("recorded %d claims, want 8", len(rec.Claims))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user