Files
miandmhoennig f9c1ae835d Api socket (#5)
Co-authored-by: mhoennig <michael@hoennig.de>
Reviewed-on: #5
2026-09-10 22:09:58 +02:00

79 lines
2.3 KiB
Go

package cli
import (
"net"
"os"
"path/filepath"
"strings"
"testing"
"time"
)
func TestSocketPathPrefersTheRuntimeDirectory(t *testing.T) {
t.Setenv("XDG_RUNTIME_DIR", "/run/user/1000")
got, err := socketPath("", "/home/user/.werkdock")
if err != nil || got != "/run/user/1000/werkdock.sock" {
t.Errorf("got %q, %v", got, err)
}
// an argument wins, in podman's spelling or plain
for _, arg := range []string{"/tmp/other.sock", "unix:///tmp/other.sock"} {
if got, err := socketPath(arg, "/store"); err != nil || got != "/tmp/other.sock" {
t.Errorf("%q: got %q, %v", arg, got, err)
}
}
t.Setenv("XDG_RUNTIME_DIR", "")
if got, err := socketPath("", "/home/user/.werkdock"); err != nil || got != "/home/user/.werkdock/werkdock.sock" {
t.Errorf("without a runtime directory: got %q, %v", got, err)
}
}
// A unix socket path has a hard kernel limit; a long home directory
// would otherwise fail with an obscure message far from the cause.
func TestSocketPathRefusesAPathTooLongForAUnixSocket(t *testing.T) {
long := "/" + strings.Repeat("directory/", 12) + "werkdock.sock"
_, err := socketPath(long, "/store")
if err == nil || !strings.Contains(err.Error(), "too long") {
t.Errorf("got %v", err)
}
}
func TestListenReplacesADeadSocketButNotALiveOne(t *testing.T) {
dir := t.TempDir()
socket := filepath.Join(dir, "werkdock.sock")
// a file left behind by a service that died
if err := os.WriteFile(socket, nil, 0o600); err != nil {
t.Fatal(err)
}
ln, err := listen(socket)
if err != nil {
t.Fatalf("stale socket not replaced: %v", err)
}
defer ln.Close()
info, err := os.Stat(socket)
if err != nil {
t.Fatal(err)
}
if perm := info.Mode().Perm(); perm != 0o600 {
t.Errorf("the socket is the API: mode %o, want 600", perm)
}
// and now a second service must not take it over
accepted := make(chan struct{}, 1)
go func() {
if conn, err := ln.Accept(); err == nil {
conn.Close()
accepted <- struct{}{}
}
}()
if _, err := listen(socket); err == nil || !strings.Contains(err.Error(), "already listening") {
t.Errorf("second service: %v", err)
}
select {
case <-accepted:
case <-time.After(2 * time.Second):
t.Error("the live check never connected")
}
if _, err := net.Dial("unix", socket); err != nil {
t.Errorf("the first service lost its socket: %v", err)
}
}