alloc_hotpath_test.go RawHistoryFolder

1package wayland
2
3import (
4	"testing"
5	"time"
6
7	"github.com/bnema/neferwl/internal/ports"
8	"github.com/stretchr/testify/mock"
9)
10
11// The steady-state hot paths that run for every frame or commit allocate
12// nothing (or one pooled object per damage-history generation).
13
14func TestReleaseHeldAllocations(t *testing.T) {
15	out := &output{place: ports.OutputPlacement{Info: ports.OutputInfo{Name: "DP-2", RefreshMilli: 60000}}}
16	s := &Server{outputs: []*output{out}, reports: map[string]ports.OutputPresented{}}
17	reports := []ports.OutputPresented{{Output: "DP-2", Seen: map[ports.WindowID]uint64{1: 1}}}
18	now := time.Unix(100, 0)
19	s.releaseHeld(now, reports)
20	if allocs := testing.AllocsPerRun(100, func() { s.releaseHeld(now, reports) }); allocs != 0 {
21		t.Errorf("releaseHeld: %.1f allocs, want 0", allocs)
22	}
23}
24
25func TestCommitDamageAllocations(t *testing.T) {
26	srv := &Server{fifoSurfaces: map[*surface]struct{}{}}
27	surf := &surface{server: srv}
28	commit := func() {
29		surf.Damage(nil, 0, 0, 4, 4)
30		surf.DamageBuffer(nil, 1, 1, 2, 2)
31		surf.queueUpdate()
32		surf.queue[0].applyGraph()
33	}
34	commit()
35	if allocs := testing.AllocsPerRun(100, commit); allocs != 0 {
36		t.Errorf("damage requests + queueUpdate + apply: %.1f allocs, want 0", allocs)
37	}
38	// The queued update keeps its rects while the next commit collects its own.
39	surf.Damage(nil, 0, 0, 1, 1)
40	surf.queueUpdate()
41	first := surf.queue[0]
42	surf.Damage(nil, 5, 5, 2, 2)
43	if len(first.damage) != 1 || first.damage[0].W != 1 || len(surf.next.damage) != 1 || surf.next.damage[0].W != 2 {
44		t.Fatalf("damage shared between commits: queued %v pending %v", first.damage, surf.next.damage)
45	}
46	surf.queueUpdate()
47	if second := surf.queue[1]; len(second.damage) != 1 || second.damage[0].W != 2 || first.damage[0].W != 1 {
48		t.Fatalf("damage mixed up: %v %v", first.damage, second.damage)
49	}
50}
51
52// An explicit-sync commit moves its points into the update: the commit
53// itself allocates no commitSync, and a pending one is not overwritten.
54func TestCommitSyncStorageIsPerUpdate(t *testing.T) {
55	dev := newMocksyncobjDevice(t)
56	dev.EXPECT().signalled(mock.Anything, mock.Anything).Return(true, nil)
57	srv := &Server{fifoSurfaces: map[*surface]struct{}{}}
58	sw, err := newSyncWaiter(func() {})
59	if err != nil {
60		t.Fatal(err)
61	}
62	defer sw.pipeR.Close()
63	defer sw.close()
64	srv.syncWait = sw
65	tl := &timeline{dev: dev, handle: 7, alive: true}
66	surf := &surface{server: srv, sync: &syncState{}}
67	take := func(point uint64) {
68		surf.sync.acquire, surf.sync.release = syncPoint{tl: tl, point: point}, syncPoint{tl: tl, point: point + 1}
69		surf.takeSyncPoints()
70		surf.queueUpdate()
71	}
72	take(10)
73	take(20)
74	a, b := surf.queue[0], surf.queue[1]
75	if a.sync == nil || b.sync == nil || a.sync == b.sync || a.sync.acquire.point != 10 || b.sync.acquire.point != 20 || surf.next.sync != nil {
76		t.Fatalf("sync points mixed up: %+v %+v pending %+v", a.sync, b.sync, surf.next.sync)
77	}
78	// The commit's points live in the surface until queueUpdate: no heap
79	// commitSync per commit (the mocked device's own allocations would drown
80	// an AllocsPerRun count here).
81	surf.sync.acquire, surf.sync.release = syncPoint{tl: tl, point: 30}, syncPoint{tl: tl, point: 31}
82	surf.takeSyncPoints()
83	if surf.next.sync != &surf.syncScratch {
84		t.Fatal("commit points not held in the surface scratch")
85	}
86}
87
88func TestEmitContentAllocations(t *testing.T) {
89	s := &Server{
90		contentSeq: map[ports.WindowID]uint64{},
91		damage:     map[ports.WindowID][]ports.SeqDamage{},
92		latest:     map[ports.WindowID]ports.SurfaceContent{},
93	}
94	c := ports.SurfaceContent{ID: 1, Solid: &ports.SolidColor{}}
95	var held []ports.SurfaceContent // readers retaining published histories
96	var snapshots [][]ports.SeqDamage
97	for range 3 * damageHistoryCap {
98		s.emitContent(c, damage{full: true})
99		got := s.latest[1]
100		held = append(held, got)
101		snapshots = append(snapshots, append([]ports.SeqDamage(nil), got.DamageHistory...))
102	}
103	for i, h := range held {
104		// A published history never changes, nor can its owner append to it.
105		if len(h.DamageHistory) != len(snapshots[i]) || cap(h.DamageHistory) != len(h.DamageHistory) {
106			t.Fatalf("history %d: len %d cap %d", i, len(h.DamageHistory), cap(h.DamageHistory))
107		}
108		for j, d := range h.DamageHistory {
109			if d.Seq != snapshots[i][j].Seq || d.Full != snapshots[i][j].Full {
110				t.Fatalf("history %d changed at %d: %+v want %+v", i, j, d, snapshots[i][j])
111			}
112		}
113		if n := len(h.DamageHistory); h.DamageHistory[n-1].Seq != h.Seq || n > damageHistory {
114			t.Fatalf("history %d: %+v", i, h.DamageHistory)
115		}
116	}
117	allocs := testing.AllocsPerRun(100, func() { s.emitContent(c, damage{full: true}) })
118	if allocs != 0 {
119		t.Errorf("emitContent: %.2f allocs, want 0 (amortized)", allocs)
120	}
121	t.Logf("emitContent: %.2f allocs", allocs)
122}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 23

Tags 10

↑↓ moveenter openesc close