github.com/LukasHeimann/cloudfoundrycli/v8@v8.4.4/command/v7/logs_command_test.go (about) 1 package v7_test 2 3 import ( 4 "context" 5 "errors" 6 "time" 7 8 "github.com/LukasHeimann/cloudfoundrycli/v8/actor/actionerror" 9 "github.com/LukasHeimann/cloudfoundrycli/v8/actor/sharedaction" 10 "github.com/LukasHeimann/cloudfoundrycli/v8/actor/sharedaction/sharedactionfakes" 11 "github.com/LukasHeimann/cloudfoundrycli/v8/actor/v7action" 12 "github.com/LukasHeimann/cloudfoundrycli/v8/command/commandfakes" 13 . "github.com/LukasHeimann/cloudfoundrycli/v8/command/v7" 14 "github.com/LukasHeimann/cloudfoundrycli/v8/command/v7/v7fakes" 15 "github.com/LukasHeimann/cloudfoundrycli/v8/util/configv3" 16 "github.com/LukasHeimann/cloudfoundrycli/v8/util/ui" 17 . "github.com/onsi/ginkgo" 18 . "github.com/onsi/gomega" 19 . "github.com/onsi/gomega/gbytes" 20 ) 21 22 var _ = Describe("logs command", func() { 23 var ( 24 cmd LogsCommand 25 testUI *ui.UI 26 fakeConfig *commandfakes.FakeConfig 27 fakeSharedActor *commandfakes.FakeSharedActor 28 fakeActor *v7fakes.FakeActor 29 logCacheClient *sharedactionfakes.FakeLogCacheClient 30 binaryName string 31 executeErr error 32 ) 33 34 BeforeEach(func() { 35 testUI = ui.NewTestUI(nil, NewBuffer(), NewBuffer()) 36 fakeConfig = new(commandfakes.FakeConfig) 37 fakeSharedActor = new(commandfakes.FakeSharedActor) 38 fakeActor = new(v7fakes.FakeActor) 39 logCacheClient = new(sharedactionfakes.FakeLogCacheClient) 40 41 cmd = LogsCommand{ 42 BaseCommand: BaseCommand{ 43 UI: testUI, 44 Config: fakeConfig, 45 SharedActor: fakeSharedActor, 46 Actor: fakeActor, 47 }, 48 LogCacheClient: logCacheClient, 49 } 50 51 binaryName = "faceman" 52 fakeConfig.BinaryNameReturns(binaryName) 53 cmd.RequiredArgs.AppName = "some-app" 54 fakeActor.GetCurrentUserReturns(configv3.User{Name: "some-user"}, nil) 55 }) 56 57 JustBeforeEach(func() { 58 executeErr = cmd.Execute(nil) 59 }) 60 61 When("the checkTarget fails", func() { 62 BeforeEach(func() { 63 fakeSharedActor.CheckTargetReturns( 64 actionerror.NotLoggedInError{BinaryName: binaryName}) 65 }) 66 It("returns an error", func() { 67 orgRequired, spaceRequired := fakeSharedActor.CheckTargetArgsForCall(0) 68 Expect(orgRequired).To(BeTrue()) 69 Expect(spaceRequired).To(BeTrue()) 70 71 Expect(executeErr).To(MatchError( 72 actionerror.NotLoggedInError{BinaryName: binaryName})) 73 }) 74 }) 75 76 When("checkTarget succeeds", func() { 77 BeforeEach(func() { 78 fakeConfig.TargetedSpaceReturns(configv3.Space{ 79 Name: "some-space-name", 80 GUID: "some-space-guid", 81 }) 82 fakeConfig.TargetedOrganizationReturns(configv3.Organization{ 83 Name: "some-org-name", 84 }) 85 }) 86 87 When("the --recent flag is provided", func() { 88 BeforeEach(func() { 89 cmd.Recent = true 90 }) 91 92 It("displays flavor text", func() { 93 Expect(testUI.Out).To(Say("Retrieving logs for app some-app in org some-org-name / space some-space-name as some-user...")) 94 }) 95 96 When("the logs actor returns an error", func() { 97 var expectedErr error 98 BeforeEach(func() { 99 expectedErr = errors.New("some-error") 100 fakeActor.GetRecentLogsForApplicationByNameAndSpaceReturns( 101 []sharedaction.LogMessage{ 102 *sharedaction.NewLogMessage( 103 "all your base are belong to us", 104 "1", 105 time.Unix(0, 0), 106 "app", 107 "1", 108 ), 109 }, 110 v7action.Warnings{"some-warning-1", "some-warning-2"}, 111 expectedErr) 112 }) 113 114 It("displays the errors along with the logs and warnings", func() { 115 Expect(executeErr).To(MatchError(expectedErr)) 116 Expect(testUI.Out).To(Say("all your base are belong to us")) 117 Expect(testUI.Err).To(Say("some-warning-1")) 118 Expect(testUI.Err).To(Say("some-warning-2")) 119 }) 120 }) 121 122 When("the logs actor returns logs", func() { 123 BeforeEach(func() { 124 fakeActor.GetRecentLogsForApplicationByNameAndSpaceReturns( 125 []sharedaction.LogMessage{ 126 *sharedaction.NewLogMessage( 127 "i am message 1", 128 "1", 129 time.Unix(0, 0), 130 "app", 131 "1", 132 ), 133 *sharedaction.NewLogMessage( 134 "i am message 2", 135 "1", 136 time.Unix(1, 0), 137 "another-app", 138 "2", 139 ), 140 }, 141 v7action.Warnings{"some-warning-1", "some-warning-2"}, 142 nil) 143 }) 144 145 It("displays the recent log messages and warnings", func() { 146 Expect(executeErr).NotTo(HaveOccurred()) 147 Expect(testUI.Err).To(Say("some-warning-1")) 148 Expect(testUI.Err).To(Say("some-warning-2")) 149 150 Expect(testUI.Out).To(Say("i am message 1")) 151 Expect(testUI.Out).To(Say("i am message 2")) 152 153 Expect(fakeActor.GetRecentLogsForApplicationByNameAndSpaceCallCount()).To(Equal(1)) 154 appName, spaceGUID, client := fakeActor.GetRecentLogsForApplicationByNameAndSpaceArgsForCall(0) 155 156 Expect(appName).To(Equal("some-app")) 157 Expect(spaceGUID).To(Equal("some-space-guid")) 158 Expect(client).To(Equal(logCacheClient)) 159 }) 160 }) 161 }) 162 163 When("the --recent flag is not provided", func() { 164 BeforeEach(func() { 165 cmd.Recent = false 166 fakeActor.ScheduleTokenRefreshStub = func( 167 after func(time.Duration) <-chan time.Time, 168 stop chan struct{}, stoppedRefreshing chan struct{}) (<-chan error, error) { 169 errCh := make(chan error, 1) 170 go func() { 171 <-stop 172 close(stoppedRefreshing) 173 }() 174 return errCh, nil 175 } 176 }) 177 178 When("the logs setup returns an error", func() { 179 var expectedErr error 180 181 BeforeEach(func() { 182 expectedErr = errors.New("some-error") 183 fakeActor.GetStreamingLogsForApplicationByNameAndSpaceReturns(nil, 184 nil, 185 nil, 186 v7action.Warnings{"some-warning-1", 187 "some-warning-2"}, 188 expectedErr) 189 }) 190 191 It("displays the error and all warnings", func() { 192 Expect(executeErr).To(MatchError(expectedErr)) 193 Expect(testUI.Err).To(Say("some-warning-1")) 194 Expect(testUI.Err).To(Say("some-warning-2")) 195 }) 196 }) 197 198 When("the logs stream returns an error", func() { 199 var ( 200 expectedErr error 201 cancelFunctionHasBeenCalled bool 202 ) 203 204 BeforeEach(func() { 205 expectedErr = errors.New("banana") 206 207 fakeActor.GetStreamingLogsForApplicationByNameAndSpaceStub = 208 func(appName string, spaceGUID string, client sharedaction.LogCacheClient) ( 209 <-chan sharedaction.LogMessage, 210 <-chan error, 211 context.CancelFunc, 212 v7action.Warnings, error) { 213 logStream := make(chan sharedaction.LogMessage) 214 errorStream := make(chan error) 215 cancelFunctionHasBeenCalled = false 216 streamsWereClosed := false 217 218 cancelFunc := func() { 219 if cancelFunctionHasBeenCalled { 220 return 221 } 222 cancelFunctionHasBeenCalled = true 223 if !streamsWereClosed { 224 close(logStream) 225 close(errorStream) 226 streamsWereClosed = true 227 } 228 } 229 go func() { 230 errorStream <- expectedErr 231 close(logStream) 232 close(errorStream) 233 streamsWereClosed = true 234 }() 235 236 return logStream, errorStream, cancelFunc, v7action.Warnings{"steve for all I care"}, nil 237 } 238 }) 239 240 When("the token refresher returns an error", func() { 241 BeforeEach(func() { 242 cmd.Recent = false 243 fakeActor.ScheduleTokenRefreshReturns(nil, errors.New("firs swimming")) 244 }) 245 It("displays the errors", func() { 246 Expect(executeErr).To(MatchError("firs swimming")) 247 Expect(fakeActor.GetStreamingLogsForApplicationByNameAndSpaceCallCount()).To(Equal(0)) 248 }) 249 }) 250 251 When("isCFOnK8s is true", func() { 252 BeforeEach(func() { 253 fakeConfig.IsCFOnK8sReturns(true) 254 }) 255 256 It("does not call ScheduleTokenRefresh", func() { 257 Expect(fakeActor.ScheduleTokenRefreshCallCount()).To(Equal(0)) 258 }) 259 }) 260 261 It("displays the error and all warnings", func() { 262 Expect(executeErr).NotTo(HaveOccurred()) 263 Expect(testUI.Err).To(Say("steve for all I care")) 264 Expect(cancelFunctionHasBeenCalled).To(BeTrue()) 265 }) 266 }) 267 268 When("the logs actor returns logs", func() { 269 BeforeEach(func() { 270 fakeActor.GetStreamingLogsForApplicationByNameAndSpaceStub = 271 func(_ string, _ string, _ sharedaction.LogCacheClient) ( 272 <-chan sharedaction.LogMessage, 273 <-chan error, context.CancelFunc, 274 v7action.Warnings, 275 error) { 276 277 logStream := make(chan sharedaction.LogMessage) 278 errorStream := make(chan error) 279 280 go func() { 281 logStream <- *sharedaction.NewLogMessage("Here are some staging logs!", "OUT", time.Now(), sharedaction.StagingLog, "sourceInstance") //TODO: is it ok to leave staging logs here? 282 logStream <- *sharedaction.NewLogMessage("Here are some other staging logs!", "OUT", time.Now(), sharedaction.StagingLog, "sourceInstance") 283 close(logStream) 284 close(errorStream) 285 }() 286 287 return logStream, errorStream, func() {}, v7action.Warnings{"some-warning-1", "some-warning-2"}, nil 288 } 289 }) 290 291 It("displays flavor text", func() { 292 Expect(testUI.Out).To(Say("Retrieving logs for app some-app in org some-org-name / space some-space-name as some-user...")) 293 }) 294 295 It("displays all streaming log messages and warnings", func() { 296 Expect(executeErr).NotTo(HaveOccurred()) 297 Expect(testUI.Err).To(Say("some-warning-1")) 298 Expect(testUI.Err).To(Say("some-warning-2")) 299 300 Expect(testUI.Out).To(Say("Here are some staging logs!")) 301 Expect(testUI.Out).To(Say("Here are some other staging logs!")) 302 303 Expect(fakeActor.GetStreamingLogsForApplicationByNameAndSpaceCallCount()).To(Equal(1)) 304 appName, spaceGUID, client := fakeActor.GetStreamingLogsForApplicationByNameAndSpaceArgsForCall(0) 305 306 Expect(appName).To(Equal("some-app")) 307 Expect(spaceGUID).To(Equal("some-space-guid")) 308 Expect(client).To(Equal(logCacheClient)) 309 }) 310 311 When("scheduling a token refresh errors immediately", func() { 312 BeforeEach(func() { 313 cmd.Recent = false 314 fakeActor.ScheduleTokenRefreshReturns(nil, errors.New("fjords pining")) 315 }) 316 It("displays the errors", func() { 317 Expect(executeErr).To(MatchError("fjords pining")) 318 Expect(fakeActor.GetStreamingLogsForApplicationByNameAndSpaceCallCount()).To(Equal(0)) 319 }) 320 }) 321 322 When("there is an error refreshing a token sometime later", func() { 323 BeforeEach(func() { 324 cmd.Recent = false 325 fakeActor.ScheduleTokenRefreshStub = func( 326 after func(time.Duration) <-chan time.Time, 327 stop chan struct{}, stoppedRefreshing chan struct{}) (<-chan error, error) { 328 errCh := make(chan error, 1) 329 go func() { 330 errCh <- errors.New("fjords pining") 331 <-stop 332 close(stoppedRefreshing) 333 }() 334 return errCh, nil 335 } 336 }) 337 It("displays the errors", func() { 338 Expect(executeErr).NotTo(HaveOccurred()) 339 Expect(fakeActor.GetStreamingLogsForApplicationByNameAndSpaceCallCount()).To(Equal(1)) 340 Expect(testUI.Err).To(Say("fjords pining")) 341 }) 342 }) 343 }) 344 }) 345 }) 346 })