mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-16 22:59:04 +02:00
* fix(cli): recover daemon executable path Co-authored-by: multica-agent <github@multica.ai> * fix(daemon): reuse executable fallback for restart Co-authored-by: multica-agent <github@multica.ai> --------- Co-authored-by: Eve <eve@multica-ai.local> Co-authored-by: multica-agent <github@multica.ai>
129 lines
3.4 KiB
Go
129 lines
3.4 KiB
Go
package selfexec
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestResolveWithUsesOSExecutable(t *testing.T) {
|
|
want := filepath.Join(t.TempDir(), "does-not-need-to-exist")
|
|
|
|
got, err := resolveWith(func() (string, error) {
|
|
return want, nil
|
|
}, nil)
|
|
if err != nil {
|
|
t.Fatalf("resolveWith() error = %v", err)
|
|
}
|
|
if got != want {
|
|
t.Fatalf("resolveWith() = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestResolveWithFallsBackToArgv0(t *testing.T) {
|
|
executableErr := errors.New("cannot find executable path")
|
|
failExecutable := func() (string, error) { return "", executableErr }
|
|
|
|
t.Run("absolute path", func(t *testing.T) {
|
|
want := writeTestExecutable(t, t.TempDir(), "multica")
|
|
|
|
got, err := resolveWith(failExecutable, []string{want})
|
|
if err != nil {
|
|
t.Fatalf("resolveWith() error = %v", err)
|
|
}
|
|
if got != want {
|
|
t.Fatalf("resolveWith() = %q, want %q", got, want)
|
|
}
|
|
})
|
|
|
|
t.Run("relative path", func(t *testing.T) {
|
|
dir := t.TempDir()
|
|
want := writeTestExecutable(t, dir, "multica")
|
|
t.Chdir(dir)
|
|
argv0 := "." + string(os.PathSeparator) + filepath.Base(want)
|
|
|
|
got, err := resolveWith(failExecutable, []string{argv0})
|
|
if err != nil {
|
|
t.Fatalf("resolveWith() error = %v", err)
|
|
}
|
|
if got != want {
|
|
t.Fatalf("resolveWith() = %q, want %q", got, want)
|
|
}
|
|
})
|
|
|
|
t.Run("PATH command", func(t *testing.T) {
|
|
dir := t.TempDir()
|
|
want := writeTestExecutable(t, dir, "multica")
|
|
t.Setenv("PATH", dir)
|
|
|
|
got, err := resolveWith(failExecutable, []string{"multica"})
|
|
if err != nil {
|
|
t.Fatalf("resolveWith() error = %v", err)
|
|
}
|
|
if got != want {
|
|
t.Fatalf("resolveWith() = %q, want %q", got, want)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestResolveWithRejectsInvalidFallback(t *testing.T) {
|
|
executableErr := errors.New("cannot find executable path")
|
|
failExecutable := func() (string, error) { return "", executableErr }
|
|
|
|
tests := []struct {
|
|
name string
|
|
args []string
|
|
want string
|
|
}{
|
|
{name: "missing argv0", args: nil, want: "argv[0] is empty"},
|
|
{name: "empty argv0", args: []string{""}, want: "argv[0] is empty"},
|
|
{name: "missing executable", args: []string{"multica-does-not-exist"}, want: "multica-does-not-exist"},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
_, err := resolveWith(failExecutable, tt.args)
|
|
if err == nil {
|
|
t.Fatal("resolveWith() error = nil, want failure")
|
|
}
|
|
if !errors.Is(err, executableErr) {
|
|
t.Fatalf("error = %q, want original os.Executable error", err)
|
|
}
|
|
if !strings.Contains(err.Error(), tt.want) {
|
|
t.Fatalf("error = %q, want %q", err, tt.want)
|
|
}
|
|
})
|
|
}
|
|
|
|
if runtime.GOOS != "windows" {
|
|
t.Run("non-executable file", func(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "multica")
|
|
if err := os.WriteFile(path, []byte("not executable"), 0o644); err != nil {
|
|
t.Fatalf("write non-executable fixture: %v", err)
|
|
}
|
|
|
|
_, err := resolveWith(failExecutable, []string{path})
|
|
if err == nil {
|
|
t.Fatal("resolveWith() error = nil, want failure")
|
|
}
|
|
if !errors.Is(err, executableErr) {
|
|
t.Fatalf("error = %q, want original os.Executable error", err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func writeTestExecutable(t *testing.T, dir, base string) string {
|
|
t.Helper()
|
|
if runtime.GOOS == "windows" {
|
|
base += ".exe"
|
|
}
|
|
path := filepath.Join(dir, base)
|
|
if err := os.WriteFile(path, []byte("test executable"), 0o755); err != nil {
|
|
t.Fatalf("write executable fixture: %v", err)
|
|
}
|
|
return path
|
|
}
|