github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/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  		"alpmdb-cataloger",
    30  		"apkdb-cataloger",
    31  		"binary-cataloger",
    32  		"conan-cataloger",
    33  		"dartlang-lock-cataloger",
    34  		"dpkgdb-cataloger",
    35  		"dotnet-deps-cataloger",
    36  		"elixir-mix-lock-cataloger",
    37  		"erlang-rebar-lock-cataloger",
    38  		"go-mod-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-index-cataloger",
    50  		"python-package-cataloger",
    51  		"rpm-db-cataloger",
    52  		"rpm-file-cataloger",
    53  		"ruby-gemfile-cataloger",
    54  		"ruby-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-gemspec-cataloger",
    71  				"python-package-cataloger",
    72  				"php-composer-installed-cataloger",
    73  				"javascript-package-cataloger",
    74  				"dpkgdb-cataloger",
    75  				"rpmdb-cataloger",
    76  				"java-cataloger",
    77  				"apkdb-cataloger",
    78  				"go-module-binary-cataloger",
    79  			},
    80  			want: []string{
    81  				"ruby-gemspec-cataloger",
    82  				"python-package-cataloger",
    83  				"php-composer-installed-cataloger",
    84  				"javascript-package-cataloger",
    85  				"dpkgdb-cataloger",
    86  				"rpmdb-cataloger",
    87  				"java-cataloger",
    88  				"apkdb-cataloger",
    89  				"go-module-binary-cataloger",
    90  			},
    91  		},
    92  		{
    93  			name: "exact name match",
    94  			patterns: []string{
    95  				"rpmdb-cataloger",
    96  				"javascript-package-cataloger",
    97  			},
    98  			catalogers: []string{
    99  				"ruby-gemspec-cataloger",
   100  				"python-package-cataloger",
   101  				"php-composer-installed-cataloger",
   102  				"javascript-package-cataloger",
   103  				"dpkgdb-cataloger",
   104  				"rpmdb-cataloger",
   105  				"java-cataloger",
   106  				"apkdb-cataloger",
   107  				"go-module-binary-cataloger",
   108  			},
   109  			want: []string{
   110  				"javascript-package-cataloger",
   111  				"rpmdb-cataloger",
   112  			},
   113  		},
   114  		{
   115  			name: "partial name match",
   116  			patterns: []string{
   117  				"ruby",
   118  				"installed",
   119  			},
   120  			catalogers: []string{
   121  				"ruby-gemspec-cataloger",
   122  				"ruby-gemfile-cataloger",
   123  				"python-package-cataloger",
   124  				"php-composer-installed-cataloger",
   125  				"javascript-package-cataloger",
   126  				"dpkgdb-cataloger",
   127  				"rpmdb-cataloger",
   128  				"java-cataloger",
   129  				"apkdb-cataloger",
   130  				"go-module-binary-cataloger",
   131  			},
   132  			want: []string{
   133  				"php-composer-installed-cataloger",
   134  				"ruby-gemspec-cataloger",
   135  				"ruby-gemfile-cataloger",
   136  			},
   137  		},
   138  		{
   139  			name: "ignore 'cataloger' keyword",
   140  			patterns: []string{
   141  				"cataloger",
   142  			},
   143  			catalogers: []string{
   144  				"ruby-gemspec-cataloger",
   145  				"ruby-gemfile-cataloger",
   146  				"python-package-cataloger",
   147  				"php-composer-installed-cataloger",
   148  				"javascript-package-cataloger",
   149  				"dpkgdb-cataloger",
   150  				"rpmdb-cataloger",
   151  				"java-cataloger",
   152  				"apkdb-cataloger",
   153  				"go-module-binary-cataloger",
   154  			},
   155  			want: []string{},
   156  		},
   157  		{
   158  			name: "only some patterns match",
   159  			patterns: []string{
   160  				"cataloger",
   161  				"go-module",
   162  			},
   163  			catalogers: []string{
   164  				"ruby-gemspec-cataloger",
   165  				"ruby-gemfile-cataloger",
   166  				"python-package-cataloger",
   167  				"php-composer-installed-cataloger",
   168  				"javascript-package-cataloger",
   169  				"dpkgdb-cataloger",
   170  				"rpmdb-cataloger",
   171  				"java-cataloger",
   172  				"apkdb-cataloger",
   173  				"go-module-binary-cataloger",
   174  			},
   175  			want: []string{
   176  				"go-module-binary-cataloger",
   177  			},
   178  		},
   179  		{
   180  			name: "don't cross match ecosystems with matching prefix",
   181  			patterns: []string{
   182  				"java-cataloger",
   183  			},
   184  			catalogers: []string{
   185  				"javascript-package-cataloger",
   186  				"java-cataloger",
   187  			},
   188  			want: []string{
   189  				"java-cataloger",
   190  			},
   191  		},
   192  		{
   193  			name: "don't cross match ecosystems with short, common name",
   194  			patterns: []string{
   195  				"go",
   196  			},
   197  			catalogers: largeCatalogerList,
   198  			want: []string{
   199  				"go-mod-file-cataloger",
   200  				"go-module-binary-cataloger",
   201  				//"rust-cargo-lock-cataloger",  // with naive "contains" matching
   202  				//"cargo-auditable-binary-cataloger",  // with naive "contains" matching
   203  			},
   204  		},
   205  		{
   206  			name: "ignore partial matches",
   207  			patterns: []string{
   208  				"mod",
   209  			},
   210  			catalogers: largeCatalogerList,
   211  			want: []string{
   212  				"go-mod-file-cataloger",
   213  				//"go-module-binary-cataloger", // unfortunately not a full word (this should probably be renamed)
   214  			},
   215  		},
   216  	}
   217  	for _, tt := range tests {
   218  		t.Run(tt.name, func(t *testing.T) {
   219  			var catalogers []pkg.Cataloger
   220  			for _, n := range tt.catalogers {
   221  				catalogers = append(catalogers, dummy{name: n})
   222  			}
   223  			got := filterCatalogers(catalogers, tt.patterns)
   224  			var gotNames []string
   225  			for _, g := range got {
   226  				gotNames = append(gotNames, g.Name())
   227  			}
   228  			assert.ElementsMatch(t, tt.want, gotNames)
   229  		})
   230  	}
   231  }
   232  
   233  func Test_contains(t *testing.T) {
   234  	tests := []struct {
   235  		name              string
   236  		enabledCatalogers []string
   237  		catalogerName     string
   238  		want              bool
   239  	}{
   240  		{
   241  			name: "keep exact match",
   242  			enabledCatalogers: []string{
   243  				"php-composer-installed-cataloger",
   244  			},
   245  			catalogerName: "php-composer-installed-cataloger",
   246  			want:          true,
   247  		},
   248  		{
   249  			name: "match substring",
   250  			enabledCatalogers: []string{
   251  				"python",
   252  			},
   253  			catalogerName: "python-package-cataloger",
   254  			want:          true,
   255  		},
   256  		{
   257  			name: "dont match on 'cataloger'",
   258  			enabledCatalogers: []string{
   259  				"cataloger",
   260  			},
   261  			catalogerName: "python-package-cataloger",
   262  			want:          false,
   263  		},
   264  	}
   265  	for _, tt := range tests {
   266  		t.Run(tt.name, func(t *testing.T) {
   267  			assert.Equal(t, tt.want, contains(tt.enabledCatalogers, tt.catalogerName))
   268  		})
   269  	}
   270  }
   271  
   272  func Test_hasFullWord(t *testing.T) {
   273  
   274  	tests := []struct {
   275  		name         string
   276  		targetPhrase string
   277  		candidate    string
   278  		want         bool
   279  	}{
   280  		{
   281  			name:         "exact match",
   282  			targetPhrase: "php-composer-installed-cataloger",
   283  			candidate:    "php-composer-installed-cataloger",
   284  			want:         true,
   285  		},
   286  		{
   287  			name:         "partial, full word match",
   288  			targetPhrase: "composer",
   289  			candidate:    "php-composer-installed-cataloger",
   290  			want:         true,
   291  		},
   292  		{
   293  			name:         "partial, full, multi-word match",
   294  			targetPhrase: "php-composer",
   295  			candidate:    "php-composer-installed-cataloger",
   296  			want:         true,
   297  		},
   298  		{
   299  			name:         "prefix match",
   300  			targetPhrase: "php",
   301  			candidate:    "php-composer-installed-cataloger",
   302  			want:         true,
   303  		},
   304  		{
   305  			name:         "postfix match with -cataloger suffix",
   306  			targetPhrase: "installed",
   307  			candidate:    "php-composer-installed-cataloger",
   308  			want:         true,
   309  		},
   310  		{
   311  			name:         "postfix match",
   312  			targetPhrase: "installed",
   313  			candidate:    "php-composer-installed",
   314  			want:         true,
   315  		},
   316  		{
   317  			name:         "ignore cataloger keyword",
   318  			targetPhrase: "cataloger",
   319  			candidate:    "php-composer-installed-cataloger",
   320  			want:         false,
   321  		},
   322  		{
   323  			name:         "ignore partial match",
   324  			targetPhrase: "hp",
   325  			candidate:    "php-composer-installed-cataloger",
   326  			want:         false,
   327  		},
   328  		{
   329  			name:         "ignore empty string",
   330  			targetPhrase: "",
   331  			candidate:    "php-composer-installed-cataloger",
   332  			want:         false,
   333  		},
   334  	}
   335  	for _, tt := range tests {
   336  		t.Run(tt.name, func(t *testing.T) {
   337  			assert.Equalf(t, tt.want, hasFullWord(tt.targetPhrase, tt.candidate), "hasFullWord(%v, %v)", tt.targetPhrase, tt.candidate)
   338  		})
   339  	}
   340  }