Files
syft/syft/pkg/cataloger/binary/classifier_test.go
T
William Murphy b7a6d5e946 feat: Record where CPEs come from (#2552)
Syft can get CPEs from several source, including generating them based on
package data, finding them in the NVD CPE dictionary, or finding them declared
in a manifest or existing SBOM. Record where Syft got CPEs so that consumers of
SBOMs can reason about how trustworthy they are.

Signed-off-by: Will Murphy <will.murphy@anchore.com>
2024-02-02 16:17:52 +00:00

131 lines
3.3 KiB
Go

package binary
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/anchore/packageurl-go"
"github.com/anchore/syft/syft/cpe"
"github.com/anchore/syft/syft/file"
)
func Test_ClassifierCPEs(t *testing.T) {
tests := []struct {
name string
fixture string
classifier Classifier
cpes []string
}{
{
name: "no CPEs",
fixture: "test-fixtures/version.txt",
classifier: Classifier{
Package: "some-app",
FileGlob: "**/version.txt",
EvidenceMatcher: FileContentsVersionMatcher(`(?m)my-verison:(?P<version>[0-9.]+)`),
CPEs: []cpe.CPE{},
},
cpes: nil,
},
{
name: "one Attributes",
fixture: "test-fixtures/version.txt",
classifier: Classifier{
Package: "some-app",
FileGlob: "**/version.txt",
EvidenceMatcher: FileContentsVersionMatcher(`(?m)my-verison:(?P<version>[0-9.]+)`),
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
},
},
cpes: []string{
"cpe:2.3:a:some:app:1.8:*:*:*:*:*:*:*",
},
},
{
name: "multiple CPEs",
fixture: "test-fixtures/version.txt",
classifier: Classifier{
Package: "some-app",
FileGlob: "**/version.txt",
EvidenceMatcher: FileContentsVersionMatcher(`(?m)my-verison:(?P<version>[0-9.]+)`),
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
cpe.Must("cpe:2.3:a:some:apps:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
},
},
cpes: []string{
"cpe:2.3:a:some:app:1.8:*:*:*:*:*:*:*",
"cpe:2.3:a:some:apps:1.8:*:*:*:*:*:*:*",
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
resolver := file.NewMockResolverForPaths(test.fixture)
ls, err := resolver.FilesByPath(test.fixture)
require.NoError(t, err)
require.Len(t, ls, 1)
pkgs, err := test.classifier.EvidenceMatcher(resolver, test.classifier, ls[0])
require.NoError(t, err)
require.Len(t, pkgs, 1)
p := pkgs[0]
var cpes []string
for _, c := range p.CPEs {
cpes = append(cpes, c.Attributes.String())
}
require.Equal(t, test.cpes, cpes)
})
}
}
func TestClassifier_MarshalJSON(t *testing.T) {
tests := []struct {
name string
classifier Classifier
want string
wantErr assert.ErrorAssertionFunc
}{
{
name: "go case",
classifier: Classifier{
Class: "class",
FileGlob: "glob",
EvidenceMatcher: FileContentsVersionMatcher(".thing"),
Package: "pkg",
PURL: packageurl.PackageURL{
Type: "type",
Namespace: "namespace",
Name: "name",
Version: "version",
Qualifiers: nil,
Subpath: "subpath",
},
CPEs: []cpe.CPE{cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*", cpe.GeneratedSource)},
},
want: `{"class":"class","fileGlob":"glob","package":"pkg","purl":"pkg:type/namespace/name@version#subpath","cpes":["cpe:2.3:a:some:app:*:*:*:*:*:*:*:*"]}`,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.wantErr == nil {
tt.wantErr = assert.NoError
}
cfg := tt.classifier
got, err := cfg.MarshalJSON()
if !tt.wantErr(t, err) {
return
}
assert.Equal(t, tt.want, string(got))
})
}
}