Files
overlord/Overlord-Client/cmd/agent/persistence/persistence_linux_test.go
T

194 lines
5.7 KiB
Go
Raw Normal View History

//go:build linux
// +build linux
package persistence
import (
"os"
"path/filepath"
"strings"
"testing"
)
func withLinuxTempHome(t *testing.T) string {
t.Helper()
home := t.TempDir()
origHome := currentUserHomeDir
origStartupName := DefaultStartupName
currentUserHomeDir = func() (string, error) { return home, nil }
DefaultStartupName = ""
t.Cleanup(func() {
currentUserHomeDir = origHome
DefaultStartupName = origStartupName
})
return home
}
func writeLinuxSourceExecutable(t *testing.T) string {
t.Helper()
src := filepath.Join(t.TempDir(), "source-agent")
if err := os.WriteFile(src, []byte("agent-bytes"), 0644); err != nil {
t.Fatalf("write source executable: %v", err)
}
return src
}
func TestLinuxInstallCreatesSystemdServiceAndExecutable(t *testing.T) {
home := withLinuxTempHome(t)
src := writeLinuxSourceExecutable(t)
if err := InstallFrom(src); err != nil {
t.Fatalf("InstallFrom() error: %v", err)
}
target := filepath.Join(home, ".local", "share", "overlord", "agent")
gotBytes, err := os.ReadFile(target)
if err != nil {
t.Fatalf("read installed executable: %v", err)
}
if string(gotBytes) != "agent-bytes" {
t.Fatalf("installed executable content mismatch: %q", string(gotBytes))
}
if info, err := os.Stat(target); err != nil {
t.Fatalf("stat installed executable: %v", err)
} else if info.Mode().Perm() != 0755 {
t.Fatalf("installed executable mode = %o, want 0755", info.Mode().Perm())
}
servicePath := filepath.Join(home, ".config", "systemd", "user", "agent.service")
serviceBytes, err := os.ReadFile(servicePath)
if err != nil {
t.Fatalf("read systemd service: %v", err)
}
service := string(serviceBytes)
for _, want := range []string{
"Description=Overlord Agent",
"ExecStart=" + target,
"Restart=always",
"WantedBy=default.target",
} {
if !strings.Contains(service, want) {
t.Fatalf("systemd service missing %q:\n%s", want, service)
}
}
autostartPath := filepath.Join(home, ".config", "autostart", "agent.desktop")
if _, err := os.Stat(autostartPath); !os.IsNotExist(err) {
t.Fatalf("default install should prefer systemd and not write desktop entry, stat err=%v", err)
}
}
func TestLinuxConfigureCreatesSystemdServiceForExistingPath(t *testing.T) {
home := withLinuxTempHome(t)
exePath := filepath.Join(home, "bin", "existing-agent")
if err := Configure(exePath); err != nil {
t.Fatalf("Configure() error: %v", err)
}
servicePath := filepath.Join(home, ".config", "systemd", "user", "agent.service")
serviceBytes, err := os.ReadFile(servicePath)
if err != nil {
t.Fatalf("read systemd service: %v", err)
}
if service := string(serviceBytes); !strings.Contains(service, "ExecStart="+exePath) {
t.Fatalf("systemd service missing executable path %q:\n%s", exePath, service)
}
}
func TestLinuxInstallAutostartCreatesDesktopEntry(t *testing.T) {
home := withLinuxTempHome(t)
exePath := filepath.Join(home, "bin", "existing-agent")
if err := installAutostart(exePath); err != nil {
t.Fatalf("installAutostart() error: %v", err)
}
desktopPath := filepath.Join(home, ".config", "autostart", "agent.desktop")
desktopBytes, err := os.ReadFile(desktopPath)
if err != nil {
t.Fatalf("read desktop entry: %v", err)
}
desktop := string(desktopBytes)
for _, want := range []string{
"[Desktop Entry]",
"Type=Application",
"Exec=" + exePath,
"X-GNOME-Autostart-enabled=true",
} {
if !strings.Contains(desktop, want) {
t.Fatalf("desktop entry missing %q:\n%s", want, desktop)
}
}
}
func TestLinuxCustomStartupNameChangesServiceAndBinaryNames(t *testing.T) {
home := withLinuxTempHome(t)
DefaultStartupName = "updater"
if err := InstallFrom(writeLinuxSourceExecutable(t)); err != nil {
t.Fatalf("InstallFrom() error: %v", err)
}
target := filepath.Join(home, ".local", "share", "overlord", "updater")
if _, err := os.Stat(target); err != nil {
t.Fatalf("stat custom executable: %v", err)
}
servicePath := filepath.Join(home, ".config", "systemd", "user", "updater.service")
serviceBytes, err := os.ReadFile(servicePath)
if err != nil {
t.Fatalf("read custom systemd service: %v", err)
}
if service := string(serviceBytes); !strings.Contains(service, "ExecStart="+target) {
t.Fatalf("custom systemd service missing target %q:\n%s", target, service)
}
}
func TestLinuxUninstallRemovesStartupFilesAndExecutable(t *testing.T) {
home := withLinuxTempHome(t)
target := filepath.Join(home, ".local", "share", "overlord", "agent")
servicePath := filepath.Join(home, ".config", "systemd", "user", "agent.service")
desktopPath := filepath.Join(home, ".config", "autostart", "agent.desktop")
for _, path := range []string{target, servicePath, desktopPath} {
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
t.Fatalf("mkdir %q: %v", filepath.Dir(path), err)
}
if err := os.WriteFile(path, []byte("x"), 0644); err != nil {
t.Fatalf("write %q: %v", path, err)
}
}
if err := Remove(); err != nil {
t.Fatalf("Remove() error: %v", err)
}
for _, path := range []string{target, servicePath, desktopPath} {
if _, err := os.Stat(path); !os.IsNotExist(err) {
t.Fatalf("expected %q to be removed, stat err=%v", path, err)
}
}
}
func TestLinuxReplaceExecutablePreservesExecutableModeWhenTargetExists(t *testing.T) {
_ = withLinuxTempHome(t)
src := writeLinuxSourceExecutable(t)
target := filepath.Join(t.TempDir(), "agent")
if err := os.WriteFile(target, []byte("old"), 0644); err != nil {
t.Fatalf("write existing target: %v", err)
}
if err := replaceExecutable(src, target); err != nil {
t.Fatalf("replaceExecutable() error: %v", err)
}
if info, err := os.Stat(target); err != nil {
t.Fatalf("stat replaced executable: %v", err)
} else if info.Mode().Perm() != 0755 {
t.Fatalf("replaced executable mode = %o, want 0755", info.Mode().Perm())
}
}