Files
multica/server/internal/selfexec/selfexec_test.go
Multica Eve a91a390d48 fix(cli): recover daemon executable path (MUL-4514)
* 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>
2026-07-14 14:50:22 +08:00

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
}