github.com/randomtask1155/cli@v6.41.1-0.20181227003417-a98eed78cbde+incompatible/actor/v3action/application_test.go (about)

     1  package v3action_test
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strings"
     7  	"time"
     8  
     9  	"code.cloudfoundry.org/cli/actor/actionerror"
    10  	. "code.cloudfoundry.org/cli/actor/v3action"
    11  	"code.cloudfoundry.org/cli/actor/v3action/v3actionfakes"
    12  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
    13  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
    14  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
    15  
    16  	. "github.com/onsi/ginkgo"
    17  	. "github.com/onsi/gomega"
    18  )
    19  
    20  var _ = Describe("Application Actions", func() {
    21  	var (
    22  		actor                     *Actor
    23  		fakeCloudControllerClient *v3actionfakes.FakeCloudControllerClient
    24  		fakeConfig                *v3actionfakes.FakeConfig
    25  	)
    26  
    27  	BeforeEach(func() {
    28  		fakeCloudControllerClient = new(v3actionfakes.FakeCloudControllerClient)
    29  		fakeConfig = new(v3actionfakes.FakeConfig)
    30  		actor = NewActor(fakeCloudControllerClient, fakeConfig, nil, nil)
    31  	})
    32  
    33  	Describe("DeleteApplicationByNameAndSpace", func() {
    34  		var (
    35  			warnings   Warnings
    36  			executeErr error
    37  		)
    38  
    39  		JustBeforeEach(func() {
    40  			warnings, executeErr = actor.DeleteApplicationByNameAndSpace("some-app", "some-space-guid")
    41  		})
    42  
    43  		When("looking up the app guid fails", func() {
    44  			BeforeEach(func() {
    45  				fakeCloudControllerClient.GetApplicationsReturns([]ccv3.Application{}, ccv3.Warnings{"some-get-app-warning"}, errors.New("some-get-app-error"))
    46  			})
    47  
    48  			It("returns the warnings and error", func() {
    49  				Expect(warnings).To(ConsistOf("some-get-app-warning"))
    50  				Expect(executeErr).To(MatchError("some-get-app-error"))
    51  			})
    52  		})
    53  
    54  		When("looking up the app guid succeeds", func() {
    55  			BeforeEach(func() {
    56  				fakeCloudControllerClient.GetApplicationsReturns([]ccv3.Application{{Name: "some-app", GUID: "abc123"}}, ccv3.Warnings{"some-get-app-warning"}, nil)
    57  			})
    58  
    59  			When("sending the delete fails", func() {
    60  				BeforeEach(func() {
    61  					fakeCloudControllerClient.DeleteApplicationReturns("", ccv3.Warnings{"some-delete-app-warning"}, errors.New("some-delete-app-error"))
    62  				})
    63  
    64  				It("returns the warnings and error", func() {
    65  					Expect(warnings).To(ConsistOf("some-get-app-warning", "some-delete-app-warning"))
    66  					Expect(executeErr).To(MatchError("some-delete-app-error"))
    67  				})
    68  			})
    69  
    70  			When("sending the delete succeeds", func() {
    71  				BeforeEach(func() {
    72  					fakeCloudControllerClient.DeleteApplicationReturns("/some-job-url", ccv3.Warnings{"some-delete-app-warning"}, nil)
    73  				})
    74  
    75  				When("polling fails", func() {
    76  					BeforeEach(func() {
    77  						fakeCloudControllerClient.PollJobReturns(ccv3.Warnings{"some-poll-warning"}, errors.New("some-poll-error"))
    78  					})
    79  
    80  					It("returns the warnings and poll error", func() {
    81  						Expect(warnings).To(ConsistOf("some-get-app-warning", "some-delete-app-warning", "some-poll-warning"))
    82  						Expect(executeErr).To(MatchError("some-poll-error"))
    83  					})
    84  				})
    85  
    86  				When("polling succeeds", func() {
    87  					BeforeEach(func() {
    88  						fakeCloudControllerClient.PollJobReturns(ccv3.Warnings{"some-poll-warning"}, nil)
    89  					})
    90  
    91  					It("returns all the warnings and no error", func() {
    92  						Expect(warnings).To(ConsistOf("some-get-app-warning", "some-delete-app-warning", "some-poll-warning"))
    93  						Expect(executeErr).ToNot(HaveOccurred())
    94  					})
    95  				})
    96  			})
    97  		})
    98  	})
    99  
   100  	Describe("GetApplicationByNameAndSpace", func() {
   101  		When("the app exists", func() {
   102  			BeforeEach(func() {
   103  				fakeCloudControllerClient.GetApplicationsReturns(
   104  					[]ccv3.Application{
   105  						{
   106  							Name: "some-app-name",
   107  							GUID: "some-app-guid",
   108  						},
   109  					},
   110  					ccv3.Warnings{"some-warning"},
   111  					nil,
   112  				)
   113  			})
   114  
   115  			It("returns the application and warnings", func() {
   116  				app, warnings, err := actor.GetApplicationByNameAndSpace("some-app-name", "some-space-guid")
   117  				Expect(err).ToNot(HaveOccurred())
   118  				Expect(app).To(Equal(Application{
   119  					Name: "some-app-name",
   120  					GUID: "some-app-guid",
   121  				}))
   122  				Expect(warnings).To(ConsistOf("some-warning"))
   123  
   124  				Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1))
   125  				Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf(
   126  					ccv3.Query{Key: ccv3.NameFilter, Values: []string{"some-app-name"}},
   127  					ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}},
   128  				))
   129  			})
   130  		})
   131  
   132  		When("the cloud controller client returns an error", func() {
   133  			var expectedError error
   134  
   135  			BeforeEach(func() {
   136  				expectedError = errors.New("I am a CloudControllerClient Error")
   137  				fakeCloudControllerClient.GetApplicationsReturns(
   138  					[]ccv3.Application{},
   139  					ccv3.Warnings{"some-warning"},
   140  					expectedError)
   141  			})
   142  
   143  			It("returns the warnings and the error", func() {
   144  				_, warnings, err := actor.GetApplicationByNameAndSpace("some-app-name", "some-space-guid")
   145  				Expect(warnings).To(ConsistOf("some-warning"))
   146  				Expect(err).To(MatchError(expectedError))
   147  			})
   148  		})
   149  
   150  		When("the app does not exist", func() {
   151  			BeforeEach(func() {
   152  				fakeCloudControllerClient.GetApplicationsReturns(
   153  					[]ccv3.Application{},
   154  					ccv3.Warnings{"some-warning"},
   155  					nil,
   156  				)
   157  			})
   158  
   159  			It("returns an ApplicationNotFoundError and the warnings", func() {
   160  				_, warnings, err := actor.GetApplicationByNameAndSpace("some-app-name", "some-space-guid")
   161  				Expect(warnings).To(ConsistOf("some-warning"))
   162  				Expect(err).To(MatchError(actionerror.ApplicationNotFoundError{Name: "some-app-name"}))
   163  			})
   164  		})
   165  	})
   166  
   167  	Describe("GetApplicationsBySpace", func() {
   168  		When("the there are applications in the space", func() {
   169  			BeforeEach(func() {
   170  				fakeCloudControllerClient.GetApplicationsReturns(
   171  					[]ccv3.Application{
   172  						{
   173  							GUID: "some-app-guid-1",
   174  							Name: "some-app-1",
   175  						},
   176  						{
   177  							GUID: "some-app-guid-2",
   178  							Name: "some-app-2",
   179  						},
   180  					},
   181  					ccv3.Warnings{"warning-1", "warning-2"},
   182  					nil,
   183  				)
   184  			})
   185  
   186  			It("returns the application and warnings", func() {
   187  				apps, warnings, err := actor.GetApplicationsBySpace("some-space-guid")
   188  				Expect(err).ToNot(HaveOccurred())
   189  				Expect(apps).To(ConsistOf(
   190  					Application{
   191  						GUID: "some-app-guid-1",
   192  						Name: "some-app-1",
   193  					},
   194  					Application{
   195  						GUID: "some-app-guid-2",
   196  						Name: "some-app-2",
   197  					},
   198  				))
   199  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   200  
   201  				Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1))
   202  				Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf(
   203  					ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}},
   204  				))
   205  			})
   206  		})
   207  
   208  		When("the cloud controller client returns an error", func() {
   209  			var expectedError error
   210  
   211  			BeforeEach(func() {
   212  				expectedError = errors.New("I am a CloudControllerClient Error")
   213  				fakeCloudControllerClient.GetApplicationsReturns(
   214  					[]ccv3.Application{},
   215  					ccv3.Warnings{"some-warning"},
   216  					expectedError)
   217  			})
   218  
   219  			It("returns the error and warnings", func() {
   220  				_, warnings, err := actor.GetApplicationsBySpace("some-space-guid")
   221  				Expect(warnings).To(ConsistOf("some-warning"))
   222  				Expect(err).To(MatchError(expectedError))
   223  			})
   224  		})
   225  	})
   226  
   227  	Describe("CreateApplicationInSpace", func() {
   228  		var (
   229  			application Application
   230  			warnings    Warnings
   231  			err         error
   232  		)
   233  
   234  		JustBeforeEach(func() {
   235  			application, warnings, err = actor.CreateApplicationInSpace(Application{
   236  				Name:                "some-app-name",
   237  				LifecycleType:       constant.AppLifecycleTypeBuildpack,
   238  				LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"},
   239  			}, "some-space-guid")
   240  		})
   241  
   242  		When("the app successfully gets created", func() {
   243  			BeforeEach(func() {
   244  				fakeCloudControllerClient.CreateApplicationReturns(
   245  					ccv3.Application{
   246  						Name:                "some-app-name",
   247  						GUID:                "some-app-guid",
   248  						LifecycleType:       constant.AppLifecycleTypeBuildpack,
   249  						LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"},
   250  					},
   251  					ccv3.Warnings{"some-warning"},
   252  					nil,
   253  				)
   254  			})
   255  
   256  			It("creates and returns the application and warnings", func() {
   257  				Expect(err).ToNot(HaveOccurred())
   258  				Expect(application).To(Equal(Application{
   259  					Name:                "some-app-name",
   260  					GUID:                "some-app-guid",
   261  					LifecycleType:       constant.AppLifecycleTypeBuildpack,
   262  					LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"},
   263  				}))
   264  				Expect(warnings).To(ConsistOf("some-warning"))
   265  
   266  				Expect(fakeCloudControllerClient.CreateApplicationCallCount()).To(Equal(1))
   267  				Expect(fakeCloudControllerClient.CreateApplicationArgsForCall(0)).To(Equal(ccv3.Application{
   268  					Name: "some-app-name",
   269  					Relationships: ccv3.Relationships{
   270  						constant.RelationshipTypeSpace: ccv3.Relationship{GUID: "some-space-guid"},
   271  					},
   272  					LifecycleType:       constant.AppLifecycleTypeBuildpack,
   273  					LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"},
   274  				}))
   275  			})
   276  		})
   277  
   278  		When("the cc client returns an error", func() {
   279  			var expectedError error
   280  
   281  			BeforeEach(func() {
   282  				expectedError = errors.New("I am a CloudControllerClient Error")
   283  				fakeCloudControllerClient.CreateApplicationReturns(
   284  					ccv3.Application{},
   285  					ccv3.Warnings{"some-warning"},
   286  					expectedError,
   287  				)
   288  			})
   289  
   290  			It("raises the error and warnings", func() {
   291  				Expect(err).To(MatchError(expectedError))
   292  				Expect(warnings).To(ConsistOf("some-warning"))
   293  			})
   294  		})
   295  
   296  		When("the cc client returns an NameNotUniqueInSpaceError", func() {
   297  			BeforeEach(func() {
   298  				fakeCloudControllerClient.CreateApplicationReturns(
   299  					ccv3.Application{},
   300  					ccv3.Warnings{"some-warning"},
   301  					ccerror.NameNotUniqueInSpaceError{},
   302  				)
   303  			})
   304  
   305  			It("returns the ApplicationAlreadyExistsError and warnings", func() {
   306  				Expect(err).To(MatchError(actionerror.ApplicationAlreadyExistsError{Name: "some-app-name"}))
   307  				Expect(warnings).To(ConsistOf("some-warning"))
   308  			})
   309  		})
   310  	})
   311  
   312  	Describe("UpdateApplication", func() {
   313  		var (
   314  			submitApp, resultApp Application
   315  			warnings             Warnings
   316  			err                  error
   317  		)
   318  
   319  		JustBeforeEach(func() {
   320  			submitApp = Application{
   321  				GUID:                "some-app-guid",
   322  				StackName:           "some-stack-name",
   323  				LifecycleType:       constant.AppLifecycleTypeBuildpack,
   324  				LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"},
   325  			}
   326  			resultApp, warnings, err = actor.UpdateApplication(submitApp)
   327  		})
   328  
   329  		When("the app successfully gets updated", func() {
   330  			var apiResponseApp ccv3.Application
   331  
   332  			BeforeEach(func() {
   333  				apiResponseApp = ccv3.Application{
   334  					GUID:                "response-app-guid",
   335  					StackName:           "response-stack-name",
   336  					LifecycleType:       constant.AppLifecycleTypeBuildpack,
   337  					LifecycleBuildpacks: []string{"response-buildpack-1", "response-buildpack-2"},
   338  				}
   339  				fakeCloudControllerClient.UpdateApplicationReturns(
   340  					apiResponseApp,
   341  					ccv3.Warnings{"some-warning"},
   342  					nil,
   343  				)
   344  			})
   345  
   346  			It("creates and returns the application and warnings", func() {
   347  				Expect(err).ToNot(HaveOccurred())
   348  				Expect(resultApp).To(Equal(Application{
   349  					GUID:                apiResponseApp.GUID,
   350  					StackName:           apiResponseApp.StackName,
   351  					LifecycleType:       apiResponseApp.LifecycleType,
   352  					LifecycleBuildpacks: apiResponseApp.LifecycleBuildpacks,
   353  				}))
   354  				Expect(warnings).To(ConsistOf("some-warning"))
   355  
   356  				Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(1))
   357  				Expect(fakeCloudControllerClient.UpdateApplicationArgsForCall(0)).To(Equal(ccv3.Application{
   358  					GUID:                submitApp.GUID,
   359  					StackName:           submitApp.StackName,
   360  					LifecycleType:       submitApp.LifecycleType,
   361  					LifecycleBuildpacks: submitApp.LifecycleBuildpacks,
   362  				}))
   363  			})
   364  		})
   365  
   366  		When("the cc client returns an error", func() {
   367  			var expectedError error
   368  
   369  			BeforeEach(func() {
   370  				expectedError = errors.New("I am a CloudControllerClient Error")
   371  				fakeCloudControllerClient.UpdateApplicationReturns(
   372  					ccv3.Application{},
   373  					ccv3.Warnings{"some-warning"},
   374  					expectedError,
   375  				)
   376  			})
   377  
   378  			It("raises the error and warnings", func() {
   379  				Expect(err).To(MatchError(expectedError))
   380  				Expect(warnings).To(ConsistOf("some-warning"))
   381  			})
   382  		})
   383  	})
   384  
   385  	Describe("PollStart", func() {
   386  		var warningsChannel chan Warnings
   387  		var allWarnings Warnings
   388  		var funcDone chan interface{}
   389  
   390  		BeforeEach(func() {
   391  			warningsChannel = make(chan Warnings)
   392  			funcDone = make(chan interface{})
   393  			allWarnings = Warnings{}
   394  			go func() {
   395  				for {
   396  					select {
   397  					case warnings := <-warningsChannel:
   398  						allWarnings = append(allWarnings, warnings...)
   399  					case <-funcDone:
   400  						return
   401  					}
   402  				}
   403  			}()
   404  		})
   405  
   406  		When("getting the application processes fails", func() {
   407  			BeforeEach(func() {
   408  				fakeCloudControllerClient.GetApplicationProcessesReturns(nil, ccv3.Warnings{"get-app-warning-1", "get-app-warning-2"}, errors.New("some-error"))
   409  			})
   410  
   411  			It("returns the error and all warnings", func() {
   412  				err := actor.PollStart("some-guid", warningsChannel)
   413  				funcDone <- nil
   414  				Expect(allWarnings).To(ConsistOf("get-app-warning-1", "get-app-warning-2"))
   415  				Expect(err).To(MatchError(errors.New("some-error")))
   416  			})
   417  		})
   418  
   419  		When("getting the application processes succeeds", func() {
   420  			var processes []ccv3.Process
   421  
   422  			BeforeEach(func() {
   423  				fakeConfig.StartupTimeoutReturns(time.Second)
   424  				fakeConfig.PollingIntervalReturns(0)
   425  			})
   426  
   427  			JustBeforeEach(func() {
   428  				fakeCloudControllerClient.GetApplicationProcessesReturns(
   429  					processes,
   430  					ccv3.Warnings{"get-app-warning-1"}, nil)
   431  			})
   432  
   433  			When("there is a single process", func() {
   434  				BeforeEach(func() {
   435  					processes = []ccv3.Process{{GUID: "abc123"}}
   436  				})
   437  
   438  				When("the polling times out", func() {
   439  					BeforeEach(func() {
   440  						fakeConfig.StartupTimeoutReturns(time.Millisecond)
   441  						fakeConfig.PollingIntervalReturns(time.Millisecond * 2)
   442  						fakeCloudControllerClient.GetProcessInstancesReturns(
   443  							[]ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}},
   444  							ccv3.Warnings{"get-process-warning-1", "get-process-warning-2"},
   445  							nil,
   446  						)
   447  					})
   448  
   449  					It("returns the timeout error", func() {
   450  						err := actor.PollStart("some-guid", warningsChannel)
   451  						funcDone <- nil
   452  
   453  						Expect(allWarnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2"))
   454  						Expect(err).To(MatchError(actionerror.StartupTimeoutError{}))
   455  					})
   456  
   457  					It("gets polling and timeout values from the config", func() {
   458  						actor.PollStart("some-guid", warningsChannel)
   459  						funcDone <- nil
   460  
   461  						Expect(fakeConfig.StartupTimeoutCallCount()).To(Equal(1))
   462  						Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(1))
   463  					})
   464  				})
   465  
   466  				When("getting the process instances errors", func() {
   467  					BeforeEach(func() {
   468  						fakeCloudControllerClient.GetProcessInstancesReturns(
   469  							nil,
   470  							ccv3.Warnings{"get-process-warning-1", "get-process-warning-2"},
   471  							errors.New("some-error"),
   472  						)
   473  					})
   474  
   475  					It("returns the error", func() {
   476  						err := actor.PollStart("some-guid", warningsChannel)
   477  						funcDone <- nil
   478  
   479  						Expect(allWarnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2"))
   480  						Expect(err).To(MatchError("some-error"))
   481  					})
   482  				})
   483  
   484  				When("getting the process instances succeeds", func() {
   485  					var (
   486  						initialInstanceStates    []ccv3.ProcessInstance
   487  						eventualInstanceStates   []ccv3.ProcessInstance
   488  						pollStartErr             error
   489  						processInstanceCallCount int
   490  					)
   491  
   492  					BeforeEach(func() {
   493  						processInstanceCallCount = 0
   494  					})
   495  
   496  					JustBeforeEach(func() {
   497  						fakeCloudControllerClient.GetProcessInstancesStub = func(processGuid string) ([]ccv3.ProcessInstance, ccv3.Warnings, error) {
   498  							defer func() { processInstanceCallCount++ }()
   499  							if processInstanceCallCount == 0 {
   500  								return initialInstanceStates,
   501  									ccv3.Warnings{"get-process-warning-1", "get-process-warning-2"},
   502  									nil
   503  							} else {
   504  								return eventualInstanceStates,
   505  									ccv3.Warnings{fmt.Sprintf("get-process-warning-%d", processInstanceCallCount+2)},
   506  									nil
   507  							}
   508  						}
   509  
   510  						pollStartErr = actor.PollStart("some-guid", warningsChannel)
   511  						funcDone <- nil
   512  					})
   513  
   514  					When("there are no process instances", func() {
   515  						BeforeEach(func() {
   516  							initialInstanceStates = []ccv3.ProcessInstance{}
   517  							eventualInstanceStates = []ccv3.ProcessInstance{}
   518  						})
   519  
   520  						It("should not return an error", func() {
   521  							Expect(pollStartErr).NotTo(HaveOccurred())
   522  						})
   523  
   524  						It("should only call GetProcessInstances once before exiting", func() {
   525  							Expect(processInstanceCallCount).To(Equal(1))
   526  						})
   527  
   528  						It("should return correct warnings", func() {
   529  							Expect(allWarnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2"))
   530  						})
   531  					})
   532  
   533  					When("all instances become running by the second call", func() {
   534  						BeforeEach(func() {
   535  							initialInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}}
   536  							eventualInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceRunning}, {State: constant.ProcessInstanceRunning}}
   537  						})
   538  
   539  						It("should not return an error", func() {
   540  							Expect(pollStartErr).NotTo(HaveOccurred())
   541  						})
   542  
   543  						It("should call GetProcessInstances twice", func() {
   544  							Expect(processInstanceCallCount).To(Equal(2))
   545  						})
   546  
   547  						It("should return correct warnings", func() {
   548  							Expect(allWarnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2", "get-process-warning-3"))
   549  						})
   550  					})
   551  
   552  					When("at least one instance has become running by the second call", func() {
   553  						BeforeEach(func() {
   554  							initialInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}}
   555  							eventualInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceRunning}}
   556  						})
   557  
   558  						It("should not return an error", func() {
   559  							Expect(pollStartErr).NotTo(HaveOccurred())
   560  						})
   561  
   562  						It("should call GetProcessInstances twice", func() {
   563  							Expect(processInstanceCallCount).To(Equal(2))
   564  						})
   565  
   566  						It("should return correct warnings", func() {
   567  							Expect(len(allWarnings)).To(Equal(4))
   568  							Expect(allWarnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2", "get-process-warning-3"))
   569  						})
   570  					})
   571  
   572  					When("all of the instances have crashed by the second call", func() {
   573  						BeforeEach(func() {
   574  							initialInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}}
   575  							eventualInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceCrashed}, {State: constant.ProcessInstanceCrashed}, {State: constant.ProcessInstanceCrashed}}
   576  						})
   577  
   578  						It("should not return an error", func() {
   579  							Expect(pollStartErr).NotTo(HaveOccurred())
   580  						})
   581  
   582  						It("should call GetProcessInstances twice", func() {
   583  							Expect(processInstanceCallCount).To(Equal(2))
   584  						})
   585  
   586  						It("should return correct warnings", func() {
   587  							Expect(len(allWarnings)).To(Equal(4))
   588  							Expect(allWarnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2", "get-process-warning-3"))
   589  						})
   590  					})
   591  				})
   592  			})
   593  
   594  			Context("where there are multiple processes", func() {
   595  				var (
   596  					pollStartErr             error
   597  					processInstanceCallCount int
   598  				)
   599  
   600  				BeforeEach(func() {
   601  					processInstanceCallCount = 0
   602  					fakeConfig.StartupTimeoutReturns(time.Millisecond)
   603  					fakeConfig.PollingIntervalReturns(time.Millisecond * 2)
   604  				})
   605  
   606  				JustBeforeEach(func() {
   607  					fakeCloudControllerClient.GetProcessInstancesStub = func(processGuid string) ([]ccv3.ProcessInstance, ccv3.Warnings, error) {
   608  						defer func() { processInstanceCallCount++ }()
   609  						if strings.HasPrefix(processGuid, "good") {
   610  							return []ccv3.ProcessInstance{{State: constant.ProcessInstanceRunning}}, nil, nil
   611  						} else {
   612  							return []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}}, nil, nil
   613  						}
   614  					}
   615  
   616  					pollStartErr = actor.PollStart("some-guid", warningsChannel)
   617  					funcDone <- nil
   618  				})
   619  
   620  				When("none of the processes are ready", func() {
   621  					BeforeEach(func() {
   622  						processes = []ccv3.Process{{GUID: "bad-1"}, {GUID: "bad-2"}}
   623  					})
   624  
   625  					It("returns the timeout error", func() {
   626  						Expect(pollStartErr).To(MatchError(actionerror.StartupTimeoutError{}))
   627  					})
   628  
   629  				})
   630  
   631  				When("some of the processes are ready", func() {
   632  					BeforeEach(func() {
   633  						processes = []ccv3.Process{{GUID: "bad-1"}, {GUID: "good-1"}}
   634  					})
   635  
   636  					It("returns the timeout error", func() {
   637  						Expect(pollStartErr).To(MatchError(actionerror.StartupTimeoutError{}))
   638  					})
   639  				})
   640  
   641  				When("all of the processes are ready", func() {
   642  					BeforeEach(func() {
   643  						processes = []ccv3.Process{{GUID: "good-1"}, {GUID: "good-2"}}
   644  					})
   645  
   646  					It("returns nil", func() {
   647  						Expect(pollStartErr).ToNot(HaveOccurred())
   648  					})
   649  				})
   650  			})
   651  		})
   652  	})
   653  
   654  	Describe("StopApplication", func() {
   655  		var (
   656  			warnings   Warnings
   657  			executeErr error
   658  		)
   659  
   660  		JustBeforeEach(func() {
   661  			warnings, executeErr = actor.StopApplication("some-app-guid")
   662  		})
   663  
   664  		When("there are no client errors", func() {
   665  			BeforeEach(func() {
   666  				fakeCloudControllerClient.UpdateApplicationStopReturns(
   667  					ccv3.Application{GUID: "some-app-guid"},
   668  					ccv3.Warnings{"stop-application-warning"},
   669  					nil,
   670  				)
   671  			})
   672  
   673  			It("stops the application", func() {
   674  				Expect(executeErr).ToNot(HaveOccurred())
   675  				Expect(warnings).To(ConsistOf("stop-application-warning"))
   676  
   677  				Expect(fakeCloudControllerClient.UpdateApplicationStopCallCount()).To(Equal(1))
   678  				Expect(fakeCloudControllerClient.UpdateApplicationStopArgsForCall(0)).To(Equal("some-app-guid"))
   679  			})
   680  		})
   681  
   682  		When("stopping the application fails", func() {
   683  			var expectedErr error
   684  			BeforeEach(func() {
   685  				expectedErr = errors.New("some set stop-application error")
   686  				fakeCloudControllerClient.UpdateApplicationStopReturns(
   687  					ccv3.Application{},
   688  					ccv3.Warnings{"stop-application-warning"},
   689  					expectedErr,
   690  				)
   691  			})
   692  
   693  			It("returns the error", func() {
   694  				Expect(executeErr).To(Equal(expectedErr))
   695  				Expect(warnings).To(ConsistOf("stop-application-warning"))
   696  			})
   697  		})
   698  	})
   699  
   700  	Describe("StartApplication", func() {
   701  		When("there are no client errors", func() {
   702  			BeforeEach(func() {
   703  				fakeCloudControllerClient.UpdateApplicationStartReturns(
   704  					ccv3.Application{GUID: "some-app-guid"},
   705  					ccv3.Warnings{"start-application-warning"},
   706  					nil,
   707  				)
   708  			})
   709  
   710  			It("starts the application", func() {
   711  				app, warnings, err := actor.StartApplication("some-app-guid")
   712  
   713  				Expect(err).ToNot(HaveOccurred())
   714  				Expect(warnings).To(ConsistOf("start-application-warning"))
   715  				Expect(app).To(Equal(Application{GUID: "some-app-guid"}))
   716  
   717  				Expect(fakeCloudControllerClient.UpdateApplicationStartCallCount()).To(Equal(1))
   718  				Expect(fakeCloudControllerClient.UpdateApplicationStartArgsForCall(0)).To(Equal("some-app-guid"))
   719  			})
   720  		})
   721  
   722  		When("starting the application fails", func() {
   723  			var expectedErr error
   724  			BeforeEach(func() {
   725  				expectedErr = errors.New("some set start-application error")
   726  				fakeCloudControllerClient.UpdateApplicationStartReturns(
   727  					ccv3.Application{},
   728  					ccv3.Warnings{"start-application-warning"},
   729  					expectedErr,
   730  				)
   731  			})
   732  
   733  			It("returns the error", func() {
   734  				_, warnings, err := actor.StartApplication("some-app-guid")
   735  
   736  				Expect(err).To(Equal(expectedErr))
   737  				Expect(warnings).To(ConsistOf("start-application-warning"))
   738  			})
   739  		})
   740  	})
   741  
   742  	Describe("RestartApplication", func() {
   743  		var (
   744  			warnings   Warnings
   745  			executeErr error
   746  		)
   747  
   748  		JustBeforeEach(func() {
   749  			warnings, executeErr = actor.RestartApplication("some-app-guid")
   750  		})
   751  
   752  		When("there are no client errors", func() {
   753  			BeforeEach(func() {
   754  				fakeCloudControllerClient.UpdateApplicationRestartReturns(
   755  					ccv3.Application{GUID: "some-app-guid"},
   756  					ccv3.Warnings{"restart-application-warning"},
   757  					nil,
   758  				)
   759  			})
   760  
   761  			It("stops the application", func() {
   762  				Expect(executeErr).ToNot(HaveOccurred())
   763  				Expect(warnings).To(ConsistOf("restart-application-warning"))
   764  
   765  				Expect(fakeCloudControllerClient.UpdateApplicationRestartCallCount()).To(Equal(1))
   766  				Expect(fakeCloudControllerClient.UpdateApplicationRestartArgsForCall(0)).To(Equal("some-app-guid"))
   767  			})
   768  		})
   769  
   770  		When("restarting the application fails", func() {
   771  			var expectedErr error
   772  			BeforeEach(func() {
   773  				expectedErr = errors.New("some set restart-application error")
   774  				fakeCloudControllerClient.UpdateApplicationRestartReturns(
   775  					ccv3.Application{},
   776  					ccv3.Warnings{"restart-application-warning"},
   777  					expectedErr,
   778  				)
   779  			})
   780  
   781  			It("returns the error", func() {
   782  				Expect(executeErr).To(Equal(expectedErr))
   783  				Expect(warnings).To(ConsistOf("restart-application-warning"))
   784  			})
   785  		})
   786  	})
   787  
   788  })