detached c5dcda0

test(server): drive fd sources over raw socketpairs and report dispatch errno

commit
c5dcda01b68bb540cd69507bdfa3a527b7f12081
author
brice · · 2026-10-22 07:07 UTC
parent
5042ed7
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
checks
3/4
1 file · +19 -8
M server/xwm_test.go +19 -8
@@ -47,7 +47,7 @@ func registry(t testing.TB, d *Display, fd int) int {
4747 t.Fatal(err)
4848 }
4949 if xwmDispatch(d) < 0 {
50- t.Fatal("dispatch failed")
50+ t.Fatalf("dispatch failed: errno=%v", lastErrno())
5151 }
5252 wlDisplayFlushClients(d.c)
5353 var buf [4096]byte
@@ -116,7 +116,8 @@ func TestGlobalFilter(t *testing.T) {
116116
117117 func TestWritableInterest(t *testing.T) {
118118 d := xwmDisplay(t)
119- client, fd := xwmClient(t, d)
119+ fds := xwmSocketpair(t)
120+ fd := fds[0]
120121 reads, writes := 0, 0
121122 s, err := d.AddFDRW(fd, func() { reads++ }, func() { writes++ })
122123 if err != nil {
@@ -124,7 +125,7 @@ func TestWritableInterest(t *testing.T) {
124125 }
125126 dispatch := func() {
126127 if xwmDispatch(d) < 0 {
127- t.Fatal("dispatch failed")
128+ t.Fatalf("dispatch failed: errno=%v", lastErrno())
128129 }
129130 }
130131 dispatch()
@@ -151,10 +152,7 @@ func TestWritableInterest(t *testing.T) {
151152 t.Fatal("writable not disabled")
152153 }
153154 // Readable callbacks also stay allocation-free through the real C loop.
154- serverFD, err := client.FD()
155- if err != nil {
156- t.Fatal(err)
157- }
155+ serverFD := fds[1]
158156 var payload = [1]byte{1}
159157 if _, err := unix.Write(serverFD, payload[:]); err != nil {
160158 t.Fatal(err)
@@ -213,7 +211,8 @@ func BenchmarkGlobalFilter(b *testing.B) {
213211
214212 func BenchmarkFDCallback(b *testing.B) {
215213 d := xwmDisplay(b)
216- _, fd := xwmClient(b, d)
214+ fds := xwmSocketpair(b)
215+ fd := fds[0]
217216 s, err := d.AddFDRW(fd, func() {}, func() {})
218217 if err != nil {
219218 b.Fatal(err)
@@ -370,3 +369,15 @@ func xwmDispatch(d *Display) int32 {
370369 }
371370 return -1
372371 }
372+
373+// FD sources use raw sockets, not Wayland clients: arbitrary payloads must
374+// never enter libwayland's protocol transport or its flush/error handling.
375+func xwmSocketpair(t testing.TB) [2]int {
376+ t.Helper()
377+ fds, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_STREAM|unix.SOCK_NONBLOCK|unix.SOCK_CLOEXEC, 0)
378+ if err != nil {
379+ t.Fatal(err)
380+ }
381+ t.Cleanup(func() { unix.Close(fds[0]); unix.Close(fds[1]) })
382+ return fds
383+}
@@ -47,7 +47,7 @@ func registry(t testing.TB, d *Display, fd int) int {
47 t.Fatal(err)47 t.Fatal(err)
48 }48 }
49 if xwmDispatch(d) < 0 {49 if xwmDispatch(d) < 0 {
50- t.Fatal("dispatch failed")50+ t.Fatalf("dispatch failed: errno=%v", lastErrno())
51 }51 }
52 wlDisplayFlushClients(d.c)52 wlDisplayFlushClients(d.c)
53 var buf [4096]byte53 var buf [4096]byte
@@ -116,7 +116,8 @@ func TestGlobalFilter(t *testing.T) {
116 116
117 func TestWritableInterest(t *testing.T) {117 func TestWritableInterest(t *testing.T) {
118 d := xwmDisplay(t)118 d := xwmDisplay(t)
119- client, fd := xwmClient(t, d)119+ fds := xwmSocketpair(t)
120+ fd := fds[0]
120 reads, writes := 0, 0121 reads, writes := 0, 0
121 s, err := d.AddFDRW(fd, func() { reads++ }, func() { writes++ })122 s, err := d.AddFDRW(fd, func() { reads++ }, func() { writes++ })
122 if err != nil {123 if err != nil {
@@ -124,7 +125,7 @@ func TestWritableInterest(t *testing.T) {
124 }125 }
125 dispatch := func() {126 dispatch := func() {
126 if xwmDispatch(d) < 0 {127 if xwmDispatch(d) < 0 {
127- t.Fatal("dispatch failed")128+ t.Fatalf("dispatch failed: errno=%v", lastErrno())
128 }129 }
129 }130 }
130 dispatch()131 dispatch()
@@ -151,10 +152,7 @@ func TestWritableInterest(t *testing.T) {
151 t.Fatal("writable not disabled")152 t.Fatal("writable not disabled")
152 }153 }
153 // Readable callbacks also stay allocation-free through the real C loop.154 // Readable callbacks also stay allocation-free through the real C loop.
154- serverFD, err := client.FD()155+ serverFD := fds[1]
155- if err != nil {
156- t.Fatal(err)
157- }
158 var payload = [1]byte{1}156 var payload = [1]byte{1}
159 if _, err := unix.Write(serverFD, payload[:]); err != nil {157 if _, err := unix.Write(serverFD, payload[:]); err != nil {
160 t.Fatal(err)158 t.Fatal(err)
@@ -213,7 +211,8 @@ func BenchmarkGlobalFilter(b *testing.B) {
213 211
214 func BenchmarkFDCallback(b *testing.B) {212 func BenchmarkFDCallback(b *testing.B) {
215 d := xwmDisplay(b)213 d := xwmDisplay(b)
216- _, fd := xwmClient(b, d)214+ fds := xwmSocketpair(b)
215+ fd := fds[0]
217 s, err := d.AddFDRW(fd, func() {}, func() {})216 s, err := d.AddFDRW(fd, func() {}, func() {})
218 if err != nil {217 if err != nil {
219 b.Fatal(err)218 b.Fatal(err)
@@ -370,3 +369,15 @@ func xwmDispatch(d *Display) int32 {
370 }369 }
371 return -1370 return -1
372 }371 }
372+
373+// FD sources use raw sockets, not Wayland clients: arbitrary payloads must
374+// never enter libwayland's protocol transport or its flush/error handling.
375+func xwmSocketpair(t testing.TB) [2]int {
376+ t.Helper()
377+ fds, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_STREAM|unix.SOCK_NONBLOCK|unix.SOCK_CLOEXEC, 0)
378+ if err != nil {
379+ t.Fatal(err)
380+ }
381+ t.Cleanup(func() { unix.Close(fds[0]); unix.Close(fds[1]) })
382+ return fds
383+}

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 1

Tags 14

↑↓ moveenter openesc close