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  }