github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/syft/pkg/cataloger/rpm/parse_rpm_db_test.go (about) 1 package rpm 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/anchore/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 MetadataType: pkg.RpmMetadataType, 100 Licenses: pkg.NewLicenseSet( 101 pkg.NewLicenseFromLocations("MIT", packagesLocation), 102 ), 103 Metadata: pkg.RpmMetadata{ 104 Name: "dive", 105 Epoch: nil, 106 Arch: "x86_64", 107 Release: "1", 108 Version: "0.9.2", 109 SourceRpm: "dive-0.9.2-1.src.rpm", 110 Size: 12406784, 111 Vendor: "", 112 Files: []pkg.RpmdbFileRecord{}, 113 }, 114 }, 115 }, 116 }, 117 { 118 fixture: "test-fixtures/Packages", 119 // we only surface package paths for files that exist (here we expect a path) 120 ignorePaths: false, 121 expected: []pkg.Package{ 122 { 123 Name: "dive", 124 Version: "0.9.2-1", 125 PURL: "pkg:rpm/dive@0.9.2-1?arch=x86_64&upstream=dive-0.9.2-1.src.rpm", 126 Locations: file.NewLocationSet(packagesLocation), 127 Type: pkg.RpmPkg, 128 MetadataType: pkg.RpmMetadataType, 129 Licenses: pkg.NewLicenseSet( 130 pkg.NewLicenseFromLocations("MIT", packagesLocation), 131 ), 132 Metadata: pkg.RpmMetadata{ 133 Name: "dive", 134 Epoch: nil, 135 Arch: "x86_64", 136 Release: "1", 137 Version: "0.9.2", 138 SourceRpm: "dive-0.9.2-1.src.rpm", 139 Size: 12406784, 140 Vendor: "", 141 Files: []pkg.RpmdbFileRecord{ 142 { 143 Path: "/usr/local/bin/dive", 144 Mode: 33261, 145 Size: 12406784, 146 Digest: file.Digest{ 147 Algorithm: "sha256", 148 Value: "81d29f327ba23096b3c52ff6fe1c425641e618bc87b5c05ee377edc650afaa55", 149 }, 150 // note: there is no username, groupname, or flags for this RPM 151 }, 152 }, 153 }, 154 }, 155 }, 156 }, 157 } 158 159 for _, test := range tests { 160 t.Run(test.fixture, func(t *testing.T) { 161 pkgtest.NewCatalogTester(). 162 WithResolver(newTestFileResolver(test.ignorePaths)). 163 FromFile(t, test.fixture). 164 Expects(test.expected, nil). 165 TestParser(t, parseRpmDB) 166 }) 167 } 168 } 169 170 func TestToElVersion(t *testing.T) { 171 tests := []struct { 172 name string 173 entry pkg.RpmMetadata 174 expected string 175 }{ 176 { 177 name: "no epoch", 178 entry: pkg.RpmMetadata{ 179 Version: "1.2.3-4", 180 Release: "el7", 181 Arch: "x86-64", 182 }, 183 expected: "1.2.3-4-el7", 184 }, 185 { 186 name: "with 0 epoch", 187 entry: pkg.RpmMetadata{ 188 Version: "1.2.3-4", 189 Release: "el7", 190 Arch: "x86-64", 191 Epoch: intRef(0), 192 }, 193 expected: "0:1.2.3-4-el7", 194 }, 195 { 196 name: "with non-zero epoch", 197 entry: pkg.RpmMetadata{ 198 Version: "1.2.3-4", 199 Release: "el7", 200 Arch: "x86-64", 201 Epoch: intRef(12), 202 }, 203 expected: "12:1.2.3-4-el7", 204 }, 205 } 206 207 for _, test := range tests { 208 t.Run(test.name, func(t *testing.T) { 209 assert.Equal(t, test.expected, toELVersion(test.entry)) 210 }) 211 } 212 } 213 214 func intRef(i int) *int { 215 return &i 216 }