github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/syft/pkg/cataloger/common/cpe/apk_test.go (about) 1 package cpe 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/assert" 7 8 "github.com/anchore/syft/syft/pkg" 9 ) 10 11 func Test_candidateVendorsForAPK(t *testing.T) { 12 tests := []struct { 13 name string 14 pkg pkg.Package 15 expected []string 16 }{ 17 { 18 name: "py3-cryptography Package", 19 pkg: pkg.Package{ 20 Metadata: pkg.ApkMetadata{ 21 Package: "py3-cryptography", 22 }, 23 }, 24 expected: []string{"python-cryptography_project", "cryptography", "cryptographyproject", "cryptography_project"}, 25 }, 26 { 27 name: "py2-pypdf with explicit different origin", 28 pkg: pkg.Package{ 29 Metadata: pkg.ApkMetadata{ 30 Package: "py2-pypdf", 31 OriginPackage: "abcdefg", 32 }, 33 }, 34 expected: []string{"pypdf", "pypdfproject", "pypdf_project"}, 35 }, 36 { 37 name: "ruby-armadillo Package", 38 pkg: pkg.Package{ 39 Metadata: pkg.ApkMetadata{ 40 Package: "ruby-armadillo", 41 }, 42 }, 43 expected: []string{"armadillo"}, 44 }, 45 { 46 name: "python-3.6", 47 pkg: pkg.Package{ 48 Metadata: pkg.ApkMetadata{ 49 Package: "python-3.6", 50 }, 51 }, 52 expected: []string{"python", "python_software_foundation"}, 53 }, 54 { 55 name: "ruby-3.6", 56 pkg: pkg.Package{ 57 Metadata: pkg.ApkMetadata{ 58 Package: "ruby-3.6", 59 URL: "https://www.ruby-lang.org/", 60 }, 61 }, 62 expected: []string{"ruby", "ruby-lang"}, 63 }, 64 { 65 name: "make", 66 pkg: pkg.Package{ 67 Metadata: pkg.ApkMetadata{ 68 Package: "make", 69 URL: "https://www.gnu.org/software/make", 70 }, 71 }, 72 expected: []string{"gnu", "make"}, 73 }, 74 { 75 name: "ruby-rake with matching origin", 76 pkg: pkg.Package{ 77 Name: "ruby-rake", 78 Type: pkg.ApkPkg, 79 MetadataType: pkg.ApkMetadataType, 80 Metadata: pkg.ApkMetadata{ 81 Package: "ruby-rake", 82 URL: "https://github.com/ruby/rake", 83 OriginPackage: "ruby-rake", 84 }, 85 }, 86 expected: []string{"rake", "ruby-lang", "ruby"}, 87 }, 88 { 89 name: "ruby-rake with non-matching origin", 90 pkg: pkg.Package{ 91 Name: "ruby-rake", 92 Type: pkg.ApkPkg, 93 MetadataType: pkg.ApkMetadataType, 94 Metadata: pkg.ApkMetadata{ 95 Package: "ruby-rake", 96 URL: "https://www.ruby-lang.org/", 97 OriginPackage: "ruby", 98 }, 99 }, 100 expected: []string{"rake", "ruby-lang"}, 101 }, 102 } 103 for _, test := range tests { 104 t.Run(test.name, func(t *testing.T) { 105 assert.ElementsMatch(t, test.expected, candidateVendorsForAPK(test.pkg).uniqueValues(), "different vendors") 106 }) 107 } 108 } 109 110 func Test_candidateProductsForAPK(t *testing.T) { 111 tests := []struct { 112 name string 113 pkg pkg.Package 114 expected []string 115 }{ 116 { 117 name: "py3-cryptography Package", 118 pkg: pkg.Package{ 119 Metadata: pkg.ApkMetadata{ 120 Package: "py3-cryptography", 121 }, 122 }, 123 expected: []string{"cryptography", "python-cryptography"}, 124 }, 125 { 126 name: "py2-pypdf with explicit different origin", 127 pkg: pkg.Package{ 128 Metadata: pkg.ApkMetadata{ 129 Package: "py2-pypdf", 130 OriginPackage: "abcdefg", 131 }, 132 }, 133 expected: []string{"pypdf"}, 134 }, 135 { 136 name: "ruby-armadillo Package", 137 pkg: pkg.Package{ 138 Metadata: pkg.ApkMetadata{ 139 Package: "ruby-armadillo", 140 }, 141 }, 142 expected: []string{"armadillo"}, 143 }, 144 { 145 name: "python-3.6", 146 pkg: pkg.Package{ 147 Metadata: pkg.ApkMetadata{ 148 Package: "python-3.6", 149 }, 150 }, 151 expected: []string{"python"}, 152 }, 153 { 154 name: "ruby-3.6", 155 pkg: pkg.Package{ 156 Metadata: pkg.ApkMetadata{ 157 Package: "ruby-3.6", 158 URL: "https://www.ruby-lang.org/", 159 }, 160 }, 161 expected: []string{"ruby"}, 162 }, 163 { 164 name: "make", 165 pkg: pkg.Package{ 166 Metadata: pkg.ApkMetadata{ 167 Package: "make", 168 URL: "https://www.gnu.org/software/make", 169 }, 170 }, 171 expected: []string{"make"}, 172 }, 173 { 174 name: "ruby-rake with matching origin", 175 pkg: pkg.Package{ 176 Metadata: pkg.ApkMetadata{ 177 Package: "ruby-rake", 178 URL: "https://github.com/ruby/rake", 179 OriginPackage: "ruby-rake", 180 }, 181 }, 182 expected: []string{"rake"}, 183 }, 184 { 185 name: "ruby-rake with non-matching origin", 186 pkg: pkg.Package{ 187 Name: "ruby-rake", 188 Type: pkg.ApkPkg, 189 MetadataType: pkg.ApkMetadataType, 190 Metadata: pkg.ApkMetadata{ 191 Package: "ruby-rake", 192 URL: "https://www.ruby-lang.org/", 193 OriginPackage: "ruby", 194 }, 195 }, 196 expected: []string{"rake"}, 197 }, 198 } 199 for _, test := range tests { 200 t.Run(test.name, func(t *testing.T) { 201 assert.ElementsMatch(t, test.expected, candidateProductsForAPK(test.pkg).uniqueValues(), "different products") 202 }) 203 } 204 } 205 206 func Test_upstreamCandidates(t *testing.T) { 207 tests := []struct { 208 name string 209 metadata pkg.ApkMetadata 210 expected []upstreamCandidate 211 }{ 212 { 213 name: "gocase", 214 metadata: pkg.ApkMetadata{ 215 Package: "p", 216 }, 217 expected: []upstreamCandidate{ 218 {Name: "p", Type: pkg.UnknownPkg}, 219 }, 220 }, 221 { 222 name: "same package and origin simple case", 223 metadata: pkg.ApkMetadata{ 224 Package: "p", 225 OriginPackage: "p", 226 }, 227 expected: []upstreamCandidate{ 228 {Name: "p", Type: pkg.UnknownPkg}, 229 }, 230 }, 231 { 232 name: "different package and origin", 233 metadata: pkg.ApkMetadata{ 234 Package: "p", 235 OriginPackage: "origin", 236 }, 237 expected: []upstreamCandidate{ 238 {Name: "p", Type: pkg.UnknownPkg}, 239 }, 240 }, 241 { 242 name: "upstream python package information as qualifier py- prefix", 243 metadata: pkg.ApkMetadata{ 244 Package: "py-potatoes", 245 OriginPackage: "py-potatoes", 246 }, 247 expected: []upstreamCandidate{ 248 {Name: "potatoes", Type: pkg.PythonPkg}, 249 }, 250 }, 251 { 252 name: "upstream python package information as qualifier py3- prefix", 253 metadata: pkg.ApkMetadata{ 254 Package: "py3-potatoes", 255 OriginPackage: "py3-potatoes", 256 }, 257 expected: []upstreamCandidate{ 258 {Name: "potatoes", Type: pkg.PythonPkg}, 259 }, 260 }, 261 { 262 name: "python package with distinct origin package", 263 metadata: pkg.ApkMetadata{ 264 Package: "py3-non-existant", 265 OriginPackage: "abcdefg", 266 }, 267 expected: []upstreamCandidate{ 268 {Name: "non-existant", Type: pkg.PythonPkg}, 269 }, 270 }, 271 { 272 name: "upstream ruby package information as qualifier", 273 metadata: pkg.ApkMetadata{ 274 Package: "ruby-something", 275 OriginPackage: "ruby-something", 276 }, 277 expected: []upstreamCandidate{ 278 {Name: "something", Type: pkg.GemPkg}, 279 }, 280 }, 281 { 282 name: "ruby package with distinct origin package", 283 metadata: pkg.ApkMetadata{ 284 Package: "ruby-something", 285 OriginPackage: "1234567", 286 }, 287 expected: []upstreamCandidate{ 288 {Name: "something", Type: pkg.GemPkg}, 289 }, 290 }, 291 { 292 name: "postgesql-15 upstream postgresql", 293 metadata: pkg.ApkMetadata{ 294 Package: "postgresql-15", 295 }, 296 expected: []upstreamCandidate{ 297 {Name: "postgresql", Type: pkg.UnknownPkg}, 298 }, 299 }, 300 { 301 name: "postgesql15 upstream postgresql", 302 metadata: pkg.ApkMetadata{ 303 Package: "postgresql15", 304 }, 305 expected: []upstreamCandidate{ 306 {Name: "postgresql", Type: pkg.UnknownPkg}, 307 }, 308 }, 309 { 310 name: "go-1.19 upstream go", 311 metadata: pkg.ApkMetadata{ 312 Package: "go-1.19", 313 }, 314 expected: []upstreamCandidate{ 315 {Name: "go", Type: pkg.UnknownPkg}, 316 }, 317 }, 318 { 319 name: "go1.143 upstream go", 320 metadata: pkg.ApkMetadata{ 321 Package: "go1.143", 322 }, 323 expected: []upstreamCandidate{ 324 {Name: "go", Type: pkg.UnknownPkg}, 325 }, 326 }, 327 { 328 name: "abc-101.191.23456 upstream abc", 329 metadata: pkg.ApkMetadata{ 330 Package: "abc-101.191.23456", 331 }, 332 expected: []upstreamCandidate{ 333 {Name: "abc", Type: pkg.UnknownPkg}, 334 }, 335 }, 336 { 337 name: "abc101.191.23456 upstream abc", 338 metadata: pkg.ApkMetadata{ 339 Package: "abc101.191.23456", 340 }, 341 expected: []upstreamCandidate{ 342 {Name: "abc", Type: pkg.UnknownPkg}, 343 }, 344 }, 345 { 346 name: "abc101-12345-1045 upstream abc101-12345", 347 metadata: pkg.ApkMetadata{ 348 Package: "abc101-12345-1045", 349 }, 350 expected: []upstreamCandidate{ 351 {Name: "abc101-12345", Type: pkg.UnknownPkg}, 352 }, 353 }, 354 { 355 name: "abc101-a12345-1045 upstream abc101-a12345", 356 metadata: pkg.ApkMetadata{ 357 Package: "abc101-a12345-1045", 358 }, 359 expected: []upstreamCandidate{ 360 {Name: "abc-a12345-1045", Type: pkg.UnknownPkg}, 361 }, 362 }, 363 { 364 name: "package starting with single digit", 365 metadata: pkg.ApkMetadata{ 366 Package: "3proxy", 367 }, 368 expected: []upstreamCandidate{ 369 {Name: "3proxy", Type: pkg.UnknownPkg}, 370 }, 371 }, 372 { 373 name: "package starting with multiple digits", 374 metadata: pkg.ApkMetadata{ 375 Package: "356proxy", 376 }, 377 expected: []upstreamCandidate{ 378 {Name: "356proxy", Type: pkg.UnknownPkg}, 379 }, 380 }, 381 { 382 name: "package composed of only digits", 383 metadata: pkg.ApkMetadata{ 384 Package: "123456", 385 }, 386 expected: []upstreamCandidate{ 387 {Name: "123456", Type: pkg.UnknownPkg}, 388 }, 389 }, 390 { 391 name: "ruby-3.6 upstream ruby", 392 metadata: pkg.ApkMetadata{ 393 Package: "ruby-3.6", 394 }, 395 expected: []upstreamCandidate{ 396 {Name: "ruby", Type: pkg.UnknownPkg}, 397 }, 398 }, 399 { 400 name: "ruby3.6 upstream ruby", 401 metadata: pkg.ApkMetadata{ 402 Package: "ruby3.6", 403 }, 404 expected: []upstreamCandidate{ 405 {Name: "ruby", Type: pkg.UnknownPkg}, 406 }, 407 }, 408 { 409 name: "ruby3.6-tacos upstream tacos", 410 metadata: pkg.ApkMetadata{ 411 Package: "ruby3.6-tacos", 412 }, 413 expected: []upstreamCandidate{ 414 {Name: "tacos", Type: pkg.GemPkg}, 415 }, 416 }, 417 { 418 name: "ruby-3.6-tacos upstream tacos", 419 metadata: pkg.ApkMetadata{ 420 Package: "ruby-3.6-tacos", 421 }, 422 expected: []upstreamCandidate{ 423 {Name: "tacos", Type: pkg.GemPkg}, 424 }, 425 }, 426 { 427 name: "abc1234jksajflksa", 428 metadata: pkg.ApkMetadata{ 429 Package: "abc1234jksajflksa", 430 }, 431 expected: []upstreamCandidate{ 432 {Name: "abc1234jksajflksa", Type: pkg.UnknownPkg}, 433 }, 434 }, 435 } 436 437 for _, test := range tests { 438 t.Run(test.name, func(t *testing.T) { 439 actual := upstreamCandidates(test.metadata) 440 assert.Equal(t, test.expected, actual) 441 }) 442 } 443 }