github.com/cloudfoundry-attic/garden-linux@v0.333.2-candidate/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/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  })