github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/syft/pkg/cataloger/sbom/cataloger_test.go (about)

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