bptest

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 2, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

README

bptest

A Go testing library for Cloud Native Buildpacks that allows you to test buildpack detect and build functions directly by invoking them with configurable test data.

Why bptest?

Testing buildpacks traditionally requires running the full lifecycle or spawning subprocesses. bptest takes a different approach—it lets you call your detect and build functions directly in unit tests with complete control over the inputs (application files, platform environment, service bindings, etc.) and easy inspection of the outputs (build plans, layers, processes, labels).

Installation

go get github.com/dmikusa/bptest

Getting Started

Here's a simple example testing a detect function that looks for a pom.xml file:

package mybuildpack_test

import (
    "testing"

    "github.com/buildpacks/libcnb/v2"
    "github.com/dmikusa/bptest"
)

func TestDetect_WithPomXML(t *testing.T) {
    result := bptest.NewDetectTest().
        WithAppFileString("pom.xml", `<project><modelVersion>4.0.0</modelVersion></project>`).
        ExecuteT(t, myDetector.Detect)

    if !result.Passed() {
        t.Error("expected detect to pass when pom.xml exists")
    }
    if !result.HasPlan("jdk") {
        t.Error("expected to require jdk")
    }
}

Examples

Detect Tests
Basic Detection
func TestDetect_Pass(t *testing.T) {
    result := bptest.NewDetectTest().
        WithAppFileString("package.json", `{"name": "myapp"}`).
        ExecuteT(t, myDetector.Detect)

    if !result.Passed() {
        t.Fatal("expected detect to pass")
    }
}
Platform Environment Variables
func TestDetect_WithEnvVar(t *testing.T) {
    result := bptest.NewDetectTest().
        WithAppFileString("pom.xml", "<project/>").
        WithPlatformEnv("BP_JAVA_VERSION", "17").
        ExecuteT(t, myDetector.Detect)

    if !result.Passed() {
        t.Fatal("expected detect to pass")
    }
}
Service Bindings
func TestDetect_WithBinding(t *testing.T) {
    result := bptest.NewDetectTest().
        WithBinding(bptest.Binding{
            Name:   "my-database",
            Type:   "postgresql",
            Secret: map[string]string{
                "host":     "localhost",
                "username": "admin",
                "password": "secret",
            },
        }).
        ExecuteT(t, myDetector.Detect)

    if !result.Passed() {
        t.Fatal("expected detect to pass with database binding")
    }
}
Inspecting Build Plans
func TestDetect_BuildPlan(t *testing.T) {
    result := bptest.NewDetectTest().
        WithAppFileString("pom.xml", "<project/>").
        ExecuteT(t, myDetector.Detect)

    // Check specific requirements
    if !result.HasPlan("jdk") {
        t.Error("expected jdk in build plan")
    }

    // Get all provides and requires
    provides := result.Provides()  // []string{"jdk", "jre"}
    requires := result.Requires()  // []string{"jdk"}

    // Get metadata for a requirement
    metadata := result.RequireMetadata("jdk")
    if metadata["version"] != "17" {
        t.Errorf("expected version 17, got %v", metadata["version"])
    }
}
Build Tests
Basic Build
func TestBuild_Success(t *testing.T) {
    result := bptest.NewBuildTest().
        WithAppFileString("pom.xml", "<project/>").
        WithPlanEntry("jdk", map[string]any{"version": "17"}).
        ExecuteT(t, myBuilder.Build)

    if !result.Succeeded() {
        t.Fatalf("build failed: %v", result.Error())
    }
}
Inspecting Layers
func TestBuild_LayerCreation(t *testing.T) {
    result := bptest.NewBuildTest().
        WithPlanEntry("jdk", map[string]any{"version": "17"}).
        ExecuteT(t, myBuilder.Build)

    if !result.Succeeded() {
        t.Fatalf("build failed: %v", result.Error())
    }

    // Get a specific layer
    layer := result.Layer("jdk")
    if layer == nil {
        t.Fatal("expected jdk layer")
    }

    // Check layer types
    if !layer.IsBuild() {
        t.Error("expected build layer")
    }
    if !layer.IsCache() {
        t.Error("expected cached layer")
    }

    // Check layer metadata
    if layer.MetadataValue("version") != "17" {
        t.Error("expected version metadata")
    }

    // Check files exist
    if !layer.FileExists("bin/java") {
        t.Error("expected java binary")
    }

    // Read file contents
    content, err := layer.FileContentString("release")
    if err != nil {
        t.Errorf("failed to read release file: %v", err)
    }

    // Check environment variables
    envBuild := layer.EnvBuild()
    if envBuild["JAVA_HOME.override"] == "" {
        t.Error("expected JAVA_HOME to be set")
    }
}
Inspecting Processes
func TestBuild_Processes(t *testing.T) {
    result := bptest.NewBuildTest().
        WithAppFileString("app.jar", "").
        WithPlanEntry("jdk", nil).
        ExecuteT(t, myBuilder.Build)

    if !result.Succeeded() {
        t.Fatalf("build failed: %v", result.Error())
    }

    // Check for specific process
    if !result.HasProcess("web") {
        t.Error("expected web process")
    }

    // Get process details
    web := result.Process("web")
    if web == nil || len(web.Command) == 0 {
        t.Error("expected web process with command")
    }

    // Check default process
    defaultProc := result.DefaultProcess()
    if defaultProc == nil || defaultProc.Type != "web" {
        t.Error("expected web to be the default process")
    }
}
Rebuild Scenarios (Existing Layers)

Test how your buildpack handles rebuilds when layers already exist:

func TestBuild_Rebuild(t *testing.T) {
    result := bptest.NewBuildTest().
        WithPlanEntry("jdk", map[string]any{"version": "17"}).
        WithExistingLayer("jdk", &bptest.LayerConfig{
            Build: true,
            Cache: true,
            Metadata: map[string]any{
                "version": "11",  // Previous version
            },
            Files: map[string][]byte{
                "bin/java": []byte("old java"),
            },
        }).
        ExecuteT(t, myBuilder.Build)

    if !result.Succeeded() {
        t.Fatalf("rebuild failed: %v", result.Error())
    }

    // Verify layer was updated
    layer := result.Layer("jdk")
    if layer.MetadataValue("version") != "17" {
        t.Error("expected layer to be updated to version 17")
    }
}
Persistent Metadata (store.toml)
func TestBuild_PersistentMetadata(t *testing.T) {
    result := bptest.NewBuildTest().
        WithPersistentMetadata(map[string]any{
            "last-build-time": "2024-01-01T00:00:00Z",
        }).
        ExecuteT(t, myBuilder.Build)

    if !result.Succeeded() {
        t.Fatalf("build failed: %v", result.Error())
    }

    // Check updated persistent metadata
    meta := result.PersistentMetadata()
    if meta["last-build-time"] == "" {
        t.Error("expected persistent metadata to be set")
    }
}
Labels and Slices
func TestBuild_Labels(t *testing.T) {
    result := bptest.NewBuildTest().
        WithPlanEntry("jdk", nil).
        ExecuteT(t, myBuilder.Build)

    if !result.Succeeded() {
        t.Fatalf("build failed: %v", result.Error())
    }

    // Check labels
    if result.Label("org.opencontainers.image.title") == "" {
        t.Error("expected image title label")
    }

    // Check slices
    slices := result.Slices()
    if len(slices) == 0 {
        t.Error("expected at least one slice")
    }
}
Custom Buildpack Configuration
func TestDetect_CustomBuildpack(t *testing.T) {
    result := bptest.NewDetectTest().
        WithBuildpack(bptest.BuildpackConfig{
            API:     "0.9",
            ID:      "example/my-buildpack",
            Version: "1.2.3",
            Name:    "My Buildpack",
        }).
        WithAppFileString("app.txt", "hello").
        ExecuteT(t, myDetector.Detect)

    if !result.Passed() {
        t.Fatal("expected detect to pass")
    }
}
Target Platform Information
func TestBuild_WithTarget(t *testing.T) {
    result := bptest.NewBuildTest().
        WithTarget(bptest.TargetInfo{
            OS:            "linux",
            Arch:          "arm64",
            DistroName:    "ubuntu",
            DistroVersion: "22.04",
        }).
        WithPlanEntry("jdk", nil).
        ExecuteT(t, myBuilder.Build)

    if !result.Succeeded() {
        t.Fatalf("build failed: %v", result.Error())
    }
}
Integration Tests with Real Buildpack Configuration

For integration-style tests that use your actual buildpack.toml configuration:

func TestBuild_Integration(t *testing.T) {
    result := bptest.NewBuildTestFromBuildpack("buildpack.toml").
        WithAppFileString("pom.xml", "<project/>").
        WithPlanEntry("jdk", nil).
        ExecuteT(t, myBuilder.Build)

    if !result.Succeeded() {
        t.Fatalf("build failed: %v", result.Error())
    }
}

This copies your real buildpack.toml to a temporary directory, so you can still use WithBuildpackFile, WithBuildpackSymlink, and WithBuildpackDependencyCache to add test fixtures.

When testing buildpacks that download dependencies, you can use WithBuildpackDependencyCache to point the buildpack's dependency cache to a local test fixtures directory. This allows your tests to use mock dependencies instead of downloading from the internet:

func TestBuild_WithDependencyCache(t *testing.T) {
    // Get absolute path to testdata directory containing mock dependencies
    testdataAbs, err := filepath.Abs("testdata")
    if err != nil {
        t.Fatalf("failed to get absolute path: %v", err)
    }

    result := bptest.NewBuildTest().
        WithBuildpackDependencyCache(testdataAbs).
        WithPlanEntry("jdk", nil).
        ExecuteT(t, myBuilder.Build)

    if !result.Succeeded() {
        t.Fatalf("build failed: %v", result.Error())
    }
}

You can also add arbitrary files to the buildpack directory:

func TestBuild_WithBuildpackConfig(t *testing.T) {
    result := bptest.NewBuildTest().
        WithBuildpackFileString("config/settings.json", `{"debug": true}`).
        WithPlanEntry("jdk", nil).
        ExecuteT(t, myBuilder.Build)

    if !result.Succeeded() {
        t.Fatalf("build failed: %v", result.Error())
    }
}
Gomega Matchers

The matchers subpackage provides custom Gomega matchers for more expressive assertions. Import with dot notation for cleaner test code:

import (
    . "github.com/onsi/gomega"
    "github.com/dmikusa/bptest"
    . "github.com/dmikusa/bptest/matchers"
)

func TestDetect_WithGomega(t *testing.T) {
    g := NewWithT(t)

    result := bptest.NewDetectTest().
        WithAppFileString("pom.xml", "<project/>").
        ExecuteT(t, myDetector.Detect)

    g.Expect(result).To(HavePassed())
    g.Expect(result).To(HavePlan("jdk"))
    g.Expect(result).To(Provide("jdk"))
    g.Expect(result).To(Require("jvm"))
}

func TestBuild_WithGomega(t *testing.T) {
    g := NewWithT(t)

    result := bptest.NewBuildTest().
        WithPlanEntry("jdk", nil).
        ExecuteT(t, myBuilder.Build)

    g.Expect(result).To(HaveSucceeded())
    g.Expect(result).To(HaveLayer("jdk"))
    g.Expect(result).To(HaveProcess("web"))
    g.Expect(result).To(HaveLabel("org.opencontainers.image.title", "My App"))
}
Available Matchers

DetectResult matchers:

Matcher Description
HavePassed() Check if detection passed
HaveFailed() Check if detection failed
HavePlan(name) Check if plan provides or requires name
Provide(name) Check if provides includes name
Require(name) Check if requires includes name

BuildResult matchers:

Matcher Description
HaveSucceeded() Check if build succeeded
HaveLayer(name) Check if layer exists
HaveLayerCount(n) Check exact number of layers
HaveLayers(names...) Check that specified layers exist (others may exist)
HaveExactlyLayers(names...) Check that only specified layers exist
HaveProcess(type) Check if process type exists
HaveLabel(key) Check if label key exists
HaveLabel(key, value) Check if label has specific value

LayerResult matchers:

Matcher Description
HaveFile(path) Check if file exists in layer
HaveFileWithContents(path, contents) Check file exists with exact contents
HaveFileWithPerms(path, perms) Check file exists with exact permissions (e.g., 0755)
BeBuildLayer() Check if layer is marked for build
BeLaunchLayer() Check if layer is marked for launch
BeCacheLayer() Check if layer is marked for caching
HaveMetadata(key) Check if layer has metadata key
HaveMetadata(key, value) Check if layer metadata has specific value
Layer Matchers Example
func TestBuild_LayerMatchers(t *testing.T) {
    g := NewWithT(t)

    result := bptest.NewBuildTest().
        WithPlanEntry("jdk", nil).
        ExecuteT(t, myBuilder.Build)

    // Check layer counts
    g.Expect(result).To(HaveLayerCount(2))
    g.Expect(result).To(HaveLayers("jdk", "helper"))
    g.Expect(result).To(HaveExactlyLayers("jdk", "helper"))

    // Check layer properties
    layer := result.Layer("jdk")
    g.Expect(layer).To(BeBuildLayer())
    g.Expect(layer).To(BeCacheLayer())
    g.Expect(layer).NotTo(BeLaunchLayer())

    // Check layer files
    g.Expect(layer).To(HaveFile("bin/java"))
    g.Expect(layer).To(HaveFileWithContents("version", "17.0.1"))

    // Check layer metadata
    g.Expect(layer).To(HaveMetadata("version"))
    g.Expect(layer).To(HaveMetadata("version", "17"))
}
Buildpack Metadata

Configure buildpack metadata including configurations and dependencies:

func TestBuild_WithBuildpackMetadata(t *testing.T) {
    result := bptest.NewBuildTest().
        WithConfigurationMetadata(bptest.ConfigurationMetadata{
            Name:        "BP_JVM_VERSION",
            Description: "the Java version to install",
            Default:     "17",
            Build:       true,
        }).
        WithConfigurationMetadata(bptest.ConfigurationMetadata{
            Name:        "BPL_JVM_HEAD_ROOM",
            Description: "the headroom in memory calculation",
            Default:     "0",
            Launch:      true,
        }).
        WithDependencyMetadata(bptest.DependencyMetadata{
            ID:           "jdk",
            Name:         "BellSoft Liberica JDK",
            Version:      "17.0.1",
            URI:          "https://example.com/jdk.tar.gz",
            SHA256:       "abc123...",
            Stacks:       []string{"*"},
            CPEs:         []string{"cpe:2.3:a:oracle:jdk:17.0.1:*:*:*:*:*:*:*"},
            PURL:         "pkg:generic/bellsoft-jdk@17.0.1",
            Source:       "https://example.com/jdk-src.tar.gz",
            SourceSHA256: "def456...",
            Licenses: []bptest.LicenseMetadata{
                {Type: "GPL-2.0 WITH Classpath-exception-2.0", URI: "https://openjdk.java.net/legal/gplv2+ce.html"},
            },
        }).
        WithPlanEntry("jdk", nil).
        ExecuteT(t, myBuilder.Build)

    if !result.Succeeded() {
        t.Fatalf("build failed: %v", result.Error())
    }
}

API Reference

See the full API documentation on pkg.go.dev.

License

This project is released under version 2.0 of the Apache License.

Documentation

Overview

Package bptest provides testing utilities for Cloud Native Buildpacks.

This library allows you to test buildpack detect and build functions directly by invoking them with configurable test data, without needing to run the full buildpack lifecycle or spawn subprocesses.

Detect Tests

Use DetectTest to test your buildpack's detect function:

func TestDetect_WithPomXML(t *testing.T) {
	result := bptest.NewDetectTest().
		WithAppFileString("pom.xml", `<project><modelVersion>4.0.0</modelVersion></project>`).
		ExecuteT(t, myDetector.Detect)

	if !result.Passed() {
		t.Error("expected detect to pass when pom.xml exists")
	}
	if !result.HasPlan("jdk") {
		t.Error("expected to require jdk")
	}
}

Build Tests

Use BuildTest to test your buildpack's build function:

func TestBuild_LayerCreation(t *testing.T) {
	result := bptest.NewBuildTest().
		WithAppFileString("pom.xml", "<project/>").
		WithPlanEntry("jdk", map[string]any{"version": "17"}).
		ExecuteT(t, myBuilder.Build)

	if !result.Succeeded() {
		t.Fatalf("build failed: %v", result.Error())
	}

	layer := result.Layer("jdk")
	if !layer.IsBuild() || !layer.IsCache() {
		t.Error("expected build and cache layer")
	}
	if !layer.FileExists("bin/java") {
		t.Error("expected java binary")
	}
}

Service Bindings

Both DetectTest and BuildTest support service bindings:

func TestDetect_WithBinding(t *testing.T) {
	result := bptest.NewDetectTest().
		WithBinding(bptest.Binding{
			Name:   "my-database",
			Type:   "postgresql",
			Secret: map[string]string{
				"host":     "localhost",
				"username": "admin",
				"password": "secret",
			},
		}).
		ExecuteT(t, myDetector.Detect)

	if !result.Passed() {
		t.Fatal("expected detect to pass with database binding")
	}
}

Rebuild Scenarios

Test rebuild scenarios by providing existing layer state:

func TestBuild_Rebuild(t *testing.T) {
	result := bptest.NewBuildTest().
		WithPlanEntry("jdk", map[string]any{"version": "17"}).
		WithExistingLayer("jdk", &bptest.LayerConfig{
			Build: true,
			Cache: true,
			Metadata: map[string]any{"version": "11"},
			Files: map[string][]byte{
				"bin/java": []byte("old java"),
			},
		}).
		ExecuteT(t, myBuilder.Build)

	if !result.Succeeded() {
		t.Fatalf("rebuild failed: %v", result.Error())
	}

	layer := result.Layer("jdk")
	if layer.MetadataValue("version") != "17" {
		t.Error("expected layer to be updated to version 17")
	}
}

Platform Environment Variables

Set platform environment variables that your buildpack reads:

func TestDetect_WithEnvVar(t *testing.T) {
	result := bptest.NewDetectTest().
		WithAppFileString("pom.xml", "<project/>").
		WithPlatformEnv("BP_JAVA_VERSION", "17").
		ExecuteT(t, myDetector.Detect)

	if !result.Passed() {
		t.Fatal("expected detect to pass")
	}
}

Inspecting Build Plans

Examine the build plans returned by detect:

func TestDetect_BuildPlan(t *testing.T) {
	result := bptest.NewDetectTest().
		WithAppFileString("pom.xml", "<project/>").
		ExecuteT(t, myDetector.Detect)

	provides := result.Provides()  // []string{"jdk", "jre"}
	requires := result.Requires()  // []string{"jdk"}

	metadata := result.RequireMetadata("jdk")
	if metadata["version"] != "17" {
		t.Errorf("expected version 17, got %v", metadata["version"])
	}
}

Inspecting Layers

Examine layers created during build:

func TestBuild_LayerInspection(t *testing.T) {
	result := bptest.NewBuildTest().
		WithPlanEntry("jdk", nil).
		ExecuteT(t, myBuilder.Build)

	layer := result.Layer("jdk")

	// Check layer types
	layer.IsBuild()   // true if build layer
	layer.IsLaunch()  // true if launch layer
	layer.IsCache()   // true if cached layer

	// Check metadata
	layer.MetadataValue("version")

	// Check files
	layer.FileExists("bin/java")
	content, _ := layer.FileContentString("release")

	// Check environment variables
	envBuild := layer.EnvBuild()     // build-time env vars
	envLaunch := layer.EnvLaunch()   // launch-time env vars
}

Target Platform Information

Set target OS, architecture, and distribution:

func TestBuild_WithTarget(t *testing.T) {
	result := bptest.NewBuildTest().
		WithTarget(bptest.TargetInfo{
			OS:            "linux",
			Arch:          "arm64",
			DistroName:    "ubuntu",
			DistroVersion: "22.04",
		}).
		WithPlanEntry("jdk", nil).
		ExecuteT(t, myBuilder.Build)

	if !result.Succeeded() {
		t.Fatalf("build failed: %v", result.Error())
	}
}

Integration Tests

For integration-style tests that use your actual buildpack.toml configuration:

func TestBuild_Integration(t *testing.T) {
	result := bptest.NewBuildTestFromBuildpack("buildpack.toml").
		WithAppFileString("pom.xml", "<project/>").
		WithPlanEntry("jdk", nil).
		ExecuteT(t, myBuilder.Build)

	if !result.Succeeded() {
		t.Fatalf("build failed: %v", result.Error())
	}
}

Dependency Caching

When testing buildpacks that download dependencies, use WithBuildpackDependencyCache to point the buildpack's dependency cache to a local test fixtures directory:

func TestBuild_WithDependencyCache(t *testing.T) {
	testdataAbs, _ := filepath.Abs("testdata")

	result := bptest.NewBuildTest().
		WithBuildpackDependencyCache(testdataAbs).
		WithPlanEntry("jdk", nil).
		ExecuteT(t, myBuilder.Build)

	if !result.Succeeded() {
		t.Fatalf("build failed: %v", result.Error())
	}
}

You can also add arbitrary files to the buildpack directory with WithBuildpackFile:

result := bptest.NewBuildTest().
	WithBuildpackFileString("config/settings.json", `{"debug": true}`).
	ExecuteT(t, myBuilder.Build)

Gomega Matchers

The matchers subpackage provides custom Gomega matchers for more expressive assertions. Import with dot notation for cleaner test code:

import (
	. "github.com/onsi/gomega"
	"github.com/dmikusa/bptest"
	. "github.com/dmikusa/bptest/matchers"
)

func TestDetect_WithGomega(t *testing.T) {
	g := NewWithT(t)

	result := bptest.NewDetectTest().
		WithAppFileString("pom.xml", "<project/>").
		ExecuteT(t, myDetector.Detect)

	g.Expect(result).To(HavePassed())
	g.Expect(result).To(HavePlan("jdk"))
	g.Expect(result).To(Provide("jdk"))
	g.Expect(result).To(Require("jvm"))
}

func TestBuild_WithGomega(t *testing.T) {
	g := NewWithT(t)

	result := bptest.NewBuildTest().
		WithPlanEntry("jdk", nil).
		ExecuteT(t, myBuilder.Build)

	g.Expect(result).To(HaveSucceeded())
	g.Expect(result).To(HaveLayer("jdk"))
	g.Expect(result).To(HaveProcess("web"))
	g.Expect(result).To(HaveLabel("org.opencontainers.image.title", "My App"))
}

Available matchers for DetectResult:

  • HavePassed() - check if detection passed
  • HaveFailed() - check if detection failed
  • HavePlan(name) - check if plan provides or requires name
  • Provide(name) - check if provides includes name
  • Require(name) - check if requires includes name

Available matchers for BuildResult:

  • HaveSucceeded() - check if build succeeded
  • HaveLayer(name) - check if layer exists
  • HaveLayerCount(n) - check exact number of layers
  • HaveLayers(names...) - check that specified layers exist (others may exist)
  • HaveExactlyLayers(names...) - check that only specified layers exist
  • HaveProcess(type) - check if process type exists
  • HaveLabel(key) or HaveLabel(key, value) - check label exists/matches value

Available matchers for LayerResult:

  • HaveFile(path) - check if file exists in layer
  • HaveFileWithContents(path, contents) - check file exists with exact contents
  • HaveFileWithPerms(path, perms) - check file exists with exact permissions (e.g., 0755)
  • BeBuildLayer() - check if layer is marked for build
  • BeLaunchLayer() - check if layer is marked for launch
  • BeCacheLayer() - check if layer is marked for caching
  • HaveMetadata(key) or HaveMetadata(key, value) - check layer metadata

Buildpack Metadata

Configure buildpack metadata including configurations and dependencies:

func TestBuild_WithMetadata(t *testing.T) {
	result := bptest.NewBuildTest().
		WithConfigurationMetadata(bptest.ConfigurationMetadata{
			Name:        "BP_JVM_VERSION",
			Description: "the Java version",
			Default:     "17",
			Build:       true,
		}).
		WithDependencyMetadata(bptest.DependencyMetadata{
			ID:      "jdk",
			Name:    "BellSoft Liberica JDK",
			Version: "17.0.1",
			URI:     "https://example.com/jdk.tar.gz",
			SHA256:  "abc123...",
			Stacks:  []string{"*"},
		}).
		ExecuteT(t, myBuilder.Build)

	if !result.Succeeded() {
		t.Fatalf("build failed: %v", result.Error())
	}
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ReadLayerTOML

func ReadLayerTOML(layersDir, layerName string) (*internaltoml.LayerContent, error)

ReadLayerTOML reads and returns the layer.toml content for a layer in the layers directory.

Types

type Binding

type Binding struct {
	Name     string
	Type     string
	Provider string
	Secret   map[string]string
}

Binding represents a service binding for testing.

type BuildResult

type BuildResult struct {
	// contains filtered or unexported fields
}

BuildResult wraps the result of a build function execution.

func (*BuildResult) DefaultProcess

func (r *BuildResult) DefaultProcess() *libcnb.Process

DefaultProcess returns the default process, or nil if none is marked default.

func (*BuildResult) Error

func (r *BuildResult) Error() error

Error returns the error from the build function, if any.

func (*BuildResult) HasError

func (r *BuildResult) HasError() bool

HasError returns true if the build function returned an error.

func (*BuildResult) HasProcess

func (r *BuildResult) HasProcess(processType string) bool

HasProcess returns true if a process with the given type exists.

func (*BuildResult) Label

func (r *BuildResult) Label(key string) string

Label returns the value of the label with the given key, or empty string if not found.

func (*BuildResult) Labels

func (r *BuildResult) Labels() []libcnb.Label

Labels returns all labels contributed by the build.

func (*BuildResult) Layer

func (r *BuildResult) Layer(name string) *LayerResult

Layer returns a LayerResult for the layer with the given name. Returns nil if the layer doesn't exist.

func (*BuildResult) Layers

func (r *BuildResult) Layers() *LayerInspector

Layers returns a LayerInspector for examining the contributed layers.

func (*BuildResult) PersistentMetadata

func (r *BuildResult) PersistentMetadata() map[string]any

PersistentMetadata returns the persistent metadata from the build result.

func (*BuildResult) Process

func (r *BuildResult) Process(processType string) *libcnb.Process

Process returns the process with the given type, or nil if not found.

func (*BuildResult) Processes

func (r *BuildResult) Processes() []libcnb.Process

Processes returns all processes contributed by the build.

func (*BuildResult) Slices

func (r *BuildResult) Slices() []libcnb.Slice

Slices returns all slices contributed by the build.

func (*BuildResult) Succeeded

func (r *BuildResult) Succeeded() bool

Succeeded returns true if the build completed without error.

func (*BuildResult) UnmetEntries

func (r *BuildResult) UnmetEntries() []libcnb.UnmetPlanEntry

UnmetEntries returns all unmet plan entries.

type BuildTest

type BuildTest struct {
	// contains filtered or unexported fields
}

BuildTest configures and executes buildpack build tests.

func NewBuildTest

func NewBuildTest() *BuildTest

NewBuildTest creates a new BuildTest with default values.

func NewBuildTestFromBuildpack

func NewBuildTestFromBuildpack(buildpackTOMLPath string) *BuildTest

NewBuildTestFromBuildpack creates a BuildTest using an actual buildpack.toml file. The buildpackTOMLPath should be the path to the buildpack.toml file. This is useful for integration-style tests where you want to test with the real buildpack configuration rather than synthetic test data.

The buildpack.toml is copied to a temporary directory, so WithBuildpackFile, WithBuildpackSymlink, and WithBuildpackDependencyCache still work as expected.

Note: WithBuildpack, WithConfigurationMetadata, and WithDependencyMetadata have no effect when using this constructor since the real buildpack.toml is used.

func (*BuildTest) Cleanup

func (b *BuildTest) Cleanup() error

Cleanup removes all temporary directories created during the test.

func (*BuildTest) Execute

func (b *BuildTest) Execute(build libcnb.BuildFunc) (*BuildResult, error)

Execute runs the build function and returns the result.

func (*BuildTest) ExecuteT

func (b *BuildTest) ExecuteT(t *testing.T, build libcnb.BuildFunc) *BuildResult

ExecuteT runs the build function with automatic cleanup on test completion.

func (*BuildTest) Paths

func (b *BuildTest) Paths() TestPaths

Paths returns the test directory paths after Execute has been called.

func (*BuildTest) WithAppFile

func (b *BuildTest) WithAppFile(path string, content []byte) *BuildTest

WithAppFile adds a file to the application directory.

func (*BuildTest) WithAppFileString

func (b *BuildTest) WithAppFileString(path, content string) *BuildTest

WithAppFileString adds a file to the application directory with string content.

func (*BuildTest) WithBinding

func (b *BuildTest) WithBinding(binding Binding) *BuildTest

WithBinding adds a service binding.

func (*BuildTest) WithBuildpack

func (b *BuildTest) WithBuildpack(config BuildpackConfig) *BuildTest

WithBuildpack sets the buildpack configuration.

func (*BuildTest) WithBuildpackDependencyCache

func (b *BuildTest) WithBuildpackDependencyCache(targetPath string) *BuildTest

WithBuildpackDependencyCache creates a symlink from the buildpack's "dependencies" directory to the specified target path. This is a convenience method for the common case of pointing the dependency cache to a test fixtures directory.

func (*BuildTest) WithBuildpackFile

func (b *BuildTest) WithBuildpackFile(path string, content []byte) *BuildTest

WithBuildpackFile adds a file to the buildpack directory.

func (*BuildTest) WithBuildpackFileString

func (b *BuildTest) WithBuildpackFileString(path, content string) *BuildTest

WithBuildpackFileString adds a file to the buildpack directory with string content.

func (b *BuildTest) WithBuildpackSymlink(relativePath, targetPath string) *BuildTest

WithBuildpackSymlink creates a symlink in the buildpack directory. The relativePath is relative to the buildpack directory, and targetPath is the absolute path that the symlink will point to. This is useful for setting up dependency caches that point to test fixtures.

func (*BuildTest) WithConfigurationMetadata

func (b *BuildTest) WithConfigurationMetadata(config ConfigurationMetadata) *BuildTest

WithConfigurationMetadata adds a configuration entry to the buildpack metadata.

func (*BuildTest) WithDependencyMetadata

func (b *BuildTest) WithDependencyMetadata(dep DependencyMetadata) *BuildTest

WithDependencyMetadata adds a dependency entry to the buildpack metadata.

func (*BuildTest) WithEnv

func (b *BuildTest) WithEnv(key, value string) *BuildTest

WithEnv sets an environment variable for the build function. This simulates environment variables that might be set by previous buildpacks.

func (*BuildTest) WithExistingLayer

func (b *BuildTest) WithExistingLayer(name string, config *LayerConfig) *BuildTest

WithExistingLayer configures an existing layer for rebuild scenarios.

func (*BuildTest) WithPersistentMetadata

func (b *BuildTest) WithPersistentMetadata(metadata map[string]any) *BuildTest

WithPersistentMetadata sets the persistent metadata (store.toml).

func (*BuildTest) WithPlan

func (b *BuildTest) WithPlan(plan libcnb.BuildpackPlan) *BuildTest

WithPlan sets the entire buildpack plan.

func (*BuildTest) WithPlanEntry

func (b *BuildTest) WithPlanEntry(name string, metadata map[string]any) *BuildTest

WithPlanEntry adds a buildpack plan entry.

func (*BuildTest) WithPlatformEnv

func (b *BuildTest) WithPlatformEnv(key, value string) *BuildTest

WithPlatformEnv sets a platform environment variable.

func (*BuildTest) WithStackID

func (b *BuildTest) WithStackID(stackID string) *BuildTest

WithStackID sets the stack ID.

func (*BuildTest) WithTarget

func (b *BuildTest) WithTarget(target TargetInfo) *BuildTest

WithTarget sets the target platform information.

type BuildpackConfig

type BuildpackConfig struct {
	API      string
	ID       string
	Version  string
	Name     string
	Metadata map[string]any
}

BuildpackConfig holds buildpack metadata for generating buildpack.toml.

func (BuildpackConfig) ToTOML

func (c BuildpackConfig) ToTOML() ([]byte, error)

ToTOML serializes the BuildpackConfig to TOML format.

type ConfigurationMetadata

type ConfigurationMetadata struct {
	Name        string
	Description string
	Default     string
	Launch      bool
	Build       bool
}

ConfigurationMetadata represents a buildpack configuration entry.

type DependencyMetadata

type DependencyMetadata struct {
	ID           string
	Name         string
	Version      string
	URI          string
	SHA256       string
	Stacks       []string
	CPEs         []string
	PURL         string
	Source       string
	SourceSHA256 string
	Licenses     []LicenseMetadata
}

DependencyMetadata represents a buildpack dependency entry.

type DetectResult

type DetectResult struct {
	// contains filtered or unexported fields
}

DetectResult wraps the result of a detect function execution.

func (*DetectResult) Error

func (r *DetectResult) Error() error

Error returns the error from the detect function, if any.

func (*DetectResult) Failed

func (r *DetectResult) Failed() bool

Failed returns true if detection failed (did not pass).

func (*DetectResult) HasError

func (r *DetectResult) HasError() bool

HasError returns true if the detect function returned an error.

func (*DetectResult) HasPlan

func (r *DetectResult) HasPlan(name string) bool

HasPlan returns true if any plan provides or requires the given name.

func (*DetectResult) Passed

func (r *DetectResult) Passed() bool

Passed returns true if detection passed.

func (*DetectResult) Plans

func (r *DetectResult) Plans() []libcnb.BuildPlan

Plans returns all build plans from the detect result.

func (*DetectResult) Provides

func (r *DetectResult) Provides() []string

Provides returns all provided dependency names across all plans.

func (*DetectResult) RequireMetadata

func (r *DetectResult) RequireMetadata(name string) map[string]any

RequireMetadata returns the metadata for the first requirement with the given name.

func (*DetectResult) Requires

func (r *DetectResult) Requires() []string

Requires returns all required dependency names across all plans.

type DetectTest

type DetectTest struct {
	// contains filtered or unexported fields
}

DetectTest configures and executes buildpack detect tests.

func NewDetectTest

func NewDetectTest() *DetectTest

NewDetectTest creates a new DetectTest with default values.

func NewDetectTestFromBuildpack

func NewDetectTestFromBuildpack(buildpackTOMLPath string) *DetectTest

NewDetectTestFromBuildpack creates a DetectTest using an actual buildpack.toml file. The buildpackTOMLPath should be the path to the buildpack.toml file. This is useful for integration-style tests where you want to test with the real buildpack configuration rather than synthetic test data.

The buildpack.toml is copied to a temporary directory, so WithBuildpackFile, WithBuildpackSymlink, and WithBuildpackDependencyCache still work as expected.

Note: WithBuildpack, WithConfigurationMetadata, and WithDependencyMetadata have no effect when using this constructor since the real buildpack.toml is used.

func (*DetectTest) Cleanup

func (d *DetectTest) Cleanup() error

Cleanup removes all temporary directories created during the test.

func (*DetectTest) Execute

func (d *DetectTest) Execute(detect libcnb.DetectFunc) (*DetectResult, error)

Execute runs the detect function and returns the result.

func (*DetectTest) ExecuteT

func (d *DetectTest) ExecuteT(t *testing.T, detect libcnb.DetectFunc) *DetectResult

ExecuteT runs the detect function with automatic cleanup on test completion.

func (*DetectTest) Paths

func (d *DetectTest) Paths() TestPaths

Paths returns the test directory paths after Execute has been called.

func (*DetectTest) WithAppFile

func (d *DetectTest) WithAppFile(path string, content []byte) *DetectTest

WithAppFile adds a file to the application directory.

func (*DetectTest) WithAppFileString

func (d *DetectTest) WithAppFileString(path, content string) *DetectTest

WithAppFileString adds a file to the application directory with string content.

func (*DetectTest) WithBinding

func (d *DetectTest) WithBinding(binding Binding) *DetectTest

WithBinding adds a service binding.

func (*DetectTest) WithBuildpack

func (d *DetectTest) WithBuildpack(config BuildpackConfig) *DetectTest

WithBuildpack sets the buildpack configuration.

func (*DetectTest) WithBuildpackDependencyCache

func (d *DetectTest) WithBuildpackDependencyCache(targetPath string) *DetectTest

WithBuildpackDependencyCache creates a symlink from the buildpack's "dependencies" directory to the specified target path. This is a convenience method for the common case of pointing the dependency cache to a test fixtures directory.

func (*DetectTest) WithBuildpackFile

func (d *DetectTest) WithBuildpackFile(path string, content []byte) *DetectTest

WithBuildpackFile adds a file to the buildpack directory.

func (*DetectTest) WithBuildpackFileString

func (d *DetectTest) WithBuildpackFileString(path, content string) *DetectTest

WithBuildpackFileString adds a file to the buildpack directory with string content.

func (d *DetectTest) WithBuildpackSymlink(relativePath, targetPath string) *DetectTest

WithBuildpackSymlink creates a symlink in the buildpack directory. The relativePath is relative to the buildpack directory, and targetPath is the absolute path that the symlink will point to. This is useful for setting up dependency caches that point to test fixtures.

func (*DetectTest) WithConfigurationMetadata

func (d *DetectTest) WithConfigurationMetadata(config ConfigurationMetadata) *DetectTest

WithConfigurationMetadata adds a configuration entry to the buildpack metadata.

func (*DetectTest) WithDependencyMetadata

func (d *DetectTest) WithDependencyMetadata(dep DependencyMetadata) *DetectTest

WithDependencyMetadata adds a dependency entry to the buildpack metadata.

func (*DetectTest) WithEnv

func (d *DetectTest) WithEnv(key, value string) *DetectTest

WithEnv sets an environment variable for the detect function. This simulates environment variables that might be set by previous buildpacks.

func (*DetectTest) WithPlatformEnv

func (d *DetectTest) WithPlatformEnv(key, value string) *DetectTest

WithPlatformEnv sets a platform environment variable.

func (*DetectTest) WithStackID

func (d *DetectTest) WithStackID(stackID string) *DetectTest

WithStackID sets the stack ID.

func (*DetectTest) WithTarget

func (d *DetectTest) WithTarget(target TargetInfo) *DetectTest

WithTarget sets the target platform information.

type LayerConfig

type LayerConfig struct {
	Build    bool
	Launch   bool
	Cache    bool
	Metadata map[string]any
	// Files maps relative paths to file contents for pre-populating the layer.
	Files map[string][]byte
	// Env contains environment variables to set in the layer's env directories.
	// Keys are in the format "VAR.default", "VAR.override", etc.
	Env map[string]string
}

LayerConfig configures an existing layer for rebuild scenarios.

type LayerInspector

type LayerInspector struct {
	// contains filtered or unexported fields
}

LayerInspector provides methods for examining contributed layers.

func (*LayerInspector) Count

func (i *LayerInspector) Count() int

Count returns the number of contributed layers.

func (*LayerInspector) Get

func (i *LayerInspector) Get(name string) *LayerResult

Get returns a LayerResult for the layer with the given name. Returns nil if the layer doesn't exist.

func (*LayerInspector) Names

func (i *LayerInspector) Names() []string

Names returns the names of all contributed layers.

type LayerResult

type LayerResult struct {
	// contains filtered or unexported fields
}

LayerResult provides methods for inspecting a single layer.

func (*LayerResult) BinFiles

func (r *LayerResult) BinFiles() ([]string, error)

BinFiles returns the list of files in the layer's bin directory.

func (*LayerResult) EnvBuild

func (r *LayerResult) EnvBuild() map[string]string

EnvBuild returns the build environment variables set by the layer.

func (*LayerResult) EnvLaunch

func (r *LayerResult) EnvLaunch() map[string]string

EnvLaunch returns the launch environment variables set by the layer.

func (*LayerResult) EnvShared

func (r *LayerResult) EnvShared() map[string]string

EnvShared returns the shared environment variables set by the layer.

func (*LayerResult) ExecDFiles

func (r *LayerResult) ExecDFiles() ([]string, error)

ExecDFiles returns the list of exec.d files in the layer.

func (*LayerResult) FileContent

func (r *LayerResult) FileContent(relativePath string) ([]byte, error)

FileContent returns the content of a file in the layer.

func (*LayerResult) FileContentString

func (r *LayerResult) FileContentString(relativePath string) (string, error)

FileContentString returns the content of a file as a string.

func (*LayerResult) FileExists

func (r *LayerResult) FileExists(relativePath string) bool

FileExists returns true if the file exists in the layer.

func (*LayerResult) FileMode

func (r *LayerResult) FileMode(relativePath string) (os.FileMode, error)

FileMode returns the file mode (permissions) of a file in the layer.

func (*LayerResult) IsBuild

func (r *LayerResult) IsBuild() bool

IsBuild returns true if the layer is marked for build.

func (*LayerResult) IsCache

func (r *LayerResult) IsCache() bool

IsCache returns true if the layer is marked for caching.

func (*LayerResult) IsLaunch

func (r *LayerResult) IsLaunch() bool

IsLaunch returns true if the layer is marked for launch.

func (*LayerResult) LibFiles

func (r *LayerResult) LibFiles() ([]string, error)

LibFiles returns the list of files in the layer's lib directory.

func (*LayerResult) Metadata

func (r *LayerResult) Metadata() map[string]any

Metadata returns the layer's metadata.

func (*LayerResult) MetadataValue

func (r *LayerResult) MetadataValue(key string) any

MetadataValue returns the value for a specific metadata key.

func (*LayerResult) Name

func (r *LayerResult) Name() string

Name returns the layer name.

func (*LayerResult) Path

func (r *LayerResult) Path() string

Path returns the layer's filesystem path.

type LicenseMetadata

type LicenseMetadata struct {
	Type string
	URI  string
}

LicenseMetadata represents a license entry for a dependency.

type TargetInfo

type TargetInfo struct {
	OS            string
	Arch          string
	DistroName    string
	DistroVersion string
}

TargetInfo represents the target platform information.

type TestPaths

type TestPaths struct {
	AppDir       string
	BuildpackDir string
	PlatformDir  string
	LayersDir    string
}

TestPaths holds the directory paths used during test execution.

Directories

Path Synopsis
internal
testdir
Package testdir provides temporary directory management for tests.
Package testdir provides temporary directory management for tests.
toml
Package toml provides TOML helpers for the bptest package.
Package toml provides TOML helpers for the bptest package.
Package matchers provides Gomega matchers for bptest result types.
Package matchers provides Gomega matchers for bptest result types.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL