github.com/BarDweller/libpak@v0.0.0-20230630201634-8dd5cfc15ec9/carton/buildmodule_dependency_test.go (about)

     1  /*
     2   * Copyright 2018-2020 the original author or authors.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *      https://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package carton_test
    18  
    19  import (
    20  	"os"
    21  	"testing"
    22  
    23  	"github.com/buildpacks/libcnb/mocks"
    24  	. "github.com/onsi/gomega"
    25  	"github.com/sclevine/spec"
    26  	"github.com/stretchr/testify/mock"
    27  
    28  	"github.com/BarDweller/libpak/carton"
    29  	"github.com/BarDweller/libpak/internal"
    30  )
    31  
    32  func testBuildpackDependency(t *testing.T, context spec.G, it spec.S) {
    33  	var (
    34  		Expect = NewWithT(t).Expect
    35  
    36  		exitHandler *mocks.ExitHandler
    37  		path        string
    38  	)
    39  
    40  	it.Before(func() {
    41  		var err error
    42  
    43  		exitHandler = &mocks.ExitHandler{}
    44  		exitHandler.On("Error", mock.Anything)
    45  
    46  		f, err := os.CreateTemp("", "carton-buildpack-dependency")
    47  		Expect(err).NotTo(HaveOccurred())
    48  		Expect(f.Close()).To(Succeed())
    49  		path = f.Name()
    50  	})
    51  
    52  	it.After(func() {
    53  		Expect(os.RemoveAll(path)).To(Succeed())
    54  	})
    55  
    56  	it("updates dependency", func() {
    57  		Expect(os.WriteFile(path, []byte(`api = "0.6"
    58  [buildpack]
    59  id = "some-buildpack"
    60  name = "Some Buildpack"
    61  version = "1.2.3"
    62  
    63  [[metadata.dependencies]]
    64  id      = "test-id"
    65  name    = "Test Name"
    66  version = "test-version-1"
    67  uri     = "test-uri-1"
    68  sha256  = "test-sha256-1"
    69  stacks  = [ "test-stack" ]
    70  `), 0644)).To(Succeed())
    71  
    72  		d := carton.BuildModuleDependency{
    73  			BuildModulePath: path,
    74  			ID:              "test-id",
    75  			SHA256:          "test-sha256-2",
    76  			URI:             "test-uri-2",
    77  			Version:         "test-version-2",
    78  			VersionPattern:  `test-version-[\d]`,
    79  		}
    80  
    81  		d.Update(carton.WithExitHandler(exitHandler))
    82  
    83  		Expect(os.ReadFile(path)).To(internal.MatchTOML(`api = "0.6"
    84  [buildpack]
    85  id = "some-buildpack"
    86  name = "Some Buildpack"
    87  version = "1.2.3"
    88  
    89  [[metadata.dependencies]]
    90  id      = "test-id"
    91  name    = "Test Name"
    92  version = "test-version-2"
    93  uri     = "test-uri-2"
    94  sha256  = "test-sha256-2"
    95  stacks  = [ "test-stack" ]
    96  `))
    97  	})
    98  
    99  	it("updates dependency with purl & cpes", func() {
   100  		Expect(os.WriteFile(path, []byte(`api = "0.7"
   101  [buildpack]
   102  id = "some-buildpack"
   103  name = "Some Buildpack"
   104  version = "1.2.3"
   105  
   106  [[metadata.dependencies]]
   107  id      = "test-id"
   108  name    = "Test Name"
   109  version = "test-version-1"
   110  uri     = "test-uri-1"
   111  sha256  = "test-sha256-1"
   112  stacks  = [ "test-stack" ]
   113  purl    = "pkg:generic/test-jre@different-version-1?arch=amd64"
   114  cpes    = ["cpe:2.3:a:test-vendor:test-product:test-version-1:patch1:*:*:*:*:*:*:*"]
   115  `), 0644)).To(Succeed())
   116  
   117  		d := carton.BuildModuleDependency{
   118  			BuildModulePath: path,
   119  			ID:              "test-id",
   120  			SHA256:          "test-sha256-2",
   121  			URI:             "test-uri-2",
   122  			Version:         "test-version-2",
   123  			VersionPattern:  `test-version-[\d]`,
   124  			PURL:            "different-version-2",
   125  			PURLPattern:     `different-version-[\d]`,
   126  			CPE:             "test-version-2:patch2",
   127  			CPEPattern:      `test-version-[\d]:patch[\d]`,
   128  		}
   129  
   130  		d.Update(carton.WithExitHandler(exitHandler))
   131  
   132  		Expect(os.ReadFile(path)).To(internal.MatchTOML(`api = "0.7"
   133  [buildpack]
   134  id = "some-buildpack"
   135  name = "Some Buildpack"
   136  version = "1.2.3"
   137  
   138  [[metadata.dependencies]]
   139  id      = "test-id"
   140  name    = "Test Name"
   141  version = "test-version-2"
   142  uri     = "test-uri-2"
   143  sha256  = "test-sha256-2"
   144  stacks  = [ "test-stack" ]
   145  purl    = "pkg:generic/test-jre@different-version-2?arch=amd64"
   146  cpes    = ["cpe:2.3:a:test-vendor:test-product:test-version-2:patch2:*:*:*:*:*:*:*"]
   147  `))
   148  	})
   149  
   150  	it("updates multiple dependencies with different versions", func() {
   151  		Expect(os.WriteFile(path, []byte(`api = "0.7"
   152  [buildpack]
   153  id = "some-buildpack"
   154  name = "Some Buildpack"
   155  version = "1.2.3"
   156  
   157  [[metadata.dependencies]]
   158  id      = "test-id"
   159  name    = "Test Name"
   160  version = "test-version-1"
   161  uri     = "test-uri-1"
   162  sha256  = "test-sha256-1"
   163  stacks  = [ "test-stack" ]
   164  purl    = "pkg:generic/test-jre@different-version-1?arch=amd64"
   165  cpes    = ["cpe:2.3:a:test-vendor:test-product:test-version-1:patch1:*:*:*:*:*:*:*"]
   166  
   167  [[metadata.dependencies]]
   168  id      = "test-id"
   169  name    = "Test Name"
   170  version = "test-version-2"
   171  uri     = "test-uri-2"
   172  sha256  = "test-sha256-2"
   173  stacks  = [ "test-stack" ]
   174  purl    = "pkg:generic/test-jre@different-version-2?arch=amd64"
   175  cpes    = ["cpe:2.3:a:test-vendor:test-product:test-version-2:patch2:*:*:*:*:*:*:*"]
   176  `), 0644)).To(Succeed())
   177  
   178  		d := carton.BuildModuleDependency{
   179  			BuildModulePath: path,
   180  			ID:              "test-id",
   181  			SHA256:          "test-sha256-3",
   182  			URI:             "test-uri-3",
   183  			Version:         "test-version-3",
   184  			VersionPattern:  `test-version-1`,
   185  			PURL:            "different-version-3",
   186  			PURLPattern:     `different-version-[\d]`,
   187  			CPE:             "test-version-3:patch3",
   188  			CPEPattern:      `test-version-[\d]:patch[\d]`,
   189  		}
   190  
   191  		d.Update(carton.WithExitHandler(exitHandler))
   192  
   193  		Expect(os.ReadFile(path)).To(internal.MatchTOML(`api = "0.7"
   194  [buildpack]
   195  id = "some-buildpack"
   196  name = "Some Buildpack"
   197  version = "1.2.3"
   198  
   199  [[metadata.dependencies]]
   200  id      = "test-id"
   201  name    = "Test Name"
   202  version = "test-version-3"
   203  uri     = "test-uri-3"
   204  sha256  = "test-sha256-3"
   205  stacks  = [ "test-stack" ]
   206  purl    = "pkg:generic/test-jre@different-version-3?arch=amd64"
   207  cpes    = ["cpe:2.3:a:test-vendor:test-product:test-version-3:patch3:*:*:*:*:*:*:*"]
   208  
   209  [[metadata.dependencies]]
   210  id      = "test-id"
   211  name    = "Test Name"
   212  version = "test-version-2"
   213  uri     = "test-uri-2"
   214  sha256  = "test-sha256-2"
   215  stacks  = [ "test-stack" ]
   216  purl    = "pkg:generic/test-jre@different-version-2?arch=amd64"
   217  cpes    = ["cpe:2.3:a:test-vendor:test-product:test-version-2:patch2:*:*:*:*:*:*:*"]
   218  `))
   219  	})
   220  
   221  	it("updates dependency with missing purl, still updates cpe", func() {
   222  		Expect(os.WriteFile(path, []byte(`api = "0.7"
   223  [buildpack]
   224  id = "some-buildpack"
   225  name = "Some Buildpack"
   226  version = "1.2.3"
   227  
   228  [[metadata.dependencies]]
   229  id      = "test-id"
   230  name    = "Test Name"
   231  version = "test-version-1"
   232  uri     = "test-uri-1"
   233  sha256  = "test-sha256-1"
   234  stacks  = [ "test-stack" ]
   235  cpes    = ["cpe:2.3:a:test-vendor:test-product:test-version-1:patch1:*:*:*:*:*:*:*"]
   236  `), 0644)).To(Succeed())
   237  
   238  		d := carton.BuildModuleDependency{
   239  			BuildModulePath: path,
   240  			ID:              "test-id",
   241  			SHA256:          "test-sha256-2",
   242  			URI:             "test-uri-2",
   243  			Version:         "test-version-2",
   244  			VersionPattern:  `test-version-[\d]`,
   245  			PURL:            "different-version-2",
   246  			PURLPattern:     `different-version-[\d]`,
   247  			CPE:             "test-version-2:patch2",
   248  			CPEPattern:      `test-version-[\d]:patch[\d]`,
   249  		}
   250  
   251  		d.Update(carton.WithExitHandler(exitHandler))
   252  
   253  		Expect(os.ReadFile(path)).To(internal.MatchTOML(`api = "0.7"
   254  [buildpack]
   255  id = "some-buildpack"
   256  name = "Some Buildpack"
   257  version = "1.2.3"
   258  
   259  [[metadata.dependencies]]
   260  id      = "test-id"
   261  name    = "Test Name"
   262  version = "test-version-2"
   263  uri     = "test-uri-2"
   264  sha256  = "test-sha256-2"
   265  stacks  = [ "test-stack" ]
   266  cpes    = ["cpe:2.3:a:test-vendor:test-product:test-version-2:patch2:*:*:*:*:*:*:*"]
   267  `))
   268  	})
   269  
   270  	it("updates dependency with invalid purl, still updates cpe", func() {
   271  		Expect(os.WriteFile(path, []byte(`api = "0.7"
   272  [buildpack]
   273  id = "some-buildpack"
   274  name = "Some Buildpack"
   275  version = "1.2.3"
   276  
   277  [[metadata.dependencies]]
   278  id      = "test-id"
   279  name    = "Test Name"
   280  version = "test-version-1"
   281  uri     = "test-uri-1"
   282  sha256  = "test-sha256-1"
   283  stacks  = [ "test-stack" ]
   284  purl    = 1234
   285  cpes    = ["cpe:2.3:a:test-vendor:test-product:test-version-1:patch1:*:*:*:*:*:*:*"]
   286  `), 0644)).To(Succeed())
   287  
   288  		d := carton.BuildModuleDependency{
   289  			BuildModulePath: path,
   290  			ID:              "test-id",
   291  			SHA256:          "test-sha256-2",
   292  			URI:             "test-uri-2",
   293  			Version:         "test-version-2",
   294  			VersionPattern:  `test-version-[\d]`,
   295  			PURL:            "different-version-2",
   296  			PURLPattern:     `different-version-[\d]`,
   297  			CPE:             "test-version-2:patch2",
   298  			CPEPattern:      `test-version-[\d]:patch[\d]`,
   299  		}
   300  
   301  		d.Update(carton.WithExitHandler(exitHandler))
   302  
   303  		Expect(os.ReadFile(path)).To(internal.MatchTOML(`api = "0.7"
   304  [buildpack]
   305  id = "some-buildpack"
   306  name = "Some Buildpack"
   307  version = "1.2.3"
   308  
   309  [[metadata.dependencies]]
   310  id      = "test-id"
   311  name    = "Test Name"
   312  version = "test-version-2"
   313  uri     = "test-uri-2"
   314  sha256  = "test-sha256-2"
   315  stacks  = [ "test-stack" ]
   316  purl    = 1234
   317  cpes    = ["cpe:2.3:a:test-vendor:test-product:test-version-2:patch2:*:*:*:*:*:*:*"]
   318  `))
   319  	})
   320  
   321  	it("updates dependency with invalid cpe, still updates purl", func() {
   322  		Expect(os.WriteFile(path, []byte(`api = "0.7"
   323  [buildpack]
   324  id = "some-buildpack"
   325  name = "Some Buildpack"
   326  version = "1.2.3"
   327  
   328  [[metadata.dependencies]]
   329  id      = "test-id"
   330  name    = "Test Name"
   331  version = "test-version-1"
   332  uri     = "test-uri-1"
   333  sha256  = "test-sha256-1"
   334  stacks  = [ "test-stack" ]
   335  purl    = "pkg:generic/test-jre@different-version-1?arch=amd64"
   336  cpes    = 1234
   337  `), 0644)).To(Succeed())
   338  
   339  		d := carton.BuildModuleDependency{
   340  			BuildModulePath: path,
   341  			ID:              "test-id",
   342  			SHA256:          "test-sha256-2",
   343  			URI:             "test-uri-2",
   344  			Version:         "test-version-2",
   345  			VersionPattern:  `test-version-[\d]`,
   346  			PURL:            "different-version-2",
   347  			PURLPattern:     `different-version-[\d]`,
   348  			CPE:             "test-version-2:patch2",
   349  			CPEPattern:      `test-version-[\d]:patch[\d]`,
   350  		}
   351  
   352  		d.Update(carton.WithExitHandler(exitHandler))
   353  
   354  		Expect(os.ReadFile(path)).To(internal.MatchTOML(`api = "0.7"
   355  [buildpack]
   356  id = "some-buildpack"
   357  name = "Some Buildpack"
   358  version = "1.2.3"
   359  
   360  [[metadata.dependencies]]
   361  id      = "test-id"
   362  name    = "Test Name"
   363  version = "test-version-2"
   364  uri     = "test-uri-2"
   365  sha256  = "test-sha256-2"
   366  stacks  = [ "test-stack" ]
   367  purl    = "pkg:generic/test-jre@different-version-2?arch=amd64"
   368  cpes    = 1234
   369  `))
   370  	})
   371  
   372  	it("updates indented dependency", func() {
   373  		Expect(os.WriteFile(path, []byte(`# it should preserve
   374  #   these comments
   375  #      exactly
   376  
   377  api = "0.6"
   378  [buildpack]
   379  id = "some-buildpack"
   380  name = "Some Buildpack"
   381  version = "1.2.3"
   382  
   383  [[metadata.dependencies]]
   384    id      = "test-id"
   385    name    = "Test Name"
   386    version = "test-version-1"
   387    uri     = "test-uri-1"
   388    sha256  = "test-sha256-1"
   389    stacks  = [ "test-stack" ]
   390  `), 0644)).To(Succeed())
   391  
   392  		d := carton.BuildModuleDependency{
   393  			BuildModulePath: path,
   394  			ID:              "test-id",
   395  			SHA256:          "test-sha256-2",
   396  			URI:             "test-uri-2",
   397  			Version:         "test-version-2",
   398  			VersionPattern:  `test-version-[\d]`,
   399  		}
   400  
   401  		d.Update(carton.WithExitHandler(exitHandler))
   402  
   403  		body, err := os.ReadFile(path)
   404  		Expect(err).NotTo(HaveOccurred())
   405  		Expect(string(body)).To(HavePrefix(`# it should preserve
   406  #   these comments
   407  #      exactly
   408  
   409  api = "0.6"`))
   410  		Expect(body).To(internal.MatchTOML(`api = "0.6"
   411  [buildpack]
   412  id = "some-buildpack"
   413  name = "Some Buildpack"
   414  version = "1.2.3"
   415  
   416  [[metadata.dependencies]]
   417    id      = "test-id"
   418    name    = "Test Name"
   419    version = "test-version-2"
   420    uri     = "test-uri-2"
   421    sha256  = "test-sha256-2"
   422    stacks  = [ "test-stack" ]
   423  `))
   424  	})
   425  }