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 }