github.com/lineaje-labs/syft@v0.98.1-0.20231227153149-9e393f60ff1b/syft/pkg/cataloger/redhat/parse_rpm_db_test.go (about) 1 package redhat 2 3 import ( 4 "fmt" 5 "io" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 10 "github.com/anchore/syft/syft/file" 11 "github.com/anchore/syft/syft/pkg" 12 "github.com/lineaje-labs/syft/syft/pkg/cataloger/internal/pkgtest" 13 ) 14 15 var _ file.Resolver = (*rpmdbTestFileResolverMock)(nil) 16 17 type rpmdbTestFileResolverMock struct { 18 ignorePaths bool 19 } 20 21 func (r rpmdbTestFileResolverMock) FilesByExtension(extensions ...string) ([]file.Location, error) { 22 panic("not implemented") 23 } 24 25 func (r rpmdbTestFileResolverMock) FilesByBasename(filenames ...string) ([]file.Location, error) { 26 panic("not implemented") 27 } 28 29 func (r rpmdbTestFileResolverMock) FilesByBasenameGlob(globs ...string) ([]file.Location, error) { 30 panic("not implemented") 31 } 32 33 func (r rpmdbTestFileResolverMock) FileContentsByLocation(location file.Location) (io.ReadCloser, error) { 34 panic("not implemented") 35 } 36 37 func (r rpmdbTestFileResolverMock) AllLocations() <-chan file.Location { 38 panic("not implemented") 39 } 40 41 func (r rpmdbTestFileResolverMock) FileMetadataByLocation(location file.Location) (file.Metadata, error) { 42 panic("not implemented") 43 } 44 45 func newTestFileResolver(ignorePaths bool) *rpmdbTestFileResolverMock { 46 return &rpmdbTestFileResolverMock{ 47 ignorePaths: ignorePaths, 48 } 49 } 50 51 func (r rpmdbTestFileResolverMock) HasPath(path string) bool { 52 return !r.ignorePaths 53 } 54 55 func (r *rpmdbTestFileResolverMock) FilesByPath(paths ...string) ([]file.Location, error) { 56 if r.ignorePaths { 57 // act as if no paths exist 58 return nil, nil 59 } 60 // act as if all files exist 61 var locations = make([]file.Location, len(paths)) 62 for i, p := range paths { 63 locations[i] = file.NewLocation(p) 64 } 65 return locations, nil 66 } 67 68 func (r *rpmdbTestFileResolverMock) FilesByGlob(...string) ([]file.Location, error) { 69 return nil, fmt.Errorf("not implemented") 70 } 71 72 func (r *rpmdbTestFileResolverMock) RelativeFileByPath(file.Location, string) *file.Location { 73 panic(fmt.Errorf("not implemented")) 74 return nil 75 } 76 77 func (r *rpmdbTestFileResolverMock) FilesByMIMEType(...string) ([]file.Location, error) { 78 return nil, fmt.Errorf("not implemented") 79 } 80 81 func TestParseRpmDB(t *testing.T) { 82 packagesLocation := file.NewLocation("test-fixtures/Packages") 83 tests := []struct { 84 fixture string 85 expected []pkg.Package 86 ignorePaths bool 87 }{ 88 { 89 fixture: "test-fixtures/Packages", 90 // we only surface package paths for files that exist (here we DO NOT expect a path) 91 ignorePaths: true, 92 expected: []pkg.Package{ 93 { 94 Name: "dive", 95 Version: "0.9.2-1", 96 PURL: "pkg:rpm/dive@0.9.2-1?arch=x86_64&upstream=dive-0.9.2-1.src.rpm", 97 Locations: file.NewLocationSet(file.NewLocation("test-fixtures/Packages")), 98 Type: pkg.RpmPkg, 99 Licenses: pkg.NewLicenseSet( 100 pkg.NewLicenseFromLocations("MIT", packagesLocation), 101 ), 102 Metadata: pkg.RpmDBEntry{ 103 Name: "dive", 104 Epoch: nil, 105 Arch: "x86_64", 106 Release: "1", 107 Version: "0.9.2", 108 SourceRpm: "dive-0.9.2-1.src.rpm", 109 Size: 12406784, 110 Vendor: "", 111 Files: []pkg.RpmFileRecord{}, 112 }, 113 }, 114 }, 115 }, 116 { 117 fixture: "test-fixtures/Packages", 118 // we only surface package paths for files that exist (here we expect a path) 119 ignorePaths: false, 120 expected: []pkg.Package{ 121 { 122 Name: "dive", 123 Version: "0.9.2-1", 124 PURL: "pkg:rpm/dive@0.9.2-1?arch=x86_64&upstream=dive-0.9.2-1.src.rpm", 125 Locations: file.NewLocationSet(packagesLocation), 126 Type: pkg.RpmPkg, 127 Licenses: pkg.NewLicenseSet( 128 pkg.NewLicenseFromLocations("MIT", packagesLocation), 129 ), 130 Metadata: pkg.RpmDBEntry{ 131 Name: "dive", 132 Epoch: nil, 133 Arch: "x86_64", 134 Release: "1", 135 Version: "0.9.2", 136 SourceRpm: "dive-0.9.2-1.src.rpm", 137 Size: 12406784, 138 Vendor: "", 139 Files: []pkg.RpmFileRecord{ 140 { 141 Path: "/usr/local/bin/dive", 142 Mode: 33261, 143 Size: 12406784, 144 Digest: file.Digest{ 145 Algorithm: "sha256", 146 Value: "81d29f327ba23096b3c52ff6fe1c425641e618bc87b5c05ee377edc650afaa55", 147 }, 148 // note: there is no username, groupname, or flags for this RPM 149 }, 150 }, 151 }, 152 }, 153 }, 154 }, 155 } 156 157 for _, test := range tests { 158 t.Run(test.fixture, func(t *testing.T) { 159 pkgtest.NewCatalogTester(). 160 WithResolver(newTestFileResolver(test.ignorePaths)). 161 FromFile(t, test.fixture). 162 Expects(test.expected, nil). 163 TestParser(t, parseRpmDB) 164 }) 165 } 166 } 167 168 func TestToElVersion(t *testing.T) { 169 tests := []struct { 170 name string 171 entry pkg.RpmDBEntry 172 expected string 173 }{ 174 { 175 name: "no epoch", 176 entry: pkg.RpmDBEntry{ 177 Version: "1.2.3-4", 178 Release: "el7", 179 Arch: "x86-64", 180 }, 181 expected: "1.2.3-4-el7", 182 }, 183 { 184 name: "with 0 epoch", 185 entry: pkg.RpmDBEntry{ 186 Version: "1.2.3-4", 187 Release: "el7", 188 Arch: "x86-64", 189 Epoch: intRef(0), 190 }, 191 expected: "0:1.2.3-4-el7", 192 }, 193 { 194 name: "with non-zero epoch", 195 entry: pkg.RpmDBEntry{ 196 Version: "1.2.3-4", 197 Release: "el7", 198 Arch: "x86-64", 199 Epoch: intRef(12), 200 }, 201 expected: "12:1.2.3-4-el7", 202 }, 203 } 204 205 for _, test := range tests { 206 t.Run(test.name, func(t *testing.T) { 207 assert.Equal(t, test.expected, toELVersion(test.entry.Epoch, test.entry.Version, test.entry.Release)) 208 }) 209 } 210 } 211 212 func intRef(i int) *int { 213 return &i 214 }