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  }