79 lines
2.3 KiB
Go
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)
|
|
}
|
|
}
|