mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
update existing presenter tests to use the shared format test helpers
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
parent
50408b52d1
commit
3ca797dc53
@ -4,13 +4,15 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"regexp"
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/internal/formats/common/testutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
var updateCycloneDx = flag.Bool("update-cyclonedx", false, "update the *.golden files for cyclone-dx presenters")
|
var updateCycloneDx = flag.Bool("update-cyclonedx", false, "update the *.golden files for cyclone-dx presenters")
|
||||||
|
|
||||||
func TestCycloneDxDirectoryPresenter(t *testing.T) {
|
func TestCycloneDxDirectoryPresenter(t *testing.T) {
|
||||||
catalog, metadata, _ := presenterDirectoryInput(t)
|
catalog, metadata, _ := testutils.DirectoryInput(t)
|
||||||
assertPresenterAgainstGoldenSnapshot(t,
|
testutils.AssertPresenterAgainstGoldenSnapshot(t,
|
||||||
NewCycloneDxPresenter(catalog, metadata),
|
NewCycloneDxPresenter(catalog, metadata),
|
||||||
*updateCycloneDx,
|
*updateCycloneDx,
|
||||||
cycloneDxRedactor,
|
cycloneDxRedactor,
|
||||||
@ -19,8 +21,8 @@ func TestCycloneDxDirectoryPresenter(t *testing.T) {
|
|||||||
|
|
||||||
func TestCycloneDxImagePresenter(t *testing.T) {
|
func TestCycloneDxImagePresenter(t *testing.T) {
|
||||||
testImage := "image-simple"
|
testImage := "image-simple"
|
||||||
catalog, metadata, _ := presenterImageInput(t, testImage)
|
catalog, metadata, _ := testutils.ImageInput(t, testImage)
|
||||||
assertPresenterAgainstGoldenImageSnapshot(t,
|
testutils.AssertPresenterAgainstGoldenImageSnapshot(t,
|
||||||
NewCycloneDxPresenter(catalog, metadata),
|
NewCycloneDxPresenter(catalog, metadata),
|
||||||
testImage,
|
testImage,
|
||||||
*updateCycloneDx,
|
*updateCycloneDx,
|
||||||
|
|||||||
@ -1,527 +0,0 @@
|
|||||||
package packages
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/anchore/syft/syft/source"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
|
|
||||||
"github.com/anchore/syft/internal/presenter/packages/model/spdx22"
|
|
||||||
"github.com/anchore/syft/syft/pkg"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_getSPDXExternalRefs(t *testing.T) {
|
|
||||||
testCPE := must(pkg.NewCPE("cpe:2.3:a:name:name:3.2:*:*:*:*:*:*:*"))
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
input pkg.Package
|
|
||||||
expected []spdx22.ExternalRef
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "cpe + purl",
|
|
||||||
input: pkg.Package{
|
|
||||||
CPEs: []pkg.CPE{
|
|
||||||
testCPE,
|
|
||||||
},
|
|
||||||
PURL: "a-purl",
|
|
||||||
},
|
|
||||||
expected: []spdx22.ExternalRef{
|
|
||||||
{
|
|
||||||
ReferenceCategory: spdx22.SecurityReferenceCategory,
|
|
||||||
ReferenceLocator: testCPE.BindToFmtString(),
|
|
||||||
ReferenceType: spdx22.Cpe23ExternalRefType,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ReferenceCategory: spdx22.PackageManagerReferenceCategory,
|
|
||||||
ReferenceLocator: "a-purl",
|
|
||||||
ReferenceType: spdx22.PurlExternalRefType,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
|
||||||
assert.ElementsMatch(t, test.expected, getSPDXExternalRefs(&test.input))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_getSPDXLicense(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
input pkg.Package
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "no licenses",
|
|
||||||
input: pkg.Package{},
|
|
||||||
expected: "NONE",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "no SPDX licenses",
|
|
||||||
input: pkg.Package{
|
|
||||||
Licenses: []string{
|
|
||||||
"made-up",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "NOASSERTION",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with SPDX license",
|
|
||||||
input: pkg.Package{
|
|
||||||
Licenses: []string{
|
|
||||||
"MIT",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "MIT",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with SPDX license expression",
|
|
||||||
input: pkg.Package{
|
|
||||||
Licenses: []string{
|
|
||||||
"MIT",
|
|
||||||
"GPL-3.0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "MIT AND GPL-3.0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "cap insensitive",
|
|
||||||
input: pkg.Package{
|
|
||||||
Licenses: []string{
|
|
||||||
"gpl-3.0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "GPL-3.0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "debian to spdx conversion",
|
|
||||||
input: pkg.Package{
|
|
||||||
Licenses: []string{
|
|
||||||
"GPL-2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "GPL-2.0",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
|
||||||
assert.Equal(t, test.expected, getSPDXLicense(&test.input))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_noneIfEmpty(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
value string
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "non-zero value",
|
|
||||||
value: "something",
|
|
||||||
expected: "something",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "empty",
|
|
||||||
value: "",
|
|
||||||
expected: "NONE",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "space",
|
|
||||||
value: " ",
|
|
||||||
expected: "NONE",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "tab",
|
|
||||||
value: "\t",
|
|
||||||
expected: "NONE",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
|
||||||
assert.Equal(t, test.expected, noneIfEmpty(test.value))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_getSPDXDownloadLocation(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
input pkg.Package
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "no metadata",
|
|
||||||
input: pkg.Package{},
|
|
||||||
expected: "NOASSERTION",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "from apk",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.ApkMetadata{
|
|
||||||
URL: "http://a-place.gov",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "http://a-place.gov",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "from npm",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.NpmPackageJSONMetadata{
|
|
||||||
URL: "http://a-place.gov",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "http://a-place.gov",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "empty",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.NpmPackageJSONMetadata{
|
|
||||||
URL: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "NONE",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
|
||||||
assert.Equal(t, test.expected, getSPDXDownloadLocation(&test.input))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_getSPDXHomepage(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
input pkg.Package
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
// note: since this is an optional field, no value is preferred over NONE or NOASSERTION
|
|
||||||
name: "no metadata",
|
|
||||||
input: pkg.Package{},
|
|
||||||
expected: "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "from gem",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.GemMetadata{
|
|
||||||
Homepage: "http://a-place.gov",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "http://a-place.gov",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "from npm",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.NpmPackageJSONMetadata{
|
|
||||||
Homepage: "http://a-place.gov",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "http://a-place.gov",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// note: since this is an optional field, no value is preferred over NONE or NOASSERTION
|
|
||||||
name: "empty",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.NpmPackageJSONMetadata{
|
|
||||||
Homepage: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
|
||||||
assert.Equal(t, test.expected, getSPDXHomepage(&test.input))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_getSPDXSourceInfo(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
input pkg.Package
|
|
||||||
expected []string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "locations are captured",
|
|
||||||
input: pkg.Package{
|
|
||||||
// note: no type given
|
|
||||||
Locations: []source.Location{
|
|
||||||
{
|
|
||||||
RealPath: "/a-place",
|
|
||||||
VirtualPath: "/b-place",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
RealPath: "/c-place",
|
|
||||||
VirtualPath: "/d-place",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: []string{
|
|
||||||
"from the following paths",
|
|
||||||
"/a-place",
|
|
||||||
"/c-place",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// note: no specific support for this
|
|
||||||
input: pkg.Package{
|
|
||||||
Type: pkg.KbPkg,
|
|
||||||
},
|
|
||||||
expected: []string{
|
|
||||||
"from the following paths",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: pkg.Package{
|
|
||||||
Type: pkg.RpmPkg,
|
|
||||||
},
|
|
||||||
expected: []string{
|
|
||||||
"from RPM DB",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: pkg.Package{
|
|
||||||
Type: pkg.ApkPkg,
|
|
||||||
},
|
|
||||||
expected: []string{
|
|
||||||
"from APK DB",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: pkg.Package{
|
|
||||||
Type: pkg.DebPkg,
|
|
||||||
},
|
|
||||||
expected: []string{
|
|
||||||
"from DPKG DB",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: pkg.Package{
|
|
||||||
Type: pkg.NpmPkg,
|
|
||||||
},
|
|
||||||
expected: []string{
|
|
||||||
"from installed node module manifest file",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: pkg.Package{
|
|
||||||
Type: pkg.PythonPkg,
|
|
||||||
},
|
|
||||||
expected: []string{
|
|
||||||
"from installed python package manifest file",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: pkg.Package{
|
|
||||||
Type: pkg.JavaPkg,
|
|
||||||
},
|
|
||||||
expected: []string{
|
|
||||||
"from installed java archive",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: pkg.Package{
|
|
||||||
Type: pkg.JenkinsPluginPkg,
|
|
||||||
},
|
|
||||||
expected: []string{
|
|
||||||
"from installed java archive",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: pkg.Package{
|
|
||||||
Type: pkg.GemPkg,
|
|
||||||
},
|
|
||||||
expected: []string{
|
|
||||||
"from installed gem metadata file",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: pkg.Package{
|
|
||||||
Type: pkg.GoModulePkg,
|
|
||||||
},
|
|
||||||
expected: []string{
|
|
||||||
"from go module information",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: pkg.Package{
|
|
||||||
Type: pkg.RustPkg,
|
|
||||||
},
|
|
||||||
expected: []string{
|
|
||||||
"from rust cargo manifest",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
var pkgTypes []pkg.Type
|
|
||||||
for _, test := range tests {
|
|
||||||
t.Run(test.name+" "+string(test.input.Type), func(t *testing.T) {
|
|
||||||
if test.input.Type != "" {
|
|
||||||
pkgTypes = append(pkgTypes, test.input.Type)
|
|
||||||
}
|
|
||||||
actual := getSPDXSourceInfo(&test.input)
|
|
||||||
for _, expected := range test.expected {
|
|
||||||
assert.Contains(t, actual, expected)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
assert.ElementsMatch(t, pkg.AllPkgs, pkgTypes, "missing one or more package types to test against (maybe a package type was added?)")
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_getSPDXOriginator(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
input pkg.Package
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
// note: since this is an optional field, no value is preferred over NONE or NOASSERTION
|
|
||||||
name: "no metadata",
|
|
||||||
input: pkg.Package{},
|
|
||||||
expected: "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "from gem",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.GemMetadata{
|
|
||||||
Authors: []string{
|
|
||||||
"auth1",
|
|
||||||
"auth2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "auth1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "from npm",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.NpmPackageJSONMetadata{
|
|
||||||
Author: "auth",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "auth",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "from apk",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.ApkMetadata{
|
|
||||||
Maintainer: "auth",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "auth",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "from python - just name",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.PythonPackageMetadata{
|
|
||||||
Author: "auth",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "auth",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "from python - just email",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.PythonPackageMetadata{
|
|
||||||
AuthorEmail: "auth@auth.gov",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "auth@auth.gov",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "from python - both name and email",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.PythonPackageMetadata{
|
|
||||||
Author: "auth",
|
|
||||||
AuthorEmail: "auth@auth.gov",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "auth <auth@auth.gov>",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "from rpm",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.RpmdbMetadata{
|
|
||||||
Vendor: "auth",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "auth",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "from dpkg",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.DpkgMetadata{
|
|
||||||
Maintainer: "auth",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "auth",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// note: since this is an optional field, no value is preferred over NONE or NOASSERTION
|
|
||||||
name: "empty",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.NpmPackageJSONMetadata{
|
|
||||||
Author: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
|
||||||
assert.Equal(t, test.expected, getSPDXOriginator(&test.input))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_getSPDXDescription(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
input pkg.Package
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
// note: since this is an optional field, no value is preferred over NONE or NOASSERTION
|
|
||||||
name: "no metadata",
|
|
||||||
input: pkg.Package{},
|
|
||||||
expected: "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "from apk",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.ApkMetadata{
|
|
||||||
Description: "a description!",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "a description!",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "from npm",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.NpmPackageJSONMetadata{
|
|
||||||
Description: "a description!",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "a description!",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// note: since this is an optional field, no value is preferred over NONE or NOASSERTION
|
|
||||||
name: "empty",
|
|
||||||
input: pkg.Package{
|
|
||||||
Metadata: pkg.NpmPackageJSONMetadata{
|
|
||||||
Homepage: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
|
||||||
assert.Equal(t, test.expected, getSPDXDescription(&test.input))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -5,6 +5,8 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/internal/formats/common/spdxhelpers"
|
||||||
|
|
||||||
"github.com/anchore/syft/internal/spdxlicense"
|
"github.com/anchore/syft/internal/spdxlicense"
|
||||||
|
|
||||||
"github.com/anchore/syft/internal"
|
"github.com/anchore/syft/internal"
|
||||||
@ -114,7 +116,7 @@ func (pres *SPDXTagValuePresenter) packages() map[spdx.ElementID]*spdx.Package2_
|
|||||||
// If the Concluded License is not the same as the Declared License, a written explanation should be provided
|
// If the Concluded License is not the same as the Declared License, a written explanation should be provided
|
||||||
// in the Comments on License field (section 3.16). With respect to NOASSERTION, a written explanation in
|
// in the Comments on License field (section 3.16). With respect to NOASSERTION, a written explanation in
|
||||||
// the Comments on License field (section 3.16) is preferred.
|
// the Comments on License field (section 3.16) is preferred.
|
||||||
license := getSPDXLicense(p)
|
license := spdxhelpers.License(p)
|
||||||
|
|
||||||
results[spdx.ElementID(id)] = &spdx.Package2_2{
|
results[spdx.ElementID(id)] = &spdx.Package2_2{
|
||||||
|
|
||||||
@ -274,7 +276,7 @@ func (pres *SPDXTagValuePresenter) packages() map[spdx.ElementID]*spdx.Package2_
|
|||||||
}
|
}
|
||||||
|
|
||||||
func formatSPDXExternalRefs(p *pkg.Package) (refs []*spdx.PackageExternalReference2_2) {
|
func formatSPDXExternalRefs(p *pkg.Package) (refs []*spdx.PackageExternalReference2_2) {
|
||||||
for _, ref := range getSPDXExternalRefs(p) {
|
for _, ref := range spdxhelpers.ExternalRefs(p) {
|
||||||
refs = append(refs, &spdx.PackageExternalReference2_2{
|
refs = append(refs, &spdx.PackageExternalReference2_2{
|
||||||
Category: string(ref.ReferenceCategory),
|
Category: string(ref.ReferenceCategory),
|
||||||
RefType: string(ref.ReferenceType),
|
RefType: string(ref.ReferenceType),
|
||||||
|
|||||||
@ -4,13 +4,15 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"regexp"
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/internal/formats/common/testutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
var updateSpdxTagValue = flag.Bool("update-spdx-tv", false, "update the *.golden files for spdx-tv presenters")
|
var updateSpdxTagValue = flag.Bool("update-spdx-tv", false, "update the *.golden files for spdx-tv presenters")
|
||||||
|
|
||||||
func TestSPDXTagValueDirectoryPresenter(t *testing.T) {
|
func TestSPDXTagValueDirectoryPresenter(t *testing.T) {
|
||||||
catalog, metadata, _ := presenterDirectoryInput(t)
|
catalog, metadata, _ := testutils.DirectoryInput(t)
|
||||||
assertPresenterAgainstGoldenSnapshot(t,
|
testutils.AssertPresenterAgainstGoldenSnapshot(t,
|
||||||
NewSPDXTagValuePresenter(catalog, metadata),
|
NewSPDXTagValuePresenter(catalog, metadata),
|
||||||
*updateSpdxTagValue,
|
*updateSpdxTagValue,
|
||||||
spdxTagValueRedactor,
|
spdxTagValueRedactor,
|
||||||
@ -19,8 +21,8 @@ func TestSPDXTagValueDirectoryPresenter(t *testing.T) {
|
|||||||
|
|
||||||
func TestSPDXTagValueImagePresenter(t *testing.T) {
|
func TestSPDXTagValueImagePresenter(t *testing.T) {
|
||||||
testImage := "image-simple"
|
testImage := "image-simple"
|
||||||
catalog, metadata, _ := presenterImageInput(t, testImage)
|
catalog, metadata, _ := testutils.ImageInput(t, testImage)
|
||||||
assertPresenterAgainstGoldenImageSnapshot(t,
|
testutils.AssertPresenterAgainstGoldenImageSnapshot(t,
|
||||||
NewSPDXTagValuePresenter(catalog, metadata),
|
NewSPDXTagValuePresenter(catalog, metadata),
|
||||||
testImage,
|
testImage,
|
||||||
*updateSpdxTagValue,
|
*updateSpdxTagValue,
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/internal/formats/common/testutils"
|
||||||
|
|
||||||
"github.com/go-test/deep"
|
"github.com/go-test/deep"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -11,8 +13,8 @@ var updateTablePresenterGoldenFiles = flag.Bool("update-table", false, "update t
|
|||||||
|
|
||||||
func TestTablePresenter(t *testing.T) {
|
func TestTablePresenter(t *testing.T) {
|
||||||
testImage := "image-simple"
|
testImage := "image-simple"
|
||||||
catalog, _, _ := presenterImageInput(t, testImage)
|
catalog, _, _ := testutils.ImageInput(t, testImage)
|
||||||
assertPresenterAgainstGoldenImageSnapshot(t,
|
testutils.AssertPresenterAgainstGoldenImageSnapshot(t,
|
||||||
NewTablePresenter(catalog),
|
NewTablePresenter(catalog),
|
||||||
testImage,
|
testImage,
|
||||||
*updateTablePresenterGoldenFiles,
|
*updateTablePresenterGoldenFiles,
|
||||||
|
|||||||
@ -1,79 +0,0 @@
|
|||||||
{
|
|
||||||
"SPDXID": "SPDXRef-DOCUMENT",
|
|
||||||
"name": "/some/path",
|
|
||||||
"spdxVersion": "SPDX-2.2",
|
|
||||||
"creationInfo": {
|
|
||||||
"created": "2021-09-16T20:44:35.198887Z",
|
|
||||||
"creators": [
|
|
||||||
"Organization: Anchore, Inc",
|
|
||||||
"Tool: syft-[not provided]"
|
|
||||||
],
|
|
||||||
"licenseListVersion": "3.14"
|
|
||||||
},
|
|
||||||
"dataLicense": "CC0-1.0",
|
|
||||||
"documentNamespace": "https://anchore.com/syft/image/",
|
|
||||||
"packages": [
|
|
||||||
{
|
|
||||||
"SPDXID": "SPDXRef-Package-python-package-1-1.0.1",
|
|
||||||
"name": "package-1",
|
|
||||||
"licenseConcluded": "MIT",
|
|
||||||
"downloadLocation": "NOASSERTION",
|
|
||||||
"externalRefs": [
|
|
||||||
{
|
|
||||||
"referenceCategory": "SECURITY",
|
|
||||||
"referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*",
|
|
||||||
"referenceType": "cpe23Type"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"referenceCategory": "PACKAGE_MANAGER",
|
|
||||||
"referenceLocator": "a-purl-2",
|
|
||||||
"referenceType": "purl"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filesAnalyzed": false,
|
|
||||||
"hasFiles": [
|
|
||||||
"SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9"
|
|
||||||
],
|
|
||||||
"licenseDeclared": "MIT",
|
|
||||||
"sourceInfo": "acquired package info from installed python package manifest file: /some/path/pkg1",
|
|
||||||
"versionInfo": "1.0.1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"SPDXID": "SPDXRef-Package-deb-package-2-2.0.1",
|
|
||||||
"name": "package-2",
|
|
||||||
"licenseConcluded": "NONE",
|
|
||||||
"downloadLocation": "NOASSERTION",
|
|
||||||
"externalRefs": [
|
|
||||||
{
|
|
||||||
"referenceCategory": "SECURITY",
|
|
||||||
"referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*",
|
|
||||||
"referenceType": "cpe23Type"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"referenceCategory": "PACKAGE_MANAGER",
|
|
||||||
"referenceLocator": "a-purl-2",
|
|
||||||
"referenceType": "purl"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filesAnalyzed": false,
|
|
||||||
"licenseDeclared": "NONE",
|
|
||||||
"sourceInfo": "acquired package info from DPKG DB: /some/path/pkg1",
|
|
||||||
"versionInfo": "2.0.1"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"files": [
|
|
||||||
{
|
|
||||||
"SPDXID": "SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9",
|
|
||||||
"name": "foo",
|
|
||||||
"licenseConcluded": "",
|
|
||||||
"fileName": "/some/path/pkg1/depedencies/foo"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"relationships": [
|
|
||||||
{
|
|
||||||
"spdxElementId": "SPDXRef-Package-python-package-1-1.0.1",
|
|
||||||
"relationshipType": "CONTAINS",
|
|
||||||
"relatedSpdxElement": "SPDXRef-File-package-1-04cd22424378dcd6c77fce08beb52493b5494a60ea5e1f9bdf9b16dc0cacffe9"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
{
|
|
||||||
"SPDXID": "SPDXRef-DOCUMENT",
|
|
||||||
"name": "user-image-input",
|
|
||||||
"spdxVersion": "SPDX-2.2",
|
|
||||||
"creationInfo": {
|
|
||||||
"created": "2021-09-16T20:44:35.203911Z",
|
|
||||||
"creators": [
|
|
||||||
"Organization: Anchore, Inc",
|
|
||||||
"Tool: syft-[not provided]"
|
|
||||||
],
|
|
||||||
"licenseListVersion": "3.14"
|
|
||||||
},
|
|
||||||
"dataLicense": "CC0-1.0",
|
|
||||||
"documentNamespace": "https://anchore.com/syft/image/user-image-input",
|
|
||||||
"packages": [
|
|
||||||
{
|
|
||||||
"SPDXID": "SPDXRef-Package-python-package-1-1.0.1",
|
|
||||||
"name": "package-1",
|
|
||||||
"licenseConcluded": "MIT",
|
|
||||||
"downloadLocation": "NOASSERTION",
|
|
||||||
"externalRefs": [
|
|
||||||
{
|
|
||||||
"referenceCategory": "SECURITY",
|
|
||||||
"referenceLocator": "cpe:2.3:*:some:package:1:*:*:*:*:*:*:*",
|
|
||||||
"referenceType": "cpe23Type"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"referenceCategory": "PACKAGE_MANAGER",
|
|
||||||
"referenceLocator": "a-purl-1",
|
|
||||||
"referenceType": "purl"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filesAnalyzed": false,
|
|
||||||
"licenseDeclared": "MIT",
|
|
||||||
"sourceInfo": "acquired package info from installed python package manifest file: /somefile-1.txt",
|
|
||||||
"versionInfo": "1.0.1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"SPDXID": "SPDXRef-Package-deb-package-2-2.0.1",
|
|
||||||
"name": "package-2",
|
|
||||||
"licenseConcluded": "NONE",
|
|
||||||
"downloadLocation": "NOASSERTION",
|
|
||||||
"externalRefs": [
|
|
||||||
{
|
|
||||||
"referenceCategory": "SECURITY",
|
|
||||||
"referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*",
|
|
||||||
"referenceType": "cpe23Type"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"referenceCategory": "PACKAGE_MANAGER",
|
|
||||||
"referenceLocator": "a-purl-2",
|
|
||||||
"referenceType": "purl"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filesAnalyzed": false,
|
|
||||||
"licenseDeclared": "NONE",
|
|
||||||
"sourceInfo": "acquired package info from DPKG DB: /somefile-2.txt",
|
|
||||||
"versionInfo": "2.0.1"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -3,13 +3,15 @@ package packages
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/internal/formats/common/testutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
var updateTextPresenterGoldenFiles = flag.Bool("update-text", false, "update the *.golden files for text presenters")
|
var updateTextPresenterGoldenFiles = flag.Bool("update-text", false, "update the *.golden files for text presenters")
|
||||||
|
|
||||||
func TestTextDirectoryPresenter(t *testing.T) {
|
func TestTextDirectoryPresenter(t *testing.T) {
|
||||||
catalog, metadata, _ := presenterDirectoryInput(t)
|
catalog, metadata, _ := testutils.DirectoryInput(t)
|
||||||
assertPresenterAgainstGoldenSnapshot(t,
|
testutils.AssertPresenterAgainstGoldenSnapshot(t,
|
||||||
NewTextPresenter(catalog, metadata),
|
NewTextPresenter(catalog, metadata),
|
||||||
*updateTextPresenterGoldenFiles,
|
*updateTextPresenterGoldenFiles,
|
||||||
)
|
)
|
||||||
@ -17,8 +19,8 @@ func TestTextDirectoryPresenter(t *testing.T) {
|
|||||||
|
|
||||||
func TestTextImagePresenter(t *testing.T) {
|
func TestTextImagePresenter(t *testing.T) {
|
||||||
testImage := "image-simple"
|
testImage := "image-simple"
|
||||||
catalog, metadata, _ := presenterImageInput(t, testImage)
|
catalog, metadata, _ := testutils.ImageInput(t, testImage)
|
||||||
assertPresenterAgainstGoldenImageSnapshot(t,
|
testutils.AssertPresenterAgainstGoldenImageSnapshot(t,
|
||||||
NewTextPresenter(catalog, metadata),
|
NewTextPresenter(catalog, metadata),
|
||||||
testImage,
|
testImage,
|
||||||
*updateTextPresenterGoldenFiles,
|
*updateTextPresenterGoldenFiles,
|
||||||
|
|||||||
@ -1,199 +0,0 @@
|
|||||||
package packages
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/anchore/go-testutils"
|
|
||||||
"github.com/anchore/stereoscope/pkg/filetree"
|
|
||||||
"github.com/anchore/stereoscope/pkg/imagetest"
|
|
||||||
"github.com/anchore/syft/syft/distro"
|
|
||||||
"github.com/anchore/syft/syft/pkg"
|
|
||||||
"github.com/anchore/syft/syft/presenter"
|
|
||||||
"github.com/anchore/syft/syft/source"
|
|
||||||
"github.com/sergi/go-diff/diffmatchpatch"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
type redactor func(s []byte) []byte
|
|
||||||
|
|
||||||
func assertPresenterAgainstGoldenImageSnapshot(t *testing.T, pres presenter.Presenter, testImage string, updateSnapshot bool, redactors ...redactor) {
|
|
||||||
var buffer bytes.Buffer
|
|
||||||
|
|
||||||
// grab the latest image contents and persist
|
|
||||||
if updateSnapshot {
|
|
||||||
imagetest.UpdateGoldenFixtureImage(t, testImage)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := pres.Present(&buffer)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
actual := buffer.Bytes()
|
|
||||||
|
|
||||||
// replace the expected snapshot contents with the current presenter contents
|
|
||||||
if updateSnapshot {
|
|
||||||
testutils.UpdateGoldenFileContents(t, actual)
|
|
||||||
}
|
|
||||||
|
|
||||||
var expected = testutils.GetGoldenFileContents(t)
|
|
||||||
|
|
||||||
// remove dynamic values, which should be tested independently
|
|
||||||
for _, r := range redactors {
|
|
||||||
actual = r(actual)
|
|
||||||
expected = r(expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// assert that the golden file snapshot matches the actual contents
|
|
||||||
if !bytes.Equal(expected, actual) {
|
|
||||||
dmp := diffmatchpatch.New()
|
|
||||||
diffs := dmp.DiffMain(string(expected), string(actual), true)
|
|
||||||
t.Errorf("mismatched output:\n%s", dmp.DiffPrettyText(diffs))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertPresenterAgainstGoldenSnapshot(t *testing.T, pres presenter.Presenter, updateSnapshot bool, redactors ...redactor) {
|
|
||||||
var buffer bytes.Buffer
|
|
||||||
|
|
||||||
err := pres.Present(&buffer)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
actual := buffer.Bytes()
|
|
||||||
|
|
||||||
// replace the expected snapshot contents with the current presenter contents
|
|
||||||
if updateSnapshot {
|
|
||||||
testutils.UpdateGoldenFileContents(t, actual)
|
|
||||||
}
|
|
||||||
|
|
||||||
var expected = testutils.GetGoldenFileContents(t)
|
|
||||||
|
|
||||||
// remove dynamic values, which should be tested independently
|
|
||||||
for _, r := range redactors {
|
|
||||||
actual = r(actual)
|
|
||||||
expected = r(expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(expected, actual) {
|
|
||||||
dmp := diffmatchpatch.New()
|
|
||||||
diffs := dmp.DiffMain(string(expected), string(actual), true)
|
|
||||||
t.Errorf("mismatched output:\n%s", dmp.DiffPrettyText(diffs))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func presenterImageInput(t testing.TB, testImage string) (*pkg.Catalog, source.Metadata, *distro.Distro) {
|
|
||||||
t.Helper()
|
|
||||||
catalog := pkg.NewCatalog()
|
|
||||||
img := imagetest.GetGoldenFixtureImage(t, testImage)
|
|
||||||
|
|
||||||
_, ref1, _ := img.SquashedTree().File("/somefile-1.txt", filetree.FollowBasenameLinks)
|
|
||||||
_, ref2, _ := img.SquashedTree().File("/somefile-2.txt", filetree.FollowBasenameLinks)
|
|
||||||
|
|
||||||
// populate catalog with test data
|
|
||||||
catalog.Add(pkg.Package{
|
|
||||||
ID: "package-1-id",
|
|
||||||
Name: "package-1",
|
|
||||||
Version: "1.0.1",
|
|
||||||
Locations: []source.Location{
|
|
||||||
source.NewLocationFromImage(string(ref1.RealPath), *ref1, img),
|
|
||||||
},
|
|
||||||
Type: pkg.PythonPkg,
|
|
||||||
FoundBy: "the-cataloger-1",
|
|
||||||
Language: pkg.Python,
|
|
||||||
MetadataType: pkg.PythonPackageMetadataType,
|
|
||||||
Licenses: []string{"MIT"},
|
|
||||||
Metadata: pkg.PythonPackageMetadata{
|
|
||||||
Name: "package-1",
|
|
||||||
Version: "1.0.1",
|
|
||||||
},
|
|
||||||
PURL: "a-purl-1",
|
|
||||||
CPEs: []pkg.CPE{
|
|
||||||
must(pkg.NewCPE("cpe:2.3:*:some:package:1:*:*:*:*:*:*:*")),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
catalog.Add(pkg.Package{
|
|
||||||
ID: "package-2-id",
|
|
||||||
Name: "package-2",
|
|
||||||
Version: "2.0.1",
|
|
||||||
Locations: []source.Location{
|
|
||||||
source.NewLocationFromImage(string(ref2.RealPath), *ref2, img),
|
|
||||||
},
|
|
||||||
Type: pkg.DebPkg,
|
|
||||||
FoundBy: "the-cataloger-2",
|
|
||||||
MetadataType: pkg.DpkgMetadataType,
|
|
||||||
Metadata: pkg.DpkgMetadata{
|
|
||||||
Package: "package-2",
|
|
||||||
Version: "2.0.1",
|
|
||||||
},
|
|
||||||
PURL: "a-purl-2",
|
|
||||||
CPEs: []pkg.CPE{
|
|
||||||
must(pkg.NewCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*")),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
// 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, err := source.NewFromImage(img, "user-image-input")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
dist, err := distro.NewDistro(distro.Debian, "1.2.3", "like!")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
return catalog, src.Metadata, &dist
|
|
||||||
}
|
|
||||||
|
|
||||||
func presenterDirectoryInput(t testing.TB) (*pkg.Catalog, source.Metadata, *distro.Distro) {
|
|
||||||
catalog := pkg.NewCatalog()
|
|
||||||
|
|
||||||
// populate catalog with test data
|
|
||||||
catalog.Add(pkg.Package{
|
|
||||||
ID: "package-1-id",
|
|
||||||
Name: "package-1",
|
|
||||||
Version: "1.0.1",
|
|
||||||
Type: pkg.PythonPkg,
|
|
||||||
FoundBy: "the-cataloger-1",
|
|
||||||
Locations: []source.Location{
|
|
||||||
{RealPath: "/some/path/pkg1"},
|
|
||||||
},
|
|
||||||
Language: pkg.Python,
|
|
||||||
MetadataType: pkg.PythonPackageMetadataType,
|
|
||||||
Licenses: []string{"MIT"},
|
|
||||||
Metadata: pkg.PythonPackageMetadata{
|
|
||||||
Name: "package-1",
|
|
||||||
Version: "1.0.1",
|
|
||||||
Files: []pkg.PythonFileRecord{
|
|
||||||
{
|
|
||||||
Path: "/some/path/pkg1/depedencies/foo",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
PURL: "a-purl-2",
|
|
||||||
CPEs: []pkg.CPE{
|
|
||||||
must(pkg.NewCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*")),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
catalog.Add(pkg.Package{
|
|
||||||
ID: "package-2-id",
|
|
||||||
Name: "package-2",
|
|
||||||
Version: "2.0.1",
|
|
||||||
Type: pkg.DebPkg,
|
|
||||||
FoundBy: "the-cataloger-2",
|
|
||||||
Locations: []source.Location{
|
|
||||||
{RealPath: "/some/path/pkg1"},
|
|
||||||
},
|
|
||||||
MetadataType: pkg.DpkgMetadataType,
|
|
||||||
Metadata: pkg.DpkgMetadata{
|
|
||||||
Package: "package-2",
|
|
||||||
Version: "2.0.1",
|
|
||||||
},
|
|
||||||
PURL: "a-purl-2",
|
|
||||||
CPEs: []pkg.CPE{
|
|
||||||
must(pkg.NewCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*")),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
dist, err := distro.NewDistro(distro.Debian, "1.2.3", "like!")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
src, err := source.NewFromDirectory("/some/path")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
return catalog, src.Metadata, &dist
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user