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

     1  package cataloger
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/assert"
     7  
     8  	"github.com/anchore/syft/syft/artifact"
     9  	"github.com/anchore/syft/syft/file"
    10  	"github.com/anchore/syft/syft/pkg"
    11  )
    12  
    13  var _ pkg.Cataloger = (*dummy)(nil)
    14  
    15  type dummy struct {
    16  	name string
    17  }
    18  
    19  func (d dummy) Name() string {
    20  	return d.name
    21  }
    22  
    23  func (d dummy) Catalog(_ file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
    24  	panic("not implemented")
    25  }
    26  
    27  func Test_filterCatalogers(t *testing.T) {
    28  	largeCatalogerList := []string{
    29  		"alpm-db-cataloger",
    30  		"apkdb-cataloger",
    31  		"binary-cataloger",
    32  		"conan-cataloger",
    33  		"dartlang-lock-cataloger",
    34  		"dpkg-db-cataloger",
    35  		"dotnet-deps-cataloger",
    36  		"elixir-mix-lock-cataloger",
    37  		"erlang-rebar-lock-cataloger",
    38  		"go-module-file-cataloger",
    39  		"go-module-binary-cataloger",
    40  		"haskell-cataloger",
    41  		"graalvm-native-image-cataloger",
    42  		"java-cataloger",
    43  		"java-pom-cataloger",
    44  		"javascript-package-cataloger",
    45  		"javascript-lock-cataloger",
    46  		"php-composer-installed-cataloger",
    47  		"php-composer-lock-cataloger",
    48  		"portage-cataloger",
    49  		"python-package-cataloger",
    50  		"python-installed-package-cataloger",
    51  		"rpm-db-cataloger",
    52  		"rpm-archive-cataloger",
    53  		"ruby-gemfile-cataloger",
    54  		"ruby-installed-gemspec-cataloger",
    55  		"rust-cargo-lock-cataloger",
    56  		"cargo-auditable-binary-cataloger",
    57  		"sbom-cataloger",
    58  		"cocoapods-cataloger",
    59  	}
    60  	tests := []struct {
    61  		name       string
    62  		patterns   []string
    63  		catalogers []string
    64  		want       []string
    65  	}{
    66  		{
    67  			name:     "no filtering",
    68  			patterns: nil,
    69  			catalogers: []string{
    70  				"ruby-installed-gemspec-cataloger",
    71  				"python-installed-package-cataloger",
    72  				"php-composer-installed-cataloger",
    73  				"javascript-package-cataloger",
    74  				"dpkg-db-cataloger",
    75  				"rpm-db-cataloger",
    76  				"java-cataloger",
    77  				"apkdb-cataloger",
    78  				"go-module-binary-cataloger",
    79  			},
    80  			want: []string{
    81  				"ruby-installed-gemspec-cataloger",
    82  				"python-installed-package-cataloger",
    83  				"php-composer-installed-cataloger",
    84  				"javascript-package-cataloger",
    85  				"dpkg-db-cataloger",
    86  				"rpm-db-cataloger",
    87  				"java-cataloger",
    88  				"apkdb-cataloger",
    89  				"go-module-binary-cataloger",
    90  			},
    91  		},
    92  		{
    93  			name: "exact name match",
    94  			patterns: []string{
    95  				"rpm-db-cataloger",
    96  				"javascript-package-cataloger",
    97  			},
    98  			catalogers: []string{
    99  				"ruby-installed-gemspec-cataloger",
   100  				"python-installed-package-cataloger",
   101  				"php-composer-installed-cataloger",
   102  				"javascript-package-cataloger",
   103  				"dpkg-db-cataloger",
   104  				"rpm-db-cataloger",
   105  				"java-cataloger",
   106  				"apkdb-cataloger",
   107  				"go-module-binary-cataloger",
   108  			},
   109  			want: []string{
   110  				"javascript-package-cataloger",
   111  				"rpm-db-cataloger",
   112  			},
   113  		},
   114  		{
   115  			name: "partial name match",
   116  			patterns: []string{
   117  				"ruby",
   118  				"installed",
   119  			},
   120  			catalogers: []string{
   121  				"ruby-installed-gemspec-cataloger",
   122  				"ruby-gemfile-cataloger",
   123  				"python-installed-package-cataloger",
   124  				"php-composer-installed-cataloger",
   125  				"javascript-package-cataloger",
   126  				"dpkg-db-cataloger",
   127  				"rpm-db-cataloger",
   128  				"java-cataloger",
   129  				"apkdb-cataloger",
   130  				"go-module-binary-cataloger",
   131  			},
   132  			want: []string{
   133  				"php-composer-installed-cataloger",
   134  				"python-installed-package-cataloger",
   135  				"ruby-installed-gemspec-cataloger",
   136  				"ruby-gemfile-cataloger",
   137  			},
   138  		},
   139  		{
   140  			name: "ignore 'cataloger' keyword",
   141  			patterns: []string{
   142  				"cataloger",
   143  			},
   144  			catalogers: []string{
   145  				"ruby-installed-gemspec-cataloger",
   146  				"ruby-gemfile-cataloger",
   147  				"python-installed-package-cataloger",
   148  				"php-composer-installed-cataloger",
   149  				"javascript-package-cataloger",
   150  				"dpkg-db-cataloger",
   151  				"rpm-db-cataloger",
   152  				"java-cataloger",
   153  				"apkdb-cataloger",
   154  				"go-module-binary-cataloger",
   155  			},
   156  			want: []string{},
   157  		},
   158  		{
   159  			name: "only some patterns match",
   160  			patterns: []string{
   161  				"cataloger",
   162  				"go-module",
   163  			},
   164  			catalogers: []string{
   165  				"ruby-installed-gemspec-cataloger",
   166  				"ruby-gemfile-cataloger",
   167  				"python-installed-package-cataloger",
   168  				"php-composer-installed-cataloger",
   169  				"javascript-package-cataloger",
   170  				"dpkg-db-cataloger",
   171  				"rpm-db-cataloger",
   172  				"java-cataloger",
   173  				"apkdb-cataloger",
   174  				"go-module-binary-cataloger",
   175  			},
   176  			want: []string{
   177  				"go-module-binary-cataloger",
   178  			},
   179  		},
   180  		{
   181  			name: "don't cross match ecosystems with matching prefix",
   182  			patterns: []string{
   183  				"java-cataloger",
   184  			},
   185  			catalogers: []string{
   186  				"javascript-package-cataloger",
   187  				"java-cataloger",
   188  			},
   189  			want: []string{
   190  				"java-cataloger",
   191  			},
   192  		},
   193  		{
   194  			name: "don't cross match ecosystems with short, common name",
   195  			patterns: []string{
   196  				"go",
   197  			},
   198  			catalogers: largeCatalogerList,
   199  			want: []string{
   200  				"go-module-file-cataloger",
   201  				"go-module-binary-cataloger",
   202  				//"rust-cargo-lock-cataloger",  // with naive "contains" matching
   203  				//"cargo-auditable-binary-cataloger",  // with naive "contains" matching
   204  			},
   205  		},
   206  		{
   207  			name: "ignore partial matches",
   208  			patterns: []string{
   209  				"mod",
   210  			},
   211  			catalogers: largeCatalogerList,
   212  			want:       []string{
   213  				// important! these are NOT found
   214  				//"go-module-file-cataloger",
   215  				//"go-module-binary-cataloger",
   216  			},
   217  		},
   218  	}
   219  	for _, tt := range tests {
   220  		t.Run(tt.name, func(t *testing.T) {
   221  			var catalogers []pkg.Cataloger
   222  			for _, n := range tt.catalogers {
   223  				catalogers = append(catalogers, dummy{name: n})
   224  			}
   225  			got := filterCatalogers(catalogers, tt.patterns)
   226  			var gotNames []string
   227  			for _, g := range got {
   228  				gotNames = append(gotNames, g.Name())
   229  			}
   230  			assert.ElementsMatch(t, tt.want, gotNames)
   231  		})
   232  	}
   233  }
   234  
   235  func Test_contains(t *testing.T) {
   236  	tests := []struct {
   237  		name              string
   238  		enabledCatalogers []string
   239  		catalogerName     string
   240  		want              bool
   241  	}{
   242  		{
   243  			name: "keep exact match",
   244  			enabledCatalogers: []string{
   245  				"php-composer-installed-cataloger",
   246  			},
   247  			catalogerName: "php-composer-installed-cataloger",
   248  			want:          true,
   249  		},
   250  		{
   251  			name: "match substring",
   252  			enabledCatalogers: []string{
   253  				"python",
   254  			},
   255  			catalogerName: "python-installed-package-cataloger",
   256  			want:          true,
   257  		},
   258  		{
   259  			name: "dont match on 'cataloger'",
   260  			enabledCatalogers: []string{
   261  				"cataloger",
   262  			},
   263  			catalogerName: "python-installed-package-cataloger",
   264  			want:          false,
   265  		},
   266  	}
   267  	for _, tt := range tests {
   268  		t.Run(tt.name, func(t *testing.T) {
   269  			assert.Equal(t, tt.want, contains(tt.enabledCatalogers, tt.catalogerName))
   270  		})
   271  	}
   272  }
   273  
   274  func Test_hasFullWord(t *testing.T) {
   275  
   276  	tests := []struct {
   277  		name         string
   278  		targetPhrase string
   279  		candidate    string
   280  		want         bool
   281  	}{
   282  		{
   283  			name:         "exact match",
   284  			targetPhrase: "php-composer-installed-cataloger",
   285  			candidate:    "php-composer-installed-cataloger",
   286  			want:         true,
   287  		},
   288  		{
   289  			name:         "partial, full word match",
   290  			targetPhrase: "composer",
   291  			candidate:    "php-composer-installed-cataloger",
   292  			want:         true,
   293  		},
   294  		{
   295  			name:         "partial, full, multi-word match",
   296  			targetPhrase: "php-composer",
   297  			candidate:    "php-composer-installed-cataloger",
   298  			want:         true,
   299  		},
   300  		{
   301  			name:         "prefix match",
   302  			targetPhrase: "php",
   303  			candidate:    "php-composer-installed-cataloger",
   304  			want:         true,
   305  		},
   306  		{
   307  			name:         "postfix match with -cataloger suffix",
   308  			targetPhrase: "installed",
   309  			candidate:    "php-composer-installed-cataloger",
   310  			want:         true,
   311  		},
   312  		{
   313  			name:         "postfix match",
   314  			targetPhrase: "installed",
   315  			candidate:    "php-composer-installed",
   316  			want:         true,
   317  		},
   318  		{
   319  			name:         "ignore cataloger keyword",
   320  			targetPhrase: "cataloger",
   321  			candidate:    "php-composer-installed-cataloger",
   322  			want:         false,
   323  		},
   324  		{
   325  			name:         "ignore partial match",
   326  			targetPhrase: "hp",
   327  			candidate:    "php-composer-installed-cataloger",
   328  			want:         false,
   329  		},
   330  		{
   331  			name:         "ignore empty string",
   332  			targetPhrase: "",
   333  			candidate:    "php-composer-installed-cataloger",
   334  			want:         false,
   335  		},
   336  	}
   337  	for _, tt := range tests {
   338  		t.Run(tt.name, func(t *testing.T) {
   339  			assert.Equalf(t, tt.want, hasFullWord(tt.targetPhrase, tt.candidate), "hasFullWord(%v, %v)", tt.targetPhrase, tt.candidate)
   340  		})
   341  	}
   342  }