1package nbview23import (4 "fmt"5 "strings"6 "testing"7 "time"89 "src.rest/cat/012/internal/notebook"10)1112// bigNotebook is 50 code cells, each with a 10,000-row output of four13// columns, expanded.14func bigNotebook() (*fakeHost, *View) {15 var b strings.Builder16 b.WriteString("[[name, size, when, ok]; ")17 for i := range 10000 {18 fmt.Fprintf(&b, "[file%d.txt, %dkb, 2026-09-%02dT10:00:00Z, true], ", i, i%900, i%28+1)19 }20 b.WriteString("[last, 1b, 2026-09-01T00:00:00Z, false]]")21 out := []byte(b.String())22 h := newHost()23 for i := range 50 {24 h.cells = append(h.cells, notebook.Cell{ID: i + 1, Source: fmt.Sprintf("t%d = ls **/* | where size > %dkb | sort-by size", i, i)})25 h.outs[i+1] = ¬ebook.Output{NUON: out, Count: i + 1}26 }27 v := newView(h, 120, 40)28 for _, c := range h.cells {29 v.foldFor(c.ID).whole = true30 }31 return h, v32}3334// Scrolling a notebook of 50 cells with 10,000-row outputs draws a35// frame in well under a frame's time, once the outputs are parsed.36func TestScrollsAtFrameSpeed(t *testing.T) {37 if testing.Short() {38 t.Skip("parses 50 large outputs")39 }40 _, v := bigNotebook()41 v.Lines() // parses what shows42 for range 50 {43 v.Wheel(-1, 10000) // passes every output, parsing it44 }45 v.Wheel(-1, -1<<30)46 start := time.Now()47 const frames = 20048 for range frames {49 v.Wheel(-1, 97)50 v.Lines()51 }52 if per := time.Since(start) / frames; per > 8*time.Millisecond {53 t.Errorf("a frame takes %s", per)54 }55}5657func BenchmarkScroll(b *testing.B) {58 _, v := bigNotebook()59 for range 60 {60 v.Wheel(-1, 10000)61 }62 v.Wheel(-1, -1<<30)63 b.ResetTimer()64 for b.Loop() {65 v.Wheel(-1, 97)66 v.Lines()67 }68}