github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/actor/loggingaction/log_cache_client_test.go (about) 1 package loggingaction_test 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "time" 8 9 "code.cloudfoundry.org/cli/actor/loggingaction" 10 11 "code.cloudfoundry.org/cli/actor/loggingaction/loggingactionfakes" 12 "code.cloudfoundry.org/go-loggregator/rpc/loggregator_v2" 13 logcache "code.cloudfoundry.org/log-cache/pkg/client" 14 . "github.com/onsi/ginkgo" 15 . "github.com/onsi/gomega" 16 ) 17 18 var _ = Describe("Logging Actions", func() { 19 var ( 20 fakeLogCacheClient *loggingactionfakes.FakeLogCacheClient 21 ) 22 23 BeforeEach(func() { 24 fakeLogCacheClient = new(loggingactionfakes.FakeLogCacheClient) 25 }) 26 27 Describe("LogMessage", func() { 28 Describe("Staging", func() { 29 When("the log is a staging log", func() { 30 It("returns true", func() { 31 message := loggingaction.LogMessage{SourceType: "STG"} 32 Expect(message.Staging()).To(BeTrue()) 33 }) 34 }) 35 36 When("the log is any other kind of log", func() { 37 It("returns false", func() { 38 message := loggingaction.LogMessage{SourceType: "APP"} 39 Expect(message.Staging()).To(BeFalse()) 40 }) 41 }) 42 }) 43 }) 44 45 Describe("GetStreamingLogs", func() { 46 var ( 47 expectedAppGUID string 48 49 messages <-chan loggingaction.LogMessage 50 errs <-chan error 51 stopStreaming context.CancelFunc 52 ) 53 54 BeforeEach(func() { 55 expectedAppGUID = "some-app-guid" 56 }) 57 58 AfterEach(func() { 59 Eventually(messages).Should(BeClosed()) 60 Eventually(errs).Should(BeClosed()) 61 }) 62 63 JustBeforeEach(func() { 64 messages, errs, stopStreaming = loggingaction.GetStreamingLogs(expectedAppGUID, fakeLogCacheClient) 65 }) 66 67 When("receiving logs", func() { 68 BeforeEach(func() { 69 fakeLogCacheClient.ReadStub = func( 70 ctx context.Context, 71 sourceID string, 72 start time.Time, 73 opts ...logcache.ReadOption, 74 ) ([]*loggregator_v2.Envelope, error) { 75 if fakeLogCacheClient.ReadCallCount() > 2 { 76 stopStreaming() 77 } 78 79 return []*loggregator_v2.Envelope{{ 80 // 2 seconds in the past to get past Walk delay 81 Timestamp: time.Now().Add(-3 * time.Second).UnixNano(), 82 SourceId: "some-app-guid", 83 InstanceId: "some-source-instance", 84 Message: &loggregator_v2.Envelope_Log{ 85 Log: &loggregator_v2.Log{ 86 Payload: []byte("message-1"), 87 Type: loggregator_v2.Log_OUT, 88 }, 89 }, 90 Tags: map[string]string{ 91 "source_type": "some-source-type", 92 }, 93 }, { 94 // 2 seconds in the past to get past Walk delay 95 Timestamp: time.Now().Add(-2 * time.Second).UnixNano(), 96 SourceId: "some-app-guid", 97 InstanceId: "some-source-instance", 98 Message: &loggregator_v2.Envelope_Log{ 99 Log: &loggregator_v2.Log{ 100 Payload: []byte("message-2"), 101 Type: loggregator_v2.Log_OUT, 102 }, 103 }, 104 Tags: map[string]string{ 105 "source_type": "some-source-type", 106 }, 107 }}, ctx.Err() 108 } 109 }) 110 111 It("converts them to log messages, sorts them, and passes them through the messages channel", func() { 112 Eventually(messages).Should(HaveLen(4)) 113 var message loggingaction.LogMessage 114 Expect(messages).To(Receive(&message)) 115 Expect(message.Message).To(Equal("message-1")) 116 Expect(messages).To(Receive(&message)) 117 Expect(message.Message).To(Equal("message-2")) 118 119 Expect(errs).ToNot(Receive()) 120 }) 121 }) 122 123 When("logs are older than 5 seconds", func() { 124 var readStart chan time.Time 125 126 BeforeEach(func() { 127 readStart = make(chan time.Time, 100) 128 fakeLogCacheClient.ReadStub = func( 129 ctx context.Context, 130 sourceID string, 131 start time.Time, 132 opts ...logcache.ReadOption, 133 ) ([]*loggregator_v2.Envelope, error) { 134 if fakeLogCacheClient.ReadCallCount() > 1 { 135 stopStreaming() 136 } 137 138 readStart <- start 139 140 return []*loggregator_v2.Envelope{{ 141 // 2 seconds in the past to get past Walk delay 142 Timestamp: time.Now().Add(-6 * time.Second).UnixNano(), 143 SourceId: "some-app-guid", 144 InstanceId: "some-source-instance", 145 Message: &loggregator_v2.Envelope_Log{ 146 Log: &loggregator_v2.Log{ 147 Payload: []byte("message-1"), 148 Type: loggregator_v2.Log_OUT, 149 }, 150 }, 151 Tags: map[string]string{ 152 "source_type": "some-source-type", 153 }, 154 }, { 155 // 2 seconds in the past to get past Walk delay 156 Timestamp: time.Now().Add(-2 * time.Second).UnixNano(), 157 SourceId: "some-app-guid", 158 InstanceId: "some-source-instance", 159 Message: &loggregator_v2.Envelope_Log{ 160 Log: &loggregator_v2.Log{ 161 Payload: []byte("message-2"), 162 Type: loggregator_v2.Log_OUT, 163 }, 164 }, 165 Tags: map[string]string{ 166 "source_type": "some-source-type", 167 }, 168 }}, ctx.Err() 169 } 170 }) 171 172 It("ignores them", func() { 173 Eventually(readStart).Should(Receive(BeTemporally("~", time.Now().Add(-5*time.Second), time.Second))) 174 }) 175 }) 176 177 When("cancelling log streaming", func() { 178 BeforeEach(func() { 179 fakeLogCacheClient.ReadStub = func( 180 ctx context.Context, 181 sourceID string, 182 start time.Time, 183 opts ...logcache.ReadOption, 184 ) ([]*loggregator_v2.Envelope, error) { 185 return nil, ctx.Err() 186 } 187 }) 188 189 It("can be called multiple times", func() { 190 Expect(stopStreaming).ToNot(Panic()) 191 Expect(stopStreaming).ToNot(Panic()) 192 }) 193 }) 194 195 Describe("log cache error", func() { 196 BeforeEach(func() { 197 fakeLogCacheClient.ReadStub = func( 198 ctx context.Context, 199 sourceID string, 200 start time.Time, 201 opts ...logcache.ReadOption, 202 ) ([]*loggregator_v2.Envelope, error) { 203 if fakeLogCacheClient.ReadCallCount() > 2 { 204 stopStreaming() 205 } 206 207 return nil, fmt.Errorf("error number %d", fakeLogCacheClient.ReadCallCount()) 208 } 209 }) 210 211 It("passes them through the errors channel", func() { 212 Eventually(errs).Should(HaveLen(2)) 213 Eventually(errs).Should(Receive(MatchError("error number 1"))) 214 Eventually(errs).Should(Receive(MatchError("error number 2"))) 215 }) 216 }) 217 }) 218 219 Describe("GetRecentLogs", func() { 220 When("the application can be found", func() { 221 When("Log Cache returns logs", func() { 222 BeforeEach(func() { 223 messages := []*loggregator_v2.Envelope{ 224 { 225 Timestamp: int64(20), 226 SourceId: "some-app-guid", 227 InstanceId: "some-source-instance", 228 Message: &loggregator_v2.Envelope_Log{ 229 Log: &loggregator_v2.Log{ 230 Payload: []byte("message-2"), 231 Type: loggregator_v2.Log_OUT, 232 }, 233 }, 234 Tags: map[string]string{ 235 "source_type": "some-source-type", 236 }, 237 }, 238 { 239 Timestamp: int64(10), 240 SourceId: "some-app-guid", 241 InstanceId: "some-source-instance", 242 Message: &loggregator_v2.Envelope_Log{ 243 Log: &loggregator_v2.Log{ 244 Payload: []byte("message-1"), 245 Type: loggregator_v2.Log_OUT, 246 }, 247 }, 248 Tags: map[string]string{ 249 "source_type": "some-source-type", 250 }, 251 }, 252 } 253 254 fakeLogCacheClient.ReadReturns(messages, nil) 255 }) 256 257 It("returns all the recent logs and warnings", func() { 258 messages, err := loggingaction.GetRecentLogs("some-app-guid", fakeLogCacheClient) 259 Expect(err).ToNot(HaveOccurred()) 260 261 Expect(messages[0].Message).To(Equal("message-1")) 262 Expect(messages[0].MessageType).To(Equal("OUT")) 263 Expect(messages[0].Timestamp).To(Equal(time.Unix(0, 10))) 264 Expect(messages[0].SourceType).To(Equal("some-source-type")) 265 Expect(messages[0].SourceInstance).To(Equal("some-source-instance")) 266 267 Expect(messages[1].Message).To(Equal("message-2")) 268 Expect(messages[1].MessageType).To(Equal("OUT")) 269 Expect(messages[1].Timestamp).To(Equal(time.Unix(0, 20))) 270 Expect(messages[1].SourceType).To(Equal("some-source-type")) 271 Expect(messages[1].SourceInstance).To(Equal("some-source-instance")) 272 }) 273 }) 274 275 When("Log Cache returns non-log envelopes", func() { 276 BeforeEach(func() { 277 messages := []*loggregator_v2.Envelope{ 278 { 279 Timestamp: int64(10), 280 SourceId: "some-app-guid", 281 InstanceId: "some-source-instance", 282 Message: &loggregator_v2.Envelope_Counter{}, 283 Tags: map[string]string{ 284 "source_type": "some-source-type", 285 }, 286 }, 287 } 288 289 fakeLogCacheClient.ReadReturns(messages, nil) 290 }) 291 292 It("ignores them", func() { 293 messages, err := loggingaction.GetRecentLogs("some-app-guid", fakeLogCacheClient) 294 Expect(err).ToNot(HaveOccurred()) 295 Expect(messages).To(BeEmpty()) 296 }) 297 }) 298 299 When("Log Cache errors", func() { 300 var expectedErr error 301 302 BeforeEach(func() { 303 expectedErr = errors.New("ZOMG") 304 fakeLogCacheClient.ReadReturns(nil, expectedErr) 305 }) 306 307 It("returns error and warnings", func() { 308 _, err := loggingaction.GetRecentLogs("some-app-guid", fakeLogCacheClient) 309 Expect(err).To(MatchError(expectedErr)) 310 }) 311 }) 312 }) 313 }) 314 })