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