github.com/anchore/syft@v1.38.2/syft/pkg/cataloger/sbom/cataloger_test.go (about)

     1  package sbom
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/require"
     8  
     9  	"github.com/anchore/syft/syft/artifact"
    10  	"github.com/anchore/syft/syft/cpe"
    11  	"github.com/anchore/syft/syft/file"
    12  	"github.com/anchore/syft/syft/pkg"
    13  	"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
    14  )
    15  
    16  func mustCPEs(s ...string) (c []cpe.CPE) {
    17  	for _, i := range s {
    18  		c = append(c, cpe.Must(i, ""))
    19  	}
    20  	return
    21  }
    22  
    23  func Test_parseSBOM(t *testing.T) {
    24  	ctx := context.TODO()
    25  	expectedPkgs := []pkg.Package{
    26  		{
    27  			Name:      "alpine-baselayout",
    28  			Version:   "3.2.0-r23",
    29  			Type:      "apk",
    30  			Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")),
    31  			Licenses:  pkg.NewLicenseSet(pkg.NewLicenseWithContext(ctx, "GPL-2.0-only")),
    32  			FoundBy:   "sbom-cataloger",
    33  			PURL:      "pkg:apk/alpine/alpine-baselayout@3.2.0-r23?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.16.3",
    34  			CPEs: mustCPEs(
    35  				"cpe:2.3:a:alpine-baselayout:alpine-baselayout:3.2.0-r23:*:*:*:*:*:*:*",
    36  				"cpe:2.3:a:alpine-baselayout:alpine_baselayout:3.2.0-r23:*:*:*:*:*:*:*",
    37  				"cpe:2.3:a:alpine_baselayout:alpine-baselayout:3.2.0-r23:*:*:*:*:*:*:*",
    38  				"cpe:2.3:a:alpine_baselayout:alpine_baselayout:3.2.0-r23:*:*:*:*:*:*:*",
    39  				"cpe:2.3:a:alpine:alpine-baselayout:3.2.0-r23:*:*:*:*:*:*:*",
    40  				"cpe:2.3:a:alpine:alpine_baselayout:3.2.0-r23:*:*:*:*:*:*:*",
    41  			),
    42  		},
    43  		{
    44  			Name:      "alpine-baselayout-data",
    45  			Version:   "3.2.0-r23",
    46  			Type:      "apk",
    47  			Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")),
    48  			Licenses:  pkg.NewLicenseSet(pkg.NewLicenseWithContext(ctx, "GPL-2.0-only")),
    49  			FoundBy:   "sbom-cataloger",
    50  			PURL:      "pkg:apk/alpine/alpine-baselayout-data@3.2.0-r23?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.16.3",
    51  			CPEs: mustCPEs(
    52  				"cpe:2.3:a:alpine-baselayout-data:alpine-baselayout-data:3.2.0-r23:*:*:*:*:*:*:*",
    53  				"cpe:2.3:a:alpine-baselayout-data:alpine_baselayout_data:3.2.0-r23:*:*:*:*:*:*:*",
    54  				"cpe:2.3:a:alpine_baselayout_data:alpine-baselayout-data:3.2.0-r23:*:*:*:*:*:*:*",
    55  				"cpe:2.3:a:alpine_baselayout_data:alpine_baselayout_data:3.2.0-r23:*:*:*:*:*:*:*",
    56  				"cpe:2.3:a:alpine-baselayout:alpine-baselayout-data:3.2.0-r23:*:*:*:*:*:*:*",
    57  				"cpe:2.3:a:alpine-baselayout:alpine_baselayout_data:3.2.0-r23:*:*:*:*:*:*:*",
    58  				"cpe:2.3:a:alpine_baselayout:alpine-baselayout-data:3.2.0-r23:*:*:*:*:*:*:*",
    59  				"cpe:2.3:a:alpine_baselayout:alpine_baselayout_data:3.2.0-r23:*:*:*:*:*:*:*",
    60  				"cpe:2.3:a:alpine:alpine-baselayout-data:3.2.0-r23:*:*:*:*:*:*:*",
    61  				"cpe:2.3:a:alpine:alpine_baselayout_data:3.2.0-r23:*:*:*:*:*:*:*",
    62  			),
    63  		},
    64  		{
    65  			Name:      "alpine-keys",
    66  			Version:   "2.4-r1",
    67  			Type:      "apk",
    68  			Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")),
    69  			Licenses:  pkg.NewLicenseSet(pkg.NewLicenseWithContext(ctx, "MIT")),
    70  			FoundBy:   "sbom-cataloger",
    71  			PURL:      "pkg:apk/alpine/alpine-keys@2.4-r1?arch=x86_64&upstream=alpine-keys&distro=alpine-3.16.3",
    72  			CPEs: mustCPEs(
    73  				"cpe:2.3:a:alpine-keys:alpine-keys:2.4-r1:*:*:*:*:*:*:*",
    74  				"cpe:2.3:a:alpine-keys:alpine_keys:2.4-r1:*:*:*:*:*:*:*",
    75  				"cpe:2.3:a:alpine_keys:alpine-keys:2.4-r1:*:*:*:*:*:*:*",
    76  				"cpe:2.3:a:alpine_keys:alpine_keys:2.4-r1:*:*:*:*:*:*:*",
    77  				"cpe:2.3:a:alpine:alpine-keys:2.4-r1:*:*:*:*:*:*:*",
    78  				"cpe:2.3:a:alpine:alpine_keys:2.4-r1:*:*:*:*:*:*:*",
    79  			),
    80  		},
    81  		{
    82  			Name:      "apk-tools",
    83  			Version:   "2.12.9-r3",
    84  			Type:      "apk",
    85  			Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")),
    86  			Licenses:  pkg.NewLicenseSet(pkg.NewLicenseWithContext(ctx, "GPL-2.0-only")),
    87  			FoundBy:   "sbom-cataloger",
    88  			PURL:      "pkg:apk/alpine/apk-tools@2.12.9-r3?arch=x86_64&upstream=apk-tools&distro=alpine-3.16.3",
    89  			CPEs: mustCPEs(
    90  				"cpe:2.3:a:apk-tools:apk-tools:2.12.9-r3:*:*:*:*:*:*:*",
    91  				"cpe:2.3:a:apk-tools:apk_tools:2.12.9-r3:*:*:*:*:*:*:*",
    92  				"cpe:2.3:a:apk_tools:apk-tools:2.12.9-r3:*:*:*:*:*:*:*",
    93  				"cpe:2.3:a:apk_tools:apk_tools:2.12.9-r3:*:*:*:*:*:*:*",
    94  				"cpe:2.3:a:apk:apk-tools:2.12.9-r3:*:*:*:*:*:*:*",
    95  				"cpe:2.3:a:apk:apk_tools:2.12.9-r3:*:*:*:*:*:*:*",
    96  			),
    97  		},
    98  		{
    99  			Name:      "busybox",
   100  			Version:   "1.35.0-r17",
   101  			Type:      "apk",
   102  			Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")),
   103  			Licenses:  pkg.NewLicenseSet(pkg.NewLicenseWithContext(ctx, "GPL-2.0-only")),
   104  			FoundBy:   "sbom-cataloger",
   105  			PURL:      "pkg:apk/alpine/busybox@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3",
   106  			CPEs: mustCPEs(
   107  				"cpe:2.3:a:busybox:busybox:1.35.0-r17:*:*:*:*:*:*:*",
   108  			),
   109  		},
   110  		{
   111  			Name:      "ca-certificates-bundle",
   112  			Version:   "20220614-r0",
   113  			Type:      "apk",
   114  			Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")),
   115  			Licenses: pkg.NewLicenseSet(
   116  				pkg.NewLicenseWithContext(ctx, "MPL-2.0"),
   117  				pkg.NewLicenseWithContext(ctx, "MIT"),
   118  			),
   119  			FoundBy: "sbom-cataloger",
   120  			PURL:    "pkg:apk/alpine/ca-certificates-bundle@20220614-r0?arch=x86_64&upstream=ca-certificates&distro=alpine-3.16.3",
   121  			CPEs: mustCPEs(
   122  				"cpe:2.3:a:ca-certificates-bundle:ca-certificates-bundle:20220614-r0:*:*:*:*:*:*:*",
   123  				"cpe:2.3:a:ca-certificates-bundle:ca_certificates_bundle:20220614-r0:*:*:*:*:*:*:*",
   124  				"cpe:2.3:a:ca_certificates_bundle:ca-certificates-bundle:20220614-r0:*:*:*:*:*:*:*",
   125  				"cpe:2.3:a:ca_certificates_bundle:ca_certificates_bundle:20220614-r0:*:*:*:*:*:*:*",
   126  				"cpe:2.3:a:ca-certificates:ca-certificates-bundle:20220614-r0:*:*:*:*:*:*:*",
   127  				"cpe:2.3:a:ca-certificates:ca_certificates_bundle:20220614-r0:*:*:*:*:*:*:*",
   128  				"cpe:2.3:a:ca_certificates:ca-certificates-bundle:20220614-r0:*:*:*:*:*:*:*",
   129  				"cpe:2.3:a:ca_certificates:ca_certificates_bundle:20220614-r0:*:*:*:*:*:*:*",
   130  				"cpe:2.3:a:ca:ca-certificates-bundle:20220614-r0:*:*:*:*:*:*:*",
   131  				"cpe:2.3:a:ca:ca_certificates_bundle:20220614-r0:*:*:*:*:*:*:*",
   132  			),
   133  		},
   134  		{
   135  			Name:      "libc-utils",
   136  			Version:   "0.7.2-r3",
   137  			Type:      "apk",
   138  			Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")),
   139  			Licenses: pkg.NewLicenseSet(
   140  				pkg.NewLicenseWithContext(ctx, "BSD-2-Clause"),
   141  				pkg.NewLicenseWithContext(ctx, "BSD-3-Clause"),
   142  			),
   143  			FoundBy: "sbom-cataloger",
   144  			PURL:    "pkg:apk/alpine/libc-utils@0.7.2-r3?arch=x86_64&upstream=libc-dev&distro=alpine-3.16.3",
   145  			CPEs: mustCPEs(
   146  				"cpe:2.3:a:libc-utils:libc-utils:0.7.2-r3:*:*:*:*:*:*:*",
   147  				"cpe:2.3:a:libc-utils:libc_utils:0.7.2-r3:*:*:*:*:*:*:*",
   148  				"cpe:2.3:a:libc_utils:libc-utils:0.7.2-r3:*:*:*:*:*:*:*",
   149  				"cpe:2.3:a:libc_utils:libc_utils:0.7.2-r3:*:*:*:*:*:*:*",
   150  				"cpe:2.3:a:libc:libc-utils:0.7.2-r3:*:*:*:*:*:*:*",
   151  				"cpe:2.3:a:libc:libc_utils:0.7.2-r3:*:*:*:*:*:*:*",
   152  			),
   153  		},
   154  		{
   155  			Name:      "libcrypto1.1",
   156  			Version:   "1.1.1s-r0",
   157  			Type:      "apk",
   158  			Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")),
   159  			Licenses:  pkg.NewLicenseSet(pkg.NewLicenseWithContext(ctx, "OpenSSL")), // SPDX expression is not set
   160  			FoundBy:   "sbom-cataloger",
   161  			PURL:      "pkg:apk/alpine/libcrypto1.1@1.1.1s-r0?arch=x86_64&upstream=openssl&distro=alpine-3.16.3",
   162  			CPEs: mustCPEs(
   163  				"cpe:2.3:a:libcrypto1.1:libcrypto1.1:1.1.1s-r0:*:*:*:*:*:*:*",
   164  			),
   165  		},
   166  		{
   167  			Name:      "libssl1.1",
   168  			Version:   "1.1.1s-r0",
   169  			Type:      "apk",
   170  			Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")),
   171  			Licenses:  pkg.NewLicenseSet(pkg.NewLicenseWithContext(ctx, "OpenSSL")), // SPDX expression is not set
   172  			FoundBy:   "sbom-cataloger",
   173  			PURL:      "pkg:apk/alpine/libssl1.1@1.1.1s-r0?arch=x86_64&upstream=openssl&distro=alpine-3.16.3",
   174  			CPEs: mustCPEs(
   175  				"cpe:2.3:a:libssl1.1:libssl1.1:1.1.1s-r0:*:*:*:*:*:*:*",
   176  			),
   177  		},
   178  		{
   179  			Name:      "musl",
   180  			Version:   "1.2.3-r1",
   181  			Type:      "apk",
   182  			Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")),
   183  			Licenses:  pkg.NewLicenseSet(pkg.NewLicenseWithContext(ctx, "MIT")), // SPDX expression is not set
   184  			FoundBy:   "sbom-cataloger",
   185  			PURL:      "pkg:apk/alpine/musl@1.2.3-r1?arch=x86_64&upstream=musl&distro=alpine-3.16.3",
   186  			CPEs: mustCPEs(
   187  				"cpe:2.3:a:musl:musl:1.2.3-r1:*:*:*:*:*:*:*",
   188  			),
   189  		},
   190  		{
   191  			Name:      "musl-utils",
   192  			Version:   "1.2.3-r1",
   193  			Type:      "apk",
   194  			Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")),
   195  			Licenses: pkg.NewLicenseSet(
   196  				pkg.NewLicenseWithContext(ctx, "MIT"),
   197  				pkg.NewLicenseWithContext(ctx, "BSD"),
   198  				pkg.NewLicenseWithContext(ctx, "GPL2+"), // SPDX expression is not set
   199  			),
   200  			FoundBy: "sbom-cataloger",
   201  			PURL:    "pkg:apk/alpine/musl-utils@1.2.3-r1?arch=x86_64&upstream=musl&distro=alpine-3.16.3",
   202  			CPEs: mustCPEs(
   203  				"cpe:2.3:a:musl-utils:musl-utils:1.2.3-r1:*:*:*:*:*:*:*",
   204  				"cpe:2.3:a:musl-utils:musl_utils:1.2.3-r1:*:*:*:*:*:*:*",
   205  				"cpe:2.3:a:musl_utils:musl-utils:1.2.3-r1:*:*:*:*:*:*:*",
   206  				"cpe:2.3:a:musl_utils:musl_utils:1.2.3-r1:*:*:*:*:*:*:*",
   207  				"cpe:2.3:a:musl:musl-utils:1.2.3-r1:*:*:*:*:*:*:*",
   208  				"cpe:2.3:a:musl:musl_utils:1.2.3-r1:*:*:*:*:*:*:*",
   209  			),
   210  		},
   211  		{
   212  			Name:      "scanelf",
   213  			Version:   "1.3.4-r0",
   214  			Type:      "apk",
   215  			Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")),
   216  			Licenses: pkg.NewLicenseSet(
   217  				pkg.NewLicenseWithContext(ctx, "GPL-2.0-only"),
   218  			),
   219  			FoundBy: "sbom-cataloger",
   220  			PURL:    "pkg:apk/alpine/scanelf@1.3.4-r0?arch=x86_64&upstream=pax-utils&distro=alpine-3.16.3",
   221  			CPEs: mustCPEs(
   222  				"cpe:2.3:a:scanelf:scanelf:1.3.4-r0:*:*:*:*:*:*:*",
   223  			),
   224  		},
   225  		{
   226  			Name:      "ssl_client",
   227  			Version:   "1.35.0-r17",
   228  			Type:      "apk",
   229  			Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")),
   230  			Licenses: pkg.NewLicenseSet(
   231  				pkg.NewLicenseWithContext(ctx, "GPL-2.0-only"),
   232  			),
   233  			FoundBy: "sbom-cataloger",
   234  			PURL:    "pkg:apk/alpine/ssl_client@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3",
   235  			CPEs: mustCPEs(
   236  				"cpe:2.3:a:ssl-client:ssl-client:1.35.0-r17:*:*:*:*:*:*:*",
   237  				"cpe:2.3:a:ssl-client:ssl_client:1.35.0-r17:*:*:*:*:*:*:*",
   238  				"cpe:2.3:a:ssl_client:ssl-client:1.35.0-r17:*:*:*:*:*:*:*",
   239  				"cpe:2.3:a:ssl_client:ssl_client:1.35.0-r17:*:*:*:*:*:*:*",
   240  				"cpe:2.3:a:ssl:ssl-client:1.35.0-r17:*:*:*:*:*:*:*",
   241  				"cpe:2.3:a:ssl:ssl_client:1.35.0-r17:*:*:*:*:*:*:*",
   242  			),
   243  		},
   244  		{
   245  			Name:      "zlib",
   246  			Version:   "1.2.12-r3",
   247  			Type:      "apk",
   248  			Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")),
   249  			Licenses: pkg.NewLicenseSet(
   250  				pkg.NewLicenseWithContext(ctx, "Zlib"),
   251  			),
   252  			FoundBy: "sbom-cataloger",
   253  			PURL:    "pkg:apk/alpine/zlib@1.2.12-r3?arch=x86_64&upstream=zlib&distro=alpine-3.16.3",
   254  			CPEs: mustCPEs(
   255  				"cpe:2.3:a:zlib:zlib:1.2.12-r3:*:*:*:*:*:*:*",
   256  			),
   257  		},
   258  	}
   259  
   260  	apkgdbLocation := file.NewLocationSet(file.Location{
   261  		LocationData: file.LocationData{
   262  			Coordinates: file.Coordinates{
   263  				RealPath:     "/lib/apk/db/installed",
   264  				FileSystemID: "sha256:e5e13b0c77cbb769548077189c3da2f0a764ceca06af49d8d558e759f5c232bd",
   265  			},
   266  		},
   267  	})
   268  
   269  	libSSL := pkg.Package{
   270  		Name:      "libssl1.1",
   271  		Version:   "1.1.1s-r0",
   272  		Type:      "apk",
   273  		Locations: apkgdbLocation,
   274  		Licenses:  pkg.NewLicenseSet(pkg.NewLicenseWithContext(ctx, "OpenSSL")),
   275  		FoundBy:   "apkdb-cataloger",
   276  		PURL:      "pkg:apk/alpine/libssl1.1@1.1.1s-r0?arch=x86_64&upstream=openssl&distro=alpine-3.16.3",
   277  		CPEs: mustCPEs(
   278  			"cpe:2.3:a:libssl1.1:libssl1.1:1.1.1s-r0:*:*:*:*:*:*:*",
   279  		),
   280  	}
   281  
   282  	sslClient := pkg.Package{
   283  		Name:      "ssl_client",
   284  		Version:   "1.35.0-r17",
   285  		Type:      "apk",
   286  		Locations: apkgdbLocation,
   287  		Licenses:  pkg.NewLicenseSet(pkg.NewLicenseWithContext(ctx, "GPL-2.0-only")),
   288  		FoundBy:   "apkdb-cataloger",
   289  		PURL:      "pkg:apk/alpine/ssl_client@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3",
   290  		CPEs: mustCPEs(
   291  			"cpe:2.3:a:ssl-client:ssl-client:1.35.0-r17:*:*:*:*:*:*:*",
   292  			"cpe:2.3:a:ssl-client:ssl_client:1.35.0-r17:*:*:*:*:*:*:*",
   293  			"cpe:2.3:a:ssl_client:ssl-client:1.35.0-r17:*:*:*:*:*:*:*",
   294  			"cpe:2.3:a:ssl_client:ssl_client:1.35.0-r17:*:*:*:*:*:*:*",
   295  			"cpe:2.3:a:ssl:ssl-client:1.35.0-r17:*:*:*:*:*:*:*",
   296  			"cpe:2.3:a:ssl:ssl_client:1.35.0-r17:*:*:*:*:*:*:*",
   297  		),
   298  	}
   299  
   300  	baseLayout := pkg.Package{
   301  		Name:      "alpine-baselayout",
   302  		Version:   "3.2.0-r23",
   303  		Type:      "apk",
   304  		Locations: apkgdbLocation,
   305  		Licenses:  pkg.NewLicenseSet(pkg.NewLicenseWithContext(ctx, "GPL-2.0-only")),
   306  		FoundBy:   "apkdb-cataloger",
   307  		PURL:      "pkg:apk/alpine/alpine-baselayout@3.2.0-r23?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.16.3",
   308  		CPEs: mustCPEs(
   309  			"cpe:2.3:a:alpine-baselayout:alpine-baselayout:3.2.0-r23:*:*:*:*:*:*:*",
   310  			"cpe:2.3:a:alpine-baselayout:alpine_baselayout:3.2.0-r23:*:*:*:*:*:*:*",
   311  			"cpe:2.3:a:alpine_baselayout:alpine-baselayout:3.2.0-r23:*:*:*:*:*:*:*",
   312  			"cpe:2.3:a:alpine_baselayout:alpine_baselayout:3.2.0-r23:*:*:*:*:*:*:*",
   313  			"cpe:2.3:a:alpine:alpine-baselayout:3.2.0-r23:*:*:*:*:*:*:*",
   314  			"cpe:2.3:a:alpine:alpine_baselayout:3.2.0-r23:*:*:*:*:*:*:*",
   315  		),
   316  	}
   317  
   318  	busybox := pkg.Package{
   319  		Name:      "busybox",
   320  		Version:   "1.35.0-r17",
   321  		Type:      "apk",
   322  		Locations: apkgdbLocation,
   323  		Licenses:  pkg.NewLicenseSet(pkg.NewLicenseWithContext(ctx, "GPL-2.0-only")),
   324  		FoundBy:   "apkdb-cataloger",
   325  		PURL:      "pkg:apk/alpine/busybox@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3",
   326  		CPEs: mustCPEs(
   327  			"cpe:2.3:a:busybox:busybox:1.35.0-r17:*:*:*:*:*:*:*",
   328  		),
   329  	}
   330  
   331  	musl := pkg.Package{
   332  		Name:      "musl",
   333  		Version:   "1.2.3-r1",
   334  		Type:      "apk",
   335  		Locations: apkgdbLocation,
   336  		Licenses:  pkg.NewLicenseSet(pkg.NewLicenseWithContext(ctx, "MIT")),
   337  		FoundBy:   "apkdb-cataloger",
   338  		PURL:      "pkg:apk/alpine/musl@1.2.3-r1?arch=x86_64&upstream=musl&distro=alpine-3.16.3",
   339  		CPEs: mustCPEs(
   340  			"cpe:2.3:a:musl:musl:1.2.3-r1:*:*:*:*:*:*:*",
   341  		),
   342  	}
   343  
   344  	expectedRelationships := []artifact.Relationship{
   345  		{
   346  			From: libSSL,
   347  			To:   sslClient,
   348  			Type: artifact.DependencyOfRelationship,
   349  		},
   350  		{
   351  			From: libSSL,
   352  			To: file.Coordinates{
   353  				RealPath:     "/lib/libssl.so.1.1",
   354  				FileSystemID: "sha256:e5e13b0c77cbb769548077189c3da2f0a764ceca06af49d8d558e759f5c232bd",
   355  			},
   356  			Type: artifact.ContainsRelationship,
   357  		},
   358  		{
   359  			From: busybox,
   360  			To:   baseLayout,
   361  			Type: artifact.DependencyOfRelationship,
   362  		},
   363  		{
   364  			From: baseLayout,
   365  			To: file.Coordinates{
   366  				RealPath:     "/etc/profile.d/color_prompt.sh.disabled",
   367  				FileSystemID: "sha256:e5e13b0c77cbb769548077189c3da2f0a764ceca06af49d8d558e759f5c232bd",
   368  			},
   369  			Type: artifact.ContainsRelationship,
   370  		},
   371  		{
   372  			From: baseLayout,
   373  			To: file.Coordinates{
   374  				RealPath:     "/etc/modprobe.d/kms.conf",
   375  				FileSystemID: "sha256:e5e13b0c77cbb769548077189c3da2f0a764ceca06af49d8d558e759f5c232bd",
   376  			},
   377  			Type: artifact.ContainsRelationship,
   378  		},
   379  		{
   380  			From: musl,
   381  			To:   libSSL,
   382  			Type: artifact.DependencyOfRelationship,
   383  		},
   384  	}
   385  
   386  	for _, p := range expectedPkgs {
   387  		expectedRelationships = append(expectedRelationships, artifact.Relationship{
   388  			From: p,
   389  			To: file.Coordinates{
   390  				RealPath: "sbom.syft.json",
   391  			},
   392  			Type: artifact.DescribedByRelationship,
   393  		})
   394  	}
   395  
   396  	tests := []struct {
   397  		name              string
   398  		fixture           string
   399  		wantPkgs          []pkg.Package
   400  		wantRelationships []artifact.Relationship
   401  		wantErr           require.ErrorAssertionFunc
   402  	}{
   403  		{
   404  			name:              "parse syft JSON",
   405  			fixture:           "test-fixtures/alpine/syft-json",
   406  			wantPkgs:          expectedPkgs,
   407  			wantRelationships: expectedRelationships,
   408  		},
   409  	}
   410  	for _, tt := range tests {
   411  		t.Run(tt.name, func(t *testing.T) {
   412  			pkgtest.NewCatalogTester().
   413  				FromDirectory(t, tt.fixture).
   414  				IgnorePackageFields("Metadata").
   415  				Expects(tt.wantPkgs, tt.wantRelationships).
   416  				TestCataloger(t, NewCataloger())
   417  		})
   418  	}
   419  }
   420  
   421  func Test_Cataloger_Globs(t *testing.T) {
   422  	tests := []struct {
   423  		name     string
   424  		fixture  string
   425  		expected []string
   426  	}{
   427  		{
   428  			name:    "obtain sbom files",
   429  			fixture: "test-fixtures/glob-paths",
   430  			expected: []string{
   431  				"bom",
   432  				"sbom",
   433  				"app.syft.json",
   434  				"app.bom",
   435  				"app.sbom",
   436  				"app.cdx",
   437  				"app.spdx",
   438  				"app.bom.json",
   439  				"app.sbom.json",
   440  				"app.cdx.json",
   441  				"app.spdx.json",
   442  			},
   443  		},
   444  	}
   445  
   446  	for _, test := range tests {
   447  		t.Run(test.name, func(t *testing.T) {
   448  			pkgtest.NewCatalogTester().
   449  				FromDirectory(t, test.fixture).
   450  				ExpectsResolverContentQueries(test.expected).
   451  				TestCataloger(t, NewCataloger())
   452  		})
   453  	}
   454  }
   455  
   456  func Test_corruptSBOM(t *testing.T) {
   457  	pkgtest.NewCatalogTester().
   458  		FromFile(t, "test-fixtures/glob-paths/app.spdx.json").
   459  		WithError().
   460  		TestParser(t, parseSBOM)
   461  }