github.com/anchore/syft@v1.38.2/syft/format/internal/spdxutil/helpers/download_location_test.go (about) 1 package helpers 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_DownloadLocation(t *testing.T) { 12 tests := []struct { 13 name string 14 input pkg.Package 15 expected string 16 }{ 17 { 18 name: "no metadata", 19 input: pkg.Package{}, 20 expected: NOASSERTION, 21 }, 22 { 23 name: "from apk", 24 input: pkg.Package{ 25 Metadata: pkg.ApkDBEntry{ 26 URL: "http://a-place.gov", 27 }, 28 }, 29 expected: "http://a-place.gov", 30 }, 31 { 32 name: "from npm", 33 input: pkg.Package{ 34 Metadata: pkg.NpmPackage{ 35 URL: "http://a-place.gov", 36 }, 37 }, 38 expected: "http://a-place.gov", 39 }, 40 { 41 name: "empty", 42 input: pkg.Package{ 43 Metadata: pkg.NpmPackage{ 44 URL: "", 45 }, 46 }, 47 expected: NOASSERTION, 48 }, 49 { 50 name: "from npm package-lock should include resolved", 51 input: pkg.Package{ 52 Metadata: pkg.NpmPackageLockEntry{ 53 Resolved: "http://package-lock.test", 54 }, 55 }, 56 expected: "http://package-lock.test", 57 }, 58 { 59 name: "from npm package-lock empty should be NONE", 60 input: pkg.Package{ 61 Metadata: pkg.NpmPackageLockEntry{ 62 Resolved: "", 63 }, 64 }, 65 expected: NOASSERTION, 66 }, 67 { 68 name: "from php installed.json", 69 input: pkg.Package{ 70 Metadata: pkg.PhpComposerInstalledEntry{ 71 Dist: pkg.PhpComposerExternalReference{ 72 URL: "http://package-lock.test", 73 }, 74 }, 75 }, 76 expected: "http://package-lock.test", 77 }, 78 { 79 name: "empty", 80 input: pkg.Package{ 81 Metadata: pkg.PhpComposerInstalledEntry{ 82 Dist: pkg.PhpComposerExternalReference{ 83 URL: "", 84 }, 85 }, 86 }, 87 expected: NOASSERTION, 88 }, 89 { 90 name: "from php composer.lock", 91 input: pkg.Package{ 92 Metadata: pkg.PhpComposerLockEntry{ 93 Dist: pkg.PhpComposerExternalReference{ 94 URL: "http://package-lock.test", 95 }, 96 }, 97 }, 98 expected: "http://package-lock.test", 99 }, 100 { 101 name: "empty", 102 input: pkg.Package{ 103 Metadata: pkg.PhpComposerLockEntry{ 104 Dist: pkg.PhpComposerExternalReference{ 105 URL: "", 106 }, 107 }, 108 }, 109 expected: NOASSERTION, 110 }, 111 { 112 name: "none", 113 input: pkg.Package{ 114 Metadata: pkg.PhpComposerLockEntry{ 115 Dist: pkg.PhpComposerExternalReference{ 116 URL: "none", 117 }, 118 }, 119 }, 120 expected: NONE, 121 }, 122 { 123 name: "none uppercase", 124 input: pkg.Package{ 125 Metadata: pkg.PhpComposerLockEntry{ 126 Dist: pkg.PhpComposerExternalReference{ 127 URL: "NONE", 128 }, 129 }, 130 }, 131 expected: NONE, 132 }, 133 { 134 name: "invalid uri", 135 input: pkg.Package{ 136 Metadata: pkg.PhpComposerLockEntry{ 137 Dist: pkg.PhpComposerExternalReference{ 138 URL: "example/package", 139 }, 140 }, 141 }, 142 expected: NOASSERTION, 143 }, 144 { 145 name: "Basic Git Protocol URL", 146 input: pkg.Package{ 147 Metadata: pkg.PhpComposerLockEntry{ 148 Dist: pkg.PhpComposerExternalReference{ 149 URL: "git://git.myproject.org/MyProject", 150 }, 151 }, 152 }, 153 expected: "git://git.myproject.org/MyProject", 154 }, 155 { 156 name: "Git HTTPS URL with .git Extension", 157 input: pkg.Package{ 158 Metadata: pkg.PhpComposerLockEntry{ 159 Dist: pkg.PhpComposerExternalReference{ 160 URL: "git+https://git.myproject.org/MyProject.git", 161 }, 162 }, 163 }, 164 expected: "git+https://git.myproject.org/MyProject.git", 165 }, 166 { 167 name: "Git HTTP URL", 168 input: pkg.Package{ 169 Metadata: pkg.PhpComposerLockEntry{ 170 Dist: pkg.PhpComposerExternalReference{ 171 URL: "git+http://git.myproject.org/MyProject", 172 }, 173 }, 174 }, 175 expected: "git+http://git.myproject.org/MyProject", 176 }, 177 { 178 name: "Git SSH URL with .git Extension", 179 input: pkg.Package{ 180 Metadata: pkg.PhpComposerLockEntry{ 181 Dist: pkg.PhpComposerExternalReference{ 182 URL: "git+ssh://git.myproject.org/MyProject.git", 183 }, 184 }, 185 }, 186 expected: "git+ssh://git.myproject.org/MyProject.git", 187 }, 188 { 189 name: "Git Protocol with Prefix", 190 input: pkg.Package{ 191 Metadata: pkg.PhpComposerLockEntry{ 192 Dist: pkg.PhpComposerExternalReference{ 193 URL: "git+git://git.myproject.org/MyProject", 194 }, 195 }, 196 }, 197 expected: "git+git://git.myproject.org/MyProject", 198 }, 199 { 200 name: "Git URL with C File Fragment", 201 input: pkg.Package{ 202 Metadata: pkg.PhpComposerLockEntry{ 203 Dist: pkg.PhpComposerExternalReference{ 204 URL: "git://git.myproject.org/MyProject#src/somefile.c", 205 }, 206 }, 207 }, 208 expected: "git://git.myproject.org/MyProject#src/somefile.c", 209 }, 210 { 211 name: "Git HTTPS URL with Java File Fragment", 212 input: pkg.Package{ 213 Metadata: pkg.PhpComposerLockEntry{ 214 Dist: pkg.PhpComposerExternalReference{ 215 URL: "git+https://git.myproject.org/MyProject#src/Class.java", 216 }, 217 }, 218 }, 219 expected: "git+https://git.myproject.org/MyProject#src/Class.java", 220 }, 221 { 222 name: "Git URL with Master Branch", 223 input: pkg.Package{ 224 Metadata: pkg.PhpComposerLockEntry{ 225 Dist: pkg.PhpComposerExternalReference{ 226 URL: "git://git.myproject.org/MyProject.git@master", 227 }, 228 }, 229 }, 230 expected: "git://git.myproject.org/MyProject.git@master", 231 }, 232 { 233 name: "Git HTTPS URL with Version Tag", 234 input: pkg.Package{ 235 Metadata: pkg.PhpComposerLockEntry{ 236 Dist: pkg.PhpComposerExternalReference{ 237 URL: "git+https://git.myproject.org/MyProject.git@v1.0", 238 }, 239 }, 240 }, 241 expected: "git+https://git.myproject.org/MyProject.git@v1.0", 242 }, 243 { 244 name: "Git URL with Full Commit Hash", 245 input: pkg.Package{ 246 Metadata: pkg.PhpComposerLockEntry{ 247 Dist: pkg.PhpComposerExternalReference{ 248 URL: "git://git.myproject.org/MyProject.git@da39a3ee5e6b4b0d3255bfef95601890afd80709", 249 }, 250 }, 251 }, 252 expected: "git://git.myproject.org/MyProject.git@da39a3ee5e6b4b0d3255bfef95601890afd80709", 253 }, 254 { 255 name: "Git HTTPS URL with Branch and CPP File Path", 256 input: pkg.Package{ 257 Metadata: pkg.PhpComposerLockEntry{ 258 Dist: pkg.PhpComposerExternalReference{ 259 URL: "git+https://git.myproject.org/MyProject.git@master#/src/MyClass.cpp", 260 }, 261 }, 262 }, 263 expected: "git+https://git.myproject.org/MyProject.git@master#/src/MyClass.cpp", 264 }, 265 { 266 name: "Git HTTPS URL with Commit Hash and Ruby File", 267 input: pkg.Package{ 268 Metadata: pkg.PhpComposerLockEntry{ 269 Dist: pkg.PhpComposerExternalReference{ 270 URL: "git+https://git.myproject.org/MyProject@da39a3ee5e6b4b0d3255bfef95601890afd80709#lib/variable.rb", 271 }, 272 }, 273 }, 274 expected: "git+https://git.myproject.org/MyProject@da39a3ee5e6b4b0d3255bfef95601890afd80709#lib/variable.rb", 275 }, 276 { 277 name: "Basic Mercurial HTTP URL", 278 input: pkg.Package{ 279 Metadata: pkg.PhpComposerLockEntry{ 280 Dist: pkg.PhpComposerExternalReference{ 281 URL: "hg+http://hg.myproject.org/MyProject", 282 }, 283 }, 284 }, 285 expected: "hg+http://hg.myproject.org/MyProject", 286 }, 287 { 288 name: "Basic Mercurial HTTPS URL", 289 input: pkg.Package{ 290 Metadata: pkg.PhpComposerLockEntry{ 291 Dist: pkg.PhpComposerExternalReference{ 292 URL: "hg+https://hg.myproject.org/MyProject", 293 }, 294 }, 295 }, 296 expected: "hg+https://hg.myproject.org/MyProject", 297 }, 298 { 299 name: "Basic Mercurial SSH URL", 300 input: pkg.Package{ 301 Metadata: pkg.PhpComposerLockEntry{ 302 Dist: pkg.PhpComposerExternalReference{ 303 URL: "hg+ssh://hg.myproject.org/MyProject", 304 }, 305 }, 306 }, 307 expected: "hg+ssh://hg.myproject.org/MyProject", 308 }, 309 { 310 name: "Mercurial URL with File Fragment", 311 input: pkg.Package{ 312 Metadata: pkg.PhpComposerLockEntry{ 313 Dist: pkg.PhpComposerExternalReference{ 314 URL: "hg+https://hg.myproject.org/MyProject#src/somefile.c", 315 }, 316 }, 317 }, 318 expected: "hg+https://hg.myproject.org/MyProject#src/somefile.c", 319 }, 320 { 321 name: "Mercurial URL with Java Class Fragment", 322 input: pkg.Package{ 323 Metadata: pkg.PhpComposerLockEntry{ 324 Dist: pkg.PhpComposerExternalReference{ 325 URL: "hg+https://hg.myproject.org/MyProject#src/Class.java", 326 }, 327 }, 328 }, 329 expected: "hg+https://hg.myproject.org/MyProject#src/Class.java", 330 }, 331 { 332 name: "Mercurial URL with Commit Hash", 333 input: pkg.Package{ 334 Metadata: pkg.PhpComposerLockEntry{ 335 Dist: pkg.PhpComposerExternalReference{ 336 URL: "hg+https://hg.myproject.org/MyProject@da39a3ee5e6b", 337 }, 338 }, 339 }, 340 expected: "hg+https://hg.myproject.org/MyProject@da39a3ee5e6b", 341 }, 342 { 343 name: "Mercurial URL with Year Reference", 344 input: pkg.Package{ 345 Metadata: pkg.PhpComposerLockEntry{ 346 Dist: pkg.PhpComposerExternalReference{ 347 URL: "hg+https://hg.myproject.org/MyProject@2019", 348 }, 349 }, 350 }, 351 expected: "hg+https://hg.myproject.org/MyProject@2019", 352 }, 353 { 354 name: "Mercurial URL with Version Tag", 355 input: pkg.Package{ 356 Metadata: pkg.PhpComposerLockEntry{ 357 Dist: pkg.PhpComposerExternalReference{ 358 URL: "hg+https://hg.myproject.org/MyProject@v1.0", 359 }, 360 }, 361 }, 362 expected: "hg+https://hg.myproject.org/MyProject@v1.0", 363 }, 364 { 365 name: "Mercurial URL with Feature Branch", 366 input: pkg.Package{ 367 Metadata: pkg.PhpComposerLockEntry{ 368 Dist: pkg.PhpComposerExternalReference{ 369 URL: "hg+https://hg.myproject.org/MyProject@special_feature", 370 }, 371 }, 372 }, 373 expected: "hg+https://hg.myproject.org/MyProject@special_feature", 374 }, 375 { 376 name: "Mercurial URL with Branch and File Path", 377 input: pkg.Package{ 378 Metadata: pkg.PhpComposerLockEntry{ 379 Dist: pkg.PhpComposerExternalReference{ 380 URL: "hg+https://hg.myproject.org/MyProject@master#/src/MyClass.cpp", 381 }, 382 }, 383 }, 384 expected: "hg+https://hg.myproject.org/MyProject@master#/src/MyClass.cpp", 385 }, 386 { 387 name: "Mercurial URL with Commit Hash and Ruby File", 388 input: pkg.Package{ 389 Metadata: pkg.PhpComposerLockEntry{ 390 Dist: pkg.PhpComposerExternalReference{ 391 URL: "hg+https://hg.myproject.org/MyProject@da39a3ee5e6b#lib/variable.rb", 392 }, 393 }, 394 }, 395 expected: "hg+https://hg.myproject.org/MyProject@da39a3ee5e6b#lib/variable.rb", 396 }, 397 398 // Test cases for Subversion (svn) URLs 399 { 400 name: "Basic SVN URL", 401 input: pkg.Package{ 402 Metadata: pkg.PhpComposerLockEntry{ 403 Dist: pkg.PhpComposerExternalReference{ 404 URL: "svn://svn.myproject.org/svn/MyProject", 405 }, 406 }, 407 }, 408 expected: "svn://svn.myproject.org/svn/MyProject", 409 }, 410 { 411 name: "SVN URL with Protocol Prefix", 412 input: pkg.Package{ 413 Metadata: pkg.PhpComposerLockEntry{ 414 Dist: pkg.PhpComposerExternalReference{ 415 URL: "svn+svn://svn.myproject.org/svn/MyProject", 416 }, 417 }, 418 }, 419 expected: "svn+svn://svn.myproject.org/svn/MyProject", 420 }, 421 { 422 name: "SVN HTTP URL with Trunk", 423 input: pkg.Package{ 424 Metadata: pkg.PhpComposerLockEntry{ 425 Dist: pkg.PhpComposerExternalReference{ 426 URL: "svn+http://svn.myproject.org/svn/MyProject/trunk", 427 }, 428 }, 429 }, 430 expected: "svn+http://svn.myproject.org/svn/MyProject/trunk", 431 }, 432 { 433 name: "SVN HTTPS URL with Trunk", 434 input: pkg.Package{ 435 Metadata: pkg.PhpComposerLockEntry{ 436 Dist: pkg.PhpComposerExternalReference{ 437 URL: "svn+https://svn.myproject.org/svn/MyProject/trunk", 438 }, 439 }, 440 }, 441 expected: "svn+https://svn.myproject.org/svn/MyProject/trunk", 442 }, 443 { 444 name: "SVN URL with C File Fragment", 445 input: pkg.Package{ 446 Metadata: pkg.PhpComposerLockEntry{ 447 Dist: pkg.PhpComposerExternalReference{ 448 URL: "svn+https://svn.myproject.org/MyProject#src/somefile.c", 449 }, 450 }, 451 }, 452 expected: "svn+https://svn.myproject.org/MyProject#src/somefile.c", 453 }, 454 { 455 name: "SVN URL with Java Class Fragment", 456 input: pkg.Package{ 457 Metadata: pkg.PhpComposerLockEntry{ 458 Dist: pkg.PhpComposerExternalReference{ 459 URL: "svn+https://svn.myproject.org/MyProject#src/Class.java", 460 }, 461 }, 462 }, 463 expected: "svn+https://svn.myproject.org/MyProject#src/Class.java", 464 }, 465 { 466 name: "SVN URL with Trunk and C File Fragment", 467 input: pkg.Package{ 468 Metadata: pkg.PhpComposerLockEntry{ 469 Dist: pkg.PhpComposerExternalReference{ 470 URL: "svn+https://svn.myproject.org/MyProject/trunk#src/somefile.c", 471 }, 472 }, 473 }, 474 expected: "svn+https://svn.myproject.org/MyProject/trunk#src/somefile.c", 475 }, 476 { 477 name: "SVN URL with Full File Path", 478 input: pkg.Package{ 479 Metadata: pkg.PhpComposerLockEntry{ 480 Dist: pkg.PhpComposerExternalReference{ 481 URL: "svn+https://svn.myproject.org/MyProject/trunk/src/somefile.c", 482 }, 483 }, 484 }, 485 expected: "svn+https://svn.myproject.org/MyProject/trunk/src/somefile.c", 486 }, 487 { 488 name: "SVN URL with Revision Number", 489 input: pkg.Package{ 490 Metadata: pkg.PhpComposerLockEntry{ 491 Dist: pkg.PhpComposerExternalReference{ 492 URL: "svn+https://svn.myproject.org/svn/MyProject/trunk@2019", 493 }, 494 }, 495 }, 496 expected: "svn+https://svn.myproject.org/svn/MyProject/trunk@2019", 497 }, 498 { 499 name: "SVN URL with Revision and CPP File Path", 500 input: pkg.Package{ 501 Metadata: pkg.PhpComposerLockEntry{ 502 Dist: pkg.PhpComposerExternalReference{ 503 URL: "svn+https://svn.myproject.org/MyProject@123#/src/MyClass.cpp", 504 }, 505 }, 506 }, 507 expected: "svn+https://svn.myproject.org/MyProject@123#/src/MyClass.cpp", 508 }, 509 { 510 name: "SVN URL with Trunk, Revision and Ruby File Path", 511 input: pkg.Package{ 512 Metadata: pkg.PhpComposerLockEntry{ 513 Dist: pkg.PhpComposerExternalReference{ 514 URL: "svn+https://svn.myproject.org/MyProject/trunk@1234#lib/variable/variable.rb", 515 }, 516 }, 517 }, 518 expected: "svn+https://svn.myproject.org/MyProject/trunk@1234#lib/variable/variable.rb", 519 }, 520 521 // Test cases for Bazaar (bzr) URLs 522 { 523 name: "Bazaar HTTPS URL with Trunk", 524 input: pkg.Package{ 525 Metadata: pkg.PhpComposerLockEntry{ 526 Dist: pkg.PhpComposerExternalReference{ 527 URL: "bzr+https://bzr.myproject.org/MyProject/trunk", 528 }, 529 }, 530 }, 531 expected: "bzr+https://bzr.myproject.org/MyProject/trunk", 532 }, 533 { 534 name: "Bazaar HTTP URL with Trunk", 535 input: pkg.Package{ 536 Metadata: pkg.PhpComposerLockEntry{ 537 Dist: pkg.PhpComposerExternalReference{ 538 URL: "bzr+http://bzr.myproject.org/MyProject/trunk", 539 }, 540 }, 541 }, 542 expected: "bzr+http://bzr.myproject.org/MyProject/trunk", 543 }, 544 { 545 name: "Bazaar SFTP URL with Trunk", 546 input: pkg.Package{ 547 Metadata: pkg.PhpComposerLockEntry{ 548 Dist: pkg.PhpComposerExternalReference{ 549 URL: "bzr+sftp://myproject.org/MyProject/trunk", 550 }, 551 }, 552 }, 553 expected: "bzr+sftp://myproject.org/MyProject/trunk", 554 }, 555 { 556 name: "Bazaar SSH URL with Trunk", 557 input: pkg.Package{ 558 Metadata: pkg.PhpComposerLockEntry{ 559 Dist: pkg.PhpComposerExternalReference{ 560 URL: "bzr+ssh://myproject.org/MyProject/trunk", 561 }, 562 }, 563 }, 564 expected: "bzr+ssh://myproject.org/MyProject/trunk", 565 }, 566 { 567 name: "Bazaar FTP URL with Trunk", 568 input: pkg.Package{ 569 Metadata: pkg.PhpComposerLockEntry{ 570 Dist: pkg.PhpComposerExternalReference{ 571 URL: "bzr+ftp://myproject.org/MyProject/trunk", 572 }, 573 }, 574 }, 575 expected: "bzr+ftp://myproject.org/MyProject/trunk", 576 }, 577 { 578 name: "Bazaar Launchpad URL", 579 input: pkg.Package{ 580 Metadata: pkg.PhpComposerLockEntry{ 581 Dist: pkg.PhpComposerExternalReference{ 582 URL: "bzr+lp:MyProject", 583 }, 584 }, 585 }, 586 expected: "bzr+lp:MyProject", 587 }, 588 { 589 name: "Bazaar URL with C File Fragment", 590 input: pkg.Package{ 591 Metadata: pkg.PhpComposerLockEntry{ 592 Dist: pkg.PhpComposerExternalReference{ 593 URL: "bzr+https://bzr.myproject.org/MyProject/trunk#src/somefile.c", 594 }, 595 }, 596 }, 597 expected: "bzr+https://bzr.myproject.org/MyProject/trunk#src/somefile.c", 598 }, 599 { 600 name: "Bazaar URL with Java Class Fragment", 601 input: pkg.Package{ 602 Metadata: pkg.PhpComposerLockEntry{ 603 Dist: pkg.PhpComposerExternalReference{ 604 URL: "bzr+https://bzr.myproject.org/MyProject/trunk#src/Class.java", 605 }, 606 }, 607 }, 608 expected: "bzr+https://bzr.myproject.org/MyProject/trunk#src/Class.java", 609 }, 610 { 611 name: "Bazaar URL with Revision", 612 input: pkg.Package{ 613 Metadata: pkg.PhpComposerLockEntry{ 614 Dist: pkg.PhpComposerExternalReference{ 615 URL: "bzr+https://bzr.myproject.org/MyProject/trunk@2019", 616 }, 617 }, 618 }, 619 expected: "bzr+https://bzr.myproject.org/MyProject/trunk@2019", 620 }, 621 { 622 name: "Bazaar URL with Version Tag", 623 input: pkg.Package{ 624 Metadata: pkg.PhpComposerLockEntry{ 625 Dist: pkg.PhpComposerExternalReference{ 626 URL: "bzr+http://bzr.myproject.org/MyProject/trunk@v1.0", 627 }, 628 }, 629 }, 630 expected: "bzr+http://bzr.myproject.org/MyProject/trunk@v1.0", 631 }, 632 { 633 name: "Bazaar URL with Revision and C File Fragment", 634 input: pkg.Package{ 635 Metadata: pkg.PhpComposerLockEntry{ 636 Dist: pkg.PhpComposerExternalReference{ 637 URL: "bzr+https://bzr.myproject.org/MyProject/trunk@2019#src/somefile.c", 638 }, 639 }, 640 }, 641 expected: "bzr+https://bzr.myproject.org/MyProject/trunk@2019#src/somefile.c", 642 }, 643 } 644 for _, test := range tests { 645 t.Run(test.name, func(t *testing.T) { 646 assert.Equal(t, test.expected, DownloadLocation(test.input)) 647 }) 648 } 649 }