github.com/cloudfoundry-attic/cli-with-i18n@v6.32.1-0.20171002233121-7401370d3b85+incompatible/actor/v2action/logging_test.go (about) 1 package v2action_test 2 3 import ( 4 "errors" 5 "time" 6 7 . "code.cloudfoundry.org/cli/actor/v2action" 8 "code.cloudfoundry.org/cli/actor/v2action/v2actionfakes" 9 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv2" 10 noaaErrors "github.com/cloudfoundry/noaa/errors" 11 "github.com/cloudfoundry/sonde-go/events" 12 . "github.com/onsi/ginkgo" 13 . "github.com/onsi/gomega" 14 ) 15 16 var _ = Describe("Logging Actions", func() { 17 var ( 18 actor *Actor 19 fakeNOAAClient *v2actionfakes.FakeNOAAClient 20 fakeConfig *v2actionfakes.FakeConfig 21 fakeCloudControllerClient *v2actionfakes.FakeCloudControllerClient 22 ) 23 24 BeforeEach(func() { 25 fakeNOAAClient = new(v2actionfakes.FakeNOAAClient) 26 fakeConfig = new(v2actionfakes.FakeConfig) 27 fakeCloudControllerClient = new(v2actionfakes.FakeCloudControllerClient) 28 actor = NewActor(fakeCloudControllerClient, nil, nil) 29 }) 30 31 Describe("LogMessage", func() { 32 Describe("Staging", func() { 33 Context("when the log is a staging log", func() { 34 It("returns true", func() { 35 message := NewLogMessage("", 0, time.Now(), "STG", "") 36 Expect(message.Staging()).To(BeTrue()) 37 }) 38 }) 39 40 Context("when the log is any other kind of log", func() { 41 It("returns true", func() { 42 message := NewLogMessage("", 0, time.Now(), "APP", "") 43 Expect(message.Staging()).To(BeFalse()) 44 }) 45 }) 46 }) 47 }) 48 49 Describe("GetStreamingLogs", func() { 50 var ( 51 expectedAppGUID string 52 53 messages <-chan *LogMessage 54 errs <-chan error 55 eventStream chan *events.LogMessage 56 errStream chan error 57 ) 58 59 BeforeEach(func() { 60 expectedAppGUID = "some-app-guid" 61 62 eventStream = make(chan *events.LogMessage) 63 errStream = make(chan error) 64 }) 65 66 // If tests panic due to this close, it is likely you have a failing 67 // expectation and the channels are being closed because the test has 68 // failed/short circuited and is going through teardown. 69 AfterEach(func() { 70 close(eventStream) 71 close(errStream) 72 73 Eventually(messages).Should(BeClosed()) 74 Eventually(errs).Should(BeClosed()) 75 }) 76 77 JustBeforeEach(func() { 78 messages, errs = actor.GetStreamingLogs(expectedAppGUID, fakeNOAAClient, fakeConfig) 79 }) 80 81 Context("when receiving events", func() { 82 BeforeEach(func() { 83 fakeNOAAClient.TailingLogsStub = func(appGUID string, authToken string) (<-chan *events.LogMessage, <-chan error) { 84 Expect(appGUID).To(Equal(expectedAppGUID)) 85 Expect(authToken).To(BeEmpty()) 86 87 go func() { 88 outMessage := events.LogMessage_OUT 89 ts1 := int64(10) 90 sourceType := "some-source-type" 91 sourceInstance := "some-source-instance" 92 93 eventStream <- &events.LogMessage{ 94 Message: []byte("message-1"), 95 MessageType: &outMessage, 96 Timestamp: &ts1, 97 SourceType: &sourceType, 98 SourceInstance: &sourceInstance, 99 } 100 101 errMessage := events.LogMessage_ERR 102 ts2 := int64(20) 103 104 eventStream <- &events.LogMessage{ 105 Message: []byte("message-2"), 106 MessageType: &errMessage, 107 Timestamp: &ts2, 108 SourceType: &sourceType, 109 SourceInstance: &sourceInstance, 110 } 111 }() 112 113 return eventStream, errStream 114 } 115 }) 116 117 It("converts them to log messages and passes them through the messages channel", func() { 118 message := <-messages 119 Expect(message.Message()).To(Equal("message-1")) 120 Expect(message.Type()).To(Equal("OUT")) 121 Expect(message.Timestamp()).To(Equal(time.Unix(0, 10))) 122 Expect(message.SourceType()).To(Equal("some-source-type")) 123 Expect(message.SourceInstance()).To(Equal("some-source-instance")) 124 125 message = <-messages 126 Expect(message.Message()).To(Equal("message-2")) 127 Expect(message.Type()).To(Equal("ERR")) 128 Expect(message.Timestamp()).To(Equal(time.Unix(0, 20))) 129 Expect(message.SourceType()).To(Equal("some-source-type")) 130 Expect(message.SourceInstance()).To(Equal("some-source-instance")) 131 }) 132 }) 133 134 Context("when receiving errors", func() { 135 var ( 136 err1 error 137 err2 error 138 139 waiting chan bool 140 ) 141 142 Describe("nil error", func() { 143 BeforeEach(func() { 144 waiting = make(chan bool) 145 fakeNOAAClient.TailingLogsStub = func(_ string, _ string) (<-chan *events.LogMessage, <-chan error) { 146 go func() { 147 errStream <- nil 148 close(waiting) 149 }() 150 151 return eventStream, errStream 152 } 153 }) 154 155 It("does not pass the nil along", func() { 156 Eventually(waiting).Should(BeClosed()) 157 Consistently(errs).ShouldNot(Receive()) 158 }) 159 }) 160 161 Describe("unexpected error", func() { 162 BeforeEach(func() { 163 err1 = errors.New("ZOMG") 164 err2 = errors.New("Fiddlesticks") 165 166 fakeNOAAClient.TailingLogsStub = func(_ string, _ string) (<-chan *events.LogMessage, <-chan error) { 167 go func() { 168 errStream <- err1 169 errStream <- err2 170 }() 171 172 return eventStream, errStream 173 } 174 }) 175 176 It("passes them through the errors channel", func() { 177 Eventually(errs).Should(Receive(Equal(err1))) 178 Eventually(errs).Should(Receive(Equal(err2))) 179 }) 180 }) 181 182 Describe("NOAA's RetryError", func() { 183 Context("when NOAA is able to recover", func() { 184 BeforeEach(func() { 185 fakeNOAAClient.TailingLogsStub = func(_ string, _ string) (<-chan *events.LogMessage, <-chan error) { 186 go func() { 187 errStream <- noaaErrors.NewRetryError(errors.New("error 1")) 188 189 outMessage := events.LogMessage_OUT 190 ts1 := int64(10) 191 sourceType := "some-source-type" 192 sourceInstance := "some-source-instance" 193 194 eventStream <- &events.LogMessage{ 195 Message: []byte("message-1"), 196 MessageType: &outMessage, 197 Timestamp: &ts1, 198 SourceType: &sourceType, 199 SourceInstance: &sourceInstance, 200 } 201 }() 202 203 return eventStream, errStream 204 } 205 }) 206 207 It("continues without issue", func() { 208 Eventually(messages).Should(Receive()) 209 Consistently(errs).ShouldNot(Receive()) 210 }) 211 }) 212 }) 213 }) 214 }) 215 216 Describe("GetRecentLogsForApplicationByNameAndSpace", func() { 217 Context("when the application can be found", func() { 218 BeforeEach(func() { 219 fakeCloudControllerClient.GetApplicationsReturns( 220 []ccv2.Application{ 221 { 222 Name: "some-app", 223 GUID: "some-app-guid", 224 }, 225 }, 226 ccv2.Warnings{"some-app-warnings"}, 227 nil, 228 ) 229 }) 230 231 Context("when NOAA returns logs", func() { 232 BeforeEach(func() { 233 outMessage := events.LogMessage_OUT 234 ts1 := int64(10) 235 ts2 := int64(20) 236 sourceType := "some-source-type" 237 sourceInstance := "some-source-instance" 238 239 var messages []*events.LogMessage 240 messages = append(messages, &events.LogMessage{ 241 Message: []byte("message-2"), 242 MessageType: &outMessage, 243 Timestamp: &ts2, 244 SourceType: &sourceType, 245 SourceInstance: &sourceInstance, 246 }) 247 messages = append(messages, &events.LogMessage{ 248 Message: []byte("message-1"), 249 MessageType: &outMessage, 250 Timestamp: &ts1, 251 SourceType: &sourceType, 252 SourceInstance: &sourceInstance, 253 }) 254 255 fakeNOAAClient.RecentLogsReturns(messages, nil) 256 }) 257 258 It("returns all the recent logs and warnings", func() { 259 messages, warnings, err := actor.GetRecentLogsForApplicationByNameAndSpace("some-app", "some-space-guid", fakeNOAAClient, fakeConfig) 260 Expect(err).ToNot(HaveOccurred()) 261 Expect(warnings).To(ConsistOf("some-app-warnings")) 262 Expect(messages[0].Message()).To(Equal("message-1")) 263 Expect(messages[0].Type()).To(Equal("OUT")) 264 Expect(messages[0].Timestamp()).To(Equal(time.Unix(0, 10))) 265 Expect(messages[0].SourceType()).To(Equal("some-source-type")) 266 Expect(messages[0].SourceInstance()).To(Equal("some-source-instance")) 267 268 Expect(messages[1].Message()).To(Equal("message-2")) 269 Expect(messages[1].Type()).To(Equal("OUT")) 270 Expect(messages[1].Timestamp()).To(Equal(time.Unix(0, 20))) 271 Expect(messages[1].SourceType()).To(Equal("some-source-type")) 272 Expect(messages[1].SourceInstance()).To(Equal("some-source-instance")) 273 }) 274 }) 275 276 Context("when NOAA errors", func() { 277 var expectedErr error 278 279 BeforeEach(func() { 280 expectedErr = errors.New("ZOMG") 281 fakeNOAAClient.RecentLogsReturns(nil, expectedErr) 282 }) 283 284 It("returns error and warnings", func() { 285 _, warnings, err := actor.GetRecentLogsForApplicationByNameAndSpace("some-app", "some-space-guid", fakeNOAAClient, fakeConfig) 286 Expect(err).To(MatchError(expectedErr)) 287 Expect(warnings).To(ConsistOf("some-app-warnings")) 288 }) 289 }) 290 }) 291 292 Context("when finding the application errors", func() { 293 var expectedErr error 294 295 BeforeEach(func() { 296 expectedErr = errors.New("ZOMG") 297 fakeCloudControllerClient.GetApplicationsReturns( 298 nil, 299 ccv2.Warnings{"some-app-warnings"}, 300 expectedErr, 301 ) 302 }) 303 304 It("returns error and warnings", func() { 305 _, warnings, err := actor.GetRecentLogsForApplicationByNameAndSpace("some-app", "some-space-guid", fakeNOAAClient, fakeConfig) 306 Expect(err).To(MatchError(expectedErr)) 307 Expect(warnings).To(ConsistOf("some-app-warnings")) 308 309 Expect(fakeNOAAClient.RecentLogsCallCount()).To(Equal(0)) 310 }) 311 }) 312 }) 313 314 Describe("GetStreamingLogsForApplicationByNameAndSpace", func() { 315 Context("when the application can be found", func() { 316 var ( 317 expectedAppGUID string 318 319 eventStream chan *events.LogMessage 320 errStream chan error 321 322 messages <-chan *LogMessage 323 logErrs <-chan error 324 ) 325 326 // If tests panic due to this close, it is likely you have a failing 327 // expectation and the channels are being closed because the test has 328 // failed/short circuited and is going through teardown. 329 AfterEach(func() { 330 close(eventStream) 331 close(errStream) 332 333 Eventually(messages).Should(BeClosed()) 334 Eventually(logErrs).Should(BeClosed()) 335 }) 336 337 BeforeEach(func() { 338 expectedAppGUID = "some-app-guid" 339 340 eventStream = make(chan *events.LogMessage) 341 errStream = make(chan error) 342 fakeCloudControllerClient.GetApplicationsReturns( 343 []ccv2.Application{ 344 { 345 Name: "some-app", 346 GUID: expectedAppGUID, 347 }, 348 }, 349 ccv2.Warnings{"some-app-warnings"}, 350 nil, 351 ) 352 353 fakeNOAAClient.TailingLogsStub = func(appGUID string, authToken string) (<-chan *events.LogMessage, <-chan error) { 354 Expect(appGUID).To(Equal(expectedAppGUID)) 355 Expect(authToken).To(BeEmpty()) 356 357 go func() { 358 outMessage := events.LogMessage_OUT 359 ts1 := int64(10) 360 sourceType := "some-source-type" 361 sourceInstance := "some-source-instance" 362 363 eventStream <- &events.LogMessage{ 364 Message: []byte("message-1"), 365 MessageType: &outMessage, 366 Timestamp: &ts1, 367 SourceType: &sourceType, 368 SourceInstance: &sourceInstance, 369 } 370 371 errMessage := events.LogMessage_ERR 372 ts2 := int64(20) 373 374 eventStream <- &events.LogMessage{ 375 Message: []byte("message-2"), 376 MessageType: &errMessage, 377 Timestamp: &ts2, 378 SourceType: &sourceType, 379 SourceInstance: &sourceInstance, 380 } 381 }() 382 383 return eventStream, errStream 384 } 385 }) 386 387 It("converts them to log messages and passes them through the messages channel", func() { 388 var err error 389 var warnings Warnings 390 messages, logErrs, warnings, err = actor.GetStreamingLogsForApplicationByNameAndSpace("some-app", "some-space-guid", fakeNOAAClient, fakeConfig) 391 392 Expect(err).ToNot(HaveOccurred()) 393 Expect(warnings).To(ConsistOf("some-app-warnings")) 394 395 message := <-messages 396 Expect(message.Message()).To(Equal("message-1")) 397 Expect(message.Type()).To(Equal("OUT")) 398 Expect(message.Timestamp()).To(Equal(time.Unix(0, 10))) 399 Expect(message.SourceType()).To(Equal("some-source-type")) 400 Expect(message.SourceInstance()).To(Equal("some-source-instance")) 401 402 message = <-messages 403 Expect(message.Message()).To(Equal("message-2")) 404 Expect(message.Type()).To(Equal("ERR")) 405 Expect(message.Timestamp()).To(Equal(time.Unix(0, 20))) 406 Expect(message.SourceType()).To(Equal("some-source-type")) 407 Expect(message.SourceInstance()).To(Equal("some-source-instance")) 408 }) 409 }) 410 411 Context("when finding the application errors", func() { 412 var expectedErr error 413 414 BeforeEach(func() { 415 expectedErr = errors.New("ZOMG") 416 fakeCloudControllerClient.GetApplicationsReturns( 417 nil, 418 ccv2.Warnings{"some-app-warnings"}, 419 expectedErr, 420 ) 421 }) 422 423 It("returns error and warnings", func() { 424 _, _, warnings, err := actor.GetStreamingLogsForApplicationByNameAndSpace("some-app", "some-space-guid", fakeNOAAClient, fakeConfig) 425 Expect(err).To(MatchError(expectedErr)) 426 Expect(warnings).To(ConsistOf("some-app-warnings")) 427 428 Expect(fakeNOAAClient.TailingLogsCallCount()).To(Equal(0)) 429 }) 430 }) 431 }) 432 })