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 }