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 }