- run.memory.mutex.Lock()
- appended := run.memory.log.Len()
- run.memory.mutex.Unlock()
- require.Equal(t, 2, appended)
-
- close(gate)
- require.Empty(t, <-done)
- require.NoError(t, run.memory.Close())
-
- mutex.Lock()
- defer mutex.Unlock()
-
- require.Equal(t, 2, most)
- require.Equal(t, 3, server.Calls())
-}
-
-func TestTimeTextCountsTheCallsAtOnce(t *testing.T) {
- start := time.Date(2026, 1, 1, 12, 0, 0, 0, time.UTC)
- record := func(offset, seconds float64) usageRecord {
- return usageRecord{
- Date: start.Add(time.Duration(offset * float64(time.Second))).Format(time.RFC3339Nano),
- Seconds: seconds,
- }
- }
-
- text := timeText([]usageRecord{record(0, 10), record(2, 4), record(3, 2), record(10, 10)})
- require.Equal(t, "time: 20 s in all, 6.5 s per call (median 10.0, max 10.0), calls at once: at most 3, 1.3 on average", text)
-}
-
-// probeLog returns count messages of made-up work on a small bakery order
-// system, with the mix of kinds and sizes of syntheticMessage. The same count
-// always gives the same log.
-func probeLog(count int) []probeEntry {
- g := probeWriter{
- random: rand.New(rand.NewPCG(7, 11)),
- }
-
- messages := make([]probeEntry, count)
- for id := range messages {
- kind, text := g.message()
- messages[id] = probeEntry{
- Kind: kind,
- Text: text,
- }
- }
-
- return messages
-}
-
-// probeWriter writes readable made-up messages.
-type probeWriter struct {
- random *rand.Rand
-}
-
-func (g *probeWriter) message() (string, string) {
- roll := g.random.IntN(100)
- switch {
- case roll < 5:
- return "user", g.fill(g.userLine, 10+g.random.IntN(200))
- case roll < 10:
- return "reply", g.fill(g.replyLine, 100+g.random.IntN(1500))
- case roll < 12:
- return "note", g.fill(g.noteLine, 50+g.random.IntN(600))
- case roll < 13:
- return "work", "[" + g.pick(people) + "] report: " + g.fill(g.replyLine, 300+g.random.IntN(3000))
- case roll < 56:
- return "tool", g.toolCall(60 + g.random.IntN(400))
- case roll < 57:
- return "echo", g.fill(g.outputLine, 30000+g.random.IntN(30000))
- default:
- return "echo", g.fill(g.outputLine, 20+g.random.IntN(4000))
- }
-}
-
-// fill joins lines of write until the text has about size bytes.
-func (g *probeWriter) fill(write func() string, size int) string {
- var text strings.Builder
- for text.Len() < size {
- if text.Len() > 0 {
- text.WriteByte(' ')
- }
-
- text.WriteString(write())
- }
-
- return text.String()
-}
-
-func (g *probeWriter) userLine() string {
- return g.pick([]string{
- fmt.Sprintf("Please check why the %s %s.", g.pick(things), g.pick(problems)),
- fmt.Sprintf("Move the %s to %s before %s.", g.pick(things), g.pick(places), g.pick(days)),
- fmt.Sprintf("Thanks, that works. Next, %s.", g.pick(tasks)),
- fmt.Sprintf("No, keep the old %s. %s asked for it.", g.pick(things), g.pick(people)),
- fmt.Sprintf("How many %s orders came in on %s?", g.pick(breads), g.pick(days)),
- })
-}
-
-func (g *probeWriter) replyLine() string {
- return g.pick([]string{
- fmt.Sprintf("I looked at %s. The %s %s because %s.", g.pick(files), g.pick(things), g.pick(problems), g.pick(causes)),
- fmt.Sprintf("I changed %s, and the tests pass now.", g.pick(changes)),
- fmt.Sprintf("There were %d %s orders on %s, %d of them late.", 10+g.random.IntN(90), g.pick(breads), g.pick(days), g.random.IntN(10)),
- fmt.Sprintf("Open question: should %s get %s?", g.pick(people), g.pick(tasks)),
- })
-}
-
-func (g *probeWriter) noteLine() string {
- return g.pick([]string{
- fmt.Sprintf("%s prefers %s.", g.pick(people), g.pick(preferences)),
- fmt.Sprintf("The bakery opens at %d and closes at %d on %s.", 5+g.random.IntN(3), 17+g.random.IntN(4), g.pick(days)),
- })