github.com/anchore/syft@v1.4.2-0.20240516191711-1bec1fc5d397/syft/format/internal/testutil/image_input.go (about) 1 package testutil 2 3 import ( 4 "os" 5 "path/filepath" 6 "testing" 7 8 "github.com/stretchr/testify/require" 9 10 "github.com/anchore/stereoscope/pkg/filetree" 11 "github.com/anchore/stereoscope/pkg/image" 12 "github.com/anchore/stereoscope/pkg/imagetest" 13 "github.com/anchore/syft/syft/cpe" 14 "github.com/anchore/syft/syft/file" 15 "github.com/anchore/syft/syft/linux" 16 "github.com/anchore/syft/syft/pkg" 17 "github.com/anchore/syft/syft/sbom" 18 "github.com/anchore/syft/syft/source/stereoscopesource" 19 ) 20 21 func ImageInput(t testing.TB, testImage string, options ...ImageOption) sbom.SBOM { 22 t.Helper() 23 catalog := pkg.NewCollection() 24 var cfg imageCfg 25 var img *image.Image 26 for _, opt := range options { 27 opt(&cfg) 28 } 29 30 defer changeToDirectoryWithGoldenFixture(t, testImage)() 31 32 switch cfg.fromSnapshot { 33 case true: 34 img = imagetest.GetGoldenFixtureImage(t, testImage) 35 default: 36 img = imagetest.GetFixtureImage(t, "docker-archive", testImage) 37 } 38 39 populateImageCatalog(catalog, img) 40 41 // this is a hard coded value that is not given by the fixture helper and must be provided manually 42 img.Metadata.ManifestDigest = "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368" 43 44 src := stereoscopesource.New(img, stereoscopesource.ImageConfig{ 45 Reference: "user-image-input", 46 }) 47 48 return sbom.SBOM{ 49 Artifacts: sbom.Artifacts{ 50 Packages: catalog, 51 LinuxDistribution: &linux.Release{ 52 PrettyName: "debian", 53 Name: "debian", 54 ID: "debian", 55 IDLike: []string{"like!"}, 56 Version: "1.2.3", 57 VersionID: "1.2.3", 58 }, 59 }, 60 Source: src.Describe(), 61 Descriptor: sbom.Descriptor{ 62 Name: "syft", 63 Version: "v0.42.0-bogus", 64 // the application configuration should be persisted here, however, we do not want to import 65 // the application configuration in this package (it's reserved only for ingestion by the cmd package) 66 Configuration: map[string]string{ 67 "config-key": "config-value", 68 }, 69 }, 70 } 71 } 72 73 func changeToDirectoryWithGoldenFixture(t testing.TB, testImage string) func() { 74 // check if test fixture exists... if not, check if there is a shared fixture relative to this dir 75 fn := func() {} 76 77 path := filepath.Join("test-fixtures", testImage) 78 if _, err := os.Stat(path); err != nil { 79 // change dir, restore as defer 80 wd, err := os.Getwd() 81 require.NoError(t, err) 82 fn = func() { 83 require.NoError(t, os.Chdir(wd)) 84 } 85 86 // change dir to the testutil dir 87 require.NoError(t, os.Chdir(filepath.Join(wd, "..", "internal", "testutil"))) 88 t.Cleanup(fn) 89 90 if _, err := os.Stat(path); err != nil { 91 t.Fatalf("unable to find test fixture: %s", path) 92 } 93 } 94 return fn 95 } 96 97 func populateImageCatalog(catalog *pkg.Collection, img *image.Image) { 98 // TODO: this helper function is coupled to the image-simple fixture, which seems like a bad idea 99 _, ref1, _ := img.SquashedTree().File("/somefile-1.txt", filetree.FollowBasenameLinks) 100 _, ref2, _ := img.SquashedTree().File("/somefile-2.txt", filetree.FollowBasenameLinks) 101 102 // populate catalog with test data 103 if ref1 != nil { 104 catalog.Add(pkg.Package{ 105 Name: "package-1", 106 Version: "1.0.1", 107 Locations: file.NewLocationSet( 108 file.NewLocationFromImage(string(ref1.RealPath), *ref1.Reference, img), 109 ), 110 Type: pkg.PythonPkg, 111 FoundBy: "the-cataloger-1", 112 Language: pkg.Python, 113 Licenses: pkg.NewLicenseSet( 114 pkg.NewLicense("MIT"), 115 ), 116 Metadata: pkg.PythonPackage{ 117 Name: "package-1", 118 Version: "1.0.1", 119 }, 120 PURL: "a-purl-1", // intentionally a bad pURL for test fixtures 121 CPEs: []cpe.CPE{ 122 cpe.Must("cpe:2.3:*:some:package:1:*:*:*:*:*:*:*", cpe.GeneratedSource), 123 }, 124 }) 125 } 126 127 if ref2 != nil { 128 catalog.Add(pkg.Package{ 129 Name: "package-2", 130 Version: "2.0.1", 131 Locations: file.NewLocationSet( 132 file.NewLocationFromImage(string(ref2.RealPath), *ref2.Reference, img), 133 ), 134 Type: pkg.DebPkg, 135 FoundBy: "the-cataloger-2", 136 Metadata: pkg.DpkgDBEntry{ 137 Package: "package-2", 138 Version: "2.0.1", 139 }, 140 PURL: "pkg:deb/debian/package-2@2.0.1", 141 CPEs: []cpe.CPE{ 142 cpe.Must("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), 143 }, 144 }) 145 } 146 }