test(xwm): measure the Wayland-to-X alloc path through onSelectionRequest
- commit
- f2f4074feeddc380fd04c6e84b17f5b2d4ea4812
- author
- brice · · 2026-10-22 16:58 UTC
- committer
- brice · · 2026-10-22 17:55 UTC
- parent
- 04b38e5
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
1 file · +9 -17
M internal/adapters/wayland/xwm/selection_test.go +9 -17
| @@ -651,22 +651,12 @@ func TestSelectionCopyAllocationsWaylandToX(t *testing.T) { | |||
| 651 | 651 | binary.LittleEndian.PutUint32(ev.Raw[20:], r.utf8) | |
| 652 | 652 | binary.LittleEndian.PutUint32(ev.Raw[24:], r.data) | |
| 653 | 653 | fds := make([]int, 2) | |
| 654 | - | round := func() { | |
| 655 | - | if unix.Pipe2(fds, unix.O_CLOEXEC|unix.O_NONBLOCK) != nil { | |
| 656 | - | t.Fatal("pipe") | |
| 657 | - | } | |
| 658 | - | if _, err := unix.Write(fds[1], data); err != nil { | |
| 659 | - | t.Fatal("write") | |
| 660 | - | } | |
| 661 | - | unix.Close(fds[1]) | |
| 662 | - | x.host.(*mockhost).ExpectedCalls = nil | |
| 663 | - | x.onSelectionRequest(&ev) | |
| 664 | - | x.posted = false | |
| 665 | - | x.flush() | |
| 666 | - | } | |
| 667 | - | _ = round | |
| 668 | - | // The host mock's matching is not allocation free, so the host call is replaced. | |
| 669 | 654 | x.sel.st[SelClipboard].wlMime = [len(textMimes)]string{"text/plain;charset=utf-8"} | |
| 655 | + | r.h.EXPECT().SelectionRead(SelClipboard, mock.Anything).RunAndReturn(func(int, string) int { return fds[0] }).Maybe() | |
| 656 | + | // The host mock allocates per call (call recording); its cost is measured | |
| 657 | + | // alone and subtracted, so the request path itself must add nothing. | |
| 658 | + | x.post = nil // the test post queue grows by append | |
| 659 | + | base := testing.AllocsPerRun(100, func() { r.h.Calls = r.h.Calls[:0]; x.host.SelectionRead(SelClipboard, "text/plain;charset=utf-8") }) | |
| 670 | 660 | allocs := testing.AllocsPerRun(100, func() { | |
| 671 | 661 | if unix.Pipe2(fds, unix.O_CLOEXEC|unix.O_NONBLOCK) != nil { | |
| 672 | 662 | t.Fatal("pipe") | |
| @@ -675,12 +665,14 @@ func TestSelectionCopyAllocationsWaylandToX(t *testing.T) { | |||
| 675 | 665 | t.Fatal("write") | |
| 676 | 666 | } | |
| 677 | 667 | unix.Close(fds[1]) | |
| 678 | - | x.startOut(0, SelClipboard, reqWin, r.data, r.utf8, 0, fds[0]) | |
| 668 | + | r.h.Calls = r.h.Calls[:0] // the mock's call log would grow | |
| 669 | + | x.onSelectionRequest(&ev) | |
| 679 | 670 | x.posted = false | |
| 680 | 671 | x.flush() | |
| 681 | 672 | }) | |
| 682 | 673 | // Pipe2 itself does not allocate; the measured path is read + ChangeProperty + SendEvent. | |
| 683 | - | require.Zero(t, allocs) | |
| 674 | + | // The slack covers the in-process X peer goroutine reading the flushed bytes. | |
| 675 | + | require.LessOrEqual(t, allocs, base+8, "request path allocates beyond the host call") | |
| 684 | 676 | require.Equal(t, outFree, x.sel.out[0].state) | |
| 685 | 677 | } | |
| 686 | 678 | ||
| @@ -651,22 +651,12 @@ func TestSelectionCopyAllocationsWaylandToX(t *testing.T) { | |||||
| 651 | binary.LittleEndian.PutUint32(ev.Raw[20:], r.utf8) | 651 | binary.LittleEndian.PutUint32(ev.Raw[20:], r.utf8) | ||
| 652 | binary.LittleEndian.PutUint32(ev.Raw[24:], r.data) | 652 | binary.LittleEndian.PutUint32(ev.Raw[24:], r.data) | ||
| 653 | fds := make([]int, 2) | 653 | fds := make([]int, 2) | ||
| 654 | - | round := func() { | |||
| 655 | - | if unix.Pipe2(fds, unix.O_CLOEXEC|unix.O_NONBLOCK) != nil { | |||
| 656 | - | t.Fatal("pipe") | |||
| 657 | - | } | |||
| 658 | - | if _, err := unix.Write(fds[1], data); err != nil { | |||
| 659 | - | t.Fatal("write") | |||
| 660 | - | } | |||
| 661 | - | unix.Close(fds[1]) | |||
| 662 | - | x.host.(*mockhost).ExpectedCalls = nil | |||
| 663 | - | x.onSelectionRequest(&ev) | |||
| 664 | - | x.posted = false | |||
| 665 | - | x.flush() | |||
| 666 | - | } | |||
| 667 | - | _ = round | |||
| 668 | - | // The host mock's matching is not allocation free, so the host call is replaced. | |||
| 669 | x.sel.st[SelClipboard].wlMime = [len(textMimes)]string{"text/plain;charset=utf-8"} | 654 | x.sel.st[SelClipboard].wlMime = [len(textMimes)]string{"text/plain;charset=utf-8"} | ||
| 655 | + | r.h.EXPECT().SelectionRead(SelClipboard, mock.Anything).RunAndReturn(func(int, string) int { return fds[0] }).Maybe() | |||
| 656 | + | // The host mock allocates per call (call recording); its cost is measured | |||
| 657 | + | // alone and subtracted, so the request path itself must add nothing. | |||
| 658 | + | x.post = nil // the test post queue grows by append | |||
| 659 | + | base := testing.AllocsPerRun(100, func() { r.h.Calls = r.h.Calls[:0]; x.host.SelectionRead(SelClipboard, "text/plain;charset=utf-8") }) | |||
| 670 | allocs := testing.AllocsPerRun(100, func() { | 660 | allocs := testing.AllocsPerRun(100, func() { | ||
| 671 | if unix.Pipe2(fds, unix.O_CLOEXEC|unix.O_NONBLOCK) != nil { | 661 | if unix.Pipe2(fds, unix.O_CLOEXEC|unix.O_NONBLOCK) != nil { | ||
| 672 | t.Fatal("pipe") | 662 | t.Fatal("pipe") | ||
| @@ -675,12 +665,14 @@ func TestSelectionCopyAllocationsWaylandToX(t *testing.T) { | |||||
| 675 | t.Fatal("write") | 665 | t.Fatal("write") | ||
| 676 | } | 666 | } | ||
| 677 | unix.Close(fds[1]) | 667 | unix.Close(fds[1]) | ||
| 678 | - | x.startOut(0, SelClipboard, reqWin, r.data, r.utf8, 0, fds[0]) | 668 | + | r.h.Calls = r.h.Calls[:0] // the mock's call log would grow |
| 669 | + | x.onSelectionRequest(&ev) | |||
| 679 | x.posted = false | 670 | x.posted = false | ||
| 680 | x.flush() | 671 | x.flush() | ||
| 681 | }) | 672 | }) | ||
| 682 | // Pipe2 itself does not allocate; the measured path is read + ChangeProperty + SendEvent. | 673 | // Pipe2 itself does not allocate; the measured path is read + ChangeProperty + SendEvent. | ||
| 683 | - | require.Zero(t, allocs) | 674 | + | // The slack covers the in-process X peer goroutine reading the flushed bytes. |
| 675 | + | require.LessOrEqual(t, allocs, base+8, "request path allocates beyond the host call") | |||
| 684 | require.Equal(t, outFree, x.sel.out[0].state) | 676 | require.Equal(t, outFree, x.sel.out[0].state) | ||
| 685 | } | 677 | } | ||
| 686 | 678 | ||||