Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: #953 Derive language from pURL - https://github.com/anchore/syft… #957

Merged
merged 7 commits into from
Apr 26, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions internal/formats/common/cyclonedxhelpers/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ func decodeComponent(c *cyclonedx.Component) *pkg.Package {
p.Type = pkg.TypeFromPURL(p.PURL)
}

if p.Language == "" {
p.Language = pkg.LanguageFromPURL(p.PURL)
}

return p
}

Expand Down
28 changes: 28 additions & 0 deletions internal/formats/common/cyclonedxhelpers/component_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,31 @@ func Test_deriveBomRef(t *testing.T) {
})
}
}

func Test_decodeComponent(t *testing.T) {
javaComponentWithNoSyftProperties := cyclonedx.Component{
Name: "ch.qos.logback/logback-classic",
Version: "1.2.3",
PackageURL: "pkg:maven/ch.qos.logback/logback-classic@1.2.3",
Type: "library",
BOMRef: "pkg:maven/ch.qos.logback/logback-classic@1.2.3",
}

tests := []struct {
name string
component cyclonedx.Component
want pkg.Language
}{
{
name: "derive language from pURL if missing",
component: javaComponentWithNoSyftProperties,
want: pkg.Java,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.want, decodeComponent(&tt.component).Language)
})
}
}
3 changes: 3 additions & 0 deletions syft/pkg/cataloger/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ func Catalog(resolver source.FileResolver, release *linux.Release, catalogers ..

// generate PURL (note: this is excluded from package ID, so is safe to mutate)
p.PURL = pkg.URL(p, release)
if p.Language == "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: an extra comment explaining why this is here would be good since there is some high-level reasoning for it that isn't apparent.

p.Language = pkg.LanguageFromPURL(p.PURL)
}

// create file-to-package relationships for files owned by the package
owningRelationships, err := packageFileOwnershipRelationships(p, resolver)
Expand Down
26 changes: 14 additions & 12 deletions test/integration/encode_decode_cycle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/anchore/syft/internal/formats/cyclonedxxml"
"github.com/anchore/syft/internal/formats/syftjson"
"github.com/anchore/syft/syft/source"
"github.com/google/go-cmp/cmp"
"regexp"
"testing"

Expand All @@ -21,12 +22,14 @@ import (
)

// TestEncodeDecodeEncodeCycleComparison is testing for differences in how SBOM documents get encoded on multiple cycles.
// By encding and decoding the sbom we can compare the differences between the set of resulting objects. However,
// By encoding and decoding the sbom we can compare the differences between the set of resulting objects. However,
// this requires specific comparisons being done, and select redactions/omissions being made. Additionally, there are
// already unit tests on each format encoder-decoder for properly functioning comparisons in depth, so there is no need
// to do an object-to-object comparison. For this reason this test focuses on a bytes-to-bytes comparison after an
// encode-decode-encode loop which will detect lossy behavior in both directions.
func TestEncodeDecodeEncodeCycleComparison(t *testing.T) {
// use second image for relationships
images := []string{"image-pkg-coverage", "image-owning-package"}
tests := []struct {
formatOption sbom.FormatID
redactor func(in []byte) []byte
Expand Down Expand Up @@ -55,9 +58,8 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) {
}

for _, test := range tests {
// use second image for relationships
for _, image := range []string{"image-pkg-coverage", "image-owning-package"} {
t.Run(fmt.Sprintf("%s/%s", test.formatOption, image), func(t *testing.T) {
t.Run(fmt.Sprintf("%s", test.formatOption), func(t *testing.T) {
for _, image := range images {
originalSBOM, _ := catalogFixtureImage(t, image, source.SquashedScope)

format := syft.FormatByID(test.formatOption)
Expand All @@ -81,15 +83,15 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) {
if test.json {
s1 := string(by1)
s2 := string(by2)
assert.JSONEq(t, s1, s2)
} else {
if !assert.True(t, bytes.Equal(by1, by2)) {
dmp := diffmatchpatch.New()
diffs := dmp.DiffMain(string(by1), string(by2), true)
t.Errorf("diff: %s", dmp.DiffPrettyText(diffs))
if diff := cmp.Diff(s1, s2); diff != "" {
t.Errorf("Encode/Decode mismatch (-want +got):\n%s", diff)
}
} else if !assert.True(t, bytes.Equal(by1, by2)) {
dmp := diffmatchpatch.New()
diffs := dmp.DiffMain(string(by1), string(by2), true)
t.Errorf("diff: %s", dmp.DiffPrettyText(diffs))
}
})
}
}
})
}
}