github.com/swisscom/cloudfoundry-cli@v7.1.0+incompatible/cf/api/logs/log_cache_repository_test.go (about) 1 package logs_test 2 3 import ( 4 "context" 5 "errors" 6 "time" 7 8 "code.cloudfoundry.org/cli/actor/sharedaction" 9 "code.cloudfoundry.org/cli/actor/sharedaction/sharedactionfakes" 10 "code.cloudfoundry.org/cli/cf/api/logs" 11 . "github.com/onsi/ginkgo" 12 . "github.com/onsi/gomega" 13 ) 14 15 var _ = Describe("logs with log cache", func() { 16 17 Describe("RecentLogsFor", func() { 18 It("retrieves the logs", func() { 19 recentLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) ([]sharedaction.LogMessage, error) { 20 message := *sharedaction.NewLogMessage( 21 "some-message", 22 "OUT", 23 time.Unix(0, 0), 24 "STG", 25 "some-source-instance", 26 ) 27 message2 := *sharedaction.NewLogMessage( 28 "some-message2", 29 "OUT", 30 time.Unix(0, 0), 31 "STG", 32 "some-source-instance2", 33 ) 34 return []sharedaction.LogMessage{message, message2}, nil 35 } 36 getStreamingLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) (<-chan sharedaction.LogMessage, <-chan error, context.CancelFunc) { 37 inputLogChan := make(chan sharedaction.LogMessage) 38 errors := make(chan error) 39 cancelFunc := func() {} 40 return inputLogChan, errors, cancelFunc 41 } 42 client := sharedactionfakes.FakeLogCacheClient{} 43 repository := logs.NewLogCacheRepository(&client, recentLogsFunc, getStreamingLogsFunc) 44 logs, err := repository.RecentLogsFor("app-guid") 45 46 Expect(err).ToNot(HaveOccurred()) 47 Expect(len(logs)).To(Equal(2)) 48 Expect(logs[0].ToSimpleLog()).To(Equal("some-message")) 49 Expect(logs[1].ToSimpleLog()).To(Equal("some-message2")) 50 }) 51 52 When("theres an error retrieving the logs", func() { 53 It("returns the error", func() { 54 recentLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) ([]sharedaction.LogMessage, error) { 55 return nil, errors.New("some error") 56 } 57 getStreamingLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) (<-chan sharedaction.LogMessage, <-chan error, context.CancelFunc) { 58 inputLogChan := make(chan sharedaction.LogMessage) 59 errors := make(chan error) 60 cancelFunc := func() {} 61 return inputLogChan, errors, cancelFunc 62 } 63 client := sharedactionfakes.FakeLogCacheClient{} 64 repository := logs.NewLogCacheRepository(&client, recentLogsFunc, getStreamingLogsFunc) 65 _, err := repository.RecentLogsFor("app-guid") 66 Expect(err).To(MatchError("some error")) 67 }) 68 }) 69 }) 70 71 Describe("TailLogsFor", func() { 72 var ( 73 inputLogChan chan sharedaction.LogMessage 74 inputErrorChan chan error 75 logCacheMessage *logs.LogCacheMessage 76 internalError error 77 ) 78 79 cancelFunc := func() {} 80 81 recentLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) ([]sharedaction.LogMessage, error) { 82 return []sharedaction.LogMessage{}, nil 83 } 84 85 It("writes to output log channel until input log message channel is closed", func() { 86 getStreamingLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) (<-chan sharedaction.LogMessage, <-chan error, context.CancelFunc) { 87 inputLogChan = make(chan sharedaction.LogMessage, 2) 88 inputErrorChan = make(chan error, 2) 89 90 go func() { 91 defer close(inputLogChan) 92 93 message := *sharedaction.NewLogMessage( 94 "some-message", 95 "OUT", 96 time.Unix(0, 0), 97 "STG", 98 "some-source-instance", 99 ) 100 message2 := *sharedaction.NewLogMessage( 101 "some-message2", 102 "OUT", 103 time.Unix(0, 0), 104 "STG", 105 "some-source-instance2", 106 ) 107 inputLogChan <- message 108 inputLogChan <- message2 109 110 time.Sleep(1 * time.Second) 111 }() 112 113 return inputLogChan, inputErrorChan, cancelFunc 114 } 115 116 client := sharedactionfakes.FakeLogCacheClient{} 117 repository := logs.NewLogCacheRepository(&client, recentLogsFunc, getStreamingLogsFunc) 118 outputLogChan := make(chan logs.Loggable, 2) 119 outputErrorChan := make(chan error, 2) 120 121 repository.TailLogsFor("app-guid", func() {}, outputLogChan, outputErrorChan) 122 123 Eventually(outputLogChan).Should(HaveLen(2)) 124 Expect(outputLogChan).To(Receive(&logCacheMessage)) 125 Expect(logCacheMessage.ToSimpleLog()).To(Equal("some-message")) 126 Expect(outputLogChan).To(Receive(&logCacheMessage)) 127 Expect(logCacheMessage.ToSimpleLog()).To(Equal("some-message2")) 128 Expect(inputErrorChan).ToNot(Receive()) 129 }) 130 131 It("writes to output log channel until input error channel is closed", func() { 132 getStreamingLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) (<-chan sharedaction.LogMessage, <-chan error, context.CancelFunc) { 133 inputLogChan = make(chan sharedaction.LogMessage, 2) 134 inputErrorChan = make(chan error, 2) 135 136 go func() { 137 defer close(inputErrorChan) 138 139 message := *sharedaction.NewLogMessage( 140 "some-message", 141 "OUT", 142 time.Unix(0, 0), 143 "STG", 144 "some-source-instance", 145 ) 146 message2 := *sharedaction.NewLogMessage( 147 "some-message2", 148 "OUT", 149 time.Unix(0, 0), 150 "STG", 151 "some-source-instance2", 152 ) 153 inputLogChan <- message 154 inputLogChan <- message2 155 156 time.Sleep(1 * time.Second) 157 }() 158 159 return inputLogChan, inputErrorChan, cancelFunc 160 } 161 162 client := sharedactionfakes.FakeLogCacheClient{} 163 repository := logs.NewLogCacheRepository(&client, recentLogsFunc, getStreamingLogsFunc) 164 outputLogChan := make(chan logs.Loggable, 2) 165 outputErrorChan := make(chan error, 2) 166 167 repository.TailLogsFor("app-guid", func() {}, outputLogChan, outputErrorChan) 168 169 Eventually(outputLogChan).Should(HaveLen(2)) 170 Expect(outputLogChan).To(Receive(&logCacheMessage)) 171 Expect(logCacheMessage.ToSimpleLog()).To(Equal("some-message")) 172 Expect(outputLogChan).To(Receive(&logCacheMessage)) 173 Expect(logCacheMessage.ToSimpleLog()).To(Equal("some-message2")) 174 Expect(inputErrorChan).ToNot(Receive()) 175 }) 176 177 It("writes recoverable errors to output error channel until input error channel is closed", func() { 178 getStreamingLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) (<-chan sharedaction.LogMessage, <-chan error, context.CancelFunc) { 179 inputLogChan = make(chan sharedaction.LogMessage) 180 inputErrorChan = make(chan error, 1) 181 182 go func() { 183 defer close(inputErrorChan) 184 inputErrorChan <- errors.New("internal error") 185 time.Sleep(1 * time.Second) 186 }() 187 188 return inputLogChan, inputErrorChan, cancelFunc 189 } 190 191 client := sharedactionfakes.FakeLogCacheClient{} 192 repository := logs.NewLogCacheRepository(&client, recentLogsFunc, getStreamingLogsFunc) 193 outputLogChan := make(chan logs.Loggable) 194 outputErrorChan := make(chan error, 1) 195 repository.TailLogsFor("app-guid", func() {}, outputLogChan, outputErrorChan) 196 197 Eventually(outputErrorChan).Should(HaveLen(1)) 198 Expect(outputErrorChan).To(Receive(&internalError)) 199 Expect(internalError).To(MatchError("internal error")) 200 Expect(inputLogChan).ToNot(Receive()) 201 }) 202 203 It("writes recoverable errors to output error channel until input log message channel is closed", func() { 204 getStreamingLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) (<-chan sharedaction.LogMessage, <-chan error, context.CancelFunc) { 205 inputLogChan = make(chan sharedaction.LogMessage) 206 inputErrorChan = make(chan error, 1) 207 208 go func() { 209 defer close(inputLogChan) 210 inputErrorChan <- errors.New("internal error") 211 time.Sleep(1 * time.Second) 212 }() 213 214 return inputLogChan, inputErrorChan, cancelFunc 215 } 216 217 client := sharedactionfakes.FakeLogCacheClient{} 218 repository := logs.NewLogCacheRepository(&client, recentLogsFunc, getStreamingLogsFunc) 219 outputLogChan := make(chan logs.Loggable) 220 outputErrorChan := make(chan error, 1) 221 repository.TailLogsFor("app-guid", func() {}, outputLogChan, outputErrorChan) 222 223 Eventually(outputErrorChan).Should(HaveLen(1)) 224 Expect(outputErrorChan).To(Receive(&internalError)) 225 Expect(internalError).To(MatchError("internal error")) 226 Expect(inputLogChan).ToNot(Receive()) 227 }) 228 229 When("Close() called", func() { 230 231 It("calls repository.cancelFunc", func() { 232 cancelFuncCallCount := 0 233 234 cancelFunc = func() { 235 cancelFuncCallCount += 1 236 } 237 238 getStreamingLogsFunc := func(appGUID string, client sharedaction.LogCacheClient) (<-chan sharedaction.LogMessage, <-chan error, context.CancelFunc) { 239 inputLogChan = make(chan sharedaction.LogMessage) 240 inputErrorChan = make(chan error, 1) 241 close(inputLogChan) 242 close(inputErrorChan) 243 return inputLogChan, inputErrorChan, cancelFunc 244 } 245 246 client := sharedactionfakes.FakeLogCacheClient{} 247 repository := logs.NewLogCacheRepository(&client, recentLogsFunc, getStreamingLogsFunc) 248 outputLogChan := make(chan logs.Loggable) 249 outputErrorChan := make(chan error, 1) 250 251 repository.TailLogsFor("app-guid", func() {}, outputLogChan, outputErrorChan) 252 repository.Close() 253 Expect(cancelFuncCallCount).To(Equal(1)) 254 }) 255 }) 256 }) 257 258 XDescribe("Authentication Token Refresh", func() { 259 }) 260 })