github.com/cloudfoundry-attic/cli-with-i18n@v6.32.1-0.20171002233121-7401370d3b85+incompatible/actor/v3action/logging_test.go (about) 1 package v3action_test 2 3 import ( 4 "errors" 5 "time" 6 7 . "code.cloudfoundry.org/cli/actor/v3action" 8 "code.cloudfoundry.org/cli/actor/v3action/v3actionfakes" 9 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 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 *v3actionfakes.FakeNOAAClient 20 fakeCloudControllerClient *v3actionfakes.FakeCloudControllerClient 21 ) 22 23 BeforeEach(func() { 24 fakeNOAAClient = new(v3actionfakes.FakeNOAAClient) 25 fakeCloudControllerClient = new(v3actionfakes.FakeCloudControllerClient) 26 actor = NewActor(nil, fakeCloudControllerClient, nil) 27 }) 28 29 Describe("LogMessage", func() { 30 Describe("Staging", func() { 31 Context("when the log is a staging log", func() { 32 It("returns true", func() { 33 message := NewLogMessage("", 0, time.Now(), "STG", "") 34 Expect(message.Staging()).To(BeTrue()) 35 }) 36 }) 37 38 Context("when the log is any other kind of log", func() { 39 It("returns true", func() { 40 message := NewLogMessage("", 0, time.Now(), "APP", "") 41 Expect(message.Staging()).To(BeFalse()) 42 }) 43 }) 44 }) 45 }) 46 47 Describe("GetStreamingLogs", func() { 48 var ( 49 expectedAppGUID string 50 51 messages <-chan *LogMessage 52 errs <-chan error 53 eventStream chan *events.LogMessage 54 errStream chan error 55 ) 56 57 BeforeEach(func() { 58 expectedAppGUID = "some-app-guid" 59 60 eventStream = make(chan *events.LogMessage) 61 errStream = make(chan error) 62 }) 63 64 // If tests panic due to this close, it is likely you have a failing 65 // expectation and the channels are being closed because the test has 66 // failed/short circuited and is going through teardown. 67 AfterEach(func() { 68 close(eventStream) 69 close(errStream) 70 71 Eventually(messages).Should(BeClosed()) 72 Eventually(errs).Should(BeClosed()) 73 }) 74 75 JustBeforeEach(func() { 76 messages, errs = actor.GetStreamingLogs(expectedAppGUID, fakeNOAAClient) 77 }) 78 79 Context("when receiving events", func() { 80 BeforeEach(func() { 81 fakeNOAAClient.TailingLogsStub = func(appGUID string, authToken string) (<-chan *events.LogMessage, <-chan error) { 82 Expect(appGUID).To(Equal(expectedAppGUID)) 83 Expect(authToken).To(BeEmpty()) 84 85 go func() { 86 outMessage := events.LogMessage_OUT 87 ts1 := int64(10) 88 sourceType := "some-source-type" 89 sourceInstance := "some-source-instance" 90 91 eventStream <- &events.LogMessage{ 92 Message: []byte("message-1"), 93 MessageType: &outMessage, 94 Timestamp: &ts1, 95 SourceType: &sourceType, 96 SourceInstance: &sourceInstance, 97 } 98 99 errMessage := events.LogMessage_ERR 100 ts2 := int64(20) 101 102 eventStream <- &events.LogMessage{ 103 Message: []byte("message-2"), 104 MessageType: &errMessage, 105 Timestamp: &ts2, 106 SourceType: &sourceType, 107 SourceInstance: &sourceInstance, 108 } 109 }() 110 111 return eventStream, errStream 112 } 113 }) 114 115 It("converts them to log messages and passes them through the messages channel", func() { 116 message := <-messages 117 Expect(message.Message()).To(Equal("message-1")) 118 Expect(message.Type()).To(Equal("OUT")) 119 Expect(message.Timestamp()).To(Equal(time.Unix(0, 10))) 120 Expect(message.SourceType()).To(Equal("some-source-type")) 121 Expect(message.SourceInstance()).To(Equal("some-source-instance")) 122 123 message = <-messages 124 Expect(message.Message()).To(Equal("message-2")) 125 Expect(message.Type()).To(Equal("ERR")) 126 Expect(message.Timestamp()).To(Equal(time.Unix(0, 20))) 127 Expect(message.SourceType()).To(Equal("some-source-type")) 128 Expect(message.SourceInstance()).To(Equal("some-source-instance")) 129 }) 130 }) 131 132 Context("when receiving errors", func() { 133 var ( 134 err1 error 135 err2 error 136 137 waiting chan bool 138 ) 139 140 Describe("nil error", func() { 141 BeforeEach(func() { 142 waiting = make(chan bool) 143 fakeNOAAClient.TailingLogsStub = func(_ string, _ string) (<-chan *events.LogMessage, <-chan error) { 144 go func() { 145 errStream <- nil 146 close(waiting) 147 }() 148 149 return eventStream, errStream 150 } 151 }) 152 153 It("does not pass the nil along", func() { 154 Eventually(waiting).Should(BeClosed()) 155 Consistently(errs).ShouldNot(Receive()) 156 }) 157 }) 158 159 Describe("unexpected error", func() { 160 BeforeEach(func() { 161 err1 = errors.New("ZOMG") 162 err2 = errors.New("Fiddlesticks") 163 164 fakeNOAAClient.TailingLogsStub = func(_ string, _ string) (<-chan *events.LogMessage, <-chan error) { 165 go func() { 166 errStream <- err1 167 errStream <- err2 168 }() 169 170 return eventStream, errStream 171 } 172 }) 173 174 It("passes them through the errors channel", func() { 175 Eventually(errs).Should(Receive(Equal(err1))) 176 Eventually(errs).Should(Receive(Equal(err2))) 177 }) 178 }) 179 180 Describe("NOAA's RetryError", func() { 181 Context("when NOAA is able to recover", func() { 182 BeforeEach(func() { 183 fakeNOAAClient.TailingLogsStub = func(_ string, _ string) (<-chan *events.LogMessage, <-chan error) { 184 go func() { 185 errStream <- noaaErrors.NewRetryError(errors.New("error 1")) 186 187 outMessage := events.LogMessage_OUT 188 ts1 := int64(10) 189 sourceType := "some-source-type" 190 sourceInstance := "some-source-instance" 191 192 eventStream <- &events.LogMessage{ 193 Message: []byte("message-1"), 194 MessageType: &outMessage, 195 Timestamp: &ts1, 196 SourceType: &sourceType, 197 SourceInstance: &sourceInstance, 198 } 199 }() 200 201 return eventStream, errStream 202 } 203 }) 204 205 It("continues without issue", func() { 206 Eventually(messages).Should(Receive()) 207 Consistently(errs).ShouldNot(Receive()) 208 }) 209 }) 210 }) 211 }) 212 }) 213 214 Describe("GetStreamingLogsForApplicationByNameAndSpace", func() { 215 Context("when the application can be found", func() { 216 var ( 217 expectedAppGUID string 218 219 eventStream chan *events.LogMessage 220 errStream chan error 221 222 messages <-chan *LogMessage 223 logErrs <-chan error 224 ) 225 226 // If tests panic due to this close, it is likely you have a failing 227 // expectation and the channels are being closed because the test has 228 // failed/short circuited and is going through teardown. 229 AfterEach(func() { 230 close(eventStream) 231 close(errStream) 232 233 Eventually(messages).Should(BeClosed()) 234 Eventually(logErrs).Should(BeClosed()) 235 }) 236 237 BeforeEach(func() { 238 expectedAppGUID = "some-app-guid" 239 240 eventStream = make(chan *events.LogMessage) 241 errStream = make(chan error) 242 fakeCloudControllerClient.GetApplicationsReturns( 243 []ccv3.Application{ 244 { 245 Name: "some-app", 246 GUID: expectedAppGUID, 247 }, 248 }, 249 ccv3.Warnings{"some-app-warnings"}, 250 nil, 251 ) 252 253 fakeNOAAClient.TailingLogsStub = func(appGUID string, authToken string) (<-chan *events.LogMessage, <-chan error) { 254 Expect(appGUID).To(Equal(expectedAppGUID)) 255 Expect(authToken).To(BeEmpty()) 256 257 go func() { 258 outMessage := events.LogMessage_OUT 259 ts1 := int64(10) 260 sourceType := "some-source-type" 261 sourceInstance := "some-source-instance" 262 263 eventStream <- &events.LogMessage{ 264 Message: []byte("message-1"), 265 MessageType: &outMessage, 266 Timestamp: &ts1, 267 SourceType: &sourceType, 268 SourceInstance: &sourceInstance, 269 } 270 271 errMessage := events.LogMessage_ERR 272 ts2 := int64(20) 273 274 eventStream <- &events.LogMessage{ 275 Message: []byte("message-2"), 276 MessageType: &errMessage, 277 Timestamp: &ts2, 278 SourceType: &sourceType, 279 SourceInstance: &sourceInstance, 280 } 281 }() 282 283 return eventStream, errStream 284 } 285 }) 286 287 It("converts them to log messages and passes them through the messages channel", func() { 288 var err error 289 var warnings Warnings 290 messages, logErrs, warnings, err = actor.GetStreamingLogsForApplicationByNameAndSpace("some-app", "some-space-guid", fakeNOAAClient) 291 292 Expect(err).ToNot(HaveOccurred()) 293 Expect(warnings).To(ConsistOf("some-app-warnings")) 294 295 message := <-messages 296 Expect(message.Message()).To(Equal("message-1")) 297 Expect(message.Type()).To(Equal("OUT")) 298 Expect(message.Timestamp()).To(Equal(time.Unix(0, 10))) 299 Expect(message.SourceType()).To(Equal("some-source-type")) 300 Expect(message.SourceInstance()).To(Equal("some-source-instance")) 301 302 message = <-messages 303 Expect(message.Message()).To(Equal("message-2")) 304 Expect(message.Type()).To(Equal("ERR")) 305 Expect(message.Timestamp()).To(Equal(time.Unix(0, 20))) 306 Expect(message.SourceType()).To(Equal("some-source-type")) 307 Expect(message.SourceInstance()).To(Equal("some-source-instance")) 308 }) 309 }) 310 311 Context("when finding the application errors", func() { 312 var expectedErr error 313 314 BeforeEach(func() { 315 expectedErr = errors.New("ZOMG") 316 fakeCloudControllerClient.GetApplicationsReturns( 317 nil, 318 ccv3.Warnings{"some-app-warnings"}, 319 expectedErr, 320 ) 321 }) 322 323 It("returns error and warnings", func() { 324 _, _, warnings, err := actor.GetStreamingLogsForApplicationByNameAndSpace("some-app", "some-space-guid", fakeNOAAClient) 325 Expect(err).To(MatchError(expectedErr)) 326 Expect(warnings).To(ConsistOf("some-app-warnings")) 327 328 Expect(fakeNOAAClient.TailingLogsCallCount()).To(Equal(0)) 329 }) 330 }) 331 }) 332 })