github.com/rish1988/moby@v25.0.2+incompatible/cmd/dockerd/daemon_linux_test.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "os" 8 "strconv" 9 "testing" 10 11 "github.com/docker/docker/daemon/config" 12 "github.com/docker/docker/pkg/reexec" 13 "golang.org/x/sys/unix" 14 "gotest.tools/v3/assert" 15 ) 16 17 const ( 18 testListenerNoAddrCmdPhase1 = "test-listener-no-addr1" 19 testListenerNoAddrCmdPhase2 = "test-listener-no-addr2" 20 ) 21 22 type listenerTestResponse struct { 23 Err string 24 } 25 26 func initListenerTestPhase1() { 27 os.Setenv("LISTEN_PID", strconv.Itoa(os.Getpid())) 28 os.Setenv("LISTEN_FDS", "1") 29 30 // NOTE: We cannot use O_CLOEXEC here because we need the fd to stay open for the child process. 31 _, err := unix.Socket(unix.AF_UNIX, unix.SOCK_STREAM, 0) 32 if err != nil { 33 fmt.Fprintln(os.Stderr, err) 34 os.Exit(1) 35 } 36 37 cmd := reexec.Command(testListenerNoAddrCmdPhase2) 38 if err := unix.Exec(cmd.Path, cmd.Args, os.Environ()); err != nil { 39 fmt.Fprintln(os.Stderr, err) 40 os.Exit(1) 41 } 42 } 43 44 func initListenerTestPhase2() { 45 cfg := &config.Config{ 46 CommonConfig: config.CommonConfig{ 47 Hosts: []string{"fd://"}, 48 }, 49 } 50 _, _, err := loadListeners(cfg, nil) 51 var resp listenerTestResponse 52 if err != nil { 53 resp.Err = err.Error() 54 } 55 56 if err := json.NewEncoder(os.Stdout).Encode(resp); err != nil { 57 fmt.Fprintln(os.Stderr, err) 58 os.Exit(1) 59 } 60 } 61 62 // Test to make sure that the listen specs without an address are handled 63 // It requires a 2-phase setup due to how socket activation works (which we are using to test). 64 // It requires LISTEN_FDS and LISTEN_PID to be set in the environment. 65 // 66 // LISTEN_PID is used by socket activation to determine if the process is the one that should be activated. 67 // LISTEN_FDS is used by socket activation to determine how many file descriptors are passed to the process. 68 // 69 // We can sort of fake this without using extra processes, but it ends up not 70 // being a true test because that's not how socket activation is expected to 71 // work and we'll end up with nil listeners since the test framework has other 72 // file descriptors open. 73 // 74 // This is not currently testing `tcp://` or `unix://` listen specs without an address because those can conflict with the machine running the test. 75 // This could be worked around by using linux namespaces, however that would require root privileges which unit tests don't typically have. 76 func TestLoadListenerNoAddr(t *testing.T) { 77 cmd := reexec.Command(testListenerNoAddrCmdPhase1) 78 stdout := bytes.NewBuffer(nil) 79 cmd.Stdout = stdout 80 stderr := bytes.NewBuffer(nil) 81 cmd.Stderr = stderr 82 83 assert.NilError(t, cmd.Run(), stderr.String()) 84 85 var resp listenerTestResponse 86 assert.NilError(t, json.NewDecoder(stdout).Decode(&resp)) 87 assert.Equal(t, resp.Err, "") 88 }