mirror of
https://github.com/anchore/syft.git
synced 2026-11-02 15:36:41 +01:00
feat: update syft license concept to complex struct (#1743)
this PR makes the following changes to update the underlying license model to have more expressive capabilities it also provides some guarantee's surrounding the license values themselves - Licenses are updated from string -> pkg.LicenseSet which contain pkg.License with the following fields: - original `Value` read by syft - If it's possible to construct licenses will always have a valid SPDX expression for downstream consumption - the above is run against a generated list of SPDX license ID to try and find the correct ID - SPDX concluded vs declared is added to the new struct - URL source for license is added to the new struct - Location source is added to the new struct to show where the expression was pulled from
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/syft/license"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
func TestLicenseSet_Add(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
licenses []License
|
||||
want []License
|
||||
}{
|
||||
{
|
||||
name: "add one simple license",
|
||||
licenses: []License{
|
||||
NewLicense("MIT"),
|
||||
},
|
||||
want: []License{
|
||||
NewLicense("MIT"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add multiple simple licenses",
|
||||
licenses: []License{
|
||||
NewLicense("MIT"),
|
||||
NewLicense("MIT"),
|
||||
NewLicense("Apache-2.0"),
|
||||
},
|
||||
want: []License{
|
||||
NewLicense("Apache-2.0"),
|
||||
NewLicense("MIT"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "attempt to add a license with no name",
|
||||
licenses: []License{
|
||||
NewLicense(""),
|
||||
},
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "keep multiple licenses sorted",
|
||||
licenses: []License{
|
||||
NewLicense("MIT"),
|
||||
NewLicense("Apache-2.0"),
|
||||
},
|
||||
want: []License{
|
||||
NewLicense("Apache-2.0"),
|
||||
NewLicense("MIT"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "deduplicate licenses with locations",
|
||||
licenses: []License{
|
||||
NewLicenseFromLocations("MIT", source.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "1"})),
|
||||
NewLicenseFromLocations("MIT", source.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "1"})),
|
||||
NewLicenseFromLocations("MIT", source.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "2"})),
|
||||
},
|
||||
want: []License{
|
||||
NewLicenseFromLocations(
|
||||
"MIT",
|
||||
source.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "1"}),
|
||||
source.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "2"}),
|
||||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "same licenses with different locations",
|
||||
licenses: []License{
|
||||
NewLicense("MIT"),
|
||||
NewLicenseFromLocations("MIT", source.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "2"})),
|
||||
NewLicenseFromLocations("MIT", source.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "1"})),
|
||||
},
|
||||
want: []License{
|
||||
NewLicenseFromLocations(
|
||||
"MIT",
|
||||
source.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "1"}),
|
||||
source.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "2"}),
|
||||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "same license from different sources",
|
||||
licenses: []License{
|
||||
NewLicense("MIT"),
|
||||
NewLicenseFromLocations("MIT", source.NewLocation("/place")),
|
||||
NewLicenseFromURLs("MIT", "https://example.com"),
|
||||
},
|
||||
want: []License{
|
||||
{
|
||||
Value: "MIT",
|
||||
SPDXExpression: "MIT",
|
||||
Type: license.Declared,
|
||||
URL: internal.NewStringSet("https://example.com"),
|
||||
Location: source.NewLocationSet(source.NewLocation("/place")),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "different licenses from different sources with different types constitute two licenses",
|
||||
licenses: []License{
|
||||
NewLicenseFromType("MIT", license.Concluded),
|
||||
NewLicenseFromType("MIT", license.Declared),
|
||||
NewLicenseFromLocations("MIT", source.NewLocation("/place")),
|
||||
NewLicenseFromURLs("MIT", "https://example.com"),
|
||||
},
|
||||
want: []License{
|
||||
{
|
||||
Value: "MIT",
|
||||
SPDXExpression: "MIT",
|
||||
Type: license.Concluded,
|
||||
URL: internal.NewStringSet(),
|
||||
Location: source.NewLocationSet(),
|
||||
},
|
||||
{
|
||||
Value: "MIT",
|
||||
SPDXExpression: "MIT",
|
||||
Type: license.Declared,
|
||||
URL: internal.NewStringSet("https://example.com"),
|
||||
Location: source.NewLocationSet(source.NewLocation("/place")),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := NewLicenseSet()
|
||||
s.Add(tt.licenses...)
|
||||
testMe := s.ToSlice()
|
||||
assert.Equal(t, tt.want, testMe)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user