mirror of
https://github.com/anchore/syft.git
synced 2026-10-30 14:02:26 +01:00
* ci: run the full unit suite on windows via make unit Drops the curated `unit:windows` subset; the windows job now bootstraps like linux and runs `make unit`. Exceptions get added as failures show up. Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * ci: skip fixture refresh for windows unit tests binny has no windows release, so the bootstrap action can't install the tools the fixture refresh needs. Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * test: skip linux container fixtures when docker can't run them Windows CI runners only run windows containers, so image fixtures go through `testutils.SkipWithoutLinuxContainers`. No behavior change on linux/mac. Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix: close leaked file handles and posix squashfs paths on windows - output writers are now closed on early returns in `scan`/`convert` (open handles block cleanup on windows) - `newSBOMMultiWriter` used `path.Dir` on host paths, so output subdirectories were never created on windows - squashfs walk paths were built with `filepath.Join` - skip a few posix-only test cases (dir perms, xdg fallback, go-rpmdb ndb handle leak upstream) Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix(golang): resolve go source module dir natively on windows - `parseGoModFile` passed the resolver's posix (`/c/...`) path to the go toolchain, so go source resolution silently found nothing on windows - skip container-built fixtures (go archs, java builds) and golden image tarballs on windows; stereoscope's layer cache filenames contain `:`, which windows rejects Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix: keep posix paths posix on windows - `ChrootContext.ToChrootPath` nested volumes (`D:\cwd\C:\root`) when the scan root was on another drive, so the prefix was never trimmed - bitnami, python wheel/egg, and alpm parsers used `filepath` on posix location paths - alpm backup-file lookups silently missed on windows Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * ci: pull the test fixture cache for windows unit tests Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix: don't map virtual file tree paths through the host on windows `FiletreeResolver` without a chroot (snaps) ran request paths through `filepath.Abs`, rooting them on the current volume (`/payload.txt` -> `/d/payload.txt`), so snap scans on windows found nothing. Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix: match tar entry globs as posix on windows - `matchesAnyGlob` used `doublestar.PathMatch` (host separator) on tar entry names, so tar-wrapped java archives silently produced nothing on windows - test helpers now treat binary snippet keys and `FromFile` locations as posix Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * incorporate windows path fix Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * incorporate go-rpmdb close fix Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * close squashfs fixture writers before finalizing - windows dir listings can report a zero size for files still open, so the manifest was packed empty (also adds a temporary windows diagnostic for the binary cataloger) Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * temp: surface windows binary cataloger diagnostics Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix: keep directory symlink targets posix on windows - the directory indexer joined symlink targets with native separators, so links in the posix file tree pointed nowhere and globs on link names found nothing - binary fixture logical keys used native separators, so nested snippets were picked as the fixture dir on windows Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * keep addSymlinkToIndex under the funlen limit Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * drop windows skips covered by the stereoscope and go-rpmdb bumps Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
152 lines
4.5 KiB
Go
152 lines
4.5 KiB
Go
package testutil
|
|
|
|
import (
|
|
"context"
|
|
"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/internal/testutils"
|
|
"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"
|
|
)
|
|
|
|
//nolint:goconst // fixture data: the repeated names and versions are what the golden files assert against, so they read better spelled out than behind constants
|
|
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:
|
|
testutils.SkipWithoutLinuxContainers(t)
|
|
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("testdata", 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
|
|
}
|
|
|
|
//nolint:goconst // fixture data: the repeated names and versions are what the golden files assert against, so they read better spelled out than behind constants
|
|
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)
|
|
ctx := context.TODO()
|
|
// 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.NewLicenseWithContext(ctx, "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),
|
|
},
|
|
})
|
|
}
|
|
}
|