Skip to content

Commit

Permalink
refactor: use runTest for SBOM tests
Browse files Browse the repository at this point in the history
Signed-off-by: knqyf263 <[email protected]>
  • Loading branch information
knqyf263 committed May 3, 2024
1 parent 65e3a69 commit 74f3f42
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 106 deletions.
32 changes: 7 additions & 25 deletions integration/client_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ func TestClientServer(t *testing.T) {
}

runTest(t, osArgs, tt.golden, "", types.FormatJSON, runOptions{
override: clearUID,
override: overrideUID,
})
})
}
Expand Down Expand Up @@ -400,7 +400,7 @@ func TestClientServerWithFormat(t *testing.T) {
osArgs := setupClient(t, tt.args, addr, cacheDir, tt.golden)

runTest(t, osArgs, tt.golden, "", tt.args.Format, runOptions{
override: clearUID,
override: overrideUID,
})
})
}
Expand Down Expand Up @@ -480,7 +480,7 @@ func TestClientServerWithToken(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
osArgs := setupClient(t, tt.args, addr, cacheDir, tt.golden)
runTest(t, osArgs, tt.golden, "", types.FormatJSON, runOptions{
override: clearUID,
override: overrideUID,
wantErr: tt.wantErr,
})
})
Expand Down Expand Up @@ -508,7 +508,9 @@ func TestClientServerWithRedis(t *testing.T) {
osArgs := setupClient(t, testArgs, addr, cacheDir, golden)

// Run Trivy client
runTest(t, osArgs, golden, "", types.FormatJSON, runOptions{})
runTest(t, osArgs, golden, "", types.FormatJSON, runOptions{
override: overrideUID,
})
})

// Terminate the Redis container
Expand All @@ -519,8 +521,7 @@ func TestClientServerWithRedis(t *testing.T) {

// Run Trivy client
runTest(t, osArgs, "", "", types.FormatJSON, runOptions{
override: clearUID,
wantErr: "unable to store cache",
wantErr: "unable to store cache",
})
})
}
Expand Down Expand Up @@ -668,22 +669,3 @@ func setupRedis(t *testing.T, ctx context.Context) (testcontainers.Container, st
addr := fmt.Sprintf("redis://%s:%s", ip, p.Port())
return redis, addr
}

// clearUID only checks for the presence of the package UID and clears the UID;
// the UID is calculated from the package metadata, but the UID does not match
// as it varies slightly depending on the mode of scanning, e.g. the digest of the layer.
func clearUID(t *testing.T, want, got *types.Report) {
for i, result := range got.Results {
for j, vuln := range result.Vulnerabilities {
assert.NotEmptyf(t, vuln.PkgIdentifier.UID, "UID is empty: %s", vuln.VulnerabilityID)
// Do not compare UID as the package metadata is slightly different between the tests,
// causing different UIDs.
got.Results[i].Vulnerabilities[j].PkgIdentifier.UID = ""
}
}
for i, result := range want.Results {
for j := range result.Vulnerabilities {
want.Results[i].Vulnerabilities[j].PkgIdentifier.UID = ""
}
}
}
27 changes: 25 additions & 2 deletions integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,10 @@ func readSpdxJson(t *testing.T, filePath string) *spdx.Document {
return bom
}

type OverrideFunc func(t *testing.T, want, got *types.Report)
type runOptions struct {
wantErr string
override func(t *testing.T, want, got *types.Report)
override OverrideFunc
fakeUUID string
}

Expand Down Expand Up @@ -308,10 +309,32 @@ func validateReport(t *testing.T, schema string, report any) {
}
}

func overrideFuncs(funcs ...func(*testing.T, *types.Report, *types.Report)) func(*testing.T, *types.Report, *types.Report) {
func overrideFuncs(funcs ...OverrideFunc) OverrideFunc {
return func(t *testing.T, want, got *types.Report) {
for _, f := range funcs {
if f == nil {
continue
}
f(t, want, got)
}
}
}

// overrideUID only checks for the presence of the package UID and clears the UID;
// the UID is calculated from the package metadata, but the UID does not match
// as it varies slightly depending on the mode of scanning, e.g. the digest of the layer.
func overrideUID(t *testing.T, want, got *types.Report) {
for i, result := range got.Results {
for j, vuln := range result.Vulnerabilities {
assert.NotEmptyf(t, vuln.PkgIdentifier.UID, "UID is empty: %s", vuln.VulnerabilityID)
// Do not compare UID as the package metadata is slightly different between the tests,
// causing different UIDs.
got.Results[i].Vulnerabilities[j].PkgIdentifier.UID = ""
}
}
for i, result := range want.Results {
for j := range result.Vulnerabilities {
want.Results[i].Vulnerabilities[j].PkgIdentifier.UID = ""
}
}
}
2 changes: 1 addition & 1 deletion integration/registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func TestRegistry(t *testing.T) {
// Run Trivy
runTest(t, osArgs, tc.golden, "", types.FormatJSON, runOptions{
wantErr: tc.wantErr,
override: overrideFuncs(clearUID, func(t *testing.T, _, got *types.Report) {
override: overrideFuncs(overrideUID, func(t *testing.T, _, got *types.Report) {
got.ArtifactName = tc.imageName
for i := range got.Results {
got.Results[i].Target = fmt.Sprintf("%s (alpine 3.10.2)", tc.imageName)
Expand Down
134 changes: 56 additions & 78 deletions integration/sbom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import (
"path/filepath"
"testing"

ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/types"
)

Expand All @@ -25,7 +25,7 @@ func TestSBOM(t *testing.T) {
name string
args args
golden string
override types.Report
override OverrideFunc
}{
{
name: "centos7 cyclonedx",
Expand All @@ -35,31 +35,17 @@ func TestSBOM(t *testing.T) {
artifactType: "cyclonedx",
},
golden: "testdata/centos-7.json.golden",
override: types.Report{
ArtifactName: "testdata/fixtures/sbom/centos-7-cyclonedx.json",
ArtifactType: ftypes.ArtifactType("cyclonedx"),
Results: types.Results{
{
Target: "testdata/fixtures/sbom/centos-7-cyclonedx.json (centos 7.6.1810)",
Vulnerabilities: []types.DetectedVulnerability{
{
PkgIdentifier: ftypes.PkgIdentifier{
BOMRef: "pkg:rpm/centos/[email protected]?arch=x86_64&distro=centos-7.6.1810",
},
},
{
PkgIdentifier: ftypes.PkgIdentifier{
BOMRef: "pkg:rpm/centos/[email protected]?arch=x86_64&epoch=1&distro=centos-7.6.1810",
},
},
{
PkgIdentifier: ftypes.PkgIdentifier{
BOMRef: "pkg:rpm/centos/[email protected]?arch=x86_64&epoch=1&distro=centos-7.6.1810",
},
},
},
},
},
override: func(t *testing.T, want, got *types.Report) {
want.ArtifactName = "testdata/fixtures/sbom/centos-7-cyclonedx.json"
want.ArtifactType = ftypes.ArtifactCycloneDX

require.Len(t, got.Results, 1)
want.Results[0].Target = "testdata/fixtures/sbom/centos-7-cyclonedx.json (centos 7.6.1810)"

require.Len(t, got.Results[0].Vulnerabilities, 3)
want.Results[0].Vulnerabilities[0].PkgIdentifier.BOMRef = "pkg:rpm/centos/[email protected]?arch=x86_64&distro=centos-7.6.1810"
want.Results[0].Vulnerabilities[1].PkgIdentifier.BOMRef = "pkg:rpm/centos/[email protected]?arch=x86_64&epoch=1&distro=centos-7.6.1810"
want.Results[0].Vulnerabilities[2].PkgIdentifier.BOMRef = "pkg:rpm/centos/[email protected]?arch=x86_64&epoch=1&distro=centos-7.6.1810"
},
},
{
Expand Down Expand Up @@ -88,31 +74,17 @@ func TestSBOM(t *testing.T) {
artifactType: "cyclonedx",
},
golden: "testdata/centos-7.json.golden",
override: types.Report{
ArtifactName: "testdata/fixtures/sbom/centos-7-cyclonedx.intoto.jsonl",
ArtifactType: ftypes.ArtifactType("cyclonedx"),
Results: types.Results{
{
Target: "testdata/fixtures/sbom/centos-7-cyclonedx.intoto.jsonl (centos 7.6.1810)",
Vulnerabilities: []types.DetectedVulnerability{
{
PkgIdentifier: ftypes.PkgIdentifier{
BOMRef: "pkg:rpm/centos/[email protected]?arch=x86_64&distro=centos-7.6.1810",
},
},
{
PkgIdentifier: ftypes.PkgIdentifier{
BOMRef: "pkg:rpm/centos/[email protected]?arch=x86_64&epoch=1&distro=centos-7.6.1810",
},
},
{
PkgIdentifier: ftypes.PkgIdentifier{
BOMRef: "pkg:rpm/centos/[email protected]?arch=x86_64&epoch=1&distro=centos-7.6.1810",
},
},
},
},
},
override: func(t *testing.T, want, got *types.Report) {
want.ArtifactName = "testdata/fixtures/sbom/centos-7-cyclonedx.intoto.jsonl"
want.ArtifactType = ftypes.ArtifactCycloneDX

require.Len(t, got.Results, 1)
want.Results[0].Target = "testdata/fixtures/sbom/centos-7-cyclonedx.intoto.jsonl (centos 7.6.1810)"

require.Len(t, got.Results[0].Vulnerabilities, 3)
want.Results[0].Vulnerabilities[0].PkgIdentifier.BOMRef = "pkg:rpm/centos/[email protected]?arch=x86_64&distro=centos-7.6.1810"
want.Results[0].Vulnerabilities[1].PkgIdentifier.BOMRef = "pkg:rpm/centos/[email protected]?arch=x86_64&epoch=1&distro=centos-7.6.1810"
want.Results[0].Vulnerabilities[2].PkgIdentifier.BOMRef = "pkg:rpm/centos/[email protected]?arch=x86_64&epoch=1&distro=centos-7.6.1810"
},
},
{
Expand All @@ -123,14 +95,12 @@ func TestSBOM(t *testing.T) {
artifactType: "spdx",
},
golden: "testdata/centos-7.json.golden",
override: types.Report{
ArtifactName: "testdata/fixtures/sbom/centos-7-spdx.txt",
ArtifactType: ftypes.ArtifactType("spdx"),
Results: types.Results{
{
Target: "testdata/fixtures/sbom/centos-7-spdx.txt (centos 7.6.1810)",
},
},
override: func(t *testing.T, want, got *types.Report) {
want.ArtifactName = "testdata/fixtures/sbom/centos-7-spdx.txt"
want.ArtifactType = ftypes.ArtifactSPDX

require.Len(t, got.Results, 1)
want.Results[0].Target = "testdata/fixtures/sbom/centos-7-spdx.txt (centos 7.6.1810)"
},
},
{
Expand All @@ -141,14 +111,12 @@ func TestSBOM(t *testing.T) {
artifactType: "spdx",
},
golden: "testdata/centos-7.json.golden",
override: types.Report{
ArtifactName: "testdata/fixtures/sbom/centos-7-spdx.json",
ArtifactType: ftypes.ArtifactType("spdx"),
Results: types.Results{
{
Target: "testdata/fixtures/sbom/centos-7-spdx.json (centos 7.6.1810)",
},
},
override: func(t *testing.T, want, got *types.Report) {
want.ArtifactName = "testdata/fixtures/sbom/centos-7-spdx.json"
want.ArtifactType = ftypes.ArtifactSPDX

require.Len(t, got.Results, 1)
want.Results[0].Target = "testdata/fixtures/sbom/centos-7-spdx.json (centos 7.6.1810)"
},
},
{
Expand Down Expand Up @@ -195,20 +163,30 @@ func TestSBOM(t *testing.T) {
osArgs = append(osArgs, tt.args.input)

// Run "trivy sbom"
err := execute(osArgs)
assert.NoError(t, err)

// Compare want and got
switch tt.args.format {
case "json":
compareSBOMReports(t, tt.golden, outputFile, tt.override)
default:
require.Fail(t, "invalid format", "format: %s", tt.args.format)
}
runTest(t, osArgs, tt.golden, outputFile, types.Format(tt.args.format), runOptions{
override: overrideFuncs(overrideSBOMReport, overrideUID, tt.override),
})
})
}
}

func overrideSBOMReport(t *testing.T, want, got *types.Report) {
want.Metadata.ImageID = ""
want.Metadata.ImageConfig = v1.ConfigFile{}
want.Metadata.DiffIDs = nil
for i, result := range want.Results {
for j := range result.Vulnerabilities {
want.Results[i].Vulnerabilities[j].Layer.DiffID = ""
}
}

// when running on Windows FS
got.ArtifactName = filepath.ToSlash(filepath.Clean(got.ArtifactName))
for i, result := range got.Results {
got.Results[i].Target = filepath.ToSlash(filepath.Clean(result.Target))
}
}

// TODO(teppei): merge into compareReports
func compareSBOMReports(t *testing.T, wantFile, gotFile string, overrideWant types.Report) {
want := readReport(t, wantFile)
Expand Down

0 comments on commit 74f3f42

Please sign in to comment.