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