main 3d41bc5

grid_test.go RawHistoryFolder

1package core_test
2
3import (
4	"image"
5	"math"
6	"testing"
7
8	"github.com/stretchr/testify/assert"
9	"github.com/stretchr/testify/require"
10
11	"github.com/bnema/nefercap/internal/core"
12	"github.com/bnema/nefercap/internal/ports"
13)
14
15// gridWant builds the expected lines for a physical size and the pixel
16// coordinates of the three vertical and three horizontal lines.
17func gridWant(w, h int, xs, ys [3]int) core.GridLines {
18	var g core.GridLines
19	for i := range 3 {
20		g[i] = image.Rect(xs[i], 0, xs[i]+1, h)
21		g[3+i] = image.Rect(0, ys[i], w, ys[i]+1)
22	}
23	return g
24}
25
26func TestMonitorGridExactPhysicalLines(t *testing.T) {
27	for name, c := range map[string]struct {
28		w, h  int
29		scale float64
30		want  core.GridLines
31	}{
32		"1920x1080 at 1":    {1920, 1080, 1, gridWant(1920, 1080, [3]int{640, 960, 1280}, [3]int{360, 540, 720})},
33		"1600x900 at 1.2":   {1600, 900, 1.2, gridWant(1920, 1080, [3]int{640, 960, 1280}, [3]int{360, 540, 720})},
34		"1536x864 at 1.25":  {1536, 864, 1.25, gridWant(1920, 1080, [3]int{640, 960, 1280}, [3]int{360, 540, 720})},
35		"1280x720 at 1.5":   {1280, 720, 1.5, gridWant(1920, 1080, [3]int{640, 960, 1280}, [3]int{360, 540, 720})},
36		"960x540 at 2":      {960, 540, 2, gridWant(1920, 1080, [3]int{640, 960, 1280}, [3]int{360, 540, 720})},
37		"odd 1366x768 at 1": {1366, 768, 1, gridWant(1366, 768, [3]int{455, 683, 910}, [3]int{256, 384, 512})},
38		// 1367*1.25 = 1708.75 and 769*1.25 = 961.25 round up to whole buffer pixels.
39		"odd fractional 1367x769 at 1.25": {1367, 769, 1.25, gridWant(1709, 962, [3]int{569, 854, 1139}, [3]int{320, 481, 641})},
40		// 1001*1.2 = 1201.2 and 601*1.2 = 721.2.
41		"odd fractional 1001x601 at 1.2": {1001, 601, 1.2, gridWant(1202, 722, [3]int{400, 601, 801}, [3]int{240, 361, 481})},
42		"1x1 at 1":                       {1, 1, 1, gridWant(1, 1, [3]int{}, [3]int{})},
43		"2x2 at 1":                       {2, 2, 1, gridWant(2, 2, [3]int{0, 1, 1}, [3]int{0, 1, 1})},
44		"3x3 at 1":                       {3, 3, 1, gridWant(3, 3, [3]int{1, 1, 2}, [3]int{1, 1, 2})},
45	} {
46		t.Run(name, func(t *testing.T) {
47			got, err := core.MonitorGrid(c.w, c.h, c.scale)
48			require.NoError(t, err)
49			assert.Equal(t, c.want, got)
50			for i, r := range got {
51				if i < 3 {
52					assert.Equal(t, 1, r.Dx(), "vertical %d is one physical pixel wide", i)
53				} else {
54					assert.Equal(t, 1, r.Dy(), "horizontal %d is one physical pixel tall", i)
55				}
56			}
57		})
58	}
59}
60
61func TestMonitorGridLineOrderAndBounds(t *testing.T) {
62	g, err := core.MonitorGrid(1920, 1080, 1)
63	require.NoError(t, err)
64	assert.Equal(t, core.GridLineCount, len(g))
65	assert.Less(t, g[0].Min.X, g[1].Min.X)
66	assert.Less(t, g[1].Min.X, g[2].Min.X)
67	assert.Less(t, g[3].Min.Y, g[4].Min.Y)
68	assert.Less(t, g[4].Min.Y, g[5].Min.Y)
69	whole := image.Rect(0, 0, 1920, 1080)
70	for _, r := range g {
71		assert.True(t, r.In(whole), "%v stays inside the physical monitor", r)
72	}
73}
74
75func TestPhysicalExtentMatchesExactFractionalScales(t *testing.T) {
76	// Compositor fractional scales are k/120. The buffer edge is
77	// ceil(logical*k/120) computed exactly in integers; float noise at exact
78	// boundaries (for example 1600*1.2) must not add a pixel.
79	for k := 120; k <= 480; k++ {
80		scale := float64(k) / 120
81		for n := 1; n <= ports.MaxDimension; n += 1 + n/97 {
82			want := (n*k + 119) / 120
83			got, err := core.PhysicalExtent(n, scale)
84			require.NoError(t, err)
85			if got != want {
86				t.Fatalf("PhysicalExtent(%d, %d/120) = %d, want %d", n, k, got, want)
87			}
88		}
89		for n := 1; n <= 4096; n++ { // every small size
90			want := (n*k + 119) / 120
91			got, err := core.PhysicalExtent(n, scale)
92			require.NoError(t, err)
93			if got != want {
94				t.Fatalf("PhysicalExtent(%d, %d/120) = %d, want %d", n, k, got, want)
95			}
96		}
97	}
98}
99
100func TestMonitorGridSweepInvariants(t *testing.T) {
101	for k := 120; k <= 360; k += 7 {
102		scale := float64(k) / 120
103		for w := 1; w <= 3000; w += 13 {
104			h := w/2 + 1
105			g, err := core.MonitorGrid(w, h, scale)
106			require.NoError(t, err)
107			pw, _ := core.PhysicalExtent(w, scale)
108			ph, _ := core.PhysicalExtent(h, scale)
109			for i, r := range g {
110				if !r.In(image.Rect(0, 0, pw, ph)) || r.Empty() {
111					t.Fatalf("%dx%d@%d/120 line %d = %v outside %dx%d", w, h, k, i, r, pw, ph)
112				}
113				if i < 3 && (r.Dx() != 1 || r.Dy() != ph) || i >= 3 && (r.Dy() != 1 || r.Dx() != pw) {
114					t.Fatalf("%dx%d@%d/120 line %d = %v is not one pixel wide over the full monitor", w, h, k, i, r)
115				}
116			}
117			if g[0].Min.X > g[1].Min.X || g[1].Min.X > g[2].Min.X || g[3].Min.Y > g[4].Min.Y || g[4].Min.Y > g[5].Min.Y {
118				t.Fatalf("%dx%d@%d/120 lines out of order: %v", w, h, k, g)
119			}
120		}
121	}
122}
123
124func TestMonitorGridRejectsInvalidInput(t *testing.T) {
125	nan, inf := math.NaN(), math.Inf(1)
126	for name, c := range map[string]struct {
127		w, h  int
128		scale float64
129	}{
130		"zero width":        {0, 1080, 1},
131		"zero height":       {1920, 0, 1},
132		"negative width":    {-1, 1080, 1},
133		"negative height":   {1920, -1, 1},
134		"width too large":   {ports.MaxDimension + 1, 1080, 1},
135		"height too large":  {1920, ports.MaxDimension + 1, 1},
136		"zero scale":        {1920, 1080, 0},
137		"negative scale":    {1920, 1080, -1},
138		"NaN scale":         {1920, 1080, nan},
139		"infinite scale":    {1920, 1080, inf},
140		"negative infinity": {1920, 1080, -inf},
141		"scale too large":   {1920, 1080, core.MaxGridScale * 2},
142		"vanishing scale":   {1, 1, 1e-12},
143	} {
144		t.Run(name, func(t *testing.T) {
145			g, err := core.MonitorGrid(c.w, c.h, c.scale)
146			assert.ErrorIs(t, err, core.ErrInvalidGrid)
147			assert.Equal(t, core.GridLines{}, g, "no partial result")
148		})
149	}
150	_, err := core.PhysicalExtent(0, 1)
151	assert.ErrorIs(t, err, core.ErrInvalidGrid)
152	_, err = core.PhysicalExtent(10, nan)
153	assert.ErrorIs(t, err, core.ErrInvalidGrid)
154}
155
156func TestMonitorGridAcceptsLimits(t *testing.T) {
157	g, err := core.MonitorGrid(ports.MaxDimension, ports.MaxDimension, core.MaxGridScale)
158	require.NoError(t, err)
159	pw := ports.MaxDimension * core.MaxGridScale
160	assert.Equal(t, pw, g[3].Dx())
161}
162
163func TestMonitorGridAllocations(t *testing.T) {
164	var g core.GridLines
165	n := testing.AllocsPerRun(200, func() {
166		g, _ = core.MonitorGrid(1600, 900, 1.2)
167		_, _ = core.MonitorGrid(0, 900, 1.2) // the error path too
168	})
169	assert.Zero(t, n)
170	_ = g
171}
172
173func BenchmarkMonitorGrid(b *testing.B) {
174	b.ReportAllocs()
175	var g core.GridLines
176	for i := 0; b.Loop(); i++ {
177		g, _ = core.MonitorGrid(1600+i%3, 900, 1.2)
178	}
179	_ = g
180}

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 2

Tags 9

↑↓ moveenter openesc close