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 }