1- package reexec
1+ package reexec_test
22
33import (
44 "context"
55 "errors"
66 "fmt"
77 "os"
8- "os/exec"
98 "path/filepath"
109 "reflect"
1110 "runtime"
1211 "strings"
1312 "testing"
1413 "time"
14+
15+ "github.com/moby/sys/reexec"
16+ "github.com/moby/sys/reexec/internal/reexecoverride"
1517)
1618
1719const (
@@ -21,23 +23,23 @@ const (
2123)
2224
2325func init () {
24- Register (testReExec , func () {
26+ reexec . Register (testReExec , func () {
2527 panic ("Return Error" )
2628 })
27- Register (testReExec2 , func () {
29+ reexec . Register (testReExec2 , func () {
2830 var args string
2931 if len (os .Args ) > 1 {
3032 args = fmt .Sprintf ("(args: %#v)" , os .Args [1 :])
3133 }
3234 fmt .Println ("Hello" , testReExec2 , args )
3335 os .Exit (0 )
3436 })
35- Register (testReExec3 , func () {
37+ reexec . Register (testReExec3 , func () {
3638 fmt .Println ("Hello " + testReExec3 )
3739 time .Sleep (1 * time .Second )
3840 os .Exit (0 )
3941 })
40- if Init () {
42+ if reexec . Init () {
4143 // Make sure we exit in case re-exec didn't os.Exit on its own.
4244 os .Exit (0 )
4345 }
@@ -73,7 +75,7 @@ func TestRegister(t *testing.T) {
7375 t .Errorf ("got %q, want %q" , r , tc .expectedErr )
7476 }
7577 }()
76- Register (tc .name , func () {})
78+ reexec . Register (tc .name , func () {})
7779 })
7880 }
7981}
@@ -102,7 +104,7 @@ func TestCommand(t *testing.T) {
102104 }
103105 for _ , tc := range tests {
104106 t .Run (tc .doc , func (t * testing.T ) {
105- cmd := Command (tc .cmdAndArgs ... )
107+ cmd := reexec . Command (tc .cmdAndArgs ... )
106108 if ! reflect .DeepEqual (cmd .Args , tc .cmdAndArgs ) {
107109 t .Fatalf ("got %+v, want %+v" , cmd .Args , tc .cmdAndArgs )
108110 }
@@ -169,7 +171,7 @@ func TestCommandContext(t *testing.T) {
169171 ctx , cancel := context .WithTimeout (context .Background (), 100 * time .Millisecond )
170172 defer cancel ()
171173
172- cmd := CommandContext (ctx , tc .cmdAndArgs ... )
174+ cmd := reexec . CommandContext (ctx , tc .cmdAndArgs ... )
173175 if ! reflect .DeepEqual (cmd .Args , tc .cmdAndArgs ) {
174176 t .Fatalf ("got %+v, want %+v" , cmd .Args , tc .cmdAndArgs )
175177 }
@@ -208,11 +210,10 @@ func TestRunNaiveSelf(t *testing.T) {
208210 ctx , cancel := context .WithTimeout (context .Background (), 100 * time .Millisecond )
209211 defer cancel ()
210212
211- // Similar to [rexec.CommandContext], but using naiveSelf to skip the
212- // optimized "/proc/self/exe" on Linux.
213- cmd := exec .CommandContext (ctx , naiveSelf (os .Args [0 ]), testReExec2 )
214- cmd .Args = cmd .Args [1 :]
213+ // Force Self() to use naiveSelf(os.Args[0]), instead of "/proc/self/exe" on Linux.
214+ reexecoverride .OverrideArgv0 (t , os .Args [0 ])
215215
216+ cmd := reexec .CommandContext (ctx , testReExec2 )
216217 out , err := cmd .CombinedOutput ()
217218 if err != nil {
218219 t .Fatalf ("Unable to start command: %v" , err )
@@ -226,12 +227,23 @@ func TestRunNaiveSelf(t *testing.T) {
226227}
227228
228229func TestNaiveSelfResolve (t * testing.T ) {
230+ t .Run ("fast path on Linux" , func (t * testing.T ) {
231+ if runtime .GOOS != "linux" {
232+ t .Skip ("only supported on Linux" )
233+ }
234+ resolved := reexec .Self ()
235+ expected := "/proc/self/exe"
236+ if resolved != expected {
237+ t .Errorf ("got %v, want %v" , resolved , expected )
238+ }
239+ })
229240 t .Run ("resolve in PATH" , func (t * testing.T ) {
230241 executable := "sh"
231242 if runtime .GOOS == "windows" {
232243 executable = "cmd"
233244 }
234- resolved := naiveSelf (executable )
245+ reexecoverride .OverrideArgv0 (t , executable )
246+ resolved := reexec .Self ()
235247 if resolved == executable {
236248 t .Errorf ("did not resolve via PATH; got %q" , resolved )
237249 }
@@ -241,23 +253,26 @@ func TestNaiveSelfResolve(t *testing.T) {
241253 })
242254 t .Run ("not in PATH" , func (t * testing.T ) {
243255 const executable = "some-nonexistent-executable"
244- resolved := naiveSelf (executable )
256+ reexecoverride .OverrideArgv0 (t , executable )
257+ resolved := reexec .Self ()
245258 want , _ := filepath .Abs (executable )
246259 if resolved != want {
247260 t .Errorf ("expected absolute path; got %q, want %q" , resolved , want )
248261 }
249262 })
250263 t .Run ("relative path" , func (t * testing.T ) {
251264 executable := filepath .Join ("." , "some-executable" )
252- resolved := naiveSelf (executable )
265+ reexecoverride .OverrideArgv0 (t , executable )
266+ resolved := reexec .Self ()
253267 want , _ := filepath .Abs (executable )
254268 if resolved != want {
255269 t .Errorf ("expected absolute path; got %q, want %q" , resolved , want )
256270 }
257271 })
258272 t .Run ("absolute path unchanged" , func (t * testing.T ) {
259273 executable := filepath .Join (os .TempDir (), "some-executable" )
260- resolved := naiveSelf (executable )
274+ reexecoverride .OverrideArgv0 (t , executable )
275+ resolved := reexec .Self ()
261276 if resolved != executable {
262277 t .Errorf ("should not modify absolute paths; got %q, want %q" , resolved , executable )
263278 }
0 commit comments