Files
mesh-catalog/modules/picom/cmd/picom-tools/picom_test.go
T
jschoubben 73f2962bab
mesh/merge-gate pass: builds picom → g14, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery superseded: a newer head of the same pull request
picom: the backend and damage tracking are each machine's settings (hq issue 345)
A window mapped but left unpainted, or stale after a workspace switch, is a known failure of picom's glx
backend with damage tracking on some drivers, and the first suspect for the empty calendar reminder on
the workstation. Research 037 already found the backend to depend on the machine's driver. Both become
preferences whose defaults are today's (glx, use-damage true), so nothing changes until a machine is
given xrender or use-damage false to test it.
2026-10-09 12:25:08 +02:00

132 lines
4.7 KiB
Go

package main
import (
"errors"
"os"
"path/filepath"
"strings"
"testing"
)
// A pid above the kernel's largest, so a signal a test sends reaches nothing.
const nobody = 4194400
func TestTheModulesOwnConfigurationReadsAsRulesInOrder(t *testing.T) {
raw, err := os.ReadFile(filepath.Join("..", "..", "files", "picom.conf"))
if err != nil {
t.Fatal(err)
}
r := parseRules("picom.conf", withDefaults(string(raw)), nil)
if r.Global["backend"] != "glx" || r.Global["vsync"] != "true" || r.Global["shadow"] != "false" {
t.Fatalf("global options: %v", r.Global)
}
if len(r.Rules) != 5 {
t.Fatalf("five rules: %+v", r.Rules)
}
focused, unfocused := r.Rules[2], r.Rules[3]
if focused.Match != "class_g = 'XTerm' && focused" || focused.Options["opacity"] != "0.95" ||
unfocused.Match != "class_g = 'XTerm' && !focused" || unfocused.Options["opacity"] != "0.75" {
t.Fatalf("the terminal rules: %+v %+v", focused, unfocused)
}
if last := r.Rules[4]; last.Match != "fullscreen" || last.Options["opacity"] != "1" {
t.Fatalf("full screen is opaque, and last so it wins: %+v", last)
}
if len(r.Legacy) != 0 {
t.Fatalf("the module's file sets no option the rules supersede: %v", r.Legacy)
}
if _, inGlobal := r.Global["match"]; inGlobal {
t.Fatal("a rule's key leaked into the global options")
}
}
func TestTodaysFileIsReportedForTheOptionsItsRulesWouldIgnore(t *testing.T) {
conf := "inactive-opacity = 1.0;\nopacity-rule = [ \"95:class_g = 'XTerm'\" ];\nrules = (\n { match = \"focused\"; opacity = 1; }\n);\n"
r := parseRules("x", conf, []int{7})
if len(r.Rules) != 1 || r.Rules[0].Match != "focused" || len(r.Running) != 1 {
t.Fatalf("%+v", r)
}
if strings.Join(r.Legacy, ",") != "opacity-rule,inactive-opacity" {
t.Fatalf("legacy: %v", r.Legacy)
}
}
func TestAWindowIdIsHexOrDecimalAndNeverZero(t *testing.T) {
for in, want := range map[string]string{"0x3C00012": "0x3c00012", "62914578": "0x3c00012"} {
if got, err := windowID(in); err != nil || got != want {
t.Errorf("%s: %s, %v", in, got, err)
}
}
for _, bad := range []string{"0", "0x0", "window", "-1", "0x1ffffffff"} {
if _, err := windowID(bad); err == nil {
t.Errorf("%s was accepted", bad)
}
}
}
func TestOpacityIsAPercentOfTheFullCardinal(t *testing.T) {
if opacityCardinal(0) != 0 || opacityCardinal(100) != 0xffffffff || opacityCardinal(75) != 3221225471 {
t.Fatalf("%d %d %d", opacityCardinal(0), opacityCardinal(100), opacityCardinal(75))
}
r := parseWindow("0x1", "_NET_WM_WINDOW_OPACITY(CARDINAL) = 3221225471\nWM_CLASS(STRING) = \"xterm\", \"XTerm\"\n_NET_WM_NAME(UTF8_STRING) = \"op@host: ~\"\n")
if r.Opacity == nil || *r.Opacity != 75 || r.Class != "XTerm" || r.Title != "op@host: ~" {
t.Fatalf("%+v", r)
}
if r := parseWindow("0x1", "_NET_WM_WINDOW_OPACITY: not found.\n"); r.Opacity != nil {
t.Fatalf("no value of its own: %+v", r)
}
}
func TestSettingTheFocusedWindowsOpacityAsksXpropAndNamesTheRuleThatOutranksIt(t *testing.T) {
root := fakeMachine(t)
fakeProcess(t, nobody, "i3", "DISPLAY=:1")
conf := filepath.Join(root, "home", ".config", "picom")
if err := os.MkdirAll(conf, 0o755); err != nil {
t.Fatal(err)
}
src, _ := os.ReadFile(filepath.Join("..", "..", "files", "picom.conf"))
if err := os.WriteFile(filepath.Join(conf, "picom.conf"), src, 0o644); err != nil {
t.Fatal(err)
}
bin := fakeBinaries(t, map[string]string{"xprop": `echo "xprop $* DISPLAY=$DISPLAY" >> "$LOG"
case "$*" in
"-root _NET_ACTIVE_WINDOW") echo "_NET_ACTIVE_WINDOW(WINDOW): window id # 0x3c00012" ;;
*WM_CLASS*) printf '_NET_WM_WINDOW_OPACITY(CARDINAL) = 2147483648\nWM_CLASS(STRING) = "xterm", "XTerm"\n' ;;
esac`})
t.Setenv("LOG", filepath.Join(bin, "log"))
r, err := WindowOpacity("", 50)
if err != nil {
t.Fatal(err)
}
if r.Window != "0x3c00012" || r.Opacity == nil || *r.Opacity != 50 || !strings.Contains(r.Note, "XTerm") {
t.Fatalf("%+v", r)
}
log, _ := os.ReadFile(filepath.Join(bin, "log"))
if !strings.Contains(string(log), "xprop -id 0x3c00012 -f _NET_WM_WINDOW_OPACITY 32c -set _NET_WM_WINDOW_OPACITY 2147483648 DISPLAY=:1") {
t.Fatalf("xprop was asked:\n%s", log)
}
}
func TestWithoutASessionTheToolsThatDrawSaySo(t *testing.T) {
fakeMachine(t)
if _, err := WindowOpacity("", -1); !errors.Is(err, ErrNoSession) {
t.Fatalf("window opacity: %v", err)
}
on := true
if _, err := Toggle(&on); !errors.Is(err, ErrNoSession) {
t.Fatalf("toggle on: %v", err)
}
}
func TestARunningPicomIsToldToReinitialiseNotRestarted(t *testing.T) {
fakeMachine(t)
fakeProcess(t, nobody, "picom", "DISPLAY=:1")
r, err := Restart(false)
if err != nil || r.Action != "reinitialised" {
t.Fatalf("%+v, %v", r, err)
}
on := true
if r, err := Toggle(&on); err != nil || !r.Compositing || r.PIDs[0] != nobody {
t.Fatalf("on while running: %+v, %v", r, err)
}
}