package integration import ( "fmt" "github.com/anchore/syft/syft/source" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "testing" ) func TestPackageDeduplication(t *testing.T) { tests := []struct { scope source.Scope packageCount int instanceCount map[string]int locationCount map[string]int }{ { scope: source.AllLayersScope, packageCount: 172, // without deduplication this would be 618 instanceCount: map[string]int{ "basesystem": 1, "wget": 1, "curl": 2, // upgraded in the image "vsftpd": 1, "httpd": 1, }, locationCount: map[string]int{ "basesystem-10.0-7.el7.centos": 4, "curl-7.29.0-59.el7": 1, // from base image "curl-7.29.0-59.el7_9.1": 3, // upgrade "wget-1.14-18.el7_6.1": 3, "vsftpd-3.0.2-29.el7_9": 2, "httpd-2.4.6-97.el7.centos.5": 1, }, }, { scope: source.SquashedScope, packageCount: 170, instanceCount: map[string]int{ "basesystem": 1, "wget": 1, "curl": 1, // upgraded, but the most recent "vsftpd": 1, "httpd": 1, }, locationCount: map[string]int{ "basesystem-10.0-7.el7.centos": 1, "curl-7.29.0-59.el7_9.1": 1, // upgrade "wget-1.14-18.el7_6.1": 1, "vsftpd-3.0.2-29.el7_9": 1, "httpd-2.4.6-97.el7.centos.5": 1, }, }, } for _, tt := range tests { t.Run(string(tt.scope), func(t *testing.T) { sbom, _ := catalogFixtureImage(t, "image-vertical-package-dups", tt.scope) assert.Equal(t, tt.packageCount, sbom.Artifacts.PackageCatalog.PackageCount()) for name, expectedInstanceCount := range tt.instanceCount { pkgs := sbom.Artifacts.PackageCatalog.PackagesByName(name) // with multiple packages with the same name, something is wrong (or this is the wrong fixture) require.Len(t, pkgs, expectedInstanceCount) for _, p := range pkgs { nameVersion := fmt.Sprintf("%s-%s", name, p.Version) expectedLocationCount, ok := tt.locationCount[nameVersion] if !ok { t.Fatalf("missing name-version: %s", nameVersion) } // we should see merged locations (assumption, there was 1 location for each package) assert.Len(t, p.Locations.ToSlice(), expectedLocationCount) // all paths should match assert.Len(t, p.Locations.CoordinateSet().Paths(), 1) } } }) } }