A package and nothing else, the tool the desktop's scripts depend on. Four Go tools: copy, paste (text, base64 for other types, empty when nothing), targets and session. The runtime is given no session words, but runs as the account in the machine's own namespace, so the session is found rather than configured: the process's DISPLAY, else the account's processes' DISPLAY and XAUTHORITY from /proc (the window manager's first), else the only X socket with ~/.Xauthority. Measured with both variables unset: :1 found through i3, the server answered. With no session every tool says so and runs nothing.
95 lines
3.2 KiB
Go
95 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// aMachine gives findSession a /proc and an X socket directory of the test's own.
|
|
func aMachine(t *testing.T, env map[string]string) (proc, sockets string) {
|
|
t.Helper()
|
|
root := t.TempDir()
|
|
proc, sockets = filepath.Join(root, "proc"), filepath.Join(root, "x11")
|
|
for _, d := range []string{proc, sockets} {
|
|
if err := os.MkdirAll(d, 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
wasProc, wasX, wasEnv := procRoot, x11Sockets, getenv
|
|
procRoot, x11Sockets = proc, sockets
|
|
getenv = func(k string) string { return env[k] }
|
|
t.Cleanup(func() { procRoot, x11Sockets, getenv = wasProc, wasX, wasEnv })
|
|
return proc, sockets
|
|
}
|
|
|
|
func aProcess(t *testing.T, proc string, pid int, comm string, env ...string) {
|
|
t.Helper()
|
|
dir := filepath.Join(proc, strconv.Itoa(pid))
|
|
if err := os.MkdirAll(dir, 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_ = os.WriteFile(filepath.Join(dir, "comm"), []byte(comm+"\n"), 0o644)
|
|
_ = os.WriteFile(filepath.Join(dir, "environ"), []byte(strings.Join(env, "\x00")+"\x00"), 0o644)
|
|
}
|
|
|
|
func aSocket(t *testing.T, dir, name string) {
|
|
t.Helper()
|
|
if err := os.WriteFile(filepath.Join(dir, name), nil, 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestSessionTheWindowManagersDisplayAndCookieAreTheSessions(t *testing.T) {
|
|
proc, sockets := aMachine(t, map[string]string{"MESH_OPERATOR_HOME": "/home/op"})
|
|
aSocket(t, sockets, "X1")
|
|
aProcess(t, proc, 3, "bash", "DISPLAY=:9", "XAUTHORITY=/stale")
|
|
aProcess(t, proc, 4, "kitty", "DISPLAY=:1", "XAUTHORITY=/home/op/.Xauthority")
|
|
aProcess(t, proc, 5, "i3", "DISPLAY=:1.0", "XAUTHORITY=/home/op/.Xauthority")
|
|
aProcess(t, proc, 6, "sshd", "PATH=/bin")
|
|
s, err := findSession()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if s.Display != ":1.0" || s.XAuthority != "/home/op/.Xauthority" || !strings.Contains(s.FoundBy, "i3") {
|
|
t.Fatalf("%+v: a display without a socket (:9) is skipped, and the window manager's is preferred", s)
|
|
}
|
|
if got := strings.Join(s.Env(), " "); got != "DISPLAY=:1.0 XAUTHORITY=/home/op/.Xauthority" {
|
|
t.Fatalf("env %s", got)
|
|
}
|
|
}
|
|
|
|
func TestSessionTheOnlySocketWithTheHomesCookieIsTheFallback(t *testing.T) {
|
|
home := t.TempDir()
|
|
_ = os.WriteFile(filepath.Join(home, ".Xauthority"), []byte("c"), 0o600)
|
|
_, sockets := aMachine(t, map[string]string{"MESH_OPERATOR_HOME": home})
|
|
aSocket(t, sockets, "X0")
|
|
s, err := findSession()
|
|
if err != nil || s.Display != ":0" || s.XAuthority != filepath.Join(home, ".Xauthority") || s.FoundBy != "socket" {
|
|
t.Fatalf("%+v %v", s, err)
|
|
}
|
|
}
|
|
|
|
func TestSessionNoSessionIsSaidNotGuessed(t *testing.T) {
|
|
_, sockets := aMachine(t, map[string]string{})
|
|
if _, err := findSession(); err == nil || !strings.Contains(err.Error(), "no graphical session") {
|
|
t.Fatalf("none: %v", err)
|
|
}
|
|
aSocket(t, sockets, "X0")
|
|
aSocket(t, sockets, "X1")
|
|
if _, err := findSession(); err == nil || !strings.Contains(err.Error(), "2 X sockets") {
|
|
t.Fatalf("two: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestSessionTheProcessesOwnDisplayComesFirst(t *testing.T) {
|
|
_, sockets := aMachine(t, map[string]string{"DISPLAY": ":2", "XAUTHORITY": "/a"})
|
|
aSocket(t, sockets, "X2")
|
|
s, err := findSession()
|
|
if err != nil || s.Display != ":2" || s.FoundBy != "environment" {
|
|
t.Fatalf("%+v %v", s, err)
|
|
}
|
|
}
|