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