package main import ( "errors" "os" "path/filepath" "strconv" "strings" "testing" "time" ) // fakeMachine points the session finder at a temporary /proc, /run/user and X socket directory, with // none of the test process's own session variables, and gives back the root. func fakeMachine(t *testing.T) string { t.Helper() root := t.TempDir() procRoot, runUserDir, x11Sockets = filepath.Join(root, "proc"), filepath.Join(root, "run-user"), filepath.Join(root, "x11") for _, d := range []string{procRoot, runUserDir, x11Sockets} { if err := os.MkdirAll(d, 0o755); err != nil { t.Fatal(err) } } for _, k := range sessionKeys { t.Setenv(k, "") } t.Setenv("MESH_OPERATOR_HOME", filepath.Join(root, "home")) t.Cleanup(func() { procRoot, runUserDir, x11Sockets = "/proc", "/run/user", "/tmp/.X11-unix" }) return root } func fakeProcess(t *testing.T, pid int, comm string, env ...string) { t.Helper() dir := filepath.Join(procRoot, strconv.Itoa(pid)) if err := os.MkdirAll(dir, 0o755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(dir, "comm"), []byte(comm+"\n"), 0o644); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(dir, "environ"), []byte(strings.Join(env, "\x00")+"\x00"), 0o600); err != nil { t.Fatal(err) } } func TestTheSessionIsReadFromTheWindowManagerBeforeAnyOtherProcess(t *testing.T) { fakeMachine(t) fakeProcess(t, 900, "xterm", "DISPLAY=:9", "XAUTHORITY=/elsewhere") fakeProcess(t, 100, "i3", "DISPLAY=:1", "XAUTHORITY=/home/op/.Xauthority", "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus", "XDG_SESSION_ID=3", "SECRET_TOKEN=never-copied") fakeProcess(t, 50, "bash", "PATH=/usr/bin") s, err := findSession() if err != nil { t.Fatal(err) } if s.Display != ":1" || s.XAuthority != "/home/op/.Xauthority" || s.SessionID != "3" || !strings.Contains(s.From, "i3 (pid 100)") { t.Fatalf("the window manager's environment: %+v", s) } for _, kv := range s.Env() { if strings.HasPrefix(kv, "SECRET_TOKEN=") { t.Fatal("a variable of the session process that is not a session variable was handed on") } } } func TestAnyProcessCarryingADisplayServesWhenTheWindowManagerIsNotFound(t *testing.T) { fakeMachine(t) fakeProcess(t, 10, "firefox", "DISPLAY=:0") fakeProcess(t, 20, "firefox", "DISPLAY=:2") s, err := findSession() if err != nil || s.Display != ":2" { t.Fatalf("the newest of two equals: %+v, %v", s, err) } } func TestNoSessionIsAClearAnswerNotAGuess(t *testing.T) { fakeMachine(t) fakeProcess(t, 10, "sshd", "PATH=/usr/bin") _, err := findSession() if !errors.Is(err, ErrNoSession) || !strings.Contains(err.Error(), "logged in to the desktop") { t.Fatalf("no session: %v", err) } } func TestOneXSocketAndTheAccountsAuthorityFileAreASession(t *testing.T) { root := fakeMachine(t) if err := os.WriteFile(filepath.Join(x11Sockets, "X0"), nil, 0o644); err != nil { t.Fatal(err) } if err := os.MkdirAll(filepath.Join(root, "home"), 0o755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(root, "home", ".Xauthority"), nil, 0o600); err != nil { t.Fatal(err) } s, err := findSession() if err != nil || s.Display != ":0" || !strings.HasSuffix(s.XAuthority, "/home/.Xauthority") { t.Fatalf("socket and authority: %+v, %v", s, err) } } func TestTheBusIsTheAccountsRuntimeDirectoryWhenNoProcessNamesIt(t *testing.T) { fakeMachine(t) runtime := filepath.Join(runUserDir, strconv.Itoa(os.Getuid())) if _, err := findBus(); !errors.Is(err, ErrNoBus) { t.Fatalf("no runtime directory is no bus: %v", err) } if err := os.MkdirAll(runtime, 0o700); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(runtime, "bus"), nil, 0o600); err != nil { t.Fatal(err) } s, err := findBus() if err != nil || s.Bus != "unix:path="+filepath.Join(runtime, "bus") || s.RuntimeDir != runtime { t.Fatalf("bus: %+v, %v", s, err) } env := strings.Join(s.Env(), "\n") if !strings.Contains(env, "XDG_RUNTIME_DIR="+runtime) || !strings.Contains(env, "DBUS_SESSION_BUS_ADDRESS=unix:path=") { t.Fatalf("the bus is handed on: %s", env) } } func TestACommandIsBoundedAndANonZeroExitIsAResult(t *testing.T) { fakeMachine(t) s := Session{} r, err := s.run(5*time.Second, "in", "sh", "-c", "cat; echo err >&2; exit 3") if err != nil || r.Stdout != "in" || r.Code != 3 || strings.TrimSpace(r.Stderr) != "err" { t.Fatalf("result: %+v, %v", r, err) } start := time.Now() if _, err := s.run(200*time.Millisecond, "", "sh", "-c", "sleep 30 & sleep 30"); err == nil || time.Since(start) > 5*time.Second { t.Fatalf("a command past its time is ended with what it started: %v after %s", err, time.Since(start)) } if _, err := s.run(time.Second, "", "no-such-program-here"); err == nil || !strings.Contains(err.Error(), "not installed") { t.Fatalf("a missing program: %v", err) } } func TestDetachAsksTheAccountsServiceManagerWithTheSessionsDisplay(t *testing.T) { fakeMachine(t) bin := fakeBinaries(t, map[string]string{ "systemctl": `echo "systemctl $*" >> "$LOG"`, "systemd-run": `echo "systemd-run $*" >> "$LOG"`, }) log := filepath.Join(bin, "log") t.Setenv("LOG", log) s := Session{Display: ":1", XAuthority: "/x", RuntimeDir: "/run/user/1"} if err := s.detach("picom-session", "picom", "--config", "/c"); err != nil { t.Fatal(err) } got, _ := os.ReadFile(log) want := "systemctl --user stop picom-session.service\n" + "systemd-run --user --collect --quiet --unit=picom-session --setenv=DISPLAY=:1 --setenv=XAUTHORITY=/x -- picom --config /c\n" if string(got) != want { t.Fatalf("detach ran:\n%s\nwant:\n%s", got, want) } if err := (Session{}).detach("x", "y"); !errors.Is(err, ErrNoBus) { t.Fatalf("no runtime directory: %v", err) } } // fakeBinaries puts shell scripts named for programs first on PATH, and answers their directory. func fakeBinaries(t *testing.T, scripts map[string]string) string { t.Helper() dir := t.TempDir() for name, body := range scripts { if err := os.WriteFile(filepath.Join(dir, name), []byte("#!/bin/sh\n"+body+"\n"), 0o755); err != nil { t.Fatal(err) } } t.Setenv("PATH", dir+string(os.PathListSeparator)+os.Getenv("PATH")) return dir }