github.com/schwarzm/garden-linux@v0.0.0-20150507151835-33bca2147c47/old/logging/logging_test.go (about) 1 package logging_test 2 3 import ( 4 "bytes" 5 "os/exec" 6 "time" 7 8 . "github.com/cloudfoundry-incubator/garden-linux/old/logging" 9 "github.com/cloudfoundry/gunk/command_runner" 10 "github.com/cloudfoundry/gunk/command_runner/fake_command_runner" 11 . "github.com/cloudfoundry/gunk/command_runner/fake_command_runner/matchers" 12 "github.com/cloudfoundry/gunk/command_runner/linux_command_runner" 13 "github.com/pivotal-golang/lager" 14 "github.com/pivotal-golang/lager/lagertest" 15 16 . "github.com/onsi/ginkgo" 17 . "github.com/onsi/gomega" 18 ) 19 20 var _ = Describe("Logging", func() { 21 var innerRunner command_runner.CommandRunner 22 var logger *lagertest.TestLogger 23 24 var runner *Runner 25 26 BeforeEach(func() { 27 innerRunner = linux_command_runner.New() 28 logger = lagertest.NewTestLogger("test") 29 }) 30 31 JustBeforeEach(func() { 32 runner = &Runner{ 33 CommandRunner: innerRunner, 34 Logger: logger, 35 } 36 }) 37 38 It("logs the duration it took to run the command", func() { 39 err := runner.Run(exec.Command("sleep", "1")) 40 Expect(err).ToNot(HaveOccurred()) 41 42 Expect(logger.TestSink.Logs()).To(HaveLen(2)) 43 44 log := logger.TestSink.Logs()[1] 45 46 took := log.Data["took"].(string) 47 Expect(took).ToNot(BeEmpty()) 48 49 duration, err := time.ParseDuration(took) 50 Expect(err).ToNot(HaveOccurred()) 51 Expect(duration).To(BeNumerically(">=", 1*time.Second)) 52 }) 53 54 It("logs the command's argv", func() { 55 err := runner.Run(exec.Command("bash", "-c", "echo sup")) 56 Expect(err).ToNot(HaveOccurred()) 57 58 Expect(logger.TestSink.Logs()).To(HaveLen(2)) 59 60 log := logger.TestSink.Logs()[0] 61 Expect(log.LogLevel).To(Equal(lager.DEBUG)) 62 Expect(log.Message).To(Equal("test.command.starting")) 63 Expect(log.Data["argv"]).To(Equal([]interface{}{"bash", "-c", "echo sup"})) 64 65 log = logger.TestSink.Logs()[1] 66 Expect(log.LogLevel).To(Equal(lager.DEBUG)) 67 Expect(log.Message).To(Equal("test.command.succeeded")) 68 Expect(log.Data["argv"]).To(Equal([]interface{}{"bash", "-c", "echo sup"})) 69 }) 70 71 Describe("running a command that exits normally", func() { 72 It("logs its exit status with 'debug' level", func() { 73 err := runner.Run(exec.Command("true")) 74 Expect(err).ToNot(HaveOccurred()) 75 76 Expect(logger.TestSink.Logs()).To(HaveLen(2)) 77 78 log := logger.TestSink.Logs()[1] 79 Expect(log.LogLevel).To(Equal(lager.DEBUG)) 80 Expect(log.Message).To(Equal("test.command.succeeded")) 81 Expect(log.Data["exit-status"]).To(Equal(float64(0))) // JSOOOOOOOOOOOOOOOOOOON 82 }) 83 84 Context("when the command has output to stdout/stderr", func() { 85 It("does not log stdout/stderr", func() { 86 err := runner.Run(exec.Command("sh", "-c", "echo hi out; echo hi err >&2")) 87 Expect(err).ToNot(HaveOccurred()) 88 89 Expect(logger.TestSink.Logs()).To(HaveLen(2)) 90 91 log := logger.TestSink.Logs()[1] 92 Expect(log.LogLevel).To(Equal(lager.DEBUG)) 93 Expect(log.Message).To(Equal("test.command.succeeded")) 94 Expect(log.Data).ToNot(HaveKey("stdout")) 95 Expect(log.Data).ToNot(HaveKey("stderr")) 96 }) 97 }) 98 }) 99 100 Describe("delegation", func() { 101 var fakeRunner *fake_command_runner.FakeCommandRunner 102 103 BeforeEach(func() { 104 fakeRunner = fake_command_runner.New() 105 innerRunner = fakeRunner 106 }) 107 108 It("runs using the provided runner", func() { 109 err := runner.Run(exec.Command("morgan-freeman")) 110 Expect(err).ToNot(HaveOccurred()) 111 112 Expect(fakeRunner).To(HaveExecutedSerially(fake_command_runner.CommandSpec{ 113 Path: "morgan-freeman", 114 })) 115 }) 116 }) 117 118 Describe("running a bogus command", func() { 119 It("logs the error", func() { 120 err := runner.Run(exec.Command("morgan-freeman")) 121 Expect(err).To(HaveOccurred()) 122 123 Expect(logger.TestSink.Logs()).To(HaveLen(2)) 124 125 log := logger.TestSink.Logs()[1] 126 Expect(log.LogLevel).To(Equal(lager.ERROR)) 127 Expect(log.Message).To(Equal("test.command.failed")) 128 Expect(log.Data["error"]).ToNot(BeEmpty()) 129 Expect(log.Data).ToNot(HaveKey("exit-status")) 130 }) 131 }) 132 133 Describe("running a command that exits nonzero", func() { 134 It("logs its status with 'error' level", func() { 135 err := runner.Run(exec.Command("false")) 136 Expect(err).To(HaveOccurred()) 137 138 Expect(logger.TestSink.Logs()).To(HaveLen(2)) 139 140 log := logger.TestSink.Logs()[1] 141 Expect(log.LogLevel).To(Equal(lager.ERROR)) 142 Expect(log.Message).To(Equal("test.command.failed")) 143 Expect(log.Data["error"]).To(Equal("exit status 1")) 144 Expect(log.Data["exit-status"]).To(Equal(float64(1))) // JSOOOOOOOOOOOOOOOOOOON 145 }) 146 147 Context("when the command has output to stdout/stderr", func() { 148 It("reports the stdout/stderr in the log data", func() { 149 err := runner.Run(exec.Command("sh", "-c", "echo hi out; echo hi err >&2; exit 1")) 150 Expect(err).To(HaveOccurred()) 151 152 Expect(logger.TestSink.Logs()).To(HaveLen(2)) 153 154 log := logger.TestSink.Logs()[1] 155 Expect(log.LogLevel).To(Equal(lager.ERROR)) 156 Expect(log.Message).To(Equal("test.command.failed")) 157 Expect(log.Data["stdout"]).To(Equal("hi out\n")) 158 Expect(log.Data["stderr"]).To(Equal("hi err\n")) 159 }) 160 161 Context("and it is being collected by the caller", func() { 162 It("multiplexes to the caller and the logs", func() { 163 stdout := new(bytes.Buffer) 164 stderr := new(bytes.Buffer) 165 166 cmd := exec.Command("sh", "-c", "echo hi out; echo hi err >&2; exit 1") 167 cmd.Stdout = stdout 168 cmd.Stderr = stderr 169 170 err := runner.Run(cmd) 171 Expect(err).To(HaveOccurred()) 172 173 Expect(logger.TestSink.Logs()).To(HaveLen(2)) 174 175 log := logger.TestSink.Logs()[1] 176 Expect(log.LogLevel).To(Equal(lager.ERROR)) 177 Expect(log.Message).To(Equal("test.command.failed")) 178 Expect(log.Data["stdout"]).To(Equal("hi out\n")) 179 Expect(log.Data["stderr"]).To(Equal("hi err\n")) 180 181 Expect(stdout.String()).To(Equal("hi out\n")) 182 Expect(stderr.String()).To(Equal("hi err\n")) 183 }) 184 }) 185 }) 186 }) 187 })