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