Skip to content

Commit 5b8f99b

Browse files
committed
exec: improve test-coverage for naiveSelf
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
1 parent 6d76d62 commit 5b8f99b

2 files changed

Lines changed: 64 additions & 23 deletions

File tree

reexec/reexec.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,12 @@ func Self() string {
8181
if runtime.GOOS == "linux" {
8282
return "/proc/self/exe"
8383
}
84-
return naiveSelf()
84+
return naiveSelf(os.Args[0])
8585
}
8686

87-
func naiveSelf() string {
88-
name := os.Args[0]
87+
// naiveSelf is a separate function to allow testing in isolation on Linux.
88+
func naiveSelf(argv0 string) string {
89+
name := argv0
8990
if filepath.Base(name) == name {
9091
if lp, err := exec.LookPath(name); err == nil {
9192
return lp

reexec/reexec_test.go

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"os/exec"
99
"path/filepath"
1010
"reflect"
11+
"runtime"
1112
"strings"
1213
"testing"
1314
"time"
@@ -197,30 +198,69 @@ func TestCommandContext(t *testing.T) {
197198
}
198199
}
199200

200-
func TestNaiveSelf(t *testing.T) {
201-
if os.Getenv("TEST_CHECK") == "1" {
202-
os.Exit(2)
203-
}
204-
cmd := exec.Command(naiveSelf(), "-test.run=TestNaiveSelf")
205-
cmd.Env = append(cmd.Environ(), "TEST_CHECK=1")
206-
err := cmd.Start()
201+
// TestRunNaiveSelf verifies that reexec.Self() (and thus CommandContext)
202+
// can resolve a path that can be used to re-execute the current test binary
203+
// when it falls back to the argv[0]-based implementation.
204+
//
205+
// It invokes the binary via naiveSelf (intentionally bypassing the Linux
206+
// /proc/self/exe fast-path) so the fallback logic is exercised consistently
207+
// across platforms.
208+
func TestRunNaiveSelf(t *testing.T) {
209+
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
210+
defer cancel()
211+
212+
// Similar to [rexec.CommandContext], but using naiveSelf to skip the
213+
// optimized "/proc/self/exe" on Linux.
214+
cmd := exec.CommandContext(ctx, naiveSelf(os.Args[0]), testReExec2)
215+
cmd.Args = cmd.Args[1:]
216+
217+
out, err := cmd.CombinedOutput()
207218
if err != nil {
208219
t.Fatalf("Unable to start command: %v", err)
209220
}
210-
err = cmd.Wait()
211-
212-
var expError *exec.ExitError
213-
if !errors.As(err, &expError) {
214-
t.Fatalf("got %T, want %T", err, expError)
215-
}
216221

217-
const expected = "exit status 2"
218-
if err.Error() != expected {
219-
t.Fatalf("got %v, want %v", err, expected)
222+
expOut := "Hello test-reexec2"
223+
actual := strings.TrimSpace(string(out))
224+
if actual != expOut {
225+
t.Errorf("got %v, want %v", actual, expOut)
220226
}
227+
}
221228

222-
os.Args[0] = "mkdir"
223-
if naiveSelf() == os.Args[0] {
224-
t.Fatalf("Expected naiveSelf to resolve the location of mkdir")
225-
}
229+
func TestNaiveSelfResolve(t *testing.T) {
230+
t.Run("resolve in PATH", func(t *testing.T) {
231+
executable := "sh"
232+
if runtime.GOOS == "windows" {
233+
executable = "cmd"
234+
}
235+
resolved := naiveSelf(executable)
236+
if resolved == executable {
237+
t.Errorf("did not resolve via PATH; got %q", resolved)
238+
}
239+
if !filepath.IsAbs(resolved) {
240+
t.Errorf("expected absolute path; got %q", resolved)
241+
}
242+
})
243+
t.Run("not in PATH", func(t *testing.T) {
244+
const executable = "some-nonexistent-executable"
245+
resolved := naiveSelf(executable)
246+
want, _ := filepath.Abs(executable)
247+
if resolved != want {
248+
t.Errorf("expected absolute path; got %q, want %q", resolved, want)
249+
}
250+
})
251+
t.Run("relative path", func(t *testing.T) {
252+
executable := filepath.Join(".", "some-executable")
253+
resolved := naiveSelf(executable)
254+
want, _ := filepath.Abs(executable)
255+
if resolved != want {
256+
t.Errorf("expected absolute path; got %q, want %q", resolved, want)
257+
}
258+
})
259+
t.Run("absolute path unchanged", func(t *testing.T) {
260+
executable := filepath.Join(os.TempDir(), "some-executable")
261+
resolved := naiveSelf(executable)
262+
if resolved != executable {
263+
t.Errorf("should not modify absolute paths; got %q, want %q", resolved, executable)
264+
}
265+
})
226266
}

0 commit comments

Comments
 (0)