Files
syft/syft/format/internal/testutil/image_input.go
T
2024-02-27 16:44:37 -05:00

147 lines
4.1 KiB
Go

package testutil
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
"github.com/anchore/stereoscope/pkg/filetree"
"github.com/anchore/stereoscope/pkg/image"
"github.com/anchore/stereoscope/pkg/imagetest"
"github.com/anchore/syft/syft/cpe"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/linux"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/sbom"
"github.com/anchore/syft/syft/source/stereoscopesource"
)
func ImageInput(t testing.TB, testImage string, options ...ImageOption) sbom.SBOM {
t.Helper()
catalog := pkg.NewCollection()
var cfg imageCfg
var img *image.Image
for _, opt := range options {
opt(&cfg)
}
defer changeToDirectoryWithGoldenFixture(t, testImage)()
switch cfg.fromSnapshot {
case true:
img = imagetest.GetGoldenFixtureImage(t, testImage)
default:
img = imagetest.GetFixtureImage(t, "docker-archive", testImage)
}
populateImageCatalog(catalog, img)
// this is a hard coded value that is not given by the fixture helper and must be provided manually
img.Metadata.ManifestDigest = "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368"
src := stereoscopesource.New(img, stereoscopesource.ImageConfig{
Reference: "user-image-input",
})
return sbom.SBOM{
Artifacts: sbom.Artifacts{
Packages: catalog,
LinuxDistribution: &linux.Release{
PrettyName: "debian",
Name: "debian",
ID: "debian",
IDLike: []string{"like!"},
Version: "1.2.3",
VersionID: "1.2.3",
},
},
Source: src.Describe(),
Descriptor: sbom.Descriptor{
Name: "syft",
Version: "v0.42.0-bogus",
// the application configuration should be persisted here, however, we do not want to import
// the application configuration in this package (it's reserved only for ingestion by the cmd package)
Configuration: map[string]string{
"config-key": "config-value",
},
},
}
}
func changeToDirectoryWithGoldenFixture(t testing.TB, testImage string) func() {
// check if test fixture exists... if not, check if there is a shared fixture relative to this dir
fn := func() {}
path := filepath.Join("test-fixtures", testImage)
if _, err := os.Stat(path); err != nil {
// change dir, restore as defer
wd, err := os.Getwd()
require.NoError(t, err)
fn = func() {
require.NoError(t, os.Chdir(wd))
}
// change dir to the testutil dir
require.NoError(t, os.Chdir(filepath.Join(wd, "..", "internal", "testutil")))
t.Cleanup(fn)
if _, err := os.Stat(path); err != nil {
t.Fatalf("unable to find test fixture: %s", path)
}
}
return fn
}
func populateImageCatalog(catalog *pkg.Collection, img *image.Image) {
// TODO: this helper function is coupled to the image-simple fixture, which seems like a bad idea
_, ref1, _ := img.SquashedTree().File("/somefile-1.txt", filetree.FollowBasenameLinks)
_, ref2, _ := img.SquashedTree().File("/somefile-2.txt", filetree.FollowBasenameLinks)
// populate catalog with test data
if ref1 != nil {
catalog.Add(pkg.Package{
Name: "package-1",
Version: "1.0.1",
Locations: file.NewLocationSet(
file.NewLocationFromImage(string(ref1.RealPath), *ref1.Reference, img),
),
Type: pkg.PythonPkg,
FoundBy: "the-cataloger-1",
Language: pkg.Python,
Licenses: pkg.NewLicenseSet(
pkg.NewLicense("MIT"),
),
Metadata: pkg.PythonPackage{
Name: "package-1",
Version: "1.0.1",
},
PURL: "a-purl-1", // intentionally a bad pURL for test fixtures
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:*:some:package:1:*:*:*:*:*:*:*", cpe.GeneratedSource),
},
})
}
if ref2 != nil {
catalog.Add(pkg.Package{
Name: "package-2",
Version: "2.0.1",
Locations: file.NewLocationSet(
file.NewLocationFromImage(string(ref2.RealPath), *ref2.Reference, img),
),
Type: pkg.DebPkg,
FoundBy: "the-cataloger-2",
Metadata: pkg.DpkgDBEntry{
Package: "package-2",
Version: "2.0.1",
},
PURL: "pkg:deb/debian/package-2@2.0.1",
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
},
})
}
}