github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/gosbom/pkg/cataloger/cataloger_test.go (about)

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