okami.mom/albedo

git clone https://git.nkp.pet/okami.mom/albedo

Aly Raffauftest(tui): check survivor ownership after trimming5ae5e3d

main
2.1 KiB64 linesraw
1// Trimming must release old descriptors without clearing surviving text.
2// Daemon E2E cannot inspect the TUI's retained memory.
3package tui
4
5import (
6	"fmt"
7	"slices"
8	"strings"
9	"testing"
10)
11
12func TestTrimSettledLinesReleasesDescriptors(t *testing.T) {
13	for _, test := range []struct {
14		name string
15		rows []string
16		kept int
17	}{
18		{name: "row cap", rows: slices.Repeat([]string{"│ short"}, MaxSettledLines+3), kept: MaxSettledLines},
19		{name: "byte cap", rows: slices.Repeat([]string{"│ " + strings.Repeat("x", 512)}, 600), kept: MaxSettledLinesBytes / (len("│ ") + 512 + 3)},
20		{name: "all rows", rows: []string{"small", strings.Repeat("x", MaxSettledLinesBytes+1)}, kept: 0},
21	} {
22		t.Run(test.name, func(t *testing.T) {
23			// Fixed-width suffixes make survivor ordering observable.
24			for i := range test.rows {
25				test.rows[i] += fmt.Sprintf("%03d", i)
26			}
27			old := test.rows
28			want := slices.Clone(old[len(old)-test.kept:])
29			m := ChatModel{Follow: true, settledLines: old, settledLinesBytes: rowBytes(old)}
30			m.trimSettledLines()
31			if !slices.Equal(m.settledLines, want) || m.settledLinesBytes != rowBytes(want) || m.droppedSettledLines != len(old)-test.kept {
32				t.Fatalf("survivors=%d bytes=%d dropped=%d", len(m.settledLines), m.settledLinesBytes, m.droppedSettledLines)
33			}
34			for i, row := range old {
35				if row != "" {
36					t.Fatalf("old descriptor %d still holds text", i)
37				}
38			}
39			if len(want) > 0 {
40				old[len(old)-1] = "changed old slice"
41				if !slices.Equal(m.settledLines, want) {
42					t.Fatal("survivors share the old descriptor slice")
43				}
44			}
45		})
46	}
47}
48
49func BenchmarkTrimSettledLinesFullDisplay(b *testing.B) {
50	for _, width := range []int{80, 512} {
51		b.Run(fmt.Sprintf("ascii%d", width), func(b *testing.B) {
52			row := "│ " + strings.Repeat("x", width)
53			count := min(MaxSettledLines, MaxSettledLinesBytes/len(row))
54			m := ChatModel{Follow: true, settledLines: slices.Repeat([]string{row}, count), settledLinesBytes: int64(count * len(row))}
55			b.ReportAllocs()
56			b.ResetTimer()
57			for i := 0; i < b.N; i++ {
58				m.settledLines = append(m.settledLines, row)
59				m.settledLinesBytes += int64(len(row))
60				m.trimSettledLines()
61			}
62		})
63	}
64}