github.com/asifdxtreme/cli@v6.1.3-0.20150123051144-9ead8700b4ae+incompatible/cf/commands/application/logs_test.go (about)

     1  package application_test
     2  
     3  import (
     4  	"time"
     5  
     6  	"code.google.com/p/gogoprotobuf/proto"
     7  	testapi "github.com/cloudfoundry/cli/cf/api/fakes"
     8  	"github.com/cloudfoundry/cli/cf/errors"
     9  	"github.com/cloudfoundry/cli/cf/models"
    10  	"github.com/cloudfoundry/cli/cf/terminal"
    11  	testcmd "github.com/cloudfoundry/cli/testhelpers/commands"
    12  	testconfig "github.com/cloudfoundry/cli/testhelpers/configuration"
    13  	testlogs "github.com/cloudfoundry/cli/testhelpers/logs"
    14  	testreq "github.com/cloudfoundry/cli/testhelpers/requirements"
    15  	testterm "github.com/cloudfoundry/cli/testhelpers/terminal"
    16  	"github.com/cloudfoundry/loggregatorlib/logmessage"
    17  
    18  	. "github.com/cloudfoundry/cli/cf/commands/application"
    19  	"github.com/cloudfoundry/cli/cf/configuration/core_config"
    20  	. "github.com/cloudfoundry/cli/testhelpers/matchers"
    21  	. "github.com/onsi/ginkgo"
    22  	. "github.com/onsi/gomega"
    23  )
    24  
    25  var _ = Describe("logs command", func() {
    26  	var (
    27  		ui                  *testterm.FakeUI
    28  		logsRepo            *testapi.FakeLogsRepository
    29  		requirementsFactory *testreq.FakeReqFactory
    30  		configRepo          core_config.ReadWriter
    31  	)
    32  
    33  	BeforeEach(func() {
    34  		ui = &testterm.FakeUI{}
    35  		configRepo = testconfig.NewRepositoryWithDefaults()
    36  		logsRepo = &testapi.FakeLogsRepository{}
    37  		requirementsFactory = &testreq.FakeReqFactory{}
    38  	})
    39  
    40  	runCommand := func(args ...string) bool {
    41  		return testcmd.RunCommand(NewLogs(ui, configRepo, logsRepo), args, requirementsFactory)
    42  	}
    43  
    44  	Describe("requirements", func() {
    45  		It("fails with usage when called without one argument", func() {
    46  			requirementsFactory.LoginSuccess = true
    47  
    48  			runCommand()
    49  			Expect(ui.FailedWithUsage).To(BeTrue())
    50  		})
    51  
    52  		It("fails requirements when not logged in", func() {
    53  			Expect(runCommand("my-app")).To(BeFalse())
    54  		})
    55  	})
    56  
    57  	Context("when logged in", func() {
    58  		var (
    59  			app models.Application
    60  		)
    61  
    62  		BeforeEach(func() {
    63  			requirementsFactory.LoginSuccess = true
    64  
    65  			app = models.Application{}
    66  			app.Name = "my-app"
    67  			app.Guid = "my-app-guid"
    68  
    69  			currentTime := time.Now()
    70  			recentLogs := []*logmessage.LogMessage{
    71  				testlogs.NewLogMessage("Log Line 1", app.Guid, "DEA", currentTime),
    72  				testlogs.NewLogMessage("Log Line 2", app.Guid, "DEA", currentTime),
    73  			}
    74  
    75  			appLogs := []*logmessage.LogMessage{
    76  				testlogs.NewLogMessage("Log Line 1", app.Guid, "DEA", time.Now()),
    77  			}
    78  
    79  			requirementsFactory.Application = app
    80  			logsRepo.RecentLogsForReturns(recentLogs, nil)
    81  
    82  			logsRepo.TailLogsForStub = func(appGuid string, onConnect func(), onMessage func(*logmessage.LogMessage)) error {
    83  				onConnect()
    84  				for _, log := range appLogs {
    85  					onMessage(log)
    86  				}
    87  				return nil
    88  			}
    89  		})
    90  
    91  		It("shows the recent logs when the --recent flag is provided", func() {
    92  			runCommand("--recent", "my-app")
    93  
    94  			Expect(requirementsFactory.ApplicationName).To(Equal("my-app"))
    95  			Expect(app.Guid).To(Equal(logsRepo.RecentLogsForArgsForCall(0)))
    96  			Expect(ui.Outputs).To(ContainSubstrings(
    97  				[]string{"Connected, dumping recent logs for app", "my-app", "my-org", "my-space", "my-user"},
    98  				[]string{"Log Line 1"},
    99  				[]string{"Log Line 2"},
   100  			))
   101  		})
   102  
   103  		Context("when the log messages contain format string identifiers", func() {
   104  			BeforeEach(func() {
   105  				logsRepo.RecentLogsForReturns([]*logmessage.LogMessage{
   106  					testlogs.NewLogMessage("hello%2Bworld%v", app.Guid, "DEA", time.Now()),
   107  				}, nil)
   108  			})
   109  
   110  			It("does not treat them as format strings", func() {
   111  				runCommand("--recent", "my-app")
   112  				Expect(ui.Outputs).To(ContainSubstrings([]string{"hello%2Bworld%v"}))
   113  			})
   114  		})
   115  
   116  		It("tails the app's logs when no flags are given", func() {
   117  			runCommand("my-app")
   118  
   119  			Expect(requirementsFactory.ApplicationName).To(Equal("my-app"))
   120  			appGuid, _, _ := logsRepo.TailLogsForArgsForCall(0)
   121  			Expect(app.Guid).To(Equal(appGuid))
   122  			Expect(ui.Outputs).To(ContainSubstrings(
   123  				[]string{"Connected, tailing logs for app", "my-app", "my-org", "my-space", "my-user"},
   124  				[]string{"Log Line 1"},
   125  			))
   126  		})
   127  
   128  		Context("when the loggregator server has an invalid cert", func() {
   129  			Context("when the skip-ssl-validation flag is not set", func() {
   130  				It("fails and informs the user about the skip-ssl-validation flag", func() {
   131  					logsRepo.TailLogsForReturns(errors.NewInvalidSSLCert("https://example.com", "it don't work good"))
   132  					runCommand("my-app")
   133  
   134  					Expect(ui.Outputs).To(ContainSubstrings(
   135  						[]string{"Received invalid SSL certificate", "https://example.com"},
   136  						[]string{"TIP"},
   137  					))
   138  				})
   139  
   140  				It("informs the user of the error when they include the --recent flag", func() {
   141  					logsRepo.RecentLogsForReturns(nil, errors.NewInvalidSSLCert("https://example.com", "how does SSL work???"))
   142  					runCommand("--recent", "my-app")
   143  
   144  					Expect(ui.Outputs).To(ContainSubstrings(
   145  						[]string{"Received invalid SSL certificate", "https://example.com"},
   146  						[]string{"TIP"},
   147  					))
   148  				})
   149  			})
   150  		})
   151  
   152  		Context("when the loggregator server has a valid cert", func() {
   153  			It("tails logs", func() {
   154  				runCommand("my-app")
   155  				Expect(ui.Outputs).To(ContainSubstrings(
   156  					[]string{"Connected, tailing logs for app", "my-org", "my-space", "my-user"},
   157  				))
   158  			})
   159  		})
   160  
   161  		Describe("Helpers", func() {
   162  			date := time.Date(2014, 4, 4, 11, 39, 20, 5, time.UTC)
   163  
   164  			createMessage := func(sourceId string, sourceName string, msgType logmessage.LogMessage_MessageType, date time.Time) *logmessage.LogMessage {
   165  				timestamp := date.UnixNano()
   166  				return &logmessage.LogMessage{
   167  					Message:     []byte("Hello World!\n\r\n\r"),
   168  					AppId:       proto.String("my-app-guid"),
   169  					MessageType: &msgType,
   170  					SourceId:    &sourceId,
   171  					Timestamp:   &timestamp,
   172  					SourceName:  &sourceName,
   173  				}
   174  			}
   175  
   176  			Context("when the message comes", func() {
   177  				It("include the instance index", func() {
   178  					msg := createMessage("4", "DEA", logmessage.LogMessage_OUT, date)
   179  					Expect(terminal.Decolorize(LogMessageOutput(msg, time.UTC))).To(Equal("2014-04-04T11:39:20.00+0000 [DEA/4]      OUT Hello World!"))
   180  				})
   181  
   182  				It("doesn't include the instance index if sourceID is empty", func() {
   183  					msg := createMessage("", "DEA", logmessage.LogMessage_OUT, date)
   184  					Expect(terminal.Decolorize(LogMessageOutput(msg, time.UTC))).To(Equal("2014-04-04T11:39:20.00+0000 [DEA]        OUT Hello World!"))
   185  				})
   186  			})
   187  
   188  			Context("when the message was written to stderr", func() {
   189  				It("shows the log type as 'ERR'", func() {
   190  					msg := createMessage("4", "STG", logmessage.LogMessage_ERR, date)
   191  					Expect(terminal.Decolorize(LogMessageOutput(msg, time.UTC))).To(Equal("2014-04-04T11:39:20.00+0000 [STG/4]      ERR Hello World!"))
   192  				})
   193  			})
   194  
   195  			It("formats the time in the given time zone", func() {
   196  				msg := createMessage("4", "RTR", logmessage.LogMessage_ERR, date)
   197  				Expect(terminal.Decolorize(LogMessageOutput(msg, time.FixedZone("the-zone", 3*60*60)))).To(Equal("2014-04-04T14:39:20.00+0300 [RTR/4]      ERR Hello World!"))
   198  			})
   199  		})
   200  	})
   201  })