github.com/paketoio/libpak@v1.3.1/layer_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 libpak_test 18 19 import ( 20 "fmt" 21 "io/ioutil" 22 "net/http" 23 "os" 24 "path/filepath" 25 "testing" 26 27 "github.com/buildpacks/libcnb" 28 . "github.com/onsi/gomega" 29 "github.com/onsi/gomega/ghttp" 30 "github.com/paketoio/libpak" 31 "github.com/sclevine/spec" 32 ) 33 34 func testLayer(t *testing.T, context spec.G, it spec.S) { 35 var ( 36 Expect = NewWithT(t).Expect 37 38 layer libcnb.Layer 39 path string 40 ) 41 42 it.Before(func() { 43 var err error 44 45 path, err = ioutil.TempDir("", "layer") 46 Expect(err).NotTo(HaveOccurred()) 47 }) 48 49 it.After(func() { 50 Expect(os.RemoveAll(path)).To(Succeed()) 51 }) 52 53 context("LayerContributor", func() { 54 var ( 55 lc libpak.LayerContributor 56 ) 57 58 it.Before(func() { 59 layer.Metadata = map[string]interface{}{} 60 layer.Path = path 61 lc.ExpectedMetadata = map[string]interface{}{ 62 "alpha": "test-alpha", 63 "bravo": map[string]interface{}{ 64 "bravo-1": "test-bravo-1", 65 "bravo-2": "test-bravo-2", 66 }, 67 } 68 }) 69 70 it("calls function with no existing metadata", func() { 71 var called bool 72 73 _, err := lc.Contribute(layer, func() (libcnb.Layer, error) { 74 called = true 75 return layer, nil 76 }) 77 Expect(err).NotTo(HaveOccurred()) 78 79 Expect(called).To(BeTrue()) 80 }) 81 82 it("calls function with non-matching metadata", func() { 83 layer.Metadata["alpha"] = "test-alpha" 84 85 var called bool 86 87 _, err := lc.Contribute(layer, func() (libcnb.Layer, error) { 88 called = true 89 return layer, nil 90 }) 91 Expect(err).NotTo(HaveOccurred()) 92 93 Expect(called).To(BeTrue()) 94 }) 95 96 it("does not call function with matching metadata", func() { 97 layer.Metadata = map[string]interface{}{ 98 "alpha": "test-alpha", 99 "bravo": map[string]interface{}{ 100 "bravo-1": "test-bravo-1", 101 "bravo-2": "test-bravo-2", 102 }, 103 } 104 105 var called bool 106 107 _, err := lc.Contribute(layer, func() (libcnb.Layer, error) { 108 called = true 109 return layer, nil 110 }) 111 Expect(err).NotTo(HaveOccurred()) 112 113 Expect(called).To(BeFalse()) 114 }) 115 116 it("returns function error", func() { 117 _, err := lc.Contribute(layer, func() (libcnb.Layer, error) { 118 return libcnb.Layer{}, fmt.Errorf("test-error") 119 }) 120 Expect(err).To(MatchError("test-error")) 121 }) 122 123 it("adds expected metadata to layer", func() { 124 layer, err := lc.Contribute(layer, func() (libcnb.Layer, error) { 125 return layer, nil 126 }) 127 Expect(err).NotTo(HaveOccurred()) 128 129 Expect(layer.Metadata).To(Equal(map[string]interface{}{ 130 "alpha": "test-alpha", 131 "bravo": map[string]interface{}{ 132 "bravo-1": "test-bravo-1", 133 "bravo-2": "test-bravo-2", 134 }, 135 })) 136 }) 137 }) 138 139 context("DependencyLayerContributor", func() { 140 var ( 141 dependency libpak.BuildpackDependency 142 dlc libpak.DependencyLayerContributor 143 server *ghttp.Server 144 ) 145 146 it.Before(func() { 147 RegisterTestingT(t) 148 server = ghttp.NewServer() 149 150 dependency = libpak.BuildpackDependency{ 151 ID: "test-id", 152 Name: "test-name", 153 Version: "1.1.1", 154 URI: fmt.Sprintf("%s/test-path", server.URL()), 155 SHA256: "576dd8416de5619ea001d9662291d62444d1292a38e96956bc4651c01f14bca1", 156 Stacks: []string{"test-stack"}, 157 Licenses: []libpak.BuildpackDependencyLicense{ 158 { 159 Type: "test-type", 160 URI: "test-uri", 161 }, 162 }, 163 } 164 165 layer.Metadata = map[string]interface{}{} 166 167 dlc.LayerContributor.ExpectedMetadata = map[string]interface{}{ 168 "id": dependency.ID, 169 "name": dependency.Name, 170 "version": dependency.Version, 171 "uri": dependency.URI, 172 "sha256": dependency.SHA256, 173 "stacks": dependency.Stacks, 174 "licenses": []map[string]interface{}{}, 175 } 176 for _, l := range dependency.Licenses { 177 dlc.LayerContributor.ExpectedMetadata["licenses"] = append( 178 dlc.LayerContributor.ExpectedMetadata["licenses"].([]map[string]interface{}), 179 map[string]interface{}{ 180 "type": l.Type, 181 "uri": l.URI, 182 }) 183 } 184 185 layer.Path = path 186 dlc.Dependency = dependency 187 dlc.DependencyCache.CachePath = path 188 dlc.DependencyCache.DownloadPath = path 189 }) 190 191 it.After(func() { 192 server.Close() 193 }) 194 195 it("calls function with no existing metadata", func() { 196 server.AppendHandlers(ghttp.RespondWith(http.StatusOK, "test-fixture")) 197 198 var called bool 199 200 _, err := dlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { 201 defer artifact.Close() 202 203 called = true 204 return layer, nil 205 }) 206 Expect(err).NotTo(HaveOccurred()) 207 208 Expect(called).To(BeTrue()) 209 }) 210 211 it("calls function with non-matching metadata", func() { 212 layer.Metadata["alpha"] = "test-alpha" 213 214 server.AppendHandlers(ghttp.RespondWith(http.StatusOK, "test-fixture")) 215 216 var called bool 217 218 _, err := dlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { 219 defer artifact.Close() 220 221 called = true 222 return layer, nil 223 }) 224 Expect(err).NotTo(HaveOccurred()) 225 226 Expect(called).To(BeTrue()) 227 }) 228 229 it("does not call function with matching metadata", func() { 230 layer.Metadata = map[string]interface{}{ 231 "id": dependency.ID, 232 "name": dependency.Name, 233 "version": dependency.Version, 234 "uri": dependency.URI, 235 "sha256": dependency.SHA256, 236 "stacks": dependency.Stacks, 237 "licenses": []map[string]interface{}{ 238 { 239 "type": dependency.Licenses[0].Type, 240 "uri": dependency.Licenses[0].URI, 241 }, 242 }, 243 } 244 245 var called bool 246 247 _, err := dlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { 248 defer artifact.Close() 249 250 called = true 251 return layer, nil 252 }) 253 Expect(err).NotTo(HaveOccurred()) 254 255 Expect(called).To(BeFalse()) 256 }) 257 258 it("returns function error", func() { 259 server.AppendHandlers(ghttp.RespondWith(http.StatusOK, "test-fixture")) 260 261 _, err := dlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { 262 defer artifact.Close() 263 264 return libcnb.Layer{}, fmt.Errorf("test-error") 265 }) 266 Expect(err).To(MatchError("test-error")) 267 }) 268 269 it("adds expected metadata to layer", func() { 270 server.AppendHandlers(ghttp.RespondWith(http.StatusOK, "test-fixture")) 271 272 layer, err := dlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { 273 defer artifact.Close() 274 return layer, nil 275 }) 276 Expect(err).NotTo(HaveOccurred()) 277 278 Expect(layer.Metadata).To(Equal(map[string]interface{}{ 279 "id": dependency.ID, 280 "name": dependency.Name, 281 "version": dependency.Version, 282 "uri": dependency.URI, 283 "sha256": dependency.SHA256, 284 "stacks": dependency.Stacks, 285 "licenses": []map[string]interface{}{ 286 { 287 "type": dependency.Licenses[0].Type, 288 "uri": dependency.Licenses[0].URI, 289 }, 290 }, 291 })) 292 }) 293 294 it("contributes to buildpack plan", func() { 295 plan := libcnb.BuildpackPlan{} 296 297 _ = libpak.NewDependencyLayerContributor(dependency, libpak.DependencyCache{}, &plan) 298 299 Expect(plan.Entries).To(ContainElement(libcnb.BuildpackPlanEntry{ 300 Name: dependency.ID, 301 Version: dependency.Version, 302 Metadata: map[string]interface{}{ 303 "name": dependency.Name, 304 "uri": dependency.URI, 305 "sha256": dependency.SHA256, 306 "stacks": dependency.Stacks, 307 "licenses": dependency.Licenses, 308 }, 309 })) 310 }) 311 }) 312 313 context("HelperLayerContributor", func() { 314 var ( 315 helper *os.File 316 hlc libpak.HelperLayerContributor 317 info libcnb.BuildpackInfo 318 ) 319 320 it.Before(func() { 321 var err error 322 helper, err = ioutil.TempFile("", "layer") 323 Expect(err).NotTo(HaveOccurred()) 324 Expect(helper.Close()).To(Succeed()) 325 326 info = libcnb.BuildpackInfo{ 327 ID: "test-id", 328 Name: "test-name", 329 Version: "test-version", 330 } 331 332 layer.Metadata = map[string]interface{}{} 333 layer.Path = path 334 335 hlc.LayerContributor.ExpectedMetadata = map[string]interface{}{ 336 "id": info.ID, 337 "name": info.Name, 338 "version": info.Version, 339 "clear-env": info.ClearEnvironment, 340 } 341 hlc.Path = helper.Name() 342 }) 343 344 it("calls function with no existing metadata", func() { 345 var called bool 346 347 _, err := hlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { 348 defer artifact.Close() 349 350 called = true 351 return layer, nil 352 }) 353 Expect(err).NotTo(HaveOccurred()) 354 355 Expect(called).To(BeTrue()) 356 }) 357 358 it("calls function with non-matching metadata", func() { 359 layer.Metadata["alpha"] = "other-alpha" 360 361 var called bool 362 363 _, err := hlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { 364 defer artifact.Close() 365 366 called = true 367 return layer, nil 368 }) 369 Expect(err).NotTo(HaveOccurred()) 370 371 Expect(called).To(BeTrue()) 372 }) 373 374 it("does not call function with matching metadata", func() { 375 layer.Metadata = map[string]interface{}{ 376 "id": info.ID, 377 "name": info.Name, 378 "version": info.Version, 379 "clear-env": info.ClearEnvironment, 380 } 381 382 var called bool 383 384 _, err := hlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { 385 defer artifact.Close() 386 387 called = true 388 return layer, nil 389 }) 390 Expect(err).NotTo(HaveOccurred()) 391 392 Expect(called).To(BeFalse()) 393 }) 394 395 it("returns function error", func() { 396 _, err := hlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { 397 defer artifact.Close() 398 399 return libcnb.Layer{}, fmt.Errorf("test-error") 400 }) 401 Expect(err).To(MatchError("test-error")) 402 }) 403 404 it("adds expected metadata to layer", func() { 405 layer, err := hlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { 406 defer artifact.Close() 407 return layer, nil 408 }) 409 Expect(err).NotTo(HaveOccurred()) 410 411 Expect(layer.Metadata).To(Equal(map[string]interface{}{ 412 "id": info.ID, 413 "name": info.Name, 414 "version": info.Version, 415 "clear-env": info.ClearEnvironment, 416 })) 417 }) 418 419 it("contributes to buildpack plan", func() { 420 plan := libcnb.BuildpackPlan{} 421 422 _ = libpak.NewHelperLayerContributor(helper.Name(), "test-name", info, &plan) 423 424 Expect(plan.Entries).To(ContainElement(libcnb.BuildpackPlanEntry{ 425 Name: filepath.Base(helper.Name()), 426 Version: info.Version, 427 Metadata: map[string]interface{}{ 428 "buildpack-id": info.ID, 429 "buildpack-version": info.Version, 430 }, 431 })) 432 }) 433 }) 434 }