// Copyright (c) 2026 Storm Dragon // Authors: Storm Dragon, Angus Kola // SPDX-License-Identifier: GPL-3.0-or-later package sessionbus import ( "bufio" "bytes" "context" "log/slog" "os" "os/exec" "path/filepath" "strings" "testing" "github.com/godbus/dbus/v5" ) func TestSessionBusHelper(t *testing.T) { expectedID := os.Getenv("CTHULHU_SESSIONBUS_EXPECTED_ID") if expectedID == "" { t.Skip("subprocess helper") } before, present := os.LookupEnv("DBUS_SESSION_BUS_ADDRESS") var output bytes.Buffer logger := slog.New(slog.NewJSONHandler(&output, &slog.HandlerOptions{Level: slog.LevelDebug})) connection, err := Connect(logger, "test") if err != nil { t.Fatal(err) } defer connection.Close() var busID string if err := connection.BusObject().Call("org.freedesktop.DBus.GetId", 0).Store(&busID); err != nil { t.Fatal(err) } if busID != expectedID { t.Fatalf("selected bus %q, want %q", busID, expectedID) } if after, exists := os.LookupEnv("DBUS_SESSION_BUS_ADDRESS"); after != before || exists != present { t.Fatal("session discovery changed process environment") } if !strings.Contains(output.String(), `"bus_id":"`+expectedID+`"`) { t.Fatal("missing bus identity diagnostic") } if strings.Contains(output.String(), os.Getenv("XDG_RUNTIME_DIR")) { t.Fatal("diagnostic exposes runtime directory") } } func TestNativeDesktopSessionBusDiscovery(t *testing.T) { if os.Getenv("CTHULHU_NATIVE_DBUS_TEST") != "1" { t.Skip("requires private session bus sockets") } startBus := func() (string, string, string) { runtimeDirectory := t.TempDir() process := exec.Command("dbus-daemon", "--session", "--nofork", "--address=unix:path="+filepath.Join(runtimeDirectory, "bus"), "--print-address=1") stdout, err := process.StdoutPipe() if err != nil { t.Fatal(err) } if err := process.Start(); err != nil { t.Fatal(err) } t.Cleanup(func() { process.Process.Kill(); process.Wait() }) address, err := bufio.NewReader(stdout).ReadString('\n') if err != nil { t.Fatal(err) } connection, err := dbus.Connect(strings.TrimSpace(address)) if err != nil { t.Fatal(err) } defer connection.Close() var busID string if err := connection.BusObject().CallWithContext(context.Background(), "org.freedesktop.DBus.GetId", 0).Store(&busID); err != nil { t.Fatal(err) } return runtimeDirectory, strings.TrimSpace(address), busID } runtimeDirectory, _, runtimeID := startBus() _, explicitAddress, explicitID := startBus() executable, err := os.Executable() if err != nil { t.Fatal(err) } for _, explicit := range []bool{false, true} { expectedID := runtimeID environment := make([]string, 0) for _, value := range os.Environ() { if !strings.HasPrefix(value, "DBUS_SESSION_BUS_ADDRESS=") && !strings.HasPrefix(value, "XDG_RUNTIME_DIR=") { environment = append(environment, value) } } if explicit { environment = append(environment, "DBUS_SESSION_BUS_ADDRESS="+explicitAddress) expectedID = explicitID } environment = append(environment, "XDG_RUNTIME_DIR="+runtimeDirectory, "CTHULHU_SESSIONBUS_EXPECTED_ID="+expectedID) process := exec.Command(executable, "-test.run=^TestSessionBusHelper$", "-test.v") process.Env = environment if output, err := process.CombinedOutput(); err != nil { t.Fatalf("explicit=%v: %v\n%s", explicit, err, output) } } }