Skip to content

Commit

Permalink
test: validate CycloneDX with the JSON schema
Browse files Browse the repository at this point in the history
  • Loading branch information
knqyf263 committed Aug 7, 2023
1 parent a796701 commit 8abf60b
Show file tree
Hide file tree
Showing 6 changed files with 6,669 additions and 31 deletions.
29 changes: 6 additions & 23 deletions integration/client_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,14 @@ package integration

import (
"context"
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"testing"
"time"

cdx "github.com/CycloneDX/cyclonedx-go"
"github.com/docker/go-connections/nat"
"github.com/samber/lo"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
testcontainers "github.com/testcontainers/testcontainers-go"
Expand Down Expand Up @@ -402,45 +399,31 @@ func TestClientServerWithFormat(t *testing.T) {
}

func TestClientServerWithCycloneDX(t *testing.T) {
if *update {
t.Skipf("This test doesn't use golden files")
}
tests := []struct {
name string
args csArgs
wantComponentsCount int
wantDependenciesCount int
name string
args csArgs
golden string
}{
{
name: "fluentd with RubyGems with CycloneDX format",
args: csArgs{
Format: "cyclonedx",
Input: "testdata/fixtures/images/fluentd-multiple-lockfiles.tar.gz",
},
wantComponentsCount: 161,
wantDependenciesCount: 162,
golden: "testdata/fluentd-multiple-lockfiles.cdx.json.golden",
},
}

addr, cacheDir := setup(t, setupOptions{})
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
osArgs, outputFile := setupClient(t, tt.args, addr, cacheDir, "")
osArgs, outputFile := setupClient(t, tt.args, addr, cacheDir, tt.golden)

// Run Trivy client
err := execute(osArgs)
require.NoError(t, err)

f, err := os.Open(outputFile)
require.NoError(t, err)
defer f.Close()

var got cdx.BOM
err = json.NewDecoder(f).Decode(&got)
require.NoError(t, err)

assert.EqualValues(t, tt.wantComponentsCount, len(lo.FromPtr(got.Components)))
assert.EqualValues(t, tt.wantDependenciesCount, len(lo.FromPtr(got.Dependencies)))
compareCycloneDX(t, tt.golden, outputFile)
})
}
}
Expand Down
18 changes: 17 additions & 1 deletion integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,20 @@ import (
"os"
"path/filepath"
"sort"
"strings"
"testing"
"time"

cdx "github.com/CycloneDX/cyclonedx-go"
"github.com/samber/lo"
spdxjson "github.com/spdx/tools-golang/json"
"github.com/spdx/tools-golang/spdx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/xeipuuv/gojsonschema"

"github.com/aquasecurity/trivy-db/pkg/db"
"github.com/aquasecurity/trivy-db/pkg/metadata"

"github.com/aquasecurity/trivy/pkg/commands"
"github.com/aquasecurity/trivy/pkg/dbtest"
"github.com/aquasecurity/trivy/pkg/types"
Expand Down Expand Up @@ -212,6 +214,20 @@ func compareCycloneDX(t *testing.T, wantFile, gotFile string) {
want := readCycloneDX(t, wantFile)
got := readCycloneDX(t, gotFile)
assert.Equal(t, want, got)

// Validate CycloneDX output against the JSON schema
schemaLoader := gojsonschema.NewReferenceLoader(got.JSONSchema)
documentLoader := gojsonschema.NewGoLoader(got)

result, err := gojsonschema.Validate(schemaLoader, documentLoader)
require.NoError(t, err)

if valid := result.Valid(); !valid {
errs := lo.Map(result.Errors(), func(err gojsonschema.ResultError, _ int) string {
return err.String()
})
assert.True(t, valid, strings.Join(errs, "\n"))
}
}

func compareSpdxJson(t *testing.T, wantFile, gotFile string) {
Expand Down
12 changes: 6 additions & 6 deletions integration/repo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func TestRepository(t *testing.T) {
skipFiles []string
skipDirs []string
command string
format string
format types.Format
includeDevDeps bool
}
tests := []struct {
Expand Down Expand Up @@ -367,7 +367,7 @@ func TestRepository(t *testing.T) {
command = tt.args.command
}

format := "json"
format := types.FormatJSON
if tt.args.format != "" {
format = tt.args.format
}
Expand All @@ -380,7 +380,7 @@ func TestRepository(t *testing.T) {
"--skip-db-update",
"--skip-policy-update",
"--format",
format,
string(format),
"--offline-scan",
}

Expand Down Expand Up @@ -464,11 +464,11 @@ func TestRepository(t *testing.T) {

// Compare want and got
switch format {
case "cyclonedx":
case types.FormatCycloneDX:
compareCycloneDX(t, tt.golden, outputFile)
case "spdx-json":
case types.FormatSPDXJSON:
compareSpdxJson(t, tt.golden, outputFile)
case "json":
case types.FormatJSON:
compareReports(t, tt.golden, outputFile, tt.override)
default:
require.Fail(t, "invalid format", "format: %s", format)
Expand Down
2 changes: 1 addition & 1 deletion integration/sbom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func TestSBOM(t *testing.T) {
format: "json",
artifactType: "cyclonedx",
},
golden: "testdata/fluentd-multiple-lockfiles-cyclonedx.json.golden",
golden: "testdata/fluentd-multiple-lockfiles.json.golden",
},
{
name: "centos7 in in-toto attestation",
Expand Down
Loading

0 comments on commit 8abf60b

Please sign in to comment.