Files
mesh-host/internal/profile/seat_test.go
jschoubben 1ea4c330df A seat is hardware; a graphical session is state
Two questions that had been answered by one capability. graphical-session asks
whether a session is running now; seat asks whether one could ever run here.
Assignment needs the second -- a headless server can never have a display
server, a workstation with nothing installed yet can, and until now those
looked identical. The mesh would have assigned xorg to the server and found out
at apply time.

"seat" rather than "display", and the distinction matters most on a phone. An
Android device plainly has a screen and has no seat: nothing there is going to
take a DRM device and present an X or Wayland session on it. A capability
called display would answer yes and be useless. This one answers no, which is
true and useful.

Read from what the kernel reports about its connectors, which distinguishes the
two ways of not having one: a machine with a graphics card and nothing plugged
in is a different thing from a machine with no graphics at all, and somebody
deciding where a desktop goes wants to know which they are looking at.

Verified against this workstation: it reports card1-DP-1 and card1-DP-2, which
are the two monitors actually connected, and ignores the DisplayPort and HDMI
that are not -- and the writeback connector reporting "unknown", which counting
would have handed a seat to machines that have none.
2026-08-29 21:12:22 +02:00

115 lines
4.2 KiB
Go

package profile
import (
"context"
"os"
"path/filepath"
"strings"
"testing"
)
// drm builds what the kernel would expose, so the cases below are the real ones rather than a
// fake's idea of them: a workstation, a server with a card and no monitor, a machine with no
// graphics at all.
func drm(t *testing.T, connectors map[string]string) {
t.Helper()
dir := t.TempDir()
for name, status := range connectors {
if err := os.MkdirAll(filepath.Join(dir, name), 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dir, name, "status"), []byte(status+"\n"), 0o644); err != nil {
t.Fatal(err)
}
}
// The card itself has no status file, and skipping it must not be mistaken for an answer.
if err := os.MkdirAll(filepath.Join(dir, "card0"), 0o755); err != nil {
t.Fatal(err)
}
old := SeatSource
SeatSource = dir
t.Cleanup(func() { SeatSource = old })
}
func TestAMachineWithAMonitorHasASeat(t *testing.T) {
drm(t, map[string]string{"card0-DP-1": "connected", "card0-HDMI-A-1": "disconnected"})
got := seat{}.Detect(context.Background())
if !got.Present {
t.Fatalf("a machine with a connected display has no seat: %s", got.Detail)
}
if !strings.Contains(got.Detail, "card0-DP-1") {
t.Errorf("the answer does not say which connector: %q", got.Detail)
}
if strings.Contains(got.Detail, "HDMI") {
t.Errorf("a disconnected connector was counted: %q", got.Detail)
}
}
func TestAServerWithAGraphicsCardAndNoMonitorHasNoSeat(t *testing.T) {
// The case this capability exists for. A display server assigned here would install, start,
// and have nowhere to draw — and the mesh would have thought it succeeded.
drm(t, map[string]string{"card0-HDMI-A-1": "disconnected", "card0-DP-1": "disconnected"})
got := seat{}.Detect(context.Background())
if got.Present {
t.Fatal("a machine with nothing plugged in reported a seat")
}
// And it says which of the two "no" answers this is, because a person deciding where a
// desktop goes wants to know whether the hardware is there.
if !strings.Contains(got.Detail, "no display attached") {
t.Errorf("the answer does not distinguish this from having no graphics at all: %q", got.Detail)
}
}
func TestAMachineWithNoGraphicsAtAllHasNoSeat(t *testing.T) {
// A container, or a phone, where the DRM subsystem is not there to read. The ordinary answer
// on most nodes and a fault on none of them, so it is a plain "no" rather than an error.
old := SeatSource
SeatSource = filepath.Join(t.TempDir(), "not-here")
t.Cleanup(func() { SeatSource = old })
got := seat{}.Detect(context.Background())
if got.Present {
t.Fatal("a machine with no graphics subsystem reported a seat")
}
if got.Detail == "" || strings.Contains(strings.ToLower(got.Detail), "error") {
t.Errorf("absence was reported as a failure: %q", got.Detail)
}
}
func TestAnUnknownConnectorIsNotASeat(t *testing.T) {
// Writeback connectors and some virtual devices report "unknown". Counting those would give
// a seat to machines that have none — and this workstation has one, so it is not theoretical.
drm(t, map[string]string{"card0-Writeback-1": "unknown"})
if (seat{}).Detect(context.Background()).Present {
t.Fatal("a connector reporting \"unknown\" was counted as a display")
}
}
func TestTheAnswerSaysHowItKnows(t *testing.T) {
// Every detector says how, so a wrong answer can be found rather than argued about.
drm(t, map[string]string{"card0-DP-1": "connected"})
if !strings.Contains((seat{}).Detect(context.Background()).How, "status") {
t.Error("the seat detector does not say what it looked at")
}
}
func TestASeatIsNotAGraphicalSession(t *testing.T) {
// The two are different questions and the whole point of adding one was that they had been
// answered by the same thing. A machine can have a seat and no session — that is every
// workstation before anything is installed on it, and exactly where a display server should
// be assigned.
drm(t, map[string]string{"card0-DP-1": "connected"})
t.Setenv("DISPLAY", "")
t.Setenv("WAYLAND_DISPLAY", "")
if !(seat{}).Detect(context.Background()).Present {
t.Fatal("a machine with a monitor and no session has no seat")
}
if (graphicalSession{}).Detect(context.Background()).Present {
t.Fatal("a machine with no session reported one")
}
}