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  }