github.com/cloudfoundry-community/cloudfoundry-cli@v6.44.1-0.20240130060226-cda5ed8e89a5+incompatible/actor/v7pushaction/actualize_test.go (about)

     1  package v7pushaction_test
     2  
     3  import (
     4  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"code.cloudfoundry.org/cli/actor/sharedaction"
     9  	"code.cloudfoundry.org/cli/actor/v7action"
    10  	. "code.cloudfoundry.org/cli/actor/v7pushaction"
    11  	"code.cloudfoundry.org/cli/actor/v7pushaction/v7pushactionfakes"
    12  	. "github.com/onsi/ginkgo"
    13  	. "github.com/onsi/gomega"
    14  )
    15  
    16  func actualizedStreamsDrainedAndClosed(
    17  	configStream <-chan PushPlan,
    18  	eventStream <-chan Event,
    19  	warningsStream <-chan Warnings,
    20  	errorStream <-chan error,
    21  ) bool {
    22  	var configStreamClosed, eventStreamClosed, warningsStreamClosed, errorStreamClosed bool
    23  	for {
    24  		select {
    25  		case _, ok := <-configStream:
    26  			if !ok {
    27  				configStreamClosed = true
    28  			}
    29  		case _, ok := <-eventStream:
    30  			if !ok {
    31  				eventStreamClosed = true
    32  			}
    33  		case _, ok := <-warningsStream:
    34  			if !ok {
    35  				warningsStreamClosed = true
    36  			}
    37  		case _, ok := <-errorStream:
    38  			if !ok {
    39  				errorStreamClosed = true
    40  			}
    41  		}
    42  		if configStreamClosed && eventStreamClosed && warningsStreamClosed && errorStreamClosed {
    43  			break
    44  		}
    45  	}
    46  	return true
    47  }
    48  
    49  // TODO: for refactor: We can use the following style of code to validate that
    50  // each event is received in a specific order
    51  
    52  // Expect(nextEvent()).Should(Equal(SettingUpApplication))
    53  // Expect(nextEvent()).Should(Equal(CreatingApplication))
    54  // Expect(nextEvent()).Should(Equal(...))
    55  // Expect(nextEvent()).Should(Equal(...))
    56  // Expect(nextEvent()).Should(Equal(...))
    57  
    58  func buildV3Resource(name string) sharedaction.V3Resource {
    59  	return sharedaction.V3Resource{
    60  		FilePath:    name,
    61  		Checksum:    ccv3.Checksum{Value: fmt.Sprintf("checksum-%s", name)},
    62  		SizeInBytes: 6,
    63  	}
    64  }
    65  
    66  var _ = Describe("Actualize", func() {
    67  	var (
    68  		actor *Actor
    69  
    70  		plan            PushPlan
    71  		fakeProgressBar *v7pushactionfakes.FakeProgressBar
    72  
    73  		successfulChangeAppFuncCallCount int
    74  		warningChangeAppFuncCallCount    int
    75  		errorChangeAppFuncCallCount      int
    76  
    77  		planStream     <-chan PushPlan
    78  		eventStream    <-chan Event
    79  		warningsStream <-chan Warnings
    80  		errorStream    <-chan error
    81  
    82  		expectedPlan PushPlan
    83  	)
    84  
    85  	successfulChangeAppFunc := func(pushPlan PushPlan, eStream chan<- Event, progressBar ProgressBar) (PushPlan, Warnings, error) {
    86  		defer GinkgoRecover()
    87  
    88  		Expect(pushPlan).To(Equal(plan))
    89  		Expect(eStream).ToNot(BeNil())
    90  		Expect(progressBar).To(Equal(fakeProgressBar))
    91  
    92  		pushPlan.Application.GUID = "successful-app-guid"
    93  		successfulChangeAppFuncCallCount++
    94  		return pushPlan, nil, nil
    95  	}
    96  
    97  	warningChangeAppFunc := func(pushPlan PushPlan, eventStream chan<- Event, progressBar ProgressBar) (PushPlan, Warnings, error) {
    98  		pushPlan.Application.GUID = "warning-app-guid"
    99  		warningChangeAppFuncCallCount++
   100  		return pushPlan, Warnings{"warning-1", "warning-2"}, nil
   101  	}
   102  
   103  	errorChangeAppFunc := func(pushPlan PushPlan, eventStream chan<- Event, progressBar ProgressBar) (PushPlan, Warnings, error) {
   104  		pushPlan.Application.GUID = "error-app-guid"
   105  		errorChangeAppFuncCallCount++
   106  		return pushPlan, nil, errors.New("some error")
   107  	}
   108  
   109  	BeforeEach(func() {
   110  		actor, _, _, _ = getTestPushActor()
   111  
   112  		successfulChangeAppFuncCallCount = 0
   113  		warningChangeAppFuncCallCount = 0
   114  		errorChangeAppFuncCallCount = 0
   115  
   116  		fakeProgressBar = new(v7pushactionfakes.FakeProgressBar)
   117  		plan = PushPlan{
   118  			Application: v7action.Application{
   119  				Name: "some-app",
   120  				GUID: "some-app-guid",
   121  			},
   122  			SpaceGUID: "some-space-guid",
   123  		}
   124  
   125  		expectedPlan = plan
   126  	})
   127  
   128  	AfterEach(func() {
   129  		Eventually(actualizedStreamsDrainedAndClosed(planStream, eventStream, warningsStream, errorStream)).Should(BeTrue())
   130  	})
   131  
   132  	JustBeforeEach(func() {
   133  		planStream, eventStream, warningsStream, errorStream = actor.Actualize(plan, fakeProgressBar)
   134  	})
   135  
   136  	Describe("ChangeApplicationFuncs", func() {
   137  		When("none of the ChangeApplicationFuncs return errors", func() {
   138  			BeforeEach(func() {
   139  				actor.ChangeApplicationFuncs = []ChangeApplicationFunc{
   140  					successfulChangeAppFunc,
   141  					warningChangeAppFunc,
   142  				}
   143  				actor.NoStartFuncs = nil
   144  				actor.StartFuncs = nil
   145  			})
   146  
   147  			It("iterates over the actor's ChangeApplicationFuncs", func() {
   148  				Eventually(warningsStream).Should(Receive(BeNil()))
   149  				expectedPlan.Application.GUID = "successful-app-guid"
   150  				Eventually(planStream).Should(Receive(Equal(expectedPlan)))
   151  
   152  				Eventually(warningsStream).Should(Receive(ConsistOf("warning-1", "warning-2")))
   153  				expectedPlan.Application.GUID = "warning-app-guid"
   154  				Eventually(planStream).Should(Receive(Equal(expectedPlan)))
   155  
   156  				Eventually(eventStream).Should(Receive(Equal(Complete)))
   157  
   158  				Expect(successfulChangeAppFuncCallCount).To(Equal(1))
   159  				Expect(warningChangeAppFuncCallCount).To(Equal(1))
   160  				Expect(errorChangeAppFuncCallCount).To(Equal(0))
   161  			})
   162  		})
   163  
   164  		When("the ChangeApplicationFuncs return errors", func() {
   165  			BeforeEach(func() {
   166  				actor.ChangeApplicationFuncs = []ChangeApplicationFunc{
   167  					errorChangeAppFunc,
   168  					successfulChangeAppFunc,
   169  				}
   170  				actor.NoStartFuncs = nil
   171  				actor.StartFuncs = nil
   172  			})
   173  
   174  			It("iterates over the actor's ChangeApplicationFuncs", func() {
   175  				Eventually(warningsStream).Should(Receive(BeNil()))
   176  				Eventually(errorStream).Should(Receive(MatchError("some error")))
   177  
   178  				Expect(successfulChangeAppFuncCallCount).To(Equal(0))
   179  				Expect(warningChangeAppFuncCallCount).To(Equal(0))
   180  				Expect(errorChangeAppFuncCallCount).To(Equal(1))
   181  
   182  				Consistently(eventStream).ShouldNot(Receive(Equal(Complete)))
   183  			})
   184  		})
   185  	})
   186  
   187  	Describe("no-start", func() {
   188  		When("it is true", func() {
   189  			BeforeEach(func() {
   190  				plan.NoStart = true
   191  				expectedPlan.NoStart = true
   192  
   193  				actor.ChangeApplicationFuncs = nil
   194  				actor.NoStartFuncs = []ChangeApplicationFunc{
   195  					successfulChangeAppFunc,
   196  				}
   197  				actor.StartFuncs = []ChangeApplicationFunc{
   198  					errorChangeAppFunc,
   199  				}
   200  			})
   201  
   202  			It("runs the actor's NoStartFuncs", func() {
   203  				Eventually(warningsStream).Should(Receive(BeNil()))
   204  				expectedPlan.Application.GUID = "successful-app-guid"
   205  				Eventually(planStream).Should(Receive(Equal(expectedPlan)))
   206  				Consistently(errorStream).ShouldNot(Receive())
   207  
   208  				Expect(successfulChangeAppFuncCallCount).To(Equal(1))
   209  				Expect(warningChangeAppFuncCallCount).To(Equal(0))
   210  				Expect(errorChangeAppFuncCallCount).To(Equal(0))
   211  
   212  				Eventually(eventStream).Should(Receive(Equal(Complete)))
   213  			})
   214  		})
   215  
   216  		When("it is false", func() {
   217  			BeforeEach(func() {
   218  				actor.ChangeApplicationFuncs = nil
   219  				actor.NoStartFuncs = []ChangeApplicationFunc{
   220  					errorChangeAppFunc,
   221  				}
   222  				actor.StartFuncs = []ChangeApplicationFunc{
   223  					successfulChangeAppFunc,
   224  				}
   225  			})
   226  
   227  			It("runs the actor's StartFuncs", func() {
   228  				Eventually(warningsStream).Should(Receive(BeNil()))
   229  				expectedPlan.Application.GUID = "successful-app-guid"
   230  				Eventually(planStream).Should(Receive(Equal(expectedPlan)))
   231  				Consistently(errorStream).ShouldNot(Receive())
   232  
   233  				Expect(successfulChangeAppFuncCallCount).To(Equal(1))
   234  				Expect(warningChangeAppFuncCallCount).To(Equal(0))
   235  				Expect(errorChangeAppFuncCallCount).To(Equal(0))
   236  
   237  				Eventually(eventStream).Should(Receive(Equal(Complete)))
   238  			})
   239  		})
   240  	})
   241  })