github.com/orange-cloudfoundry/cli@v7.1.0+incompatible/command/v7/logs_command_test.go (about) 1 package v7_test 2 3 import ( 4 "context" 5 "errors" 6 "time" 7 8 "code.cloudfoundry.org/cli/actor/actionerror" 9 "code.cloudfoundry.org/cli/actor/sharedaction" 10 "code.cloudfoundry.org/cli/actor/sharedaction/sharedactionfakes" 11 "code.cloudfoundry.org/cli/actor/v7action" 12 "code.cloudfoundry.org/cli/command/commandfakes" 13 . "code.cloudfoundry.org/cli/command/v7" 14 "code.cloudfoundry.org/cli/command/v7/v7fakes" 15 "code.cloudfoundry.org/cli/util/configv3" 16 "code.cloudfoundry.org/cli/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 fakeConfig.CurrentUserReturns(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 It("displays the error and all warnings", func() { 252 Expect(executeErr).NotTo(HaveOccurred()) 253 Expect(testUI.Err).To(Say("steve for all I care")) 254 Expect(cancelFunctionHasBeenCalled).To(BeTrue()) 255 }) 256 }) 257 258 When("the logs actor returns logs", func() { 259 BeforeEach(func() { 260 fakeActor.GetStreamingLogsForApplicationByNameAndSpaceStub = 261 func(_ string, _ string, _ sharedaction.LogCacheClient) ( 262 <-chan sharedaction.LogMessage, 263 <-chan error, context.CancelFunc, 264 v7action.Warnings, 265 error) { 266 267 logStream := make(chan sharedaction.LogMessage) 268 errorStream := make(chan error) 269 270 go func() { 271 logStream <- *sharedaction.NewLogMessage("Here are some staging logs!", "OUT", time.Now(), sharedaction.StagingLog, "sourceInstance") //TODO: is it ok to leave staging logs here? 272 logStream <- *sharedaction.NewLogMessage("Here are some other staging logs!", "OUT", time.Now(), sharedaction.StagingLog, "sourceInstance") 273 close(logStream) 274 close(errorStream) 275 }() 276 277 return logStream, errorStream, func() {}, v7action.Warnings{"some-warning-1", "some-warning-2"}, nil 278 } 279 }) 280 281 It("displays flavor text", func() { 282 Expect(testUI.Out).To(Say("Retrieving logs for app some-app in org some-org-name / space some-space-name as some-user...")) 283 }) 284 285 It("displays all streaming log messages and warnings", func() { 286 Expect(executeErr).NotTo(HaveOccurred()) 287 Expect(testUI.Err).To(Say("some-warning-1")) 288 Expect(testUI.Err).To(Say("some-warning-2")) 289 290 Expect(testUI.Out).To(Say("Here are some staging logs!")) 291 Expect(testUI.Out).To(Say("Here are some other staging logs!")) 292 293 Expect(fakeActor.GetStreamingLogsForApplicationByNameAndSpaceCallCount()).To(Equal(1)) 294 appName, spaceGUID, client := fakeActor.GetStreamingLogsForApplicationByNameAndSpaceArgsForCall(0) 295 296 Expect(appName).To(Equal("some-app")) 297 Expect(spaceGUID).To(Equal("some-space-guid")) 298 Expect(client).To(Equal(logCacheClient)) 299 }) 300 301 When("scheduling a token refresh errors immediately", func() { 302 BeforeEach(func() { 303 cmd.Recent = false 304 fakeActor.ScheduleTokenRefreshReturns(nil, errors.New("fjords pining")) 305 }) 306 It("displays the errors", func() { 307 Expect(executeErr).To(MatchError("fjords pining")) 308 Expect(fakeActor.GetStreamingLogsForApplicationByNameAndSpaceCallCount()).To(Equal(0)) 309 }) 310 }) 311 312 When("there is an error refreshing a token sometime later", func() { 313 BeforeEach(func() { 314 cmd.Recent = false 315 fakeActor.ScheduleTokenRefreshStub = func( 316 after func(time.Duration) <-chan time.Time, 317 stop chan struct{}, stoppedRefreshing chan struct{}) (<-chan error, error) { 318 errCh := make(chan error, 1) 319 go func() { 320 errCh <- errors.New("fjords pining") 321 <-stop 322 close(stoppedRefreshing) 323 }() 324 return errCh, nil 325 } 326 }) 327 It("displays the errors", func() { 328 Expect(executeErr).NotTo(HaveOccurred()) 329 Expect(fakeActor.GetStreamingLogsForApplicationByNameAndSpaceCallCount()).To(Equal(1)) 330 Expect(testUI.Err).To(Say("fjords pining")) 331 }) 332 }) 333 }) 334 }) 335 }) 336 })