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

     1  package v7action_test
     2  
     3  import (
     4  	"code.cloudfoundry.org/cli/actor/actionerror"
     5  	. "code.cloudfoundry.org/cli/actor/v7action"
     6  	"code.cloudfoundry.org/cli/actor/v7action/v7actionfakes"
     7  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
     8  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
     9  	"code.cloudfoundry.org/cli/resources"
    10  	"code.cloudfoundry.org/cli/types"
    11  	"errors"
    12  	. "github.com/onsi/ginkgo"
    13  	. "github.com/onsi/gomega"
    14  	"io"
    15  	"io/ioutil"
    16  	"os"
    17  	"path/filepath"
    18  	"strings"
    19  )
    20  
    21  var _ = Describe("Buildpack", func() {
    22  	var (
    23  		actor                     *Actor
    24  		fakeCloudControllerClient *v7actionfakes.FakeCloudControllerClient
    25  	)
    26  
    27  	BeforeEach(func() {
    28  		actor, fakeCloudControllerClient, _, _, _ = NewTestActor()
    29  	})
    30  
    31  	Describe("GetBuildpackByNameAndStack", func() {
    32  		var (
    33  			buildpackName  = "buildpack-1"
    34  			buildpackStack = "stack-name"
    35  			buildpack      Buildpack
    36  			warnings       Warnings
    37  			executeErr     error
    38  		)
    39  
    40  		JustBeforeEach(func() {
    41  			buildpack, warnings, executeErr = actor.GetBuildpackByNameAndStack(buildpackName, buildpackStack)
    42  		})
    43  
    44  		When("getting buildpacks fails", func() {
    45  			BeforeEach(func() {
    46  
    47  				buildpackStack = "real-good-stack"
    48  				fakeCloudControllerClient.GetBuildpacksReturns(
    49  					nil,
    50  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
    51  					errors.New("some-error"))
    52  			})
    53  
    54  			It("returns warnings and error", func() {
    55  				Expect(executeErr).To(MatchError("some-error"))
    56  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
    57  				Expect(fakeCloudControllerClient.GetBuildpacksCallCount()).To(Equal(1))
    58  				queries := fakeCloudControllerClient.GetBuildpacksArgsForCall(0)
    59  				Expect(queries).To(ConsistOf(
    60  					ccv3.Query{
    61  						Key:    ccv3.NameFilter,
    62  						Values: []string{buildpackName},
    63  					},
    64  					ccv3.Query{
    65  						Key:    ccv3.StackFilter,
    66  						Values: []string{buildpackStack},
    67  					},
    68  				))
    69  			})
    70  		})
    71  
    72  		When("multiple buildpacks with stacks are returned", func() {
    73  			BeforeEach(func() {
    74  				ccBuildpacks := []resources.Buildpack{
    75  					{Name: buildpackName, Stack: "a-real-stack", Position: types.NullInt{Value: 1, IsSet: true}},
    76  					{Name: buildpackName, Stack: "another-stack", Position: types.NullInt{Value: 2, IsSet: true}},
    77  				}
    78  
    79  				fakeCloudControllerClient.GetBuildpacksReturns(
    80  					ccBuildpacks,
    81  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
    82  					nil)
    83  			})
    84  
    85  			It("returns warnings and MultipleBuildpacksFoundError", func() {
    86  				Expect(executeErr).To(MatchError(actionerror.MultipleBuildpacksFoundError{BuildpackName: buildpackName}))
    87  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
    88  			})
    89  
    90  		})
    91  
    92  		When("multiple buildpacks including one with no stack are returned", func() {
    93  			BeforeEach(func() {
    94  				ccBuildpacks := []resources.Buildpack{
    95  					{GUID: "buildpack-1-guid", Name: "buildpack-1", Stack: "a-real-stack", Position: types.NullInt{Value: 1, IsSet: true}},
    96  					{GUID: "buildpack-2-guid", Name: "buildpack-2", Stack: "", Position: types.NullInt{Value: 2, IsSet: true}},
    97  				}
    98  
    99  				fakeCloudControllerClient.GetBuildpacksReturns(
   100  					ccBuildpacks,
   101  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
   102  					nil)
   103  			})
   104  
   105  			It("returns the nil stack buildpack and any warnings", func() {
   106  				Expect(executeErr).ToNot(HaveOccurred())
   107  				Expect(buildpack).To(Equal(Buildpack{Name: "buildpack-2", GUID: "buildpack-2-guid", Stack: "", Position: types.NullInt{Value: 2, IsSet: true}}))
   108  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   109  			})
   110  		})
   111  
   112  		When("zero buildpacks are returned", func() {
   113  			BeforeEach(func() {
   114  				var ccBuildpacks []resources.Buildpack
   115  
   116  				fakeCloudControllerClient.GetBuildpacksReturns(
   117  					ccBuildpacks,
   118  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
   119  					nil)
   120  			})
   121  
   122  			It("returns warnings and a BuilpackNotFoundError", func() {
   123  				Expect(executeErr).To(MatchError(actionerror.BuildpackNotFoundError{BuildpackName: buildpackName, StackName: buildpackStack}))
   124  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   125  			})
   126  		})
   127  
   128  		When("getting buildpacks is successful", func() {
   129  			When("No stack is specified", func() {
   130  				BeforeEach(func() {
   131  					buildpackStack = ""
   132  					buildpackName = "my-buildpack"
   133  
   134  					ccBuildpack := resources.Buildpack{Name: "my-buildpack", GUID: "some-guid"}
   135  					fakeCloudControllerClient.GetBuildpacksReturns(
   136  						[]resources.Buildpack{ccBuildpack},
   137  						ccv3.Warnings{"some-warning-1", "some-warning-2"},
   138  						nil)
   139  				})
   140  
   141  				It("Returns the proper buildpack", func() {
   142  					Expect(executeErr).ToNot(HaveOccurred())
   143  					Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   144  					Expect(buildpack).To(Equal(Buildpack{Name: "my-buildpack", GUID: "some-guid"}))
   145  				})
   146  
   147  				It("Does not pass a stack query to the client", func() {
   148  					Expect(fakeCloudControllerClient.GetBuildpacksCallCount()).To(Equal(1))
   149  					queries := fakeCloudControllerClient.GetBuildpacksArgsForCall(0)
   150  					Expect(queries).To(ConsistOf(
   151  						ccv3.Query{
   152  							Key:    ccv3.NameFilter,
   153  							Values: []string{buildpackName},
   154  						},
   155  					))
   156  				})
   157  			})
   158  
   159  			When("A stack is specified", func() {
   160  				BeforeEach(func() {
   161  					buildpackStack = "good-stack"
   162  					buildpackName = "my-buildpack"
   163  
   164  					ccBuildpack := resources.Buildpack{Name: "my-buildpack", GUID: "some-guid", Stack: "good-stack"}
   165  					fakeCloudControllerClient.GetBuildpacksReturns(
   166  						[]resources.Buildpack{ccBuildpack},
   167  						ccv3.Warnings{"some-warning-1", "some-warning-2"},
   168  						nil)
   169  				})
   170  
   171  				It("Returns the proper buildpack", func() {
   172  					Expect(executeErr).ToNot(HaveOccurred())
   173  					Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   174  					Expect(buildpack).To(Equal(Buildpack{Name: "my-buildpack", GUID: "some-guid", Stack: "good-stack"}))
   175  				})
   176  
   177  				It("Does pass a stack query to the client", func() {
   178  					Expect(fakeCloudControllerClient.GetBuildpacksCallCount()).To(Equal(1))
   179  					queries := fakeCloudControllerClient.GetBuildpacksArgsForCall(0)
   180  					Expect(queries).To(ConsistOf(
   181  						ccv3.Query{
   182  							Key:    ccv3.NameFilter,
   183  							Values: []string{buildpackName},
   184  						},
   185  						ccv3.Query{
   186  							Key:    ccv3.StackFilter,
   187  							Values: []string{buildpackStack},
   188  						},
   189  					))
   190  				})
   191  			})
   192  		})
   193  	})
   194  
   195  	Describe("GetBuildpacks", func() {
   196  		var (
   197  			buildpacks []Buildpack
   198  			warnings   Warnings
   199  			executeErr error
   200  		)
   201  
   202  		JustBeforeEach(func() {
   203  			buildpacks, warnings, executeErr = actor.GetBuildpacks()
   204  		})
   205  
   206  		When("getting buildpacks fails", func() {
   207  			BeforeEach(func() {
   208  				fakeCloudControllerClient.GetBuildpacksReturns(
   209  					nil,
   210  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
   211  					errors.New("some-error"))
   212  			})
   213  
   214  			It("returns warnings and error", func() {
   215  				Expect(executeErr).To(MatchError("some-error"))
   216  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   217  			})
   218  		})
   219  
   220  		When("getting buildpacks is successful", func() {
   221  			BeforeEach(func() {
   222  				ccBuildpacks := []resources.Buildpack{
   223  					{Name: "buildpack-1", Position: types.NullInt{Value: 1, IsSet: true}},
   224  					{Name: "buildpack-2", Position: types.NullInt{Value: 2, IsSet: true}},
   225  				}
   226  
   227  				fakeCloudControllerClient.GetBuildpacksReturns(
   228  					ccBuildpacks,
   229  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
   230  					nil)
   231  			})
   232  
   233  			It("returns the buildpacks and warnings", func() {
   234  				Expect(executeErr).ToNot(HaveOccurred())
   235  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   236  				Expect(buildpacks).To(Equal([]Buildpack{
   237  					{Name: "buildpack-1", Position: types.NullInt{Value: 1, IsSet: true}},
   238  					{Name: "buildpack-2", Position: types.NullInt{Value: 2, IsSet: true}},
   239  				}))
   240  
   241  				Expect(fakeCloudControllerClient.GetBuildpacksCallCount()).To(Equal(1))
   242  				Expect(fakeCloudControllerClient.GetBuildpacksArgsForCall(0)).To(ConsistOf(ccv3.Query{
   243  					Key:    ccv3.OrderBy,
   244  					Values: []string{ccv3.PositionOrder},
   245  				}))
   246  			})
   247  		})
   248  	})
   249  
   250  	Describe("CreateBuildpack", func() {
   251  		var (
   252  			buildpack  Buildpack
   253  			warnings   Warnings
   254  			executeErr error
   255  			bp         Buildpack
   256  		)
   257  
   258  		JustBeforeEach(func() {
   259  			buildpack, warnings, executeErr = actor.CreateBuildpack(bp)
   260  		})
   261  
   262  		When("creating a buildpack fails", func() {
   263  			BeforeEach(func() {
   264  				fakeCloudControllerClient.CreateBuildpackReturns(
   265  					resources.Buildpack{},
   266  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
   267  					errors.New("some-error"))
   268  			})
   269  
   270  			It("returns warnings and error", func() {
   271  				Expect(executeErr).To(MatchError("some-error"))
   272  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   273  				Expect(buildpack).To(Equal(Buildpack{}))
   274  			})
   275  		})
   276  
   277  		When("creating a buildpack is successful", func() {
   278  			var returnBuildpack Buildpack
   279  			BeforeEach(func() {
   280  				bp = Buildpack{Name: "some-name", Stack: "some-stack"}
   281  				returnBuildpack = Buildpack{GUID: "some-guid", Name: "some-name", Stack: "some-stack"}
   282  				fakeCloudControllerClient.CreateBuildpackReturns(
   283  					resources.Buildpack(returnBuildpack),
   284  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
   285  					nil)
   286  			})
   287  
   288  			It("returns the buildpacks and warnings", func() {
   289  				Expect(executeErr).ToNot(HaveOccurred())
   290  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   291  				Expect(buildpack).To(Equal(returnBuildpack))
   292  
   293  				Expect(fakeCloudControllerClient.CreateBuildpackCallCount()).To(Equal(1))
   294  				Expect(fakeCloudControllerClient.CreateBuildpackArgsForCall(0)).To(Equal(resources.Buildpack(bp)))
   295  			})
   296  		})
   297  	})
   298  
   299  	Describe("UpdateBuildpackByNameAndStack", func() {
   300  		var (
   301  			buildpackName  = "my-buidpack"
   302  			buildpackStack = "my-stack"
   303  			buildpack      = Buildpack{
   304  				Stack: "new-stack",
   305  			}
   306  
   307  			retBuildpack Buildpack
   308  			warnings     Warnings
   309  			executeErr   error
   310  		)
   311  
   312  		JustBeforeEach(func() {
   313  			retBuildpack, warnings, executeErr = actor.UpdateBuildpackByNameAndStack(buildpackName, buildpackStack, buildpack)
   314  		})
   315  
   316  		When("it is successful", func() {
   317  			var updatedBuildpack Buildpack
   318  			BeforeEach(func() {
   319  				foundBuildpack := resources.Buildpack{GUID: "a guid", Stack: ""}
   320  				updatedBuildpack = Buildpack{GUID: "a guid", Stack: "new-stack"}
   321  				fakeCloudControllerClient.GetBuildpacksReturns([]resources.Buildpack{foundBuildpack}, ccv3.Warnings{"warning-1"}, nil)
   322  				fakeCloudControllerClient.UpdateBuildpackReturns(resources.Buildpack(updatedBuildpack), ccv3.Warnings{"warning-2"}, nil)
   323  			})
   324  
   325  			It("returns the updated buildpack and warnings", func() {
   326  				Expect(executeErr).ToNot(HaveOccurred())
   327  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   328  				Expect(retBuildpack).To(Equal(updatedBuildpack))
   329  
   330  				queries := fakeCloudControllerClient.GetBuildpacksArgsForCall(0)
   331  				Expect(queries).To(ConsistOf(
   332  					ccv3.Query{
   333  						Key:    ccv3.NameFilter,
   334  						Values: []string{buildpackName},
   335  					},
   336  					ccv3.Query{
   337  						Key:    ccv3.StackFilter,
   338  						Values: []string{buildpackStack},
   339  					},
   340  				))
   341  
   342  				paramBuildpack := fakeCloudControllerClient.UpdateBuildpackArgsForCall(0)
   343  				Expect(paramBuildpack).To(Equal(resources.Buildpack{
   344  					GUID:  "a guid",
   345  					Stack: "new-stack",
   346  				}))
   347  			})
   348  		})
   349  
   350  		When("The get fails", func() {
   351  			BeforeEach(func() {
   352  				fakeCloudControllerClient.GetBuildpacksReturns([]resources.Buildpack{}, ccv3.Warnings{"warning-1"}, errors.New("whoops"))
   353  			})
   354  
   355  			It("returns the error and warnings", func() {
   356  				Expect(executeErr).To(HaveOccurred())
   357  				Expect(warnings).To(ConsistOf("warning-1"))
   358  				Expect(retBuildpack).To(Equal(Buildpack{}))
   359  			})
   360  		})
   361  
   362  		When("The update fails", func() {
   363  			BeforeEach(func() {
   364  				ccBuildpack := resources.Buildpack{GUID: "a guid", Stack: "old-stack"}
   365  				fakeCloudControllerClient.GetBuildpacksReturns([]resources.Buildpack{ccBuildpack}, ccv3.Warnings{"warning-1"}, nil)
   366  				fakeCloudControllerClient.UpdateBuildpackReturns(resources.Buildpack{}, ccv3.Warnings{"warning-2"}, errors.New("whoops"))
   367  			})
   368  
   369  			It("returns the error and warnings", func() {
   370  				Expect(executeErr).To(HaveOccurred())
   371  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   372  				Expect(retBuildpack).To(Equal(Buildpack{}))
   373  			})
   374  		})
   375  
   376  	})
   377  
   378  	Describe("UploadBuildpack", func() {
   379  		var (
   380  			bpFile     io.Reader
   381  			bpFilePath string
   382  			fakePb     *v7actionfakes.FakeSimpleProgressBar
   383  
   384  			jobURL     ccv3.JobURL
   385  			warnings   Warnings
   386  			executeErr error
   387  		)
   388  
   389  		BeforeEach(func() {
   390  			bpFile = strings.NewReader("")
   391  			fakePb = new(v7actionfakes.FakeSimpleProgressBar)
   392  			fakePb.InitializeReturns(bpFile, 66, nil)
   393  		})
   394  
   395  		JustBeforeEach(func() {
   396  			bpFilePath = "tmp/buildpack.zip"
   397  			jobURL, warnings, executeErr = actor.UploadBuildpack("some-bp-guid", bpFilePath, fakePb)
   398  		})
   399  
   400  		It("tracks the progress of the upload", func() {
   401  			Expect(executeErr).ToNot(HaveOccurred())
   402  			Expect(fakePb.InitializeCallCount()).To(Equal(1))
   403  			Expect(fakePb.InitializeArgsForCall(0)).To(Equal(bpFilePath))
   404  			Expect(fakePb.TerminateCallCount()).To(Equal(1))
   405  		})
   406  
   407  		When("reading the file errors", func() {
   408  			BeforeEach(func() {
   409  				fakePb.InitializeReturns(bpFile, 66, os.ErrNotExist)
   410  			})
   411  
   412  			It("returns the err", func() {
   413  				Expect(executeErr).To(Equal(os.ErrNotExist))
   414  			})
   415  		})
   416  
   417  		When("the upload errors", func() {
   418  			BeforeEach(func() {
   419  				fakeCloudControllerClient.UploadBuildpackReturns(
   420  					ccv3.JobURL(""),
   421  					ccv3.Warnings{"some-upload-warning"},
   422  					errors.New("some-upload-error"),
   423  				)
   424  			})
   425  
   426  			It("returns warnings and errors", func() {
   427  				Expect(warnings).To(ConsistOf("some-upload-warning"))
   428  				Expect(executeErr).To(MatchError("some-upload-error"))
   429  			})
   430  		})
   431  
   432  		When("the cc returns an error because the buildpack and stack combo already exists", func() {
   433  			BeforeEach(func() {
   434  				fakeCloudControllerClient.UploadBuildpackReturns(
   435  					ccv3.JobURL(""),
   436  					ccv3.Warnings{"some-upload-warning"},
   437  					ccerror.BuildpackAlreadyExistsForStackError{Message: "ya blew it"},
   438  				)
   439  			})
   440  
   441  			It("returns warnings and a BuildpackAlreadyExistsForStackError", func() {
   442  				Expect(warnings).To(ConsistOf("some-upload-warning"))
   443  				Expect(executeErr).To(MatchError(actionerror.BuildpackAlreadyExistsForStackError{Message: "ya blew it"}))
   444  			})
   445  		})
   446  
   447  		When("the upload is successful", func() {
   448  			BeforeEach(func() {
   449  				fakeCloudControllerClient.UploadBuildpackReturns(
   450  					ccv3.JobURL("http://example.com/some-job-url"),
   451  					ccv3.Warnings{"some-create-warning"},
   452  					nil,
   453  				)
   454  			})
   455  
   456  			It("uploads the buildpack and returns the Job URL and any warnings", func() {
   457  				Expect(executeErr).ToNot(HaveOccurred())
   458  				Expect(fakeCloudControllerClient.UploadBuildpackCallCount()).To(Equal(1))
   459  				guid, path, pbReader, size := fakeCloudControllerClient.UploadBuildpackArgsForCall(0)
   460  				Expect(guid).To(Equal("some-bp-guid"))
   461  				Expect(size).To(Equal(int64(66)))
   462  				Expect(path).To(Equal(bpFilePath))
   463  				Expect(pbReader).To(Equal(bpFile))
   464  				Expect(jobURL).To(Equal(ccv3.JobURL("http://example.com/some-job-url")))
   465  				Expect(warnings).To(ConsistOf("some-create-warning"))
   466  			})
   467  		})
   468  	})
   469  
   470  	Describe("PrepareBuildpackBits", func() {
   471  		var (
   472  			inPath         string
   473  			outPath        string
   474  			tmpDirPath     string
   475  			fakeDownloader *v7actionfakes.FakeDownloader
   476  
   477  			executeErr error
   478  		)
   479  
   480  		BeforeEach(func() {
   481  			fakeDownloader = new(v7actionfakes.FakeDownloader)
   482  		})
   483  
   484  		JustBeforeEach(func() {
   485  			outPath, executeErr = actor.PrepareBuildpackBits(inPath, tmpDirPath, fakeDownloader)
   486  		})
   487  
   488  		When("the buildpack path is a url", func() {
   489  			BeforeEach(func() {
   490  				inPath = "http://buildpacks.com/a.zip"
   491  				fakeDownloader = new(v7actionfakes.FakeDownloader)
   492  
   493  				var err error
   494  				tmpDirPath, err = ioutil.TempDir("", "buildpackdir-")
   495  				Expect(err).ToNot(HaveOccurred())
   496  			})
   497  
   498  			AfterEach(func() {
   499  				Expect(os.RemoveAll(tmpDirPath)).ToNot(HaveOccurred())
   500  			})
   501  
   502  			When("downloading the file succeeds", func() {
   503  				BeforeEach(func() {
   504  					fakeDownloader.DownloadReturns("/tmp/buildpackdir-100/a.zip", nil)
   505  				})
   506  
   507  				It("downloads the buildpack to a local file", func() {
   508  					Expect(executeErr).ToNot(HaveOccurred())
   509  					Expect(fakeDownloader.DownloadCallCount()).To(Equal(1))
   510  
   511  					inputPath, inputTmpDirPath := fakeDownloader.DownloadArgsForCall(0)
   512  					Expect(inputPath).To(Equal("http://buildpacks.com/a.zip"))
   513  					Expect(inputTmpDirPath).To(Equal(tmpDirPath))
   514  				})
   515  			})
   516  
   517  			When("downloading the file fails", func() {
   518  				BeforeEach(func() {
   519  					fakeDownloader.DownloadReturns("", errors.New("some-download-error"))
   520  				})
   521  
   522  				It("returns the error", func() {
   523  					Expect(executeErr).To(MatchError("some-download-error"))
   524  				})
   525  			})
   526  		})
   527  
   528  		When("the buildpack path points to a directory", func() {
   529  			var tempFile *os.File
   530  			BeforeEach(func() {
   531  				var err error
   532  				inPath, err = ioutil.TempDir("", "buildpackdir-")
   533  				Expect(err).ToNot(HaveOccurred())
   534  
   535  				tempFile, err = ioutil.TempFile(inPath, "foo")
   536  				Expect(err).ToNot(HaveOccurred())
   537  
   538  				tmpDirPath, err = ioutil.TempDir("", "buildpackdir-")
   539  				Expect(err).ToNot(HaveOccurred())
   540  			})
   541  
   542  			AfterEach(func() {
   543  				tempFile.Close()
   544  				Expect(os.RemoveAll(inPath)).ToNot(HaveOccurred())
   545  				Expect(os.RemoveAll(tmpDirPath)).ToNot(HaveOccurred())
   546  			})
   547  
   548  			It("returns a path to the zipped directory", func() {
   549  				Expect(executeErr).ToNot(HaveOccurred())
   550  				Expect(fakeDownloader.DownloadCallCount()).To(Equal(0))
   551  
   552  				Expect(filepath.Base(outPath)).To(Equal(filepath.Base(inPath) + ".zip"))
   553  			})
   554  		})
   555  
   556  		When("the buildpack path points to an empty directory", func() {
   557  			BeforeEach(func() {
   558  				var err error
   559  				inPath, err = ioutil.TempDir("", "some-empty-dir")
   560  				Expect(err).ToNot(HaveOccurred())
   561  
   562  				tmpDirPath, err = ioutil.TempDir("", "buildpackdir-")
   563  				Expect(err).ToNot(HaveOccurred())
   564  			})
   565  
   566  			AfterEach(func() {
   567  				Expect(os.RemoveAll(inPath)).ToNot(HaveOccurred())
   568  				Expect(os.RemoveAll(tmpDirPath)).ToNot(HaveOccurred())
   569  			})
   570  
   571  			It("returns an error", func() {
   572  				Expect(executeErr).To(MatchError(actionerror.EmptyBuildpackDirectoryError{Path: inPath}))
   573  			})
   574  		})
   575  
   576  		When("the buildpack path points to a zip file", func() {
   577  			BeforeEach(func() {
   578  				inPath = "/foo/buildpacks/a.zip"
   579  			})
   580  
   581  			It("returns the local filepath", func() {
   582  				Expect(executeErr).ToNot(HaveOccurred())
   583  				Expect(fakeDownloader.DownloadCallCount()).To(Equal(0))
   584  				Expect(outPath).To(Equal("/foo/buildpacks/a.zip"))
   585  			})
   586  		})
   587  	})
   588  
   589  	Describe("Zipit", func() {
   590  		//tested in buildpack_linux_test.go and buildpack_windows_test.go
   591  		var (
   592  			source string
   593  			target string
   594  
   595  			executeErr error
   596  		)
   597  
   598  		JustBeforeEach(func() {
   599  			executeErr = Zipit(source, target, "testzip-")
   600  		})
   601  
   602  		When("the source directory does not exist", func() {
   603  			BeforeEach(func() {
   604  				source = ""
   605  				target = ""
   606  			})
   607  
   608  			It("returns an error", func() {
   609  				Expect(os.IsNotExist(executeErr)).To(BeTrue())
   610  			})
   611  		})
   612  	})
   613  
   614  	Describe("DeleteBuildpackByNameAndStack", func() {
   615  		var (
   616  			buildpackName  = "buildpack-name"
   617  			buildpackStack = "buildpack-stack"
   618  			buildpackGUID  = "buildpack-guid"
   619  			jobURL         = "buildpack-delete-job-url"
   620  			warnings       Warnings
   621  			executeErr     error
   622  		)
   623  
   624  		JustBeforeEach(func() {
   625  			warnings, executeErr = actor.DeleteBuildpackByNameAndStack(buildpackName, buildpackStack)
   626  		})
   627  
   628  		When("getting the buildpack fails", func() {
   629  			BeforeEach(func() {
   630  				fakeCloudControllerClient.GetBuildpacksReturns(
   631  					[]resources.Buildpack{},
   632  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
   633  					errors.New("api-get-error"))
   634  			})
   635  			It("returns warnings and error", func() {
   636  				Expect(executeErr).To(MatchError("api-get-error"))
   637  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   638  				Expect(fakeCloudControllerClient.GetBuildpacksCallCount()).To(Equal(1))
   639  				queries := fakeCloudControllerClient.GetBuildpacksArgsForCall(0)
   640  				Expect(queries).To(ConsistOf(
   641  					ccv3.Query{
   642  						Key:    ccv3.NameFilter,
   643  						Values: []string{buildpackName},
   644  					},
   645  					ccv3.Query{
   646  						Key:    ccv3.StackFilter,
   647  						Values: []string{buildpackStack},
   648  					},
   649  				))
   650  			})
   651  		})
   652  
   653  		When("getting the buildpack succeeds", func() {
   654  			BeforeEach(func() {
   655  				fakeCloudControllerClient.GetBuildpacksReturns(
   656  					[]resources.Buildpack{{GUID: buildpackGUID, Name: buildpackName, Stack: buildpackStack}},
   657  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
   658  					nil)
   659  			})
   660  			When("deleting a buildpack fails", func() {
   661  				BeforeEach(func() {
   662  					fakeCloudControllerClient.DeleteBuildpackReturns(
   663  						"",
   664  						ccv3.Warnings{"some-warning-3", "some-warning-4"},
   665  						errors.New("api-delete-error"))
   666  				})
   667  
   668  				It("returns warnings and error", func() {
   669  					Expect(executeErr).To(MatchError("api-delete-error"))
   670  					Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2", "some-warning-3", "some-warning-4"))
   671  					Expect(fakeCloudControllerClient.DeleteBuildpackCallCount()).To(Equal(1))
   672  					paramGUID := fakeCloudControllerClient.DeleteBuildpackArgsForCall(0)
   673  					Expect(paramGUID).To(Equal(buildpackGUID))
   674  				})
   675  			})
   676  
   677  			When("deleting the buildpack is successful", func() {
   678  				BeforeEach(func() {
   679  					fakeCloudControllerClient.DeleteBuildpackReturns(
   680  						ccv3.JobURL(jobURL),
   681  						ccv3.Warnings{"some-warning-3", "some-warning-4"},
   682  						nil)
   683  				})
   684  
   685  				When("polling the job fails", func() {
   686  					BeforeEach(func() {
   687  						fakeCloudControllerClient.PollJobReturns(
   688  							ccv3.Warnings{"some-warning-5", "some-warning-6"},
   689  							errors.New("api-poll-job-error"))
   690  					})
   691  					It("returns warnings and an error", func() {
   692  						Expect(executeErr).To(MatchError("api-poll-job-error"))
   693  						Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2", "some-warning-3", "some-warning-4", "some-warning-5", "some-warning-6"))
   694  						Expect(fakeCloudControllerClient.PollJobCallCount()).To(Equal(1))
   695  						paramURL := fakeCloudControllerClient.PollJobArgsForCall(0)
   696  						Expect(paramURL).To(Equal(ccv3.JobURL(jobURL)))
   697  					})
   698  				})
   699  
   700  				When("polling the job succeeds", func() {
   701  					BeforeEach(func() {
   702  						fakeCloudControllerClient.PollJobReturns(
   703  							ccv3.Warnings{"some-warning-5", "some-warning-6"},
   704  							nil)
   705  					})
   706  					It("returns all warnings and no error", func() {
   707  						Expect(executeErr).ToNot(HaveOccurred())
   708  						Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2", "some-warning-3", "some-warning-4", "some-warning-5", "some-warning-6"))
   709  						Expect(fakeCloudControllerClient.PollJobCallCount()).To(Equal(1))
   710  						paramURL := fakeCloudControllerClient.PollJobArgsForCall(0)
   711  						Expect(paramURL).To(Equal(ccv3.JobURL(jobURL)))
   712  
   713  					})
   714  				})
   715  			})
   716  		})
   717  
   718  	})
   719  })