1package drm
2
3import (
4 "context"
5 "os"
6 "slices"
7 "testing"
8 "unsafe"
9
10 "github.com/bnema/neferwl/internal/adapters/logging"
11 "github.com/stretchr/testify/mock"
12)
13
14func TestLeaseResourceOwnership(t *testing.T) {
15 k := newMockkms(t)
16 conn := connector{id: 40, name: "DP-1", connected: true, nonDesktop: true, encoders: []uint32{3}}
17 c := &Card{path: "/dev/dri/card-test", crtcs: []uint32{30}, outputs: map[string]*Output{}, leasable: map[string]connector{conn.name: conn}, leases: map[uint32]leaseRecord{}, taken: map[uint32]bool{}, k: k}
18 k.EXPECT().pickCrtc(conn, []uint32{30}, mock.Anything).RunAndReturn(func(_ connector, _ []uint32, used map[uint32]bool) (uint32, error) {
19 if used[30] {
20 t.Fatal("CRTC already used")
21 }
22 return 30, nil
23 })
24 k.EXPECT().planes().Return([]planeRes{{id: 50, possible: 1}}, nil)
25 k.EXPECT().objProps(uint32(50), uint32(objPlane)).Return(map[string][2]uint64{"type": {1, planePrimary}}, nil)
26 r, w, err := os.Pipe()
27 if err != nil {
28 t.Fatal(err)
29 }
30 defer r.Close()
31 defer w.Close()
32 k.EXPECT().createLease(mock.Anything).RunAndReturn(func(ids []uint32) (*os.File, uint32, error) {
33 if !slices.Equal(ids, []uint32{40, 30, 50}) {
34 t.Errorf("objects %v", ids)
35 }
36 return w, 7, nil
37 })
38 f, id, err := c.Lease([]string{"DP-1"})
39 if err != nil || f != w || id != 7 {
40 t.Fatalf("lease fd %v id %d err %v", f, id, err)
41 }
42 if len(c.Leasable()) != 0 {
43 t.Fatal("leased connector advertised")
44 }
45 if _, _, err = c.Lease([]string{"DP-1"}); err == nil {
46 t.Fatal("duplicate lease allowed")
47 }
48 k.EXPECT().revokeLease(uint32(7)).Return(nil)
49 if err = c.Revoke(7); err != nil {
50 t.Fatal(err)
51 }
52 if len(c.Leasable()) != 1 {
53 t.Fatal("connector not available after revoke")
54 }
55}
56
57func TestLeaseABI(t *testing.T) {
58 if unsafe.Sizeof(modeCreateLease{}) != 24 || unsafe.Sizeof(modeRevokeLease{}) != 4 {
59 t.Fatal("DRM lease ioctl structs")
60 }
61 if ioctlCreateLease>>16&0x3fff != uint64(unsafe.Sizeof(modeCreateLease{})) || ioctlRevokeLease>>16&0x3fff != uint64(unsafe.Sizeof(modeRevokeLease{})) {
62 t.Fatal("DRM lease ioctl sizes")
63 }
64}
65
66func TestScanNonDesktopAndRevokeDisconnected(t *testing.T) {
67 k := newMockkms(t)
68 conn := connector{id: 40, name: "DP-1", connected: true, nonDesktop: true, modes: []modeInfo{{HDisplay: 1920}}, encoders: []uint32{3}}
69 c := &Card{k: k, path: "/dev/dri/card-test", crtcs: []uint32{30}, outputs: map[string]*Output{}, leases: map[uint32]leaseRecord{7: {names: []string{"DP-1"}, crtcs: []uint32{30}, planes: []uint32{50}}}, want: Want{}, log: logging.For(context.Background(), "drm"), taken: map[uint32]bool{}}
70 k.EXPECT().resources().Return([]uint32{30}, []uint32{40}, nil).Once()
71 k.EXPECT().connector(uint32(40)).Return(conn, nil).Once()
72 added, _, _, err := c.Scan()
73 if err != nil || len(added) != 0 {
74 t.Fatalf("non-desktop output: %v %v", added, err)
75 }
76 k.EXPECT().resources().Return([]uint32{30}, []uint32{40}, nil).Once()
77 conn.connected = false
78 k.EXPECT().connector(uint32(40)).Return(conn, nil).Once()
79 k.EXPECT().revokeLease(uint32(7)).Return(nil)
80 _, _, _, err = c.Scan()
81 if err != nil || !slices.Equal(c.FinishedLeases(), []uint32{7}) {
82 t.Fatalf("hotplug revoke: %v", err)
83 }
84}