github.com/geofffranks/garden-linux@v0.0.0-20160715111146-26c893169cfa/iodaemon/link/link_test.go (about)

     1  package link_test
     2  
     3  import (
     4  	"io/ioutil"
     5  	"net"
     6  	"os"
     7  	"os/exec"
     8  	"path"
     9  	"strconv"
    10  	"strings"
    11  	"syscall"
    12  
    13  	linkpkg "code.cloudfoundry.org/garden-linux/iodaemon/link"
    14  	"code.cloudfoundry.org/garden-linux/iodaemon/link/fake_unix_server"
    15  	. "github.com/onsi/ginkgo"
    16  	. "github.com/onsi/gomega"
    17  	"github.com/onsi/gomega/gbytes"
    18  )
    19  
    20  var _ = Describe("Link", func() {
    21  	var (
    22  		unixSockerPath            string
    23  		fakeServer                *fake_unix_server.FakeUnixServer
    24  		stdout, stderr            *gbytes.Buffer
    25  		stdoutW, stderrW, statusW *os.File
    26  	)
    27  
    28  	BeforeEach(func() {
    29  		tmpDir, err := ioutil.TempDir("", "")
    30  		Expect(err).ToNot(HaveOccurred())
    31  
    32  		unixSockerPath = path.Join(tmpDir, "iodaemon.sock")
    33  
    34  		fakeServer, err = fake_unix_server.NewFakeUnixServer(unixSockerPath)
    35  		Expect(err).ToNot(HaveOccurred())
    36  
    37  		stdout = gbytes.NewBuffer()
    38  		stderr = gbytes.NewBuffer()
    39  
    40  		var (
    41  			stdoutR, stderrR, statusR *os.File
    42  		)
    43  
    44  		stdoutR, stdoutW, err = os.Pipe()
    45  		Expect(err).ToNot(HaveOccurred())
    46  		stderrR, stderrW, err = os.Pipe()
    47  		Expect(err).ToNot(HaveOccurred())
    48  		statusR, statusW, err = os.Pipe()
    49  		Expect(err).ToNot(HaveOccurred())
    50  
    51  		fakeServer.SetConnectionHandler(func(conn net.Conn) {
    52  			rights := syscall.UnixRights(
    53  				int(stdoutR.Fd()),
    54  				int(stderrR.Fd()),
    55  				int(statusR.Fd()),
    56  			)
    57  
    58  			conn.(*net.UnixConn).WriteMsgUnix([]byte{}, rights, nil)
    59  		})
    60  	})
    61  
    62  	JustBeforeEach(func() {
    63  		go fakeServer.Serve()
    64  	})
    65  
    66  	AfterEach(func() {
    67  		Expect(fakeServer.Stop()).To(Succeed())
    68  
    69  		Expect(os.RemoveAll(path.Base(unixSockerPath))).To(Succeed())
    70  	})
    71  
    72  	Describe("Create", func() {
    73  		Context("when files are not provided", func() {
    74  			BeforeEach(func() {
    75  				fakeServer.SetConnectionHandler(func(conn net.Conn) {
    76  					conn.Close()
    77  				})
    78  			})
    79  
    80  			It("returns an error", func() {
    81  				_, err := linkpkg.Create(unixSockerPath, stdout, stderr)
    82  				Expect(err).To(HaveOccurred())
    83  			})
    84  		})
    85  
    86  		Context("when files are provided", func() {
    87  			AfterEach(func() {
    88  				stdoutW.Close()
    89  				stderrW.Close()
    90  				statusW.Close()
    91  			})
    92  
    93  			It("succeeds", func() {
    94  				_, err := linkpkg.Create(unixSockerPath, stdout, stderr)
    95  				Expect(err).ToNot(HaveOccurred())
    96  			})
    97  
    98  			It("streams stdout", func() {
    99  				_, err := linkpkg.Create(unixSockerPath, stdout, stderr)
   100  				Expect(err).ToNot(HaveOccurred())
   101  
   102  				stdoutW.Write([]byte("Hello stdout banana"))
   103  				Eventually(stdout).Should(gbytes.Say("Hello stdout banana"))
   104  			})
   105  
   106  			It("streams stderr", func() {
   107  				_, err := linkpkg.Create(unixSockerPath, stdout, stderr)
   108  				Expect(err).ToNot(HaveOccurred())
   109  
   110  				stderrW.Write([]byte("Hello stderr banana"))
   111  				Eventually(stderr).Should(gbytes.Say("Hello stderr banana"))
   112  			})
   113  
   114  			It("should set close on exec for all new file descriptors", func() {
   115  				initialNumFdsWithoutCloseOnExec := numFdsWithoutCloseOnExec()
   116  				_, err := linkpkg.Create(unixSockerPath, stdout, stderr)
   117  				Expect(err).ToNot(HaveOccurred())
   118  
   119  				finalNumFdsWithoutCloseOnExec := numFdsWithoutCloseOnExec()
   120  				Expect(finalNumFdsWithoutCloseOnExec).To(Equal(initialNumFdsWithoutCloseOnExec))
   121  			})
   122  		})
   123  	})
   124  })
   125  
   126  func numFdsWithoutCloseOnExec() int {
   127  	sleepCmd := exec.Command("sleep", "1")
   128  	Expect(sleepCmd.Start()).To(Succeed())
   129  	pid := sleepCmd.Process.Pid
   130  
   131  	out, err := exec.Command("lsof", "-p", strconv.Itoa(pid)).Output()
   132  	Expect(err).ToNot(HaveOccurred())
   133  
   134  	return strings.Count(string(out), "\n")
   135  }