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