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/reexectest"
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 (t .Context (), 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,11 @@ func TestRunNaiveSelf(t *testing.T) {
208210 ctx , cancel := context .WithTimeout (t .Context (), 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+ restore := reexectest .OverrideArgv0 (os .Args [0 ])
215+ t .Cleanup (restore )
215216
217+ cmd := reexec .CommandContext (ctx , testReExec2 )
216218 out , err := cmd .CombinedOutput ()
217219 if err != nil {
218220 t .Fatalf ("Unable to start command: %v" , err )
@@ -226,12 +228,24 @@ func TestRunNaiveSelf(t *testing.T) {
226228}
227229
228230func TestNaiveSelfResolve (t * testing.T ) {
231+ t .Run ("fast path on Linux" , func (t * testing.T ) {
232+ if runtime .GOOS != "linux" {
233+ t .Skip ("only supported on Linux" )
234+ }
235+ resolved := reexec .Self ()
236+ expected := "/proc/self/exe"
237+ if resolved != expected {
238+ t .Errorf ("got %v, want %v" , resolved , expected )
239+ }
240+ })
229241 t .Run ("resolve in PATH" , func (t * testing.T ) {
230242 executable := "sh"
231243 if runtime .GOOS == "windows" {
232244 executable = "cmd"
233245 }
234- resolved := naiveSelf (executable )
246+ restore := reexectest .OverrideArgv0 (executable )
247+ t .Cleanup (restore )
248+ resolved := reexec .Self ()
235249 if resolved == executable {
236250 t .Errorf ("did not resolve via PATH; got %q" , resolved )
237251 }
@@ -241,23 +255,29 @@ func TestNaiveSelfResolve(t *testing.T) {
241255 })
242256 t .Run ("not in PATH" , func (t * testing.T ) {
243257 const executable = "some-nonexistent-executable"
244- resolved := naiveSelf (executable )
258+ restore := reexectest .OverrideArgv0 (executable )
259+ t .Cleanup (restore )
260+ resolved := reexec .Self ()
245261 want , _ := filepath .Abs (executable )
246262 if resolved != want {
247263 t .Errorf ("expected absolute path; got %q, want %q" , resolved , want )
248264 }
249265 })
250266 t .Run ("relative path" , func (t * testing.T ) {
251267 executable := filepath .Join ("." , "some-executable" )
252- resolved := naiveSelf (executable )
268+ restore := reexectest .OverrideArgv0 (executable )
269+ t .Cleanup (restore )
270+ resolved := reexec .Self ()
253271 want , _ := filepath .Abs (executable )
254272 if resolved != want {
255273 t .Errorf ("expected absolute path; got %q, want %q" , resolved , want )
256274 }
257275 })
258276 t .Run ("absolute path unchanged" , func (t * testing.T ) {
259277 executable := filepath .Join (os .TempDir (), "some-executable" )
260- resolved := naiveSelf (executable )
278+ restore := reexectest .OverrideArgv0 (executable )
279+ resolved := reexec .Self ()
280+ restore ()
261281 if resolved != executable {
262282 t .Errorf ("should not modify absolute paths; got %q, want %q" , resolved , executable )
263283 }
0 commit comments