banger/internal/paths/layout_test.go
Thales Maciel f8979de58a
coverage: easy-wins batch across cli, system, paths, vmdns, toolingplan
Pure-Go tests for formatters, layout resolution, and validators — no
fixtures, no external processes. Targets previously-zero functions the
triage scan flagged as low-hanging fruit.

  cli          55% -> 65%
  paths        64% -> 91%
  system       65% -> 75%
  vmdns        72% -> 86%
  toolingplan  73% -> 78%

Total 52.6% -> 54.0%.
2026-04-18 17:57:05 -03:00

136 lines
3.6 KiB
Go

package paths
import (
"os"
"path/filepath"
"strings"
"testing"
)
func TestResolveUsesXDGOverrides(t *testing.T) {
dir := t.TempDir()
t.Setenv("XDG_CONFIG_HOME", filepath.Join(dir, "config"))
t.Setenv("XDG_STATE_HOME", filepath.Join(dir, "state"))
t.Setenv("XDG_CACHE_HOME", filepath.Join(dir, "cache"))
t.Setenv("XDG_RUNTIME_DIR", filepath.Join(dir, "run"))
layout, err := Resolve()
if err != nil {
t.Fatalf("Resolve: %v", err)
}
if layout.ConfigDir != filepath.Join(dir, "config", "banger") {
t.Errorf("ConfigDir = %q", layout.ConfigDir)
}
if layout.StateDir != filepath.Join(dir, "state", "banger") {
t.Errorf("StateDir = %q", layout.StateDir)
}
if layout.CacheDir != filepath.Join(dir, "cache", "banger") {
t.Errorf("CacheDir = %q", layout.CacheDir)
}
if layout.RuntimeDir != filepath.Join(dir, "run", "banger") {
t.Errorf("RuntimeDir = %q", layout.RuntimeDir)
}
if !strings.HasSuffix(layout.SocketPath, "bangerd.sock") {
t.Errorf("SocketPath = %q", layout.SocketPath)
}
if !strings.HasSuffix(layout.DBPath, "state.db") {
t.Errorf("DBPath = %q", layout.DBPath)
}
}
func TestResolveFallsBackWhenRuntimeUnset(t *testing.T) {
t.Setenv("XDG_RUNTIME_DIR", "")
layout, err := Resolve()
if err != nil {
t.Fatalf("Resolve: %v", err)
}
if !strings.Contains(layout.RuntimeDir, "banger-runtime-") {
t.Errorf("expected fallback runtime dir, got %q", layout.RuntimeDir)
}
}
func TestEnsureCreatesAllDirs(t *testing.T) {
base := t.TempDir()
layout := Layout{
ConfigDir: filepath.Join(base, "config"),
StateDir: filepath.Join(base, "state"),
CacheDir: filepath.Join(base, "cache"),
RuntimeDir: filepath.Join(base, "runtime"),
VMsDir: filepath.Join(base, "state/vms"),
ImagesDir: filepath.Join(base, "state/images"),
KernelsDir: filepath.Join(base, "state/kernels"),
OCICacheDir: filepath.Join(base, "cache/oci"),
}
if err := Ensure(layout); err != nil {
t.Fatalf("Ensure: %v", err)
}
for _, dir := range []string{
layout.ConfigDir,
layout.StateDir,
layout.CacheDir,
layout.RuntimeDir,
layout.VMsDir,
layout.ImagesDir,
layout.KernelsDir,
layout.OCICacheDir,
} {
info, err := os.Stat(dir)
if err != nil {
t.Errorf("stat %q: %v", dir, err)
continue
}
if !info.IsDir() {
t.Errorf("%q is not a directory", dir)
}
}
// Idempotent.
if err := Ensure(layout); err != nil {
t.Fatalf("Ensure (second run): %v", err)
}
}
func TestBangerdPathEnvOverride(t *testing.T) {
t.Setenv("BANGER_DAEMON_BIN", "/tmp/custom-bangerd")
got, err := BangerdPath()
if err != nil {
t.Fatalf("BangerdPath: %v", err)
}
if got != "/tmp/custom-bangerd" {
t.Errorf("got %q, want /tmp/custom-bangerd", got)
}
}
func TestBangerdPathFindsSiblingBinary(t *testing.T) {
t.Setenv("BANGER_DAEMON_BIN", "")
root := t.TempDir()
sibling := filepath.Join(root, "bangerd")
if err := os.WriteFile(sibling, []byte("#!/bin/sh\n"), 0o755); err != nil {
t.Fatalf("WriteFile: %v", err)
}
original := executablePath
executablePath = func() (string, error) { return filepath.Join(root, "banger"), nil }
t.Cleanup(func() { executablePath = original })
got, err := BangerdPath()
if err != nil {
t.Fatalf("BangerdPath: %v", err)
}
if got != sibling {
t.Errorf("got %q, want %q", got, sibling)
}
}
func TestBangerdPathNotFound(t *testing.T) {
t.Setenv("BANGER_DAEMON_BIN", "")
root := t.TempDir()
original := executablePath
executablePath = func() (string, error) { return filepath.Join(root, "banger"), nil }
t.Cleanup(func() { executablePath = original })
if _, err := BangerdPath(); err == nil {
t.Fatal("expected error when no sibling bangerd exists")
}
}