github.com/lineaje-labs/syft@v0.98.1-0.20231227153149-9e393f60ff1b/syft/pkg/cataloger/common/cpe/apk_test.go (about)

     1  package cpe
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/assert"
     7  
     8  	"github.com/anchore/syft/syft/pkg"
     9  )
    10  
    11  func Test_candidateVendorsForAPK(t *testing.T) {
    12  	tests := []struct {
    13  		name     string
    14  		pkg      pkg.Package
    15  		expected []string
    16  	}{
    17  		{
    18  			name: "py3-cryptography Package",
    19  			pkg: pkg.Package{
    20  				Metadata: pkg.ApkDBEntry{
    21  					Package: "py3-cryptography",
    22  				},
    23  			},
    24  			expected: []string{"python-cryptography_project", "cryptography", "cryptographyproject", "cryptography_project"},
    25  		},
    26  		{
    27  			name: "py2-pypdf with explicit different origin",
    28  			pkg: pkg.Package{
    29  				Metadata: pkg.ApkDBEntry{
    30  					Package:       "py2-pypdf",
    31  					OriginPackage: "abcdefg",
    32  				},
    33  			},
    34  			expected: []string{"pypdf", "pypdfproject", "pypdf_project"},
    35  		},
    36  		{
    37  			name: "ruby-armadillo Package",
    38  			pkg: pkg.Package{
    39  				Metadata: pkg.ApkDBEntry{
    40  					Package: "ruby-armadillo",
    41  				},
    42  			},
    43  			expected: []string{"armadillo"},
    44  		},
    45  		{
    46  			name: "python-3.6",
    47  			pkg: pkg.Package{
    48  				Metadata: pkg.ApkDBEntry{
    49  					Package: "python-3.6",
    50  				},
    51  			},
    52  			expected: []string{"python", "python_software_foundation"},
    53  		},
    54  		{
    55  			name: "ruby-3.6",
    56  			pkg: pkg.Package{
    57  				Metadata: pkg.ApkDBEntry{
    58  					Package: "ruby-3.6",
    59  					URL:     "https://www.ruby-lang.org/",
    60  				},
    61  			},
    62  			expected: []string{"ruby", "ruby-lang"},
    63  		},
    64  		{
    65  			name: "make",
    66  			pkg: pkg.Package{
    67  				Metadata: pkg.ApkDBEntry{
    68  					Package: "make",
    69  					URL:     "https://www.gnu.org/software/make",
    70  				},
    71  			},
    72  			expected: []string{"gnu", "make"},
    73  		},
    74  		{
    75  			name: "ruby-rake with matching origin",
    76  			pkg: pkg.Package{
    77  				Name: "ruby-rake",
    78  				Type: pkg.ApkPkg,
    79  				Metadata: pkg.ApkDBEntry{
    80  					Package:       "ruby-rake",
    81  					URL:           "https://github.com/ruby/rake",
    82  					OriginPackage: "ruby-rake",
    83  				},
    84  			},
    85  			expected: []string{"rake", "ruby-lang", "ruby"},
    86  		},
    87  		{
    88  			name: "ruby-rake with non-matching origin",
    89  			pkg: pkg.Package{
    90  				Name: "ruby-rake",
    91  				Type: pkg.ApkPkg,
    92  				Metadata: pkg.ApkDBEntry{
    93  					Package:       "ruby-rake",
    94  					URL:           "https://www.ruby-lang.org/",
    95  					OriginPackage: "ruby",
    96  				},
    97  			},
    98  			expected: []string{"rake", "ruby-lang"},
    99  		},
   100  	}
   101  	for _, test := range tests {
   102  		t.Run(test.name, func(t *testing.T) {
   103  			assert.ElementsMatch(t, test.expected, candidateVendorsForAPK(test.pkg).uniqueValues(), "different vendors")
   104  		})
   105  	}
   106  }
   107  
   108  func Test_candidateProductsForAPK(t *testing.T) {
   109  	tests := []struct {
   110  		name     string
   111  		pkg      pkg.Package
   112  		expected []string
   113  	}{
   114  		{
   115  			name: "py3-cryptography Package",
   116  			pkg: pkg.Package{
   117  				Metadata: pkg.ApkDBEntry{
   118  					Package: "py3-cryptography",
   119  				},
   120  			},
   121  			expected: []string{"cryptography", "python-cryptography"},
   122  		},
   123  		{
   124  			name: "py2-pypdf with explicit different origin",
   125  			pkg: pkg.Package{
   126  				Metadata: pkg.ApkDBEntry{
   127  					Package:       "py2-pypdf",
   128  					OriginPackage: "abcdefg",
   129  				},
   130  			},
   131  			expected: []string{"pypdf"},
   132  		},
   133  		{
   134  			name: "ruby-armadillo Package",
   135  			pkg: pkg.Package{
   136  				Metadata: pkg.ApkDBEntry{
   137  					Package: "ruby-armadillo",
   138  				},
   139  			},
   140  			expected: []string{"armadillo"},
   141  		},
   142  		{
   143  			name: "python-3.6",
   144  			pkg: pkg.Package{
   145  				Metadata: pkg.ApkDBEntry{
   146  					Package: "python-3.6",
   147  				},
   148  			},
   149  			expected: []string{"python"},
   150  		},
   151  		{
   152  			name: "ruby-3.6",
   153  			pkg: pkg.Package{
   154  				Metadata: pkg.ApkDBEntry{
   155  					Package: "ruby-3.6",
   156  					URL:     "https://www.ruby-lang.org/",
   157  				},
   158  			},
   159  			expected: []string{"ruby"},
   160  		},
   161  		{
   162  			name: "make",
   163  			pkg: pkg.Package{
   164  				Metadata: pkg.ApkDBEntry{
   165  					Package: "make",
   166  					URL:     "https://www.gnu.org/software/make",
   167  				},
   168  			},
   169  			expected: []string{"make"},
   170  		},
   171  		{
   172  			name: "ruby-rake with matching origin",
   173  			pkg: pkg.Package{
   174  				Metadata: pkg.ApkDBEntry{
   175  					Package:       "ruby-rake",
   176  					URL:           "https://github.com/ruby/rake",
   177  					OriginPackage: "ruby-rake",
   178  				},
   179  			},
   180  			expected: []string{"rake"},
   181  		},
   182  		{
   183  			name: "ruby-rake with non-matching origin",
   184  			pkg: pkg.Package{
   185  				Name: "ruby-rake",
   186  				Type: pkg.ApkPkg,
   187  				Metadata: pkg.ApkDBEntry{
   188  					Package:       "ruby-rake",
   189  					URL:           "https://www.ruby-lang.org/",
   190  					OriginPackage: "ruby",
   191  				},
   192  			},
   193  			expected: []string{"rake"},
   194  		},
   195  	}
   196  	for _, test := range tests {
   197  		t.Run(test.name, func(t *testing.T) {
   198  			assert.ElementsMatch(t, test.expected, candidateProductsForAPK(test.pkg).uniqueValues(), "different products")
   199  		})
   200  	}
   201  }
   202  
   203  func Test_upstreamCandidates(t *testing.T) {
   204  	tests := []struct {
   205  		name     string
   206  		metadata pkg.ApkDBEntry
   207  		expected []upstreamCandidate
   208  	}{
   209  		{
   210  			name: "gocase",
   211  			metadata: pkg.ApkDBEntry{
   212  				Package: "p",
   213  			},
   214  			expected: []upstreamCandidate{
   215  				{Name: "p", Type: pkg.UnknownPkg},
   216  			},
   217  		},
   218  		{
   219  			name: "same package and origin simple case",
   220  			metadata: pkg.ApkDBEntry{
   221  				Package:       "p",
   222  				OriginPackage: "p",
   223  			},
   224  			expected: []upstreamCandidate{
   225  				{Name: "p", Type: pkg.UnknownPkg},
   226  			},
   227  		},
   228  		{
   229  			name: "different package and origin",
   230  			metadata: pkg.ApkDBEntry{
   231  				Package:       "p",
   232  				OriginPackage: "origin",
   233  			},
   234  			expected: []upstreamCandidate{
   235  				{Name: "p", Type: pkg.UnknownPkg},
   236  			},
   237  		},
   238  		{
   239  			name: "upstream python package information as qualifier py- prefix",
   240  			metadata: pkg.ApkDBEntry{
   241  				Package:       "py-potatoes",
   242  				OriginPackage: "py-potatoes",
   243  			},
   244  			expected: []upstreamCandidate{
   245  				{Name: "potatoes", Type: pkg.PythonPkg},
   246  			},
   247  		},
   248  		{
   249  			name: "upstream python package information as qualifier py3- prefix",
   250  			metadata: pkg.ApkDBEntry{
   251  				Package:       "py3-potatoes",
   252  				OriginPackage: "py3-potatoes",
   253  			},
   254  			expected: []upstreamCandidate{
   255  				{Name: "potatoes", Type: pkg.PythonPkg},
   256  			},
   257  		},
   258  		{
   259  			name: "python package with distinct origin package",
   260  			metadata: pkg.ApkDBEntry{
   261  				Package:       "py3-non-existant",
   262  				OriginPackage: "abcdefg",
   263  			},
   264  			expected: []upstreamCandidate{
   265  				{Name: "non-existant", Type: pkg.PythonPkg},
   266  			},
   267  		},
   268  		{
   269  			name: "upstream ruby package information as qualifier",
   270  			metadata: pkg.ApkDBEntry{
   271  				Package:       "ruby-something",
   272  				OriginPackage: "ruby-something",
   273  			},
   274  			expected: []upstreamCandidate{
   275  				{Name: "something", Type: pkg.GemPkg},
   276  			},
   277  		},
   278  		{
   279  			name: "ruby package with distinct origin package",
   280  			metadata: pkg.ApkDBEntry{
   281  				Package:       "ruby-something",
   282  				OriginPackage: "1234567",
   283  			},
   284  			expected: []upstreamCandidate{
   285  				{Name: "something", Type: pkg.GemPkg},
   286  			},
   287  		},
   288  		{
   289  			name: "postgesql-15 upstream postgresql",
   290  			metadata: pkg.ApkDBEntry{
   291  				Package: "postgresql-15",
   292  			},
   293  			expected: []upstreamCandidate{
   294  				{Name: "postgresql", Type: pkg.UnknownPkg},
   295  			},
   296  		},
   297  		{
   298  			name: "postgesql15 upstream postgresql",
   299  			metadata: pkg.ApkDBEntry{
   300  				Package: "postgresql15",
   301  			},
   302  			expected: []upstreamCandidate{
   303  				{Name: "postgresql", Type: pkg.UnknownPkg},
   304  			},
   305  		},
   306  		{
   307  			name: "go-1.19 upstream go",
   308  			metadata: pkg.ApkDBEntry{
   309  				Package: "go-1.19",
   310  			},
   311  			expected: []upstreamCandidate{
   312  				{Name: "go", Type: pkg.UnknownPkg},
   313  			},
   314  		},
   315  		{
   316  			name: "go1.143 upstream go",
   317  			metadata: pkg.ApkDBEntry{
   318  				Package: "go1.143",
   319  			},
   320  			expected: []upstreamCandidate{
   321  				{Name: "go", Type: pkg.UnknownPkg},
   322  			},
   323  		},
   324  		{
   325  			name: "abc-101.191.23456 upstream abc",
   326  			metadata: pkg.ApkDBEntry{
   327  				Package: "abc-101.191.23456",
   328  			},
   329  			expected: []upstreamCandidate{
   330  				{Name: "abc", Type: pkg.UnknownPkg},
   331  			},
   332  		},
   333  		{
   334  			name: "abc101.191.23456 upstream abc",
   335  			metadata: pkg.ApkDBEntry{
   336  				Package: "abc101.191.23456",
   337  			},
   338  			expected: []upstreamCandidate{
   339  				{Name: "abc", Type: pkg.UnknownPkg},
   340  			},
   341  		},
   342  		{
   343  			name: "abc101-12345-1045 upstream abc101-12345",
   344  			metadata: pkg.ApkDBEntry{
   345  				Package: "abc101-12345-1045",
   346  			},
   347  			expected: []upstreamCandidate{
   348  				{Name: "abc101-12345", Type: pkg.UnknownPkg},
   349  			},
   350  		},
   351  		{
   352  			name: "abc101-a12345-1045 upstream abc101-a12345",
   353  			metadata: pkg.ApkDBEntry{
   354  				Package: "abc101-a12345-1045",
   355  			},
   356  			expected: []upstreamCandidate{
   357  				{Name: "abc-a12345-1045", Type: pkg.UnknownPkg},
   358  			},
   359  		},
   360  		{
   361  			name: "package starting with single digit",
   362  			metadata: pkg.ApkDBEntry{
   363  				Package: "3proxy",
   364  			},
   365  			expected: []upstreamCandidate{
   366  				{Name: "3proxy", Type: pkg.UnknownPkg},
   367  			},
   368  		},
   369  		{
   370  			name: "package starting with multiple digits",
   371  			metadata: pkg.ApkDBEntry{
   372  				Package: "356proxy",
   373  			},
   374  			expected: []upstreamCandidate{
   375  				{Name: "356proxy", Type: pkg.UnknownPkg},
   376  			},
   377  		},
   378  		{
   379  			name: "package composed of only digits",
   380  			metadata: pkg.ApkDBEntry{
   381  				Package: "123456",
   382  			},
   383  			expected: []upstreamCandidate{
   384  				{Name: "123456", Type: pkg.UnknownPkg},
   385  			},
   386  		},
   387  		{
   388  			name: "ruby-3.6 upstream ruby",
   389  			metadata: pkg.ApkDBEntry{
   390  				Package: "ruby-3.6",
   391  			},
   392  			expected: []upstreamCandidate{
   393  				{Name: "ruby", Type: pkg.UnknownPkg},
   394  			},
   395  		},
   396  		{
   397  			name: "ruby3.6 upstream ruby",
   398  			metadata: pkg.ApkDBEntry{
   399  				Package: "ruby3.6",
   400  			},
   401  			expected: []upstreamCandidate{
   402  				{Name: "ruby", Type: pkg.UnknownPkg},
   403  			},
   404  		},
   405  		{
   406  			name: "ruby3.6-tacos upstream tacos",
   407  			metadata: pkg.ApkDBEntry{
   408  				Package: "ruby3.6-tacos",
   409  			},
   410  			expected: []upstreamCandidate{
   411  				{Name: "tacos", Type: pkg.GemPkg},
   412  			},
   413  		},
   414  		{
   415  			name: "ruby-3.6-tacos upstream tacos",
   416  			metadata: pkg.ApkDBEntry{
   417  				Package: "ruby-3.6-tacos",
   418  			},
   419  			expected: []upstreamCandidate{
   420  				{Name: "tacos", Type: pkg.GemPkg},
   421  			},
   422  		},
   423  		{
   424  			name: "abc1234jksajflksa",
   425  			metadata: pkg.ApkDBEntry{
   426  				Package: "abc1234jksajflksa",
   427  			},
   428  			expected: []upstreamCandidate{
   429  				{Name: "abc1234jksajflksa", Type: pkg.UnknownPkg},
   430  			},
   431  		},
   432  	}
   433  
   434  	for _, test := range tests {
   435  		t.Run(test.name, func(t *testing.T) {
   436  			actual := upstreamCandidates(test.metadata)
   437  			assert.Equal(t, test.expected, actual)
   438  		})
   439  	}
   440  }