1package drm
2
3import (
4 "testing"
5
6 "github.com/bnema/neferwl/internal/ports"
7 "github.com/stretchr/testify/require"
8)
9
10// A flip of an animating scene tells core the next frame is due; the flip of
11// any other frame does not. A frames channel core has not read stays full: the
12// owner never waits. An output without a frames channel (tests, nobody to wake)
13// just flips.
14func TestCompletedFrames(t *testing.T) {
15 tests := []struct {
16 name string
17 buffer int // frames channel capacity; 0: no channel
18 animating []bool // the flips, one per frame
19 want []ports.OutputFrame
20 }{
21 {name: "a settled scene wakes nobody", buffer: 2, animating: []bool{false}},
22 {name: "an animating scene wakes core once", buffer: 2, animating: []bool{false, true}, want: []ports.OutputFrame{{Output: "DP-1"}}},
23 {name: "a full channel never blocks", buffer: 1, animating: []bool{true, true, true}, want: []ports.OutputFrame{{Output: "DP-1"}}},
24 {name: "no frames channel", animating: []bool{true}},
25 }
26 for _, tt := range tests {
27 t.Run(tt.name, func(t *testing.T) {
28 o, _, commits := testOutput(t)
29 o.cursor = nil
30 var frames chan ports.OutputFrame
31 if tt.buffer > 0 {
32 frames = make(chan ports.OutputFrame, tt.buffer)
33 o.Frames = frames
34 }
35 seen := map[ports.WindowID]uint64{}
36 for i, animating := range tt.animating {
37 require.NoError(t, o.commitFrame(70, nil, false, false, pendingFrame{animating: animating}))
38 require.True(t, o.completed(eventOf((*commits)[i]), seen))
39 }
40 if frames != nil {
41 require.Equal(t, tt.want, drain(frames))
42 }
43 })
44 }
45}
46
47func drain(ch chan ports.OutputFrame) []ports.OutputFrame {
48 var out []ports.OutputFrame
49 for len(ch) > 0 {
50 out = append(out, <-ch)
51 }
52 return out
53}
54
55// The frame send of an animating flip allocates nothing, full channel or not.
56func TestAnimatingFrameSendAllocations(t *testing.T) {
57 o, _, _ := testOutput(t)
58 frames := make(chan ports.OutputFrame, 1)
59 o.Frames = frames
60 if n := testing.AllocsPerRun(100, func() {
61 o.wakeCore() // fills the channel, or finds it full
62 select {
63 case <-frames:
64 default:
65 }
66 o.wakeCore()
67 }); n != 0 {
68 t.Fatalf("wakeCore: %v allocations", n)
69 }
70}